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