github.com/ohlinux/git-lfs@v1.5.4/git/git_test.go (about) 1 package git_test // to avoid import cycles 2 3 import ( 4 "io/ioutil" 5 "os" 6 "path/filepath" 7 "sort" 8 "testing" 9 "time" 10 11 . "github.com/git-lfs/git-lfs/git" 12 "github.com/git-lfs/git-lfs/test" 13 "github.com/git-lfs/git-lfs/tools/longpathos" 14 "github.com/stretchr/testify/assert" 15 ) 16 17 func TestCurrentRefAndCurrentRemoteRef(t *testing.T) { 18 repo := test.NewRepo(t) 19 repo.Pushd() 20 defer func() { 21 repo.Popd() 22 repo.Cleanup() 23 }() 24 25 // test commits; we'll just modify the same file each time since we're 26 // only interested in branches 27 inputs := []*test.CommitInput{ 28 { // 0 29 Files: []*test.FileInput{ 30 {Filename: "file1.txt", Size: 20}, 31 }, 32 }, 33 { // 1 34 NewBranch: "branch2", 35 Files: []*test.FileInput{ 36 {Filename: "file1.txt", Size: 25}, 37 }, 38 }, 39 { // 2 40 ParentBranches: []string{"master"}, // back on master 41 Files: []*test.FileInput{ 42 {Filename: "file1.txt", Size: 30}, 43 }, 44 }, 45 { // 3 46 NewBranch: "branch3", 47 Files: []*test.FileInput{ 48 {Filename: "file1.txt", Size: 32}, 49 }, 50 }, 51 } 52 outputs := repo.AddCommits(inputs) 53 // last commit was on branch3 54 ref, err := CurrentRef() 55 assert.Nil(t, err) 56 assert.Equal(t, &Ref{"branch3", RefTypeLocalBranch, outputs[3].Sha}, ref) 57 test.RunGitCommand(t, true, "checkout", "master") 58 ref, err = CurrentRef() 59 assert.Nil(t, err) 60 assert.Equal(t, &Ref{"master", RefTypeLocalBranch, outputs[2].Sha}, ref) 61 // Check remote 62 repo.AddRemote("origin") 63 test.RunGitCommand(t, true, "push", "-u", "origin", "master:someremotebranch") 64 ref, err = CurrentRemoteRef() 65 assert.Nil(t, err) 66 assert.Equal(t, &Ref{"origin/someremotebranch", RefTypeRemoteBranch, outputs[2].Sha}, ref) 67 68 refname, err := RemoteRefNameForCurrentBranch() 69 assert.Nil(t, err) 70 assert.Equal(t, "refs/remotes/origin/someremotebranch", refname) 71 72 remote, err := RemoteForCurrentBranch() 73 assert.Nil(t, err) 74 assert.Equal(t, "origin", remote) 75 76 ref, err = ResolveRef(outputs[2].Sha) 77 assert.Nil(t, err) 78 assert.Equal(t, &Ref{outputs[2].Sha, RefTypeOther, outputs[2].Sha}, ref) 79 } 80 81 func TestRecentBranches(t *testing.T) { 82 repo := test.NewRepo(t) 83 repo.Pushd() 84 defer func() { 85 repo.Popd() 86 repo.Cleanup() 87 }() 88 89 now := time.Now() 90 // test commits; we'll just modify the same file each time since we're 91 // only interested in branches & dates 92 inputs := []*test.CommitInput{ 93 { // 0 94 CommitDate: now.AddDate(0, 0, -20), 95 Files: []*test.FileInput{ 96 {Filename: "file1.txt", Size: 20}, 97 }, 98 }, 99 { // 1 100 CommitDate: now.AddDate(0, 0, -15), 101 NewBranch: "excluded_branch", // new branch & tag but too old 102 Tags: []string{"excluded_tag"}, 103 Files: []*test.FileInput{ 104 {Filename: "file1.txt", Size: 25}, 105 }, 106 }, 107 { // 2 108 CommitDate: now.AddDate(0, 0, -12), 109 ParentBranches: []string{"master"}, // back on master 110 Files: []*test.FileInput{ 111 {Filename: "file1.txt", Size: 30}, 112 }, 113 }, 114 { // 3 115 CommitDate: now.AddDate(0, 0, -6), 116 NewBranch: "included_branch", // new branch within 7 day limit 117 Files: []*test.FileInput{ 118 {Filename: "file1.txt", Size: 32}, 119 }, 120 }, 121 { // 4 122 CommitDate: now.AddDate(0, 0, -3), 123 NewBranch: "included_branch_2", // new branch within 7 day limit 124 Files: []*test.FileInput{ 125 {Filename: "file1.txt", Size: 36}, 126 }, 127 }, 128 { // 5 129 // Final commit, current date/time 130 ParentBranches: []string{"master"}, // back on master 131 Files: []*test.FileInput{ 132 {Filename: "file1.txt", Size: 21}, 133 }, 134 }, 135 } 136 outputs := repo.AddCommits(inputs) 137 138 // Add a couple of remotes and push some branches 139 repo.AddRemote("origin") 140 repo.AddRemote("upstream") 141 142 test.RunGitCommand(t, true, "push", "origin", "master") 143 test.RunGitCommand(t, true, "push", "origin", "excluded_branch") 144 test.RunGitCommand(t, true, "push", "origin", "included_branch") 145 test.RunGitCommand(t, true, "push", "upstream", "master") 146 test.RunGitCommand(t, true, "push", "upstream", "included_branch_2") 147 148 // Recent, local only 149 refs, err := RecentBranches(now.AddDate(0, 0, -7), false, "") 150 assert.Equal(t, nil, err) 151 expectedRefs := []*Ref{ 152 &Ref{"master", RefTypeLocalBranch, outputs[5].Sha}, 153 &Ref{"included_branch_2", RefTypeLocalBranch, outputs[4].Sha}, 154 &Ref{"included_branch", RefTypeLocalBranch, outputs[3].Sha}, 155 } 156 assert.Equal(t, expectedRefs, refs, "Refs should be correct") 157 158 // Recent, remotes too (all of them) 159 refs, err = RecentBranches(now.AddDate(0, 0, -7), true, "") 160 assert.Equal(t, nil, err) 161 expectedRefs = []*Ref{ 162 &Ref{"master", RefTypeLocalBranch, outputs[5].Sha}, 163 &Ref{"included_branch_2", RefTypeLocalBranch, outputs[4].Sha}, 164 &Ref{"included_branch", RefTypeLocalBranch, outputs[3].Sha}, 165 &Ref{"upstream/master", RefTypeRemoteBranch, outputs[5].Sha}, 166 &Ref{"upstream/included_branch_2", RefTypeRemoteBranch, outputs[4].Sha}, 167 &Ref{"origin/master", RefTypeRemoteBranch, outputs[5].Sha}, 168 &Ref{"origin/included_branch", RefTypeRemoteBranch, outputs[3].Sha}, 169 } 170 // Need to sort for consistent comparison 171 sort.Sort(test.RefsByName(expectedRefs)) 172 sort.Sort(test.RefsByName(refs)) 173 assert.Equal(t, expectedRefs, refs, "Refs should be correct") 174 175 // Recent, only single remote 176 refs, err = RecentBranches(now.AddDate(0, 0, -7), true, "origin") 177 assert.Equal(t, nil, err) 178 expectedRefs = []*Ref{ 179 &Ref{"master", RefTypeLocalBranch, outputs[5].Sha}, 180 &Ref{"origin/master", RefTypeRemoteBranch, outputs[5].Sha}, 181 &Ref{"included_branch_2", RefTypeLocalBranch, outputs[4].Sha}, 182 &Ref{"included_branch", RefTypeLocalBranch, outputs[3].Sha}, 183 &Ref{"origin/included_branch", RefTypeRemoteBranch, outputs[3].Sha}, 184 } 185 // Need to sort for consistent comparison 186 sort.Sort(test.RefsByName(expectedRefs)) 187 sort.Sort(test.RefsByName(refs)) 188 assert.Equal(t, expectedRefs, refs, "Refs should be correct") 189 } 190 191 func TestResolveEmptyCurrentRef(t *testing.T) { 192 repo := test.NewRepo(t) 193 repo.Pushd() 194 defer func() { 195 repo.Popd() 196 repo.Cleanup() 197 }() 198 199 _, err := CurrentRef() 200 assert.NotEqual(t, nil, err) 201 } 202 203 func TestWorkTrees(t *testing.T) { 204 205 // Only git 2.5+ 206 if !Config.IsGitVersionAtLeast("2.5.0") { 207 return 208 } 209 210 repo := test.NewRepo(t) 211 repo.Pushd() 212 defer func() { 213 repo.Popd() 214 repo.Cleanup() 215 }() 216 217 // test commits; we'll just modify the same file each time since we're 218 // only interested in branches & dates 219 inputs := []*test.CommitInput{ 220 { // 0 221 Files: []*test.FileInput{ 222 {Filename: "file1.txt", Size: 20}, 223 }, 224 }, 225 { // 1 226 NewBranch: "branch2", 227 Files: []*test.FileInput{ 228 {Filename: "file1.txt", Size: 25}, 229 }, 230 }, 231 { // 2 232 NewBranch: "branch3", 233 ParentBranches: []string{"master"}, // back on master 234 Files: []*test.FileInput{ 235 {Filename: "file1.txt", Size: 30}, 236 }, 237 }, 238 { // 3 239 NewBranch: "branch4", 240 ParentBranches: []string{"master"}, // back on master 241 Files: []*test.FileInput{ 242 {Filename: "file1.txt", Size: 40}, 243 }, 244 }, 245 } 246 outputs := repo.AddCommits(inputs) 247 // Checkout master again otherwise can't create a worktree from branch4 if we're on it here 248 test.RunGitCommand(t, true, "checkout", "master") 249 250 // We can create worktrees as subfolders for convenience 251 // Each one is checked out to a different branch 252 // Note that we *won't* create one for branch3 253 test.RunGitCommand(t, true, "worktree", "add", "branch2_wt", "branch2") 254 test.RunGitCommand(t, true, "worktree", "add", "branch4_wt", "branch4") 255 256 refs, err := GetAllWorkTreeHEADs(filepath.Join(repo.Path, ".git")) 257 assert.Equal(t, nil, err) 258 expectedRefs := []*Ref{ 259 &Ref{"master", RefTypeLocalBranch, outputs[0].Sha}, 260 &Ref{"branch2", RefTypeLocalBranch, outputs[1].Sha}, 261 &Ref{"branch4", RefTypeLocalBranch, outputs[3].Sha}, 262 } 263 // Need to sort for consistent comparison 264 sort.Sort(test.RefsByName(expectedRefs)) 265 sort.Sort(test.RefsByName(refs)) 266 assert.Equal(t, expectedRefs, refs, "Refs should be correct") 267 } 268 269 func TestVersionCompare(t *testing.T) { 270 assert.True(t, IsVersionAtLeast("2.6.0", "2.6.0")) 271 assert.True(t, IsVersionAtLeast("2.6.0", "2.6")) 272 assert.True(t, IsVersionAtLeast("2.6.0", "2")) 273 assert.True(t, IsVersionAtLeast("2.6.10", "2.6.5")) 274 assert.True(t, IsVersionAtLeast("2.8.1", "2.7.2")) 275 276 assert.False(t, IsVersionAtLeast("1.6.0", "2")) 277 assert.False(t, IsVersionAtLeast("2.5.0", "2.6")) 278 assert.False(t, IsVersionAtLeast("2.5.0", "2.5.1")) 279 assert.False(t, IsVersionAtLeast("2.5.2", "2.5.10")) 280 } 281 282 func TestGitAndRootDirs(t *testing.T) { 283 repo := test.NewRepo(t) 284 repo.Pushd() 285 defer func() { 286 repo.Popd() 287 repo.Cleanup() 288 }() 289 290 git, root, err := GitAndRootDirs() 291 if err != nil { 292 t.Fatal(err) 293 } 294 295 expected, err := longpathos.Stat(git) 296 if err != nil { 297 t.Fatal(err) 298 } 299 300 actual, err := longpathos.Stat(filepath.Join(root, ".git")) 301 if err != nil { 302 t.Fatal(err) 303 } 304 305 assert.True(t, os.SameFile(expected, actual)) 306 } 307 308 func TestGetTrackedFiles(t *testing.T) { 309 repo := test.NewRepo(t) 310 repo.Pushd() 311 defer func() { 312 repo.Popd() 313 repo.Cleanup() 314 }() 315 316 // test commits; we'll just modify the same file each time since we're 317 // only interested in branches 318 inputs := []*test.CommitInput{ 319 { // 0 320 Files: []*test.FileInput{ 321 {Filename: "file1.txt", Size: 20}, 322 {Filename: "file2.txt", Size: 20}, 323 {Filename: "folder1/file10.txt", Size: 20}, 324 {Filename: "folder1/anotherfile.txt", Size: 20}, 325 }, 326 }, 327 { // 1 328 Files: []*test.FileInput{ 329 {Filename: "file3.txt", Size: 20}, 330 {Filename: "file4.txt", Size: 20}, 331 {Filename: "folder2/something.txt", Size: 20}, 332 {Filename: "folder2/folder3/deep.txt", Size: 20}, 333 }, 334 }, 335 } 336 repo.AddCommits(inputs) 337 338 tracked, err := GetTrackedFiles("*.txt") 339 assert.Nil(t, err) 340 sort.Strings(tracked) // for direct comparison 341 fulllist := []string{"file1.txt", "file2.txt", "file3.txt", "file4.txt", "folder1/anotherfile.txt", "folder1/file10.txt", "folder2/folder3/deep.txt", "folder2/something.txt"} 342 assert.Equal(t, fulllist, tracked) 343 344 tracked, err = GetTrackedFiles("*file*.txt") 345 assert.Nil(t, err) 346 sort.Strings(tracked) 347 sublist := []string{"file1.txt", "file2.txt", "file3.txt", "file4.txt", "folder1/anotherfile.txt", "folder1/file10.txt"} 348 assert.Equal(t, sublist, tracked) 349 350 tracked, err = GetTrackedFiles("folder1/*") 351 assert.Nil(t, err) 352 sort.Strings(tracked) 353 sublist = []string{"folder1/anotherfile.txt", "folder1/file10.txt"} 354 assert.Equal(t, sublist, tracked) 355 356 tracked, err = GetTrackedFiles("folder2/*") 357 assert.Nil(t, err) 358 sort.Strings(tracked) 359 sublist = []string{"folder2/folder3/deep.txt", "folder2/something.txt"} 360 assert.Equal(t, sublist, tracked) 361 362 // relative dir 363 longpathos.Chdir("folder1") 364 tracked, err = GetTrackedFiles("*.txt") 365 assert.Nil(t, err) 366 sort.Strings(tracked) 367 sublist = []string{"anotherfile.txt", "file10.txt"} 368 assert.Equal(t, sublist, tracked) 369 longpathos.Chdir("..") 370 371 // absolute paths only includes matches in repo root 372 tracked, err = GetTrackedFiles("/*.txt") 373 assert.Nil(t, err) 374 sort.Strings(tracked) 375 assert.Equal(t, []string{"file1.txt", "file2.txt", "file3.txt", "file4.txt"}, tracked) 376 377 // Test includes staged but uncommitted files 378 ioutil.WriteFile("z_newfile.txt", []byte("Hello world"), 0644) 379 test.RunGitCommand(t, true, "add", "z_newfile.txt") 380 tracked, err = GetTrackedFiles("*.txt") 381 assert.Nil(t, err) 382 sort.Strings(tracked) 383 fulllist = append(fulllist, "z_newfile.txt") 384 assert.Equal(t, fulllist, tracked) 385 386 // Test includes modified files (not staged) 387 ioutil.WriteFile("file1.txt", []byte("Modifications"), 0644) 388 tracked, err = GetTrackedFiles("*.txt") 389 assert.Nil(t, err) 390 sort.Strings(tracked) 391 assert.Equal(t, fulllist, tracked) 392 393 // Test includes modified files (staged) 394 test.RunGitCommand(t, true, "add", "file1.txt") 395 tracked, err = GetTrackedFiles("*.txt") 396 assert.Nil(t, err) 397 sort.Strings(tracked) 398 assert.Equal(t, fulllist, tracked) 399 400 // Test excludes deleted files (not committed) 401 test.RunGitCommand(t, true, "rm", "file2.txt") 402 tracked, err = GetTrackedFiles("*.txt") 403 assert.Nil(t, err) 404 sort.Strings(tracked) 405 deletedlist := []string{"file1.txt", "file3.txt", "file4.txt", "folder1/anotherfile.txt", "folder1/file10.txt", "folder2/folder3/deep.txt", "folder2/something.txt", "z_newfile.txt"} 406 assert.Equal(t, deletedlist, tracked) 407 408 } 409 410 func TestLocalRefs(t *testing.T) { 411 repo := test.NewRepo(t) 412 repo.Pushd() 413 defer func() { 414 repo.Popd() 415 repo.Cleanup() 416 }() 417 418 repo.AddCommits([]*test.CommitInput{ 419 { 420 Files: []*test.FileInput{ 421 {Filename: "file1.txt", Size: 20}, 422 }, 423 }, 424 { 425 NewBranch: "branch", 426 ParentBranches: []string{"master"}, 427 Files: []*test.FileInput{ 428 {Filename: "file1.txt", Size: 20}, 429 }, 430 }, 431 }) 432 433 test.RunGitCommand(t, true, "tag", "v1") 434 435 refs, err := LocalRefs() 436 if err != nil { 437 t.Fatal(err) 438 } 439 440 actual := make(map[string]bool) 441 for _, r := range refs { 442 t.Logf("REF: %s", r.Name) 443 switch r.Type { 444 case RefTypeHEAD: 445 t.Errorf("Local HEAD ref: %v", r) 446 case RefTypeOther: 447 t.Errorf("Stash or unknown ref: %v", r) 448 case RefTypeRemoteBranch, RefTypeRemoteTag: 449 t.Errorf("Remote ref: %v", r) 450 default: 451 actual[r.Name] = true 452 } 453 } 454 455 expected := []string{"master", "branch", "v1"} 456 found := 0 457 for _, refname := range expected { 458 if actual[refname] { 459 found += 1 460 } else { 461 t.Errorf("could not find ref %q", refname) 462 } 463 } 464 465 if found != len(expected) { 466 t.Errorf("Unexpected local refs: %v", actual) 467 } 468 }