Commit Diff


commit - 26e67dac35191e72095a1e9a7216719d3abfbb7c
commit + 6ae2855c45508b25adb202d57dd345da8500b7bb
blob - 6652a0e142d22804174660f5bfac8d20073bdec6
blob + de2dc2b7ade5373c735bca1c19cdfd46b3ebef81
--- cvg/cvg.1
+++ cvg/cvg.1
@@ -581,6 +581,8 @@ are as follows:
 .Bl -tag -width Ds
 .It Fl I
 Show unversioned files even if they match an ignore pattern.
+See
+.Sx Ignore Patterns .
 .It Fl S Ar status-codes
 Suppress the output of files with a modification status matching any of the
 single-character status codes contained in the
@@ -604,42 +606,6 @@ Cannot be used together with the
 .Fl S
 option.
 .El
-.Pp
-For compatibility with
-.Xr cvs 1
-and
-.Xr git 1 ,
-.Cm got status
-reads
-.Xr glob 7
-patterns from
-.Pa .cvsignore
-and
-.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,
-.Cm got status
-supports consecutive asterisks,
-.Dq ** ,
-which will match an arbitrary amount of directories.
-Unlike
-.Xr cvs 1 ,
-.Cm got status
-only supports a single ignore pattern per line.
-Unlike
-.Xr git 1 ,
-.Cm got status
-does not support negated ignore patterns prefixed with
-.Dq \&! ,
-and gives no special significance to the location of path component separators,
-.Dq / ,
-in a pattern.
 .It Xo
 .Cm log
 .Op Fl bdPpRs
@@ -1045,9 +1011,9 @@ another repository.
 .Xc
 Schedule unversioned files in a work tree for addition to the
 repository in the next commit.
-By default, files which match a
-.Cm got status
-ignore pattern will not be added.
+By default, files which match an ignore pattern will not be added.
+See
+.Sx Ignore Patterns .
 .Pp
 If a
 .Ar path
@@ -1073,9 +1039,9 @@ The options for
 are as follows:
 .Bl -tag -width Ds
 .It Fl I
-Add files even if they match a
-.Cm got status
-ignore pattern.
+Add files even if they match an ignore pattern.
+See
+.Xs Ignore Patterns .
 .It Fl R
 Permit recursion into directories.
 If this option is not specified,
@@ -1761,6 +1727,61 @@ If a
 argument corresponds to the work tree's root directory, display information
 for all tracked files.
 .El
+.Tg ignore
+.Ss Ignore Patterns
+.Cm cvg status
+and
+.Cm  add
+read patterns from
+.Pa .cvsignore
+and
+.Pa .gitignore
+files in each traversed directory and will not display or add unversioned files
+which match these patterns.
+The patterns are matched according to
+.Xr glob 7
+rules, with extensions to improve compatibility with
+.Xr cvs 1
+and
+.Xr git 1 .
+Patterns from each
+.Pa .cvsignore
+or
+.Pa .gitignore
+file are matched relative to the directory containing that file.
+If a pattern begins with two asterisks followed by a slash,
+.Dq **/ ,
+the remainder of the pattern will match at any directory at
+or below the directory containing
+.Pa .cvsignore
+or
+.Pa gitignore
+file.
+Two asterisks surrounded by slashes,
+.Dq /**/ ,
+in the middle of a pattern will match one directory or more.
+Patterns which end with a slash,
+.Dq / ,
+will only match directories, and any paths below matching directories will
+be ignored.
+.Pp
+Unlike
+.Xr cvs 1 ,
+.Nm
+only supports a single ignore pattern per line.
+Unlike
+.Xr git 1 ,
+.Nm
+does not support negated ignore patterns prefixed with
+.Dq \&! ,
+and does not match patterns at arbitrary depth relative to the
+.Pa .gitignore 
+file unless they begin with
+.Dq **/ .
+For better
+.Xr git 1
+compatibility, patterns beginning with a slash are matched as if the slash
+were not present.
 .Sh ENVIRONMENT
 .Bl -tag -width GOT_IGNORE_GITCONFIG
 .It Ev GOT_AUTHOR
