github.com/2lambda123/git-lfs@v2.5.2+incompatible/tools/filetools_test.go (about)

     1  package tools
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  	"runtime"
     9  	"sort"
    10  	"testing"
    11  
    12  	"github.com/git-lfs/git-lfs/subprocess"
    13  	"github.com/stretchr/testify/assert"
    14  )
    15  
    16  func TestCleanPathsCleansPaths(t *testing.T) {
    17  	cleaned := CleanPaths("/foo/bar/,/foo/bar/baz", ",")
    18  	assert.Equal(t, []string{"/foo/bar", "/foo/bar/baz"}, cleaned)
    19  }
    20  
    21  func TestCleanPathsReturnsNoResultsWhenGivenNoPaths(t *testing.T) {
    22  	cleaned := CleanPaths("", ",")
    23  	assert.Empty(t, cleaned)
    24  }
    25  
    26  func TestFastWalkBasic(t *testing.T) {
    27  	rootDir, err := ioutil.TempDir(os.TempDir(), "GitLfsTestFastWalkBasic")
    28  	if err != nil {
    29  		assert.FailNow(t, "Unable to get temp dir: %v", err)
    30  	}
    31  	defer os.RemoveAll(rootDir)
    32  	os.Chdir(rootDir)
    33  
    34  	expectedEntries := createFastWalkInputData(10, 160)
    35  
    36  	walker := fastWalkWithExcludeFiles(expectedEntries[0], "")
    37  	gotEntries, gotErrors := collectFastWalkResults(walker.ch)
    38  
    39  	assert.Empty(t, gotErrors)
    40  
    41  	sort.Strings(expectedEntries)
    42  	sort.Strings(gotEntries)
    43  	assert.Equal(t, expectedEntries, gotEntries)
    44  }
    45  
    46  func BenchmarkFastWalkGitRepoChannels(b *testing.B) {
    47  	rootDir, err := ioutil.TempDir(os.TempDir(), "GitLfsBenchFastWalkGitRepoChannels")
    48  	if err != nil {
    49  		assert.FailNow(b, "Unable to get temp dir: %v", err)
    50  	}
    51  	defer os.RemoveAll(rootDir)
    52  	os.Chdir(rootDir)
    53  	entries := createFastWalkInputData(1000, 5000)
    54  
    55  	for i := 0; i < b.N; i++ {
    56  		var files, errors int
    57  		FastWalkGitRepo(entries[0], func(parent string, info os.FileInfo, err error) {
    58  			if err != nil {
    59  				errors++
    60  			} else {
    61  				files++
    62  			}
    63  		})
    64  		b.Logf("files: %d, errors: %d", files, errors)
    65  	}
    66  }
    67  
    68  func BenchmarkFastWalkGitRepoCallback(b *testing.B) {
    69  	rootDir, err := ioutil.TempDir(os.TempDir(), "GitLfsBenchFastWalkGitRepoCallback")
    70  	if err != nil {
    71  		assert.FailNow(b, "Unable to get temp dir: %v", err)
    72  	}
    73  	defer os.RemoveAll(rootDir)
    74  	os.Chdir(rootDir)
    75  	entries := createFastWalkInputData(1000, 5000)
    76  
    77  	for i := 0; i < b.N; i++ {
    78  		var files, errors int
    79  		FastWalkGitRepo(entries[0], func(parentDir string, info os.FileInfo, err error) {
    80  			if err != nil {
    81  				errors++
    82  			} else {
    83  				files++
    84  			}
    85  		})
    86  
    87  		b.Logf("files: %d, errors: %d", files, errors)
    88  	}
    89  }
    90  
    91  func TestFastWalkGitRepo(t *testing.T) {
    92  	rootDir, err := ioutil.TempDir(os.TempDir(), "GitLfsTestFastWalkGitRepo")
    93  	if err != nil {
    94  		assert.FailNow(t, "Unable to get temp dir: %v", err)
    95  	}
    96  	defer os.RemoveAll(rootDir)
    97  	os.Chdir(rootDir)
    98  
    99  	expectedEntries := createFastWalkInputData(3, 3)
   100  
   101  	mainDir := expectedEntries[0]
   102  
   103  	// Set up a git repo and add some ignored files / dirs
   104  	subprocess.SimpleExec("git", "init", mainDir)
   105  	ignored := []string{
   106  		"filethatweignore.ign",
   107  		"foldercontainingignored",
   108  		"foldercontainingignored/notthisone.ign",
   109  		"foldercontainingignored/ignoredfolder",
   110  		"foldercontainingignored/ignoredfolder/file1.txt",
   111  		"foldercontainingignored/ignoredfolder/file2.txt",
   112  		"ignoredfolder",
   113  		"ignoredfolder/file1.txt",
   114  		"ignoredfolder/file2.txt",
   115  		"ignoredfrominside",
   116  		"ignoredfrominside/thisisok.txt",
   117  		"ignoredfrominside/thisisnot.txt",
   118  		"ignoredfrominside/thisone",
   119  		"ignoredfrominside/thisone/file1.txt",
   120  	}
   121  	for _, f := range ignored {
   122  		fullPath := join(mainDir, f)
   123  		if len(filepath.Ext(f)) > 0 {
   124  			ioutil.WriteFile(fullPath, []byte("TEST"), 0644)
   125  		} else {
   126  			os.MkdirAll(fullPath, 0755)
   127  		}
   128  	}
   129  	// write root .gitignore
   130  	rootGitIgnore := `
   131  # ignore *.ign everywhere
   132  *.ign
   133  # ignore folder
   134  ignoredfolder
   135  `
   136  	ioutil.WriteFile(join(mainDir, ".gitignore"), []byte(rootGitIgnore), 0644)
   137  	// Subfolder ignore; folder will show up but but subfolder 'thisone' won't
   138  	subFolderIgnore := `
   139  thisone
   140  thisisnot.txt
   141  `
   142  	ioutil.WriteFile(join(mainDir, "ignoredfrominside", ".gitignore"), []byte(subFolderIgnore), 0644)
   143  
   144  	// This dir will be walked but content won't be
   145  	expectedEntries = append(expectedEntries, join(mainDir, "foldercontainingignored"))
   146  	// This dir will be walked and some of its content but has its own gitignore
   147  	expectedEntries = append(expectedEntries, join(mainDir, "ignoredfrominside"))
   148  	expectedEntries = append(expectedEntries, join(mainDir, "ignoredfrominside", "thisisok.txt"))
   149  	// Also gitignores
   150  	expectedEntries = append(expectedEntries, join(mainDir, ".gitignore"))
   151  	expectedEntries = append(expectedEntries, join(mainDir, "ignoredfrominside", ".gitignore"))
   152  	// nothing else should be there
   153  
   154  	gotEntries := make([]string, 0, 1000)
   155  	gotErrors := make([]error, 0, 5)
   156  	FastWalkGitRepo(mainDir, func(parent string, info os.FileInfo, err error) {
   157  		if err != nil {
   158  			gotErrors = append(gotErrors, err)
   159  		} else {
   160  			if len(parent) == 0 {
   161  				gotEntries = append(gotEntries, info.Name())
   162  			} else {
   163  				gotEntries = append(gotEntries, join(parent, info.Name()))
   164  			}
   165  		}
   166  	})
   167  
   168  	assert.Empty(t, gotErrors)
   169  
   170  	sort.Strings(expectedEntries)
   171  	sort.Strings(gotEntries)
   172  	assert.Equal(t, expectedEntries, gotEntries)
   173  
   174  }
   175  
   176  // Make test data - ensure you've Chdir'ed into a temp dir first
   177  // Returns list of files/dirs that are created
   178  // First entry is the parent dir of all others
   179  func createFastWalkInputData(smallFolder, largeFolder int) []string {
   180  	dirs := []string{
   181  		"testroot",
   182  		"testroot/folder1",
   183  		"testroot/folder2",
   184  		"testroot/folder2/subfolder1",
   185  		"testroot/folder2/subfolder2",
   186  		"testroot/folder2/subfolder3",
   187  		"testroot/folder2/subfolder4",
   188  		"testroot/folder2/subfolder4/subsub",
   189  	}
   190  	expectedEntries := make([]string, 0, 250)
   191  
   192  	for i, dir := range dirs {
   193  		os.MkdirAll(dir, 0755)
   194  		numFiles := smallFolder
   195  		expectedEntries = append(expectedEntries, dir)
   196  		if i >= 3 && i <= 5 {
   197  			// Bulk test to ensure works with > 1 batch
   198  			numFiles = largeFolder
   199  		}
   200  		for f := 0; f < numFiles; f++ {
   201  			filename := join(dir, fmt.Sprintf("file%d.txt", f))
   202  			ioutil.WriteFile(filename, []byte("TEST"), 0644)
   203  			expectedEntries = append(expectedEntries, filename)
   204  		}
   205  	}
   206  
   207  	return expectedEntries
   208  }
   209  
   210  func collectFastWalkResults(fchan <-chan fastWalkInfo) ([]string, []error) {
   211  	gotEntries := make([]string, 0, 1000)
   212  	gotErrors := make([]error, 0, 5)
   213  	for o := range fchan {
   214  		if o.Err != nil {
   215  			gotErrors = append(gotErrors, o.Err)
   216  		} else {
   217  			if len(o.ParentDir) == 0 {
   218  				gotEntries = append(gotEntries, o.Info.Name())
   219  			} else {
   220  				gotEntries = append(gotEntries, join(o.ParentDir, o.Info.Name()))
   221  			}
   222  		}
   223  	}
   224  
   225  	return gotEntries, gotErrors
   226  }
   227  
   228  func getFileMode(filename string) os.FileMode {
   229  	s, err := os.Stat(filename)
   230  	if err != nil {
   231  		return 0000
   232  	}
   233  	return s.Mode()
   234  }
   235  
   236  func TestSetWriteFlag(t *testing.T) {
   237  	f, err := ioutil.TempFile("", "lfstestwriteflag")
   238  	assert.Nil(t, err)
   239  	filename := f.Name()
   240  	defer os.Remove(filename)
   241  	f.Close()
   242  	// Set up with read/write bit for all but no execute
   243  	assert.Nil(t, os.Chmod(filename, 0666))
   244  
   245  	assert.Nil(t, SetFileWriteFlag(filename, false))
   246  	// should turn off all write
   247  	assert.EqualValues(t, 0444, getFileMode(filename))
   248  	assert.Nil(t, SetFileWriteFlag(filename, true))
   249  	// should only add back user write (on Mac/Linux)
   250  	if runtime.GOOS == "windows" {
   251  		assert.EqualValues(t, 0666, getFileMode(filename))
   252  	} else {
   253  		assert.EqualValues(t, 0644, getFileMode(filename))
   254  	}
   255  
   256  	// Can't run selective UGO tests on Windows as doesn't support separate roles
   257  	// Also Golang only supports read/write but not execute on Windows
   258  	if runtime.GOOS != "windows" {
   259  		// Set up with read/write/execute bit for all but no execute
   260  		assert.Nil(t, os.Chmod(filename, 0777))
   261  		assert.Nil(t, SetFileWriteFlag(filename, false))
   262  		// should turn off all write but not execute
   263  		assert.EqualValues(t, 0555, getFileMode(filename))
   264  		assert.Nil(t, SetFileWriteFlag(filename, true))
   265  		// should only add back user write (on Mac/Linux)
   266  		if runtime.GOOS == "windows" {
   267  			assert.EqualValues(t, 0777, getFileMode(filename))
   268  		} else {
   269  			assert.EqualValues(t, 0755, getFileMode(filename))
   270  		}
   271  
   272  		assert.Nil(t, os.Chmod(filename, 0440))
   273  		assert.Nil(t, SetFileWriteFlag(filename, false))
   274  		assert.EqualValues(t, 0440, getFileMode(filename))
   275  		assert.Nil(t, SetFileWriteFlag(filename, true))
   276  		// should only add back user write
   277  		assert.EqualValues(t, 0640, getFileMode(filename))
   278  	}
   279  }