github.com/stffabi/git-lfs@v2.3.5-0.20180214015214-8eeaa8d88902+incompatible/tools/filetools_test.go (about) 1 package tools 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 "runtime" 9 "sort" 10 "testing" 11 12 "github.com/git-lfs/git-lfs/subprocess" 13 "github.com/stretchr/testify/assert" 14 ) 15 16 func TestCleanPathsCleansPaths(t *testing.T) { 17 cleaned := CleanPaths("/foo/bar/,/foo/bar/baz", ",") 18 assert.Equal(t, []string{"/foo/bar", "/foo/bar/baz"}, cleaned) 19 } 20 21 func TestCleanPathsReturnsNoResultsWhenGivenNoPaths(t *testing.T) { 22 cleaned := CleanPaths("", ",") 23 assert.Empty(t, cleaned) 24 } 25 26 func TestFastWalkBasic(t *testing.T) { 27 rootDir, err := ioutil.TempDir(os.TempDir(), "GitLfsTestFastWalkBasic") 28 if err != nil { 29 assert.FailNow(t, "Unable to get temp dir: %v", err) 30 } 31 defer os.RemoveAll(rootDir) 32 os.Chdir(rootDir) 33 34 expectedEntries := createFastWalkInputData(10, 160) 35 36 walker := fastWalkWithExcludeFiles(expectedEntries[0], "") 37 gotEntries, gotErrors := collectFastWalkResults(walker.ch) 38 39 assert.Empty(t, gotErrors) 40 41 sort.Strings(expectedEntries) 42 sort.Strings(gotEntries) 43 assert.Equal(t, expectedEntries, gotEntries) 44 } 45 46 func BenchmarkFastWalkGitRepoChannels(b *testing.B) { 47 rootDir, err := ioutil.TempDir(os.TempDir(), "GitLfsBenchFastWalkGitRepoChannels") 48 if err != nil { 49 assert.FailNow(b, "Unable to get temp dir: %v", err) 50 } 51 defer os.RemoveAll(rootDir) 52 os.Chdir(rootDir) 53 entries := createFastWalkInputData(1000, 5000) 54 55 for i := 0; i < b.N; i++ { 56 var files, errors int 57 FastWalkGitRepo(entries[0], func(parent string, info os.FileInfo, err error) { 58 if err != nil { 59 errors++ 60 } else { 61 files++ 62 } 63 }) 64 b.Logf("files: %d, errors: %d", files, errors) 65 } 66 } 67 68 func BenchmarkFastWalkGitRepoCallback(b *testing.B) { 69 rootDir, err := ioutil.TempDir(os.TempDir(), "GitLfsBenchFastWalkGitRepoCallback") 70 if err != nil { 71 assert.FailNow(b, "Unable to get temp dir: %v", err) 72 } 73 defer os.RemoveAll(rootDir) 74 os.Chdir(rootDir) 75 entries := createFastWalkInputData(1000, 5000) 76 77 for i := 0; i < b.N; i++ { 78 var files, errors int 79 FastWalkGitRepo(entries[0], func(parentDir string, info os.FileInfo, err error) { 80 if err != nil { 81 errors++ 82 } else { 83 files++ 84 } 85 }) 86 87 b.Logf("files: %d, errors: %d", files, errors) 88 } 89 } 90 91 func TestFastWalkGitRepo(t *testing.T) { 92 rootDir, err := ioutil.TempDir(os.TempDir(), "GitLfsTestFastWalkGitRepo") 93 if err != nil { 94 assert.FailNow(t, "Unable to get temp dir: %v", err) 95 } 96 defer os.RemoveAll(rootDir) 97 os.Chdir(rootDir) 98 99 expectedEntries := createFastWalkInputData(3, 3) 100 101 mainDir := expectedEntries[0] 102 103 // Set up a git repo and add some ignored files / dirs 104 subprocess.SimpleExec("git", "init", mainDir) 105 ignored := []string{ 106 "filethatweignore.ign", 107 "foldercontainingignored", 108 "foldercontainingignored/notthisone.ign", 109 "foldercontainingignored/ignoredfolder", 110 "foldercontainingignored/ignoredfolder/file1.txt", 111 "foldercontainingignored/ignoredfolder/file2.txt", 112 "ignoredfolder", 113 "ignoredfolder/file1.txt", 114 "ignoredfolder/file2.txt", 115 "ignoredfrominside", 116 "ignoredfrominside/thisisok.txt", 117 "ignoredfrominside/thisisnot.txt", 118 "ignoredfrominside/thisone", 119 "ignoredfrominside/thisone/file1.txt", 120 } 121 for _, f := range ignored { 122 fullPath := filepath.Join(mainDir, f) 123 if len(filepath.Ext(f)) > 0 { 124 ioutil.WriteFile(fullPath, []byte("TEST"), 0644) 125 } else { 126 os.MkdirAll(fullPath, 0755) 127 } 128 } 129 // write root .gitignore 130 rootGitIgnore := ` 131 # ignore *.ign everywhere 132 *.ign 133 # ignore folder 134 ignoredfolder 135 ` 136 ioutil.WriteFile(filepath.Join(mainDir, ".gitignore"), []byte(rootGitIgnore), 0644) 137 // Subfolder ignore; folder will show up but but subfolder 'thisone' won't 138 subFolderIgnore := ` 139 thisone 140 thisisnot.txt 141 ` 142 ioutil.WriteFile(filepath.Join(mainDir, "ignoredfrominside", ".gitignore"), []byte(subFolderIgnore), 0644) 143 144 // This dir will be walked but content won't be 145 expectedEntries = append(expectedEntries, filepath.Join(mainDir, "foldercontainingignored")) 146 // This dir will be walked and some of its content but has its own gitignore 147 expectedEntries = append(expectedEntries, filepath.Join(mainDir, "ignoredfrominside")) 148 expectedEntries = append(expectedEntries, filepath.Join(mainDir, "ignoredfrominside", "thisisok.txt")) 149 // Also gitignores 150 expectedEntries = append(expectedEntries, filepath.Join(mainDir, ".gitignore")) 151 expectedEntries = append(expectedEntries, filepath.Join(mainDir, "ignoredfrominside", ".gitignore")) 152 // nothing else should be there 153 154 gotEntries := make([]string, 0, 1000) 155 gotErrors := make([]error, 0, 5) 156 FastWalkGitRepo(mainDir, func(parent string, info os.FileInfo, err error) { 157 if err != nil { 158 gotErrors = append(gotErrors, err) 159 } else { 160 gotEntries = append(gotEntries, filepath.Join(parent, info.Name())) 161 } 162 }) 163 164 assert.Empty(t, gotErrors) 165 166 sort.Strings(expectedEntries) 167 sort.Strings(gotEntries) 168 assert.Equal(t, expectedEntries, gotEntries) 169 170 } 171 172 // Make test data - ensure you've Chdir'ed into a temp dir first 173 // Returns list of files/dirs that are created 174 // First entry is the parent dir of all others 175 func createFastWalkInputData(smallFolder, largeFolder int) []string { 176 dirs := []string{ 177 "testroot", 178 "testroot/folder1", 179 "testroot/folder2", 180 "testroot/folder2/subfolder1", 181 "testroot/folder2/subfolder2", 182 "testroot/folder2/subfolder3", 183 "testroot/folder2/subfolder4", 184 "testroot/folder2/subfolder4/subsub", 185 } 186 expectedEntries := make([]string, 0, 250) 187 188 for i, dir := range dirs { 189 os.MkdirAll(dir, 0755) 190 numFiles := smallFolder 191 expectedEntries = append(expectedEntries, filepath.Clean(dir)) 192 if i >= 3 && i <= 5 { 193 // Bulk test to ensure works with > 1 batch 194 numFiles = largeFolder 195 } 196 for f := 0; f < numFiles; f++ { 197 filename := filepath.Join(dir, fmt.Sprintf("file%d.txt", f)) 198 ioutil.WriteFile(filename, []byte("TEST"), 0644) 199 expectedEntries = append(expectedEntries, filepath.Clean(filename)) 200 } 201 } 202 203 return expectedEntries 204 } 205 206 func collectFastWalkResults(fchan <-chan fastWalkInfo) ([]string, []error) { 207 gotEntries := make([]string, 0, 1000) 208 gotErrors := make([]error, 0, 5) 209 for o := range fchan { 210 if o.Err != nil { 211 gotErrors = append(gotErrors, o.Err) 212 } else { 213 gotEntries = append(gotEntries, filepath.Join(o.ParentDir, o.Info.Name())) 214 } 215 } 216 217 return gotEntries, gotErrors 218 } 219 220 func getFileMode(filename string) os.FileMode { 221 s, err := os.Stat(filename) 222 if err != nil { 223 return 0000 224 } 225 return s.Mode() 226 } 227 228 func TestSetWriteFlag(t *testing.T) { 229 f, err := ioutil.TempFile("", "lfstestwriteflag") 230 assert.Nil(t, err) 231 filename := f.Name() 232 defer os.Remove(filename) 233 f.Close() 234 // Set up with read/write bit for all but no execute 235 assert.Nil(t, os.Chmod(filename, 0666)) 236 237 assert.Nil(t, SetFileWriteFlag(filename, false)) 238 // should turn off all write 239 assert.EqualValues(t, 0444, getFileMode(filename)) 240 assert.Nil(t, SetFileWriteFlag(filename, true)) 241 // should only add back user write (on Mac/Linux) 242 if runtime.GOOS == "windows" { 243 assert.EqualValues(t, 0666, getFileMode(filename)) 244 } else { 245 assert.EqualValues(t, 0644, getFileMode(filename)) 246 } 247 248 // Can't run selective UGO tests on Windows as doesn't support separate roles 249 // Also Golang only supports read/write but not execute on Windows 250 if runtime.GOOS != "windows" { 251 // Set up with read/write/execute bit for all but no execute 252 assert.Nil(t, os.Chmod(filename, 0777)) 253 assert.Nil(t, SetFileWriteFlag(filename, false)) 254 // should turn off all write but not execute 255 assert.EqualValues(t, 0555, getFileMode(filename)) 256 assert.Nil(t, SetFileWriteFlag(filename, true)) 257 // should only add back user write (on Mac/Linux) 258 if runtime.GOOS == "windows" { 259 assert.EqualValues(t, 0777, getFileMode(filename)) 260 } else { 261 assert.EqualValues(t, 0755, getFileMode(filename)) 262 } 263 264 assert.Nil(t, os.Chmod(filename, 0440)) 265 assert.Nil(t, SetFileWriteFlag(filename, false)) 266 assert.EqualValues(t, 0440, getFileMode(filename)) 267 assert.Nil(t, SetFileWriteFlag(filename, true)) 268 // should only add back user write 269 assert.EqualValues(t, 0640, getFileMode(filename)) 270 } 271 }