github.com/treeverse/lakefs@v1.24.1-0.20240520134607-95648127bfb0/pkg/git/git_test.go (about) 1 package git_test 2 3 import ( 4 "fmt" 5 "io" 6 "os" 7 "os/exec" 8 "path/filepath" 9 "testing" 10 11 "github.com/stretchr/testify/require" 12 "github.com/treeverse/lakefs/pkg/git" 13 ) 14 15 func TestIsRepository(t *testing.T) { 16 tmpdir := t.TempDir() 17 tmpSubdir, err := os.MkdirTemp(tmpdir, "") 18 require.NoError(t, err) 19 defer func(name string) { 20 err = os.RemoveAll(name) 21 if err != nil { 22 t.Error("failed to remove temp dir", err) 23 } 24 }(tmpSubdir) 25 tmpFile, err := os.CreateTemp(tmpSubdir, "") 26 require.NoError(t, err) 27 defer func() { 28 _ = os.Remove(tmpFile.Name()) 29 _ = tmpFile.Close() 30 }() 31 32 require.False(t, git.IsRepository(tmpFile.Name())) 33 require.False(t, git.IsRepository(tmpdir)) 34 35 // Init git repo on root 36 require.NoError(t, exec.Command("git", "init", "-q", tmpdir).Run()) 37 require.False(t, git.IsRepository(tmpFile.Name())) 38 require.True(t, git.IsRepository(tmpdir)) 39 require.True(t, git.IsRepository(tmpSubdir)) 40 } 41 42 func TestGetRepositoryPath(t *testing.T) { 43 var err error 44 tmpdir := t.TempDir() 45 tmpdir, err = filepath.EvalSymlinks(tmpdir) // on macOS tmpdir is a symlink 46 require.NoError(t, err) 47 tmpSubdir, err := os.MkdirTemp(tmpdir, "") 48 require.NoError(t, err) 49 defer func(name string) { 50 _ = os.Remove(name) 51 }(tmpSubdir) 52 tmpFile, err := os.CreateTemp(tmpSubdir, "") 53 require.NoError(t, err) 54 defer func() { 55 _ = os.Remove(tmpFile.Name()) 56 _ = tmpFile.Close() 57 }() 58 59 _, err = git.GetRepositoryPath(tmpdir) 60 require.ErrorIs(t, err, git.ErrNotARepository) 61 _, err = git.GetRepositoryPath(tmpFile.Name()) 62 require.Error(t, err) 63 64 // Init git repo on root 65 require.NoError(t, exec.Command("git", "init", "-q", tmpdir).Run()) 66 gitPath, err := git.GetRepositoryPath(tmpdir) 67 require.NoError(t, err) 68 require.Equal(t, tmpdir, gitPath) 69 _, err = git.GetRepositoryPath(tmpFile.Name()) 70 require.Error(t, err) 71 gitPath, err = git.GetRepositoryPath(tmpSubdir) 72 require.NoError(t, err) 73 require.Equal(t, tmpdir, gitPath) 74 } 75 76 func TestIgnore(t *testing.T) { 77 const ( 78 excludedFile = ".excluded.ex" 79 trackedFile = "file1" 80 marker = "Test Marker" 81 ) 82 tmpdir, err := filepath.EvalSymlinks(t.TempDir()) // on macOS tmpdir is a symlink 83 require.NoError(t, err) 84 // create sub dir and file 85 tmpSubdir, err := os.MkdirTemp(tmpdir, "") 86 require.NoError(t, err) 87 tmpFile, err := os.CreateTemp(tmpSubdir, "") 88 require.NoError(t, err) 89 excludedPath := filepath.Join(tmpSubdir, excludedFile) 90 91 // Test we can't ignore if not a git repo 92 _, err = git.Ignore(tmpdir, []string{}, []string{}, marker) 93 require.ErrorIs(t, err, git.ErrNotARepository) 94 _, err = git.Ignore(tmpFile.Name(), []string{}, []string{}, marker) 95 require.Error(t, err) 96 97 // Init git repo on tmpdir 98 err = exec.Command("git", "init", "-q", tmpdir).Run() 99 require.NoError(t, err) 100 ignorePath := filepath.Join(tmpdir, git.IgnoreFile) 101 102 // Create files in repo 103 for _, fn := range []string{ 104 filepath.Join(tmpdir, trackedFile), 105 filepath.Join(tmpSubdir, "should_be_ignored"), 106 excludedPath, 107 } { 108 err = os.WriteFile(fn, []byte("content\n"), 0o644) 109 require.NoError(t, err, "failed to create file %s", fn) 110 } 111 112 // Changing the working directory 113 require.NoError(t, os.Chdir(tmpdir)) 114 verifyPathTracked(t, []string{filepath.Base(tmpSubdir), trackedFile}) 115 116 _, err = git.Ignore(tmpFile.Name(), []string{}, []string{excludedPath}, marker) 117 require.Error(t, err) 118 result, err := git.Ignore(tmpdir, []string{}, []string{excludedPath}, marker) 119 require.NoError(t, err) 120 require.Equal(t, ignorePath, result) 121 relExcludedPath, err := filepath.Rel(tmpdir, excludedPath) 122 require.NoError(t, err) 123 124 verifyPathTracked(t, []string{filepath.Base(tmpSubdir), trackedFile}) 125 126 _, err = git.Ignore(tmpSubdir, []string{tmpFile.Name()}, []string{excludedPath}, marker) 127 require.NoError(t, err) 128 relDataFile, err := filepath.Rel(tmpdir, tmpFile.Name()) 129 require.NoError(t, err) 130 verifyPathTracked(t, []string{trackedFile}) 131 132 _, err = git.Ignore(tmpSubdir, []string{tmpSubdir, filepath.Join(tmpdir, trackedFile)}, []string{}, marker) 133 require.NoError(t, err) 134 relDataSubDir, err := filepath.Rel(tmpdir, tmpSubdir) 135 require.NoError(t, err) 136 verifyPathTracked(t, []string{git.IgnoreFile}) 137 138 _, err = git.Ignore(tmpSubdir, []string{tmpSubdir, filepath.Join(tmpdir, trackedFile), ignorePath}, []string{}, marker) 139 require.NoError(t, err) 140 require.Equal(t, ignorePath, result) 141 142 contents, err := os.ReadFile(ignorePath) 143 require.NoError(t, err) 144 verifyPathTracked(t, nil) 145 146 expectedGitIgnore := fmt.Sprintf("# %s\n%s\n!%s\n%s\n%s\n%s\n# End %s\n", 147 marker, 148 relDataFile, relExcludedPath, filepath.Join(relDataSubDir, "*"), trackedFile, git.IgnoreFile, 149 marker) 150 require.Equal(t, expectedGitIgnore, string(contents)) 151 } 152 153 func verifyPathTracked(t *testing.T, paths []string) { 154 cmd := exec.Command("git", "status") 155 r, w, _ := os.Pipe() 156 cmd.Stdout = w 157 require.NoError(t, cmd.Run()) 158 require.NoError(t, w.Close()) 159 out, err := io.ReadAll(r) 160 require.NoError(t, err) 161 outStr := string(out) 162 163 if len(paths) == 0 { 164 require.Contains(t, outStr, "nothing to commit") 165 } else { 166 for _, p := range paths { 167 require.Contains(t, outStr, p) 168 } 169 } 170 } 171 172 func TestParseURL(t *testing.T) { 173 cases := []struct { 174 Url string 175 ExpectedUrl *git.URL 176 }{ 177 { 178 Url: "git@github.com:treeverse/lakeFS.git", 179 ExpectedUrl: &git.URL{ 180 Server: "github.com", 181 Owner: "treeverse", 182 Project: "lakeFS", 183 }, 184 }, 185 { 186 Url: "ssh://git@github.com/tree/lake.git", 187 ExpectedUrl: &git.URL{ 188 Server: "github.com", 189 Owner: "tree", 190 Project: "lake", 191 }, 192 }, 193 { 194 Url: "https://github.com/treeverse/lakeFS2.git", 195 ExpectedUrl: &git.URL{ 196 Server: "github.com", 197 Owner: "treeverse", 198 Project: "lakeFS2", 199 }, 200 }, 201 { 202 Url: "git://git@192.168.1.20:MyGroup/MyProject.git", 203 ExpectedUrl: &git.URL{ 204 Server: "192.168.1.20", 205 Owner: "MyGroup", 206 Project: "MyProject", 207 }, 208 }, 209 { 210 Url: "git://git@192.168.1.20:22:MyGroup/MyProject.git", 211 ExpectedUrl: &git.URL{ 212 Server: "192.168.1.20:22", 213 Owner: "MyGroup", 214 Project: "MyProject", 215 }, 216 }, 217 { 218 Url: "git://git@github.com:Hyphened-Owner/Hyphened-Project.git", 219 ExpectedUrl: &git.URL{ 220 Server: "github.com", 221 Owner: "Hyphened-Owner", 222 Project: "Hyphened-Project", 223 }, 224 }, 225 { 226 Url: "bad_url", 227 ExpectedUrl: nil, 228 }, 229 } 230 for _, tt := range cases { 231 t.Run(tt.Url, func(t *testing.T) { 232 parsed := git.ParseURL(tt.Url) 233 require.Equal(t, tt.ExpectedUrl, parsed) 234 }) 235 } 236 }