manager_test.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. package git
  2. import (
  3. "os"
  4. "path/filepath"
  5. "testing"
  6. )
  7. func TestInitCreatesRepository(t *testing.T) {
  8. manager := newTestManager(t)
  9. repoPath := filepath.Join(t.TempDir(), "newrepo")
  10. if manager.IsRepo(repoPath) {
  11. t.Fatalf("IsRepo() = true for a folder that does not exist yet")
  12. }
  13. if err := manager.Init(repoPath); err != nil {
  14. t.Fatalf("Init() returned error: %v", err)
  15. }
  16. if !manager.IsRepo(repoPath) {
  17. t.Errorf("IsRepo() = false right after Init()")
  18. }
  19. if _, err := os.Stat(filepath.Join(repoPath, ".git")); err != nil {
  20. t.Errorf("Init() did not create a .git folder: %v", err)
  21. }
  22. }
  23. func TestInitRejectsExistingRepository(t *testing.T) {
  24. manager := newTestManager(t)
  25. repoPath := newTestRepo(t, manager)
  26. if err := manager.Init(repoPath); err == nil {
  27. t.Errorf("Init() on an existing repository = nil error, want an error")
  28. }
  29. }
  30. func TestRepoRoot(t *testing.T) {
  31. manager := newTestManager(t)
  32. repoPath := newTestRepo(t, manager)
  33. nested := filepath.Join(repoPath, "a", "b")
  34. if err := os.MkdirAll(nested, 0775); err != nil {
  35. t.Fatalf("cannot create nested folder: %v", err)
  36. }
  37. tests := []struct {
  38. name string
  39. path string
  40. wantRoot string
  41. wantError bool
  42. }{
  43. {name: "repository root itself", path: repoPath, wantRoot: filepath.ToSlash(repoPath)},
  44. {name: "nested subfolder", path: nested, wantRoot: filepath.ToSlash(repoPath)},
  45. {name: "outside any repository", path: t.TempDir(), wantError: true},
  46. }
  47. for _, test := range tests {
  48. t.Run(test.name, func(t *testing.T) {
  49. root, err := manager.RepoRoot(test.path)
  50. if test.wantError {
  51. if err == nil {
  52. t.Fatalf("RepoRoot(%s) = %q, want an error", test.path, root)
  53. }
  54. return
  55. }
  56. if err != nil {
  57. t.Fatalf("RepoRoot(%s) returned error: %v", test.path, err)
  58. }
  59. //Compare resolved absolute paths: macOS temp dirs are symlinked
  60. wantAbs, _ := filepath.EvalSymlinks(test.wantRoot)
  61. gotAbs, _ := filepath.EvalSymlinks(root)
  62. if gotAbs != wantAbs {
  63. t.Errorf("RepoRoot(%s) = %q, want %q", test.path, gotAbs, wantAbs)
  64. }
  65. })
  66. }
  67. }
  68. func TestIsRepoOnPlainFolder(t *testing.T) {
  69. manager := newTestManager(t)
  70. if manager.IsRepo(t.TempDir()) {
  71. t.Errorf("IsRepo() = true for a plain folder")
  72. }
  73. }
  74. func TestCloneRejectsBadInput(t *testing.T) {
  75. manager := newTestManager(t)
  76. populated := t.TempDir()
  77. if err := os.WriteFile(filepath.Join(populated, "existing.txt"), []byte("hi"), 0664); err != nil {
  78. t.Fatalf("cannot seed folder: %v", err)
  79. }
  80. tests := []struct {
  81. name string
  82. request *CloneRequest
  83. }{
  84. {name: "empty URL", request: &CloneRequest{URL: "", Dest: filepath.Join(t.TempDir(), "x")}},
  85. {name: "empty destination", request: &CloneRequest{URL: "https://example.com/a.git", Dest: ""}},
  86. {name: "destination not empty", request: &CloneRequest{URL: "https://example.com/a.git", Dest: populated}},
  87. }
  88. for _, test := range tests {
  89. t.Run(test.name, func(t *testing.T) {
  90. if err := manager.Clone(test.request); err == nil {
  91. t.Errorf("Clone(%+v) = nil error, want an error", test.request)
  92. }
  93. })
  94. }
  95. }
  96. func TestRemotesLifecycle(t *testing.T) {
  97. manager := newTestManager(t)
  98. repoPath := newTestRepo(t, manager)
  99. remotes, err := manager.Remotes(repoPath)
  100. if err != nil {
  101. t.Fatalf("Remotes() returned error: %v", err)
  102. }
  103. if len(remotes) != 0 {
  104. t.Fatalf("Remotes() on a fresh repository = %d entries, want 0", len(remotes))
  105. }
  106. if err := manager.AddRemote(repoPath, "origin", "https://example.com/demo.git"); err != nil {
  107. t.Fatalf("AddRemote() returned error: %v", err)
  108. }
  109. remotes, err = manager.Remotes(repoPath)
  110. if err != nil {
  111. t.Fatalf("Remotes() returned error: %v", err)
  112. }
  113. if len(remotes) != 1 || remotes[0].Name != "origin" {
  114. t.Fatalf("Remotes() = %+v, want a single origin entry", remotes)
  115. }
  116. if remotes[0].URLs[0] != "https://example.com/demo.git" {
  117. t.Errorf("origin URL = %q, want %q", remotes[0].URLs[0], "https://example.com/demo.git")
  118. }
  119. //Re-adding the same name replaces the URL rather than failing
  120. if err := manager.AddRemote(repoPath, "origin", "https://example.com/other.git"); err != nil {
  121. t.Fatalf("AddRemote() on an existing name returned error: %v", err)
  122. }
  123. remotes, _ = manager.Remotes(repoPath)
  124. if len(remotes) != 1 || remotes[0].URLs[0] != "https://example.com/other.git" {
  125. t.Errorf("Remotes() after replace = %+v, want the updated URL", remotes)
  126. }
  127. if err := manager.RemoveRemote(repoPath, "origin"); err != nil {
  128. t.Fatalf("RemoveRemote() returned error: %v", err)
  129. }
  130. remotes, _ = manager.Remotes(repoPath)
  131. if len(remotes) != 0 {
  132. t.Errorf("Remotes() after remove = %d entries, want 0", len(remotes))
  133. }
  134. }
  135. func TestOperationsOnNonRepoReturnErrNotARepo(t *testing.T) {
  136. manager := newTestManager(t)
  137. plain := t.TempDir()
  138. if _, err := manager.Status(plain); err != ErrNotARepo {
  139. t.Errorf("Status() on a plain folder = %v, want ErrNotARepo", err)
  140. }
  141. if _, err := manager.Log(plain, 10); err != ErrNotARepo {
  142. t.Errorf("Log() on a plain folder = %v, want ErrNotARepo", err)
  143. }
  144. if _, err := manager.Branches(plain); err != ErrNotARepo {
  145. t.Errorf("Branches() on a plain folder = %v, want ErrNotARepo", err)
  146. }
  147. }