github.com/2lambda123/git-lfs@v2.5.2+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  	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  }