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