Download raw body.
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
ignored files can't handle trailing slashes