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  }