You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

git.go 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. // Copyright 2015 The Gogs Authors. All rights reserved.
  2. // Copyright 2017 The Gitea Authors. All rights reserved.
  3. // Use of this source code is governed by a MIT-style
  4. // license that can be found in the LICENSE file.
  5. package git
  6. import (
  7. "fmt"
  8. "os/exec"
  9. "strings"
  10. "time"
  11. "code.gitea.io/gitea/modules/process"
  12. "github.com/mcuadros/go-version"
  13. )
  14. // Version return this package's current version
  15. func Version() string {
  16. return "0.4.2"
  17. }
  18. var (
  19. // Debug enables verbose logging on everything.
  20. // This should be false in case Gogs starts in SSH mode.
  21. Debug = false
  22. // Prefix the log prefix
  23. Prefix = "[git-module] "
  24. // GitVersionRequired is the minimum Git version required
  25. GitVersionRequired = "1.7.2"
  26. // GitExecutable is the command name of git
  27. // Could be updated to an absolute path while initialization
  28. GitExecutable = "git"
  29. gitVersion string
  30. )
  31. func log(format string, args ...interface{}) {
  32. if !Debug {
  33. return
  34. }
  35. fmt.Print(Prefix)
  36. if len(args) == 0 {
  37. fmt.Println(format)
  38. } else {
  39. fmt.Printf(format+"\n", args...)
  40. }
  41. }
  42. // BinVersion returns current Git version from shell.
  43. func BinVersion() (string, error) {
  44. if len(gitVersion) > 0 {
  45. return gitVersion, nil
  46. }
  47. stdout, err := NewCommand("version").Run()
  48. if err != nil {
  49. return "", err
  50. }
  51. fields := strings.Fields(stdout)
  52. if len(fields) < 3 {
  53. return "", fmt.Errorf("not enough output: %s", stdout)
  54. }
  55. // Handle special case on Windows.
  56. i := strings.Index(fields[2], "windows")
  57. if i >= 1 {
  58. gitVersion = fields[2][:i-1]
  59. return gitVersion, nil
  60. }
  61. gitVersion = fields[2]
  62. return gitVersion, nil
  63. }
  64. func init() {
  65. absPath, err := exec.LookPath(GitExecutable)
  66. if err != nil {
  67. panic(fmt.Sprintf("Git not found: %v", err))
  68. }
  69. GitExecutable = absPath
  70. gitVersion, err := BinVersion()
  71. if err != nil {
  72. panic(fmt.Sprintf("Git version missing: %v", err))
  73. }
  74. if version.Compare(gitVersion, GitVersionRequired, "<") {
  75. panic(fmt.Sprintf("Git version not supported. Requires version > %v", GitVersionRequired))
  76. }
  77. // Git requires setting user.name and user.email in order to commit changes.
  78. for configKey, defaultValue := range map[string]string{"user.name": "Gitea", "user.email": "gitea@fake.local"} {
  79. if stdout, stderr, err := process.GetManager().Exec("git.Init(get setting)", GitExecutable, "config", "--get", configKey); err != nil || strings.TrimSpace(stdout) == "" {
  80. // ExitError indicates this config is not set
  81. if _, ok := err.(*exec.ExitError); ok || strings.TrimSpace(stdout) == "" {
  82. if _, stderr, gerr := process.GetManager().Exec("git.Init(set "+configKey+")", "git", "config", "--global", configKey, defaultValue); gerr != nil {
  83. panic(fmt.Sprintf("Failed to set git %s(%s): %s", configKey, gerr, stderr))
  84. }
  85. } else {
  86. panic(fmt.Sprintf("Failed to get git %s(%s): %s", configKey, err, stderr))
  87. }
  88. }
  89. }
  90. // Set git some configurations.
  91. if _, stderr, err := process.GetManager().Exec("git.Init(git config --global core.quotepath false)",
  92. GitExecutable, "config", "--global", "core.quotepath", "false"); err != nil {
  93. panic(fmt.Sprintf("Failed to execute 'git config --global core.quotepath false': %s", stderr))
  94. }
  95. }
  96. // Fsck verifies the connectivity and validity of the objects in the database
  97. func Fsck(repoPath string, timeout time.Duration, args ...string) error {
  98. // Make sure timeout makes sense.
  99. if timeout <= 0 {
  100. timeout = -1
  101. }
  102. _, err := NewCommand("fsck").AddArguments(args...).RunInDirTimeout(timeout, repoPath)
  103. return err
  104. }