blob - 72385745a21eb10a6eaf3ec6da928b7bbbaa0037
blob + f1c4b1579504bdb5e4e484b89a2260bf8a6171b2
--- got/got.1
+++ got/got.1
@@ -964,6 +964,8 @@ are as follows:
 .Bl -tag -width Ds
 .It Fl I
 Show unversioned files even if they match an ignore pattern.
+See
+.Sx Ignore Patterns .
 .It Fl S Ar status-codes
 Suppress the output of files with a modification status matching any of the
 single-character status codes contained in the
@@ -987,42 +989,6 @@ Cannot be used together with the
 .Fl S
 option.
 .El
-.Pp
-For compatibility with
-.Xr cvs 1
-and
-.Xr git 1 ,
-.Cm got status
-reads
-.Xr glob 7
-patterns from
-.Pa .cvsignore
-and
-.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,
-.Cm got status
-supports consecutive asterisks,
-.Dq ** ,
-which will match an arbitrary amount of directories.
-Unlike
-.Xr cvs 1 ,
-.Cm got status
-only supports a single ignore pattern per line.
-Unlike
-.Xr git 1 ,
-.Cm got status
-does not support negated ignore patterns prefixed with
-.Dq \&! ,
-and gives no special significance to the location of path component separators,
-.Dq / ,
-in a pattern.
 .It Xo
 .Cm log
 .Op Fl bdPpRst
@@ -1904,9 +1870,9 @@ another repository.
 .Xc
 Schedule unversioned files in a work tree for addition to the
 repository in the next commit.
-By default, files which match a
-.Cm got status
-ignore pattern will not be added.
+By default, files which match an ignore pattern will not be added.
+See
+.Sx Ignore Patterns .
 .Pp
 If a
 .Ar path
@@ -1932,9 +1898,9 @@ The options for
 are as follows:
 .Bl -tag -width Ds
 .It Fl I
-Add files even if they match a
-.Cm got status
-ignore pattern.
+Add files even if they match an ignore pattern.
+See
+.Xs Ignore Patterns .
 .It Fl R
 Permit recursion into directories.
 If this option is not specified,
@@ -3857,6 +3823,61 @@ If a
 argument corresponds to the work tree's root directory, display information
 for all tracked files.
 .El
+.Tg ignore
+.Ss Ignore Patterns
+.Cm got status
+and
+.Cm got add
+read patterns from
+.Pa .cvsignore
+and
+.Pa .gitignore
+files in each traversed directory and will not display or add unversioned files
+which match these patterns.
+The patterns are matched according to
+.Xr glob 7
+rules, with extensions to improve compatibility with
+.Xr cvs 1
+and
+.Xr git 1 .
+Patterns from each
+.Pa .cvsignore
+or
+.Pa .gitignore
+file are matched relative to the directory containing that file.
+If a pattern begins with two asterisks followed by a slash,
+.Dq **/ ,
+the remainder of the pattern will match at any directory at
+or below the directory containing
+.Pa .cvsignore
+or
+.Pa gitignore
+file.
+Two asterisks surrounded by slashes,
+.Dq /**/ ,
+in the middle of a pattern will match one directory or more.
+Patterns which end with a slash,
+.Dq / ,
+will only match directories, and any paths below matching directories will
+be ignored.
+.Pp
+Unlike
+.Xr cvs 1 ,
+.Nm
+only supports a single ignore pattern per line.
+Unlike
+.Xr git 1 ,
+.Nm
+does not support negated ignore patterns prefixed with
+.Dq \&! ,
+and does not match patterns at arbitrary depth relative to the
+.Pa .gitignore 
+file unless they begin with
+.Dq **/ .
+For better
+.Xr git 1
+compatibility, patterns beginning with a slash are matched as if the slash
+were not present.
 .Sh ENVIRONMENT
 .Bl -tag -width GOT_IGNORE_GITCONFIG
 .It Ev GOT_AUTHOR
