github.com/boyter/gocodewalker@v1.3.2/go-gitignore/repository_test.go (about)

     1  // SPDX-License-Identifier: MIT
     2  
     3  package gitignore_test
     4  
     5  import (
     6  	"github.com/boyter/gocodewalker/go-gitignore"
     7  	"os"
     8  	"path/filepath"
     9  	"testing"
    10  )
    11  
    12  type repositorytest struct {
    13  	file      string
    14  	directory string
    15  	cache     gitignore.Cache
    16  	cached    bool
    17  	error     func(e gitignore.Error) bool
    18  	errors    []gitignore.Error
    19  	bad       int
    20  	instance  func(string) (gitignore.GitIgnore, error)
    21  	exclude   string
    22  	gitdir    string
    23  } // repostorytest{}
    24  
    25  func (r *repositorytest) create(path string, gitdir bool) (gitignore.GitIgnore, error) {
    26  	// if we have an error handler, reset the list of errors
    27  	if r.error != nil {
    28  		r.errors = make([]gitignore.Error, 0)
    29  	}
    30  
    31  	if r.file == gitignore.File || r.file == "" {
    32  		// should we create the global exclude file
    33  		r.gitdir = os.Getenv("GIT_DIR")
    34  		if gitdir {
    35  			// create a temporary file for the global exclude file
    36  			_exclude, _err := exclude(_GITEXCLUDE)
    37  			if _err != nil {
    38  				return nil, _err
    39  			}
    40  
    41  			// extract the current value of the GIT_DIR environment variable
    42  			// and set the value to be that of the temporary file
    43  			r.exclude = _exclude
    44  			_err = os.Setenv("GIT_DIR", r.exclude)
    45  			if _err != nil {
    46  				return nil, _err
    47  			}
    48  		} else {
    49  			_err := os.Unsetenv("GIT_DIR")
    50  			if _err != nil {
    51  				return nil, _err
    52  			}
    53  		}
    54  	}
    55  
    56  	// attempt to create the GitIgnore instance
    57  	_repository, _err := r.instance(path)
    58  
    59  	// if we encountered errors, and the first error has a zero position
    60  	// then it represents a file access error
    61  	//		- extract the error and return it
    62  	//		- remove it from the list of errors
    63  	if len(r.errors) > 0 {
    64  		if r.errors[0].Position().Zero() {
    65  			_err = r.errors[0].Underlying()
    66  			r.errors = r.errors[1:]
    67  		}
    68  	}
    69  
    70  	// return the GitIgnore instance
    71  	return _repository, _err
    72  } // create()
    73  
    74  func (r *repositorytest) destroy() {
    75  	// remove the temporary files and directories
    76  	for _, _path := range []string{r.directory, r.exclude} {
    77  		if _path != "" {
    78  			defer os.RemoveAll(_path)
    79  		}
    80  	}
    81  
    82  	if r.file == gitignore.File || r.file == "" {
    83  		// reset the GIT_DIR environment variable
    84  		if r.gitdir == "" {
    85  			defer os.Unsetenv("GIT_DIR")
    86  		} else {
    87  			defer os.Setenv("GIT_DIR", r.gitdir)
    88  		}
    89  	}
    90  } // destroy()
    91  
    92  type invalidtest struct {
    93  	*repositorytest
    94  	tag   string
    95  	match func() gitignore.Match
    96  } // invalidtest{}
    97  
    98  func TestRepository(t *testing.T) {
    99  	_test := &repositorytest{}
   100  	_test.bad = _GITREPOSITORYERRORS
   101  	_test.instance = func(path string) (gitignore.GitIgnore, error) {
   102  		return gitignore.NewRepository(path)
   103  	}
   104  
   105  	// perform the repository tests
   106  	repository(t, _test, _REPOSITORYMATCHES)
   107  
   108  	// remove the temporary directory used for this test
   109  	defer _test.destroy()
   110  } // TestRepository()
   111  
   112  func TestRepositoryWithFile(t *testing.T) {
   113  	_test := &repositorytest{}
   114  	_test.bad = _GITREPOSITORYERRORS
   115  	_test.file = gitignore.File + "-with-file"
   116  	_test.instance = func(path string) (gitignore.GitIgnore, error) {
   117  		return gitignore.NewRepositoryWithFile(path, _test.file)
   118  	}
   119  
   120  	// perform the repository tests
   121  	repository(t, _test, _REPOSITORYMATCHES)
   122  
   123  	// remove the temporary directory used for this test
   124  	defer _test.destroy()
   125  } // TestRepositoryWithFile()
   126  
   127  func TestRepositoryWithErrors(t *testing.T) {
   128  	_test := &repositorytest{}
   129  	_test.bad = _GITREPOSITORYERRORS
   130  	_test.file = gitignore.File + "-with-errors"
   131  	_test.error = func(e gitignore.Error) bool {
   132  		_test.errors = append(_test.errors, e)
   133  		return true
   134  	}
   135  	_test.instance = func(path string) (gitignore.GitIgnore, error) {
   136  		return gitignore.NewRepositoryWithErrors(
   137  			path, _test.file, _test.error,
   138  		), nil
   139  	}
   140  
   141  	// perform the repository tests
   142  	repository(t, _test, _REPOSITORYMATCHES)
   143  
   144  	// remove the temporary directory used for this test
   145  	defer _test.destroy()
   146  } // TestRepositoryWithErrors()
   147  
   148  func TestRepositoryWithErrorsFalse(t *testing.T) {
   149  	_test := &repositorytest{}
   150  	_test.bad = _GITREPOSITORYERRORSFALSE
   151  	_test.file = gitignore.File + "-with-errors-false"
   152  	_test.error = func(e gitignore.Error) bool {
   153  		_test.errors = append(_test.errors, e)
   154  		return false
   155  	}
   156  	_test.instance = func(path string) (gitignore.GitIgnore, error) {
   157  		return gitignore.NewRepositoryWithErrors(
   158  			path, _test.file, _test.error,
   159  		), nil
   160  	}
   161  
   162  	// perform the repository tests
   163  	repository(t, _test, _REPOSITORYMATCHESFALSE)
   164  
   165  	// remove the temporary directory used for this test
   166  	defer _test.destroy()
   167  } // TestRepositoryWithErrorsFalse()
   168  
   169  func TestRepositoryWithCache(t *testing.T) {
   170  	_test := &repositorytest{}
   171  	_test.bad = _GITREPOSITORYERRORS
   172  	_test.cache = gitignore.NewCache()
   173  	_test.cached = true
   174  	_test.instance = func(path string) (gitignore.GitIgnore, error) {
   175  		return gitignore.NewRepositoryWithCache(
   176  			path, _test.file, _test.cache, _test.error,
   177  		), nil
   178  	}
   179  
   180  	// perform the repository tests
   181  	repository(t, _test, _REPOSITORYMATCHES)
   182  
   183  	// clean up
   184  	defer _test.destroy()
   185  
   186  	// rerun the tests while accumulating errors
   187  	_test.directory = ""
   188  	_test.file = gitignore.File + "-with-cache"
   189  	_test.error = func(e gitignore.Error) bool {
   190  		_test.errors = append(_test.errors, e)
   191  		return true
   192  	}
   193  	repository(t, _test, _REPOSITORYMATCHES)
   194  
   195  	// remove the temporary directory used for this test
   196  	_err := os.RemoveAll(_test.directory)
   197  	if _err != nil {
   198  		t.Fatalf(
   199  			"unable to remove temporary directory %s: %s",
   200  			_test.directory, _err.Error(),
   201  		)
   202  	}
   203  
   204  	// recreate the temporary directory
   205  	//		- this remove & recreate gives us an empty directory for the
   206  	//		  repository test
   207  	//		- this lets us test the caching
   208  	_err = os.MkdirAll(_test.directory, _GITMASK)
   209  	if _err != nil {
   210  		t.Fatalf(
   211  			"unable to recreate temporary directory %s: %s",
   212  			_test.directory, _err.Error(),
   213  		)
   214  	}
   215  	defer _test.destroy()
   216  
   217  	// repeat the repository tests
   218  	//		- these should succeed using just the cache data
   219  	repository(t, _test, _REPOSITORYMATCHES)
   220  } // TestRepositoryWithCache()
   221  
   222  func TestInvalidRepository(t *testing.T) {
   223  	_test := &repositorytest{}
   224  	_test.instance = func(path string) (gitignore.GitIgnore, error) {
   225  		return gitignore.NewRepository(path)
   226  	}
   227  
   228  	// perform the invalid repository tests
   229  	invalid(t, _test)
   230  } // TestInvalidRepository()
   231  
   232  func TestInvalidRepositoryWithFile(t *testing.T) {
   233  	_test := &repositorytest{}
   234  	_test.file = gitignore.File + "-invalid-with-file"
   235  	_test.instance = func(path string) (gitignore.GitIgnore, error) {
   236  		return gitignore.NewRepositoryWithFile(path, _test.file)
   237  	}
   238  
   239  	// perform the invalid repository tests
   240  	invalid(t, _test)
   241  } // TestInvalidRepositoryWithFile()
   242  
   243  func TestInvalidRepositoryWithErrors(t *testing.T) {
   244  	_test := &repositorytest{}
   245  	_test.file = gitignore.File + "-invalid-with-errors"
   246  	_test.error = func(e gitignore.Error) bool {
   247  		_test.errors = append(_test.errors, e)
   248  		return true
   249  	}
   250  	_test.instance = func(path string) (gitignore.GitIgnore, error) {
   251  		return gitignore.NewRepositoryWithErrors(
   252  			path, _test.file, _test.error,
   253  		), nil
   254  	}
   255  
   256  	// perform the invalid repository tests
   257  	invalid(t, _test)
   258  } // TestInvalidRepositoryWithErrors()
   259  
   260  func TestInvalidRepositoryWithErrorsFalse(t *testing.T) {
   261  	_test := &repositorytest{}
   262  	_test.file = gitignore.File + "-invalid-with-errors-false"
   263  	_test.error = func(e gitignore.Error) bool {
   264  		_test.errors = append(_test.errors, e)
   265  		return false
   266  	}
   267  	_test.instance = func(path string) (gitignore.GitIgnore, error) {
   268  		return gitignore.NewRepositoryWithErrors(
   269  			path, _test.file, _test.error,
   270  		), nil
   271  	}
   272  
   273  	// perform the invalid repository tests
   274  	invalid(t, _test)
   275  } // TestInvalidRepositoryWithErrorsFalse()
   276  
   277  func TestInvalidRepositoryWithCache(t *testing.T) {
   278  	_test := &repositorytest{}
   279  	_test.file = gitignore.File + "-invalid-with-cache"
   280  	_test.cache = gitignore.NewCache()
   281  	_test.cached = true
   282  	_test.error = func(e gitignore.Error) bool {
   283  		_test.errors = append(_test.errors, e)
   284  		return true
   285  	}
   286  	_test.instance = func(path string) (gitignore.GitIgnore, error) {
   287  		return gitignore.NewRepositoryWithCache(
   288  			path, _test.file, _test.cache, _test.error,
   289  		), nil
   290  	}
   291  
   292  	// perform the invalid repository tests
   293  	invalid(t, _test)
   294  
   295  	// repeat the tests using a default cache
   296  	_test.cache = nil
   297  	invalid(t, _test)
   298  } // TestInvalidRepositoryWithCache()
   299  
   300  //
   301  // helper functions
   302  //
   303  
   304  func repository(t *testing.T, test *repositorytest, m []match) {
   305  	// if the test has no configured directory, then create a new
   306  	// directory with the required .gitignore files
   307  	if test.directory == "" {
   308  		// what name should we use for the .gitignore file?
   309  		//		- if none is given, use the default
   310  		_file := test.file
   311  		if _file == "" {
   312  			_file = gitignore.File
   313  		}
   314  
   315  		// create a temporary directory populated with sample .gitignore files
   316  		//		- first, augment the test data to include file names
   317  		_map := make(map[string]string)
   318  		for _k, _content := range _GITREPOSITORY {
   319  			_map[_k+"/"+_file] = _content
   320  		}
   321  		_dir, _err := dir(_map)
   322  		if _err != nil {
   323  			t.Fatalf("unable to create temporary directory: %s", _err.Error())
   324  		}
   325  		test.directory = _dir
   326  	}
   327  
   328  	// create the repository
   329  	_repository, _err := test.create(test.directory, true)
   330  	if _err != nil {
   331  		t.Fatalf("unable to create repository: %s", _err.Error())
   332  	}
   333  
   334  	// ensure we have a non-nill repository returned
   335  	if _repository == nil {
   336  		t.Error("expected non-nill GitIgnore repository instance; nil found")
   337  	}
   338  
   339  	// ensure the base of the repository is correct
   340  	if _repository.Base() != test.directory {
   341  		t.Errorf(
   342  			"repository.Base() mismatch; expected %q, got %q",
   343  			test.directory, _repository.Base(),
   344  		)
   345  	}
   346  
   347  	// we need to check each test to see if it's matching against a
   348  	// GIT_DIR/info/exclude
   349  	//		- we only do this if the target does not use .gitignore
   350  	//		  as the name of the ignore file
   351  	_prepare := func(m match) match {
   352  		if test.file == "" || test.file == gitignore.File {
   353  			return m
   354  		} else if m.Exclude {
   355  			return match{m.Path, "", false, m.Exclude}
   356  		} else {
   357  			return m
   358  		}
   359  	} // _prepare()
   360  
   361  	// perform the repository matching using absolute paths
   362  	_cb := func(path string, isdir bool) gitignore.Match {
   363  		_path := filepath.Join(_repository.Base(), path)
   364  		return _repository.Absolute(_path, isdir)
   365  	}
   366  	for _, _test := range m {
   367  		do(t, _cb, _prepare(_test))
   368  	}
   369  
   370  	// repeat the tests using relative paths
   371  	_repository, _err = test.create(test.directory, true)
   372  	if _err != nil {
   373  		t.Fatalf("unable to create repository: %s", _err.Error())
   374  	}
   375  	_cb = func(path string, isdir bool) gitignore.Match {
   376  		return _repository.Relative(path, isdir)
   377  	}
   378  	for _, _test := range m {
   379  		do(t, _cb, _prepare(_test))
   380  	}
   381  
   382  	// perform absolute path tests with paths not under the same repository
   383  	_map := make(map[string]string)
   384  	for _, _test := range m {
   385  		_map[_test.Path] = " "
   386  	}
   387  	_new, _err := dir(_map)
   388  	if _err != nil {
   389  		t.Fatalf("unable to create temporary directory: %s", _err.Error())
   390  	}
   391  	defer os.RemoveAll(_new)
   392  
   393  	// first, perform Match() tests
   394  	_repository, _err = test.create(test.directory, true)
   395  	if _err != nil {
   396  		t.Fatalf("unable to create repository: %s", _err.Error())
   397  	}
   398  	for _, _test := range m {
   399  		_path := filepath.Join(_new, _test.Local())
   400  		_match := _repository.Match(_path)
   401  		if _match != nil {
   402  			t.Fatalf("unexpected match; expected nil, got %v", _match)
   403  		}
   404  	}
   405  
   406  	// next, perform Absolute() tests
   407  	_repository, _err = test.create(test.directory, true)
   408  	if _err != nil {
   409  		t.Fatalf("unable to create repository: %s", _err.Error())
   410  	}
   411  	for _, _test := range m {
   412  		// build the absolute path
   413  		_path := filepath.Join(_new, _test.Local())
   414  
   415  		// we don't expect to match paths not under this repository
   416  		_match := _repository.Absolute(_path, _test.IsDir())
   417  		if _match != nil {
   418  			t.Fatalf("unexpected match; expected nil, got %v", _match)
   419  		}
   420  	}
   421  
   422  	// now, repeat the Match() test after having first removed the
   423  	// temporary directory
   424  	//		- we are testing correct handling of missing files
   425  	_err = os.RemoveAll(_new)
   426  	if _err != nil {
   427  		t.Fatalf(
   428  			"unable to remove temporary directory %s: %s",
   429  			_new, _err.Error(),
   430  		)
   431  	}
   432  	_repository, _err = test.create(test.directory, true)
   433  	if _err != nil {
   434  		t.Fatalf("unable to create repository: %s", _err.Error())
   435  	}
   436  	for _, _test := range m {
   437  		_path := filepath.Join(_new, _test.Local())
   438  
   439  		// if we have an error handler configured, we should be recording
   440  		// and error in this call to Match()
   441  		_before := len(test.errors)
   442  
   443  		// perform the match
   444  		_match := _repository.Match(_path)
   445  		if _match != nil {
   446  			t.Fatalf("unexpected match; expected nil, got %v", _match)
   447  		}
   448  
   449  		// were we recording errors?
   450  		if test.error != nil {
   451  			_after := len(test.errors)
   452  			if !(_after > _before) {
   453  				t.Fatalf(
   454  					"expected Match() error; none found for %s",
   455  					_path,
   456  				)
   457  			}
   458  
   459  			// ensure the most recent error is "not exists"
   460  			_latest := test.errors[_after-1]
   461  			_underlying := _latest.Underlying()
   462  			if !os.IsNotExist(_underlying) {
   463  				t.Fatalf(
   464  					"unexpected Match() error for %s; expected %q, got %q",
   465  					_path, os.ErrNotExist.Error(), _underlying.Error(),
   466  				)
   467  			}
   468  		}
   469  	}
   470  
   471  	// ensure Match() behaves as expected if the absolute path cannot
   472  	// be determined
   473  	//		- we do this by choosing as our working directory a path
   474  	//		  that this process does not have permission to
   475  	_dir, _err := dir(nil)
   476  	if _err != nil {
   477  		t.Fatalf("unable to create temporary directory: %s", _err.Error())
   478  	}
   479  	defer os.RemoveAll(_dir)
   480  
   481  	_cwd, _err := os.Getwd()
   482  	if _err != nil {
   483  		t.Fatalf("unable to retrieve working directory: %s", _err.Error())
   484  	}
   485  	_err = os.Chdir(_dir)
   486  	if _err != nil {
   487  		t.Fatalf("unable to chdir into temporary directory: %s", _err.Error())
   488  	}
   489  	defer func(dir string) { _ = os.Chdir(dir) }(_cwd)
   490  
   491  	// remove permission from the temporary directory
   492  	_err = os.Chmod(_dir, 0)
   493  	if _err != nil {
   494  		t.Fatalf(
   495  			"unable to remove temporary directory %s: %s",
   496  			_dir, _err.Error(),
   497  		)
   498  	}
   499  
   500  	// perform the repository tests
   501  	_repository, _err = test.create(test.directory, true)
   502  	if _err != nil {
   503  		t.Fatalf("unable to create repository: %s", _err.Error())
   504  	}
   505  	for _, _test := range m {
   506  		_match := _repository.Match(_test.Local())
   507  		if _match != nil {
   508  			t.Fatalf("unexpected match; expected nil, not %v", _match)
   509  		}
   510  	}
   511  
   512  	if test.errors != nil {
   513  		// ensure the number of errors is expected
   514  		if len(test.errors) != test.bad {
   515  			t.Fatalf(
   516  				"unexpected repository errors; expected %d, got %d",
   517  				test.bad, len(test.errors),
   518  			)
   519  		} else {
   520  			// if we're here, then we intended to record errors
   521  			//		- ensure we recorded the expected errors
   522  			for _i := 0; _i < len(test.errors); _i++ {
   523  				_got := test.errors[_i]
   524  				_underlying := _got.Underlying()
   525  				if os.IsNotExist(_underlying) ||
   526  					os.IsPermission(_underlying) {
   527  					continue
   528  				} else {
   529  					t.Log(_i)
   530  					t.Fatalf("unexpected repository error: %s", _got.Error())
   531  				}
   532  			}
   533  		}
   534  	}
   535  } // repository()
   536  
   537  func invalid(t *testing.T, test *repositorytest) {
   538  	// create a temporary file to use as the repository
   539  	_file, _err := file("")
   540  	if _err != nil {
   541  		t.Fatalf("unable to create temporary file: %s", _err.Error())
   542  	}
   543  	defer os.Remove(_file.Name())
   544  
   545  	// test repository instance creation against a file
   546  	_repository, _err := test.create(_file.Name(), false)
   547  	if _err == nil {
   548  		t.Errorf(
   549  			"invalid repository error; expected %q, got nil",
   550  			gitignore.InvalidDirectoryError.Error(),
   551  		)
   552  	} else if _err != gitignore.InvalidDirectoryError {
   553  		t.Errorf(
   554  			"invalid repository mismatch; expected %q, got %q",
   555  			gitignore.InvalidDirectoryError.Error(), _err.Error(),
   556  		)
   557  	}
   558  
   559  	// ensure no repository is returned
   560  	if _repository != nil {
   561  		t.Errorf(
   562  			"invalid repository; expected nil, got %v",
   563  			_repository,
   564  		)
   565  	}
   566  
   567  	// now, remove the temporary file and repeat the tests
   568  	_err = os.Remove(_file.Name())
   569  	if _err != nil {
   570  		t.Fatalf(
   571  			"unable to remove temporary file %s: %s",
   572  			_file.Name(), _err.Error(),
   573  		)
   574  	}
   575  
   576  	// test repository instance creating against a missing file
   577  	_repository, _err = test.create(_file.Name(), false)
   578  	if _err == nil {
   579  		t.Errorf(
   580  			"invalid repository error; expected %q, got nil",
   581  			gitignore.InvalidDirectoryError.Error(),
   582  		)
   583  	} else if !os.IsNotExist(_err) {
   584  		t.Errorf(
   585  			"invalid repository mismatch; "+
   586  				"expected no such file or directory, got %q",
   587  			_err.Error(),
   588  		)
   589  	}
   590  
   591  	// ensure no repository is returned
   592  	if _repository != nil {
   593  		t.Errorf(
   594  			"invalid repository; expected nil, got %v",
   595  			_repository,
   596  		)
   597  	}
   598  
   599  	// ensure we can't create a repository instance where the absolute path
   600  	// of the repository cannot be determined
   601  	//		- we do this by choosing a working directory this process does
   602  	//		  not have access to and using a relative path
   603  	_map := map[string]string{gitignore.File: _GITIGNORE}
   604  	_dir, _err := dir(_map)
   605  	if _err != nil {
   606  		t.Fatalf("unable to create a temporary directory: %s", _err.Error())
   607  	}
   608  	defer os.RemoveAll(_dir)
   609  
   610  	// now change the working directory
   611  	_cwd, _err := os.Getwd()
   612  	if _err != nil {
   613  		t.Fatalf("unable to retrieve working directory: %s", _err.Error())
   614  	}
   615  	_err = os.Chdir(_dir)
   616  	if _err != nil {
   617  		t.Fatalf("unable to chdir into temporary directory: %s", _err.Error())
   618  	}
   619  	defer func(dir string) { _ = os.Chdir(dir) }(_cwd)
   620  
   621  	// remove permissions from the working directory
   622  	_err = os.Chmod(_dir, 0)
   623  	if _err != nil {
   624  		t.Fatalf("unable remove temporary directory permissions: %s: %s",
   625  			_dir, _err.Error(),
   626  		)
   627  	}
   628  
   629  	// test repository instance creating against a relative path
   630  	//		- the relative path exists
   631  	_, _err = test.create(gitignore.File, false)
   632  	if _err == nil {
   633  		t.Errorf("expected repository error, got nil")
   634  	} else if os.IsNotExist(_err) {
   635  		t.Errorf(
   636  			"unexpected repository error; file exists, but %q returned",
   637  			_err.Error(),
   638  		)
   639  	}
   640  
   641  	// next, create a repository where we do not have read permission
   642  	// to a .gitignore file within the repository
   643  	//		- this should trigger a panic() when attempting a file match
   644  	for _, _test := range _REPOSITORYMATCHES {
   645  		_map[_test.Path] = " "
   646  	}
   647  	_dir, _err = dir(_map)
   648  	if _err != nil {
   649  		t.Fatalf("unable to create a temporary directory: %s", _err.Error())
   650  	}
   651  	defer os.RemoveAll(_dir)
   652  
   653  	_git := filepath.Join(_dir, gitignore.File)
   654  	_err = os.Chmod(_git, 0)
   655  	if _err != nil {
   656  		t.Fatalf("unable remove temporary .gitignore permissions: %s: %s",
   657  			_git, _err.Error(),
   658  		)
   659  	}
   660  
   661  	// attempt to match a path in this repository
   662  	//		- it can be anything, so we just use the .gitignore itself
   663  	//		- between each test we recreate the repository instance to
   664  	//		  remove the effect of any caching
   665  	_instance := func() gitignore.GitIgnore {
   666  		// reset the cache
   667  		if test.cached {
   668  			if test.cache != nil {
   669  				test.cache = gitignore.NewCache()
   670  			}
   671  		}
   672  
   673  		// create the new repository
   674  		_repository, _err := test.create(_dir, false)
   675  		if _err != nil {
   676  			t.Fatalf("unable to create repository: %s", _err.Error())
   677  		}
   678  
   679  		// return the repository
   680  		return _repository
   681  	}
   682  	for _, _match := range _REPOSITORYMATCHES {
   683  		_local := _match.Local()
   684  		_isdir := _match.IsDir()
   685  		_path := filepath.Join(_dir, _local)
   686  
   687  		// try Match() with an absolute path
   688  		_test := &invalidtest{repositorytest: test}
   689  		_test.tag = "Match()"
   690  		_test.match = func() gitignore.Match {
   691  			return _instance().Match(_path)
   692  		}
   693  		run(t, _test)
   694  
   695  		// try Absolute() with an absolute path
   696  		_test = &invalidtest{repositorytest: test}
   697  		_test.tag = "Absolute()"
   698  		_test.match = func() gitignore.Match {
   699  			return _instance().Absolute(_path, _isdir)
   700  		}
   701  		run(t, _test)
   702  
   703  		// try Absolute() with an absolute path
   704  		_test = &invalidtest{repositorytest: test}
   705  		_test.tag = "Relative()"
   706  		_test.match = func() gitignore.Match {
   707  			return _instance().Relative(_local, _isdir)
   708  		}
   709  		run(t, _test)
   710  	}
   711  } // invalid()
   712  
   713  func run(t *testing.T, test *invalidtest) {
   714  	// perform the match, and ensure it returns nil, nil
   715  	_match := test.match()
   716  	if _match != nil {
   717  		t.Fatalf("%s: unexpected match: %v", test.tag, _match)
   718  	} else if test.errors == nil {
   719  		return
   720  	}
   721  
   722  	// if we're here, then we intended to record errors
   723  	//		- ensure we recorded the expected errors
   724  	for _i := 0; _i < len(test.errors); _i++ {
   725  		_got := test.errors[_i]
   726  		_underlying := _got.Underlying()
   727  		if os.IsNotExist(_underlying) ||
   728  			os.IsPermission(_underlying) {
   729  			continue
   730  		} else {
   731  			t.Fatalf(
   732  				"%s: unexpected error: %q",
   733  				test.tag, _got.Error(),
   734  			)
   735  		}
   736  	}
   737  } // run()