"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Mark Jamsek <mark@jamsek.com>
Subject:
Re: ignored files can't handle trailing slashes
To:
Lucas <lucas@sexy.is>, gameoftrees@openbsd.org
Date:
Mon, 20 Feb 2023 17:25:23 +1100

Download raw body.

Thread
  • Stefan Sperling:

    ignored files can't handle trailing slashes

    • Mark Jamsek:

      ignored files can't handle trailing slashes

  • On 23-02-19 09:40PM, Stefan Sperling wrote:
    > On Sun, Feb 05, 2023 at 02:05:30PM +0000, Lucas wrote:
    > > Hello list,
    > > 
    > > As I shared on IRC, when `got import -I dir/` is used, `dir/` is *not*
    > > ignored: fnmatch is called with the name in dirent's d_name, which
    > > doesn't include a trailing slash if the entry is of type directory.
    > > Do note that calling got_path_strip_trailing_slashes on `-I` argument
    > > is not an option: 'dir*/' can have some nasty side effects. The patch
    > > for regress/cmdline/import.sh below makes this explicit.
    > > 
    > > Same can be observed for .{cvs,git}ignore.
    > 
    > This patch fixes the same problem for 'got status'. ok?
    
    Nice, ok!
    
    > "return FNM_NOMATCH; /* XXX */" in the diff is because there is no way
    > to return struct got_error from within this function without further
    > refactoring. I think that is fine for now because paths longer than
    > PATH_MAX can probably not even be checked out, and such long patterns
    > will be very rare if they exist at all.
    
    Yes, agreed. I think this is fine.
    
    >  make 'got status' ignore patterns with trailing slashes match on directories
    >  
    > diff d0f874e072cfb4119033a71b9f162ae02eca44ab a6e726d31e2e25a79e7f5d4b6b747d2778b15c5d
    > commit - d0f874e072cfb4119033a71b9f162ae02eca44ab
    > commit + a6e726d31e2e25a79e7f5d4b6b747d2778b15c5d
    > blob - b6cc16e8e5a4b02bf33a4f2af21bc0fd0f58c4bd
    > blob + 06d9ba522ae0001bd8bb697df46c9c952023dd09
    > --- got/got.1
    > +++ got/got.1
    > @@ -788,6 +788,9 @@ As an extension to
    >  .Pa .gitignore
    >  files in each traversed directory and will not display unversioned files
    >  which match these patterns.
    > +Ignore patterns which end with a slash,
    > +.Dq / ,
    > +will only match directories.
    >  As an extension to
    >  .Xr glob 7
    >  matching rules,
    > blob - 2d75c470b84a9c0f07ca7ccd39595267ab24fd49
    > blob + a5e3af7acc609d51f0bd553fae407d173c3df895
    > --- lib/worktree.c
    > +++ lib/worktree.c
    > @@ -3559,6 +3559,26 @@ match_ignores(struct got_pathlist_head *ignores, const
    >  }
    >  
    >  static int
    > +match_path(const char *pattern, size_t pattern_len, const char *path,
    > +    int flags)
    > +{
    > +	char buf[PATH_MAX];
    > +
    > +	/*
    > +	 * Trailing slashes signify directories.
    > +	 * Append a * to make such patterns conform to fnmatch rules.
    > +	 */
    > +	if (pattern_len > 0 && pattern[pattern_len - 1] == '/') {
    > +		if (snprintf(buf, sizeof(buf), "%s*", pattern) >= sizeof(buf))
    > +			return FNM_NOMATCH; /* XXX */
    > +
    > +		return fnmatch(buf, path, flags);
    > +	}
    > +
    > +	return fnmatch(pattern, path, flags);
    > +}
    > +
    > +static int
    >  match_ignores(struct got_pathlist_head *ignores, const char *path)
    >  {
    >  	struct got_pathlist_entry *pe;
    > @@ -3569,14 +3589,15 @@ match_ignores(struct got_pathlist_head *ignores, const
    >  		struct got_pathlist_entry *pi;
    >  
    >  		TAILQ_FOREACH(pi, ignorelist, entry) {
    > -			const char *p, *pattern = pi->path;
    > +			const char *p;
    >  
    > -			if (strncmp(pattern, "**/", 3) != 0)
    > +			if (pi->path_len < 3 ||
    > +			    strncmp(pi->path, "**/", 3) != 0)
    >  				continue;
    > -			pattern += 3;
    >  			p = path;
    >  			while (*p) {
    > -				if (fnmatch(pattern, p,
    > +				if (match_path(pi->path + 3,
    > +				    pi->path_len - 3, p,
    >  				    FNM_PATHNAME | FNM_LEADING_DIR)) {
    >  					/* Retry in next directory. */
    >  					while (*p && *p != '/')
    > @@ -3601,11 +3622,11 @@ match_ignores(struct got_pathlist_head *ignores, const
    >  			struct got_pathlist_head *ignorelist = pe->data;
    >  			struct got_pathlist_entry *pi;
    >  			TAILQ_FOREACH(pi, ignorelist, entry) {
    > -				const char *pattern = pi->path;
    >  				int flags = FNM_LEADING_DIR;
    > -				if (strstr(pattern, "/**/") == NULL)
    > +				if (strstr(pi->path, "/**/") == NULL)
    >  					flags |= FNM_PATHNAME;
    > -				if (fnmatch(pattern, path, flags))
    > +				if (match_path(pi->path, pi->path_len,
    > +				    path, flags))
    >  					continue;
    >  				return 1;
    >  			}
    > blob - f992b65b13667e8a421e2e410937179db7c27aac
    > blob + f2d3d5dfe1904cd50bfc165b2d05f293cb4fad5f
    > --- regress/cmdline/status.sh
    > +++ regress/cmdline/status.sh
    > @@ -709,17 +709,20 @@ test_status_gitignore_trailing_slashes() {
    >  	echo "unversioned file" > $testroot/wt/epsilon/bar
    >  	echo "unversioned file" > $testroot/wt/epsilon/boo
    >  	echo "unversioned file" > $testroot/wt/epsilon/moo
    > -	echo "epsilon/" > $testroot/wt/.gitignore
    > +	echo "unversioned file" > $testroot/wt/upsilon
    >  
    > +	# Match the directory epsilon but not the regular file upsilon
    > +	echo "*psilon/" > $testroot/wt/.gitignore
    > +
    >  	echo '?  .gitignore' > $testroot/stdout.expected
    >  	echo '?  foo' >> $testroot/stdout.expected
    > +	echo '?  upsilon' >> $testroot/stdout.expected
    >  	(cd $testroot/wt && got status > $testroot/stdout)
    >  
    >  	cmp -s $testroot/stdout.expected $testroot/stdout
    >  	ret=$?
    >  	if [ $ret -ne 0 ]; then
    > -		#diff -u $testroot/stdout.expected $testroot/stdout
    > -		ret="xfail trailing slashes not matched"
    > +		diff -u $testroot/stdout.expected $testroot/stdout
    >  	fi
    >  	test_done "$testroot" "$ret"
    >  }
    > 
    
    -- 
    Mark Jamsek <fnc.bsdbox.org|got.bsdbox.org>
    GPG: F2FF 13DE 6A06 C471 CA80  E6E2 2930 DC66 86EE CF68
    
  • Stefan Sperling:

    ignored files can't handle trailing slashes