blob - fd2e3ed8fe3b3dbd2e5e8de7acc219ee467ee052
blob + 4e690714aa90a9b5159147f65bf8292f5ed4c327
--- lib/worktree.c
+++ lib/worktree.c
@@ -3813,19 +3813,29 @@ match_path(const char *pattern, size_t pattern_len, co
     int flags)
 {
 	char buf[PATH_MAX];
+	const char *pat = pattern;
+	size_t len = pattern_len;
 
 	/*
+	 * For gitignore(7) compatibility, ignore leading slashes
+	 */
+	if (len > 0 && pat[0] == '/') {
+		pat++;
+		len--;
+	}
+
+	/*
 	 * 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))
+	if (pat > 0 && pat[len - 1] == '/') {
+		if (snprintf(buf, sizeof(buf), "%s*", pat) >= sizeof(buf))
 			return FNM_NOMATCH; /* XXX */
 
 		return fnmatch(buf, path, flags);
 	}
 
-	return fnmatch(pattern, path, flags);
+	return fnmatch(pat, path, flags);
 }
 
 static int
blob - 018736a36965a3780dcc34fa3fd41f8d9f337425
blob + 5e57f89a8f3c5c4f999f1f0bd918335e63d74fb7
--- regress/cmdline/status.sh
+++ regress/cmdline/status.sh
@@ -654,6 +654,7 @@ test_status_gitignore() {
 	echo "unversioned file" > $testroot/wt/epsilon/boo
 	echo "unversioned file" > $testroot/wt/epsilon/moo
 	mkdir -p $testroot/wt/a/b/c/
+	echo "git would ignore this" > $testroot/wt/a/foo
 	echo "unversioned file" > $testroot/wt/a/b/c/foo
 	echo "unversioned file" > $testroot/wt/a/b/c/zoo
 	echo "foo" > $testroot/wt/.gitignore
@@ -663,6 +664,7 @@ test_status_gitignore() {
 	echo "**/zoo" >> $testroot/wt/.gitignore
 
 	echo '?  .gitignore' > $testroot/stdout.expected
+	echo '?  a/foo' >> $testroot/stdout.expected
 	echo '?  foop' >> $testroot/stdout.expected
 	(cd $testroot/wt && got status > $testroot/stdout)
 
@@ -675,6 +677,7 @@ test_status_gitignore() {
 	fi
 
 	echo '?  .gitignore' > $testroot/stdout.expected
+	echo '?  a/foo' >> $testroot/stdout.expected
 	echo '?  foop' >> $testroot/stdout.expected
 	(cd $testroot/wt/gamma && got status > $testroot/stdout)
 
@@ -690,6 +693,7 @@ test_status_gitignore() {
 ?  .gitignore
 ?  a/b/c/foo
 ?  a/b/c/zoo
+?  a/foo
 ?  barp
 ?  epsilon/bar
 ?  epsilon/boo
@@ -713,6 +717,41 @@ EOF
 	test_done "$testroot" "$ret"
 }
 
+test_status_gitignore_leading_slashes() {
+	local testroot=`test_init status_gitignore_leading_slashes`
+
+	got checkout $testroot/repo $testroot/wt > /dev/null
+	ret=$?
+	if [ $ret -ne 0 ]; then
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	echo "unversioned file" > $testroot/wt/foo
+	echo "unversioned file" > $testroot/wt/epsilon/foo
+	echo "unversioned file" > $testroot/wt/epsilon/bar
+	mkdir -p $testroot/wt/nu
+	echo "unversioned file" > $testroot/wt/nu/baz
+	mkdir -p $testroot/wt/epsilon/nu
+	echo "unversioned file" > $testroot/wt/epsilon/nu/baz
+
+	echo "/foo" > $testroot/wt/.gitignore
+	echo "/nu" >> $testroot/wt/.gitignore
+
+	echo '?  .gitignore' > $testroot/stdout.expected
+	echo '?  epsilon/bar' >> $testroot/stdout.expected
+	echo '?  epsilon/foo' >> $testroot/stdout.expected
+	echo '?  epsilon/nu/baz' >> $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
+	fi
+	test_done "$testroot" "$ret"
+}
+
 test_status_gitignore_trailing_slashes() {
 	local testroot=`test_init status_gitignore_trailing_slashes`
 
@@ -1204,6 +1243,7 @@ run_test test_status_empty_dir_unversioned_file
 run_test test_status_many_paths
 run_test test_status_cvsignore
 run_test test_status_gitignore
+run_test test_status_gitignore_leading_slashes
 run_test test_status_gitignore_trailing_slashes
 run_test test_status_gitignore_comments
 run_test test_status_multiple_gitignore_files