Commit Diff


commit - ae6a69782e0a92064dbfeb83896ce38a90977414
commit + 081470ac52a4d68384a33f36bdd0d3096d6cf772
blob - f9e5cd6f3135e7407b0775077c23ca64fd500590
blob + 8f049181b8b59970cb560bc5e0623a8015811931
--- got/got.1
+++ got/got.1
@@ -607,7 +607,7 @@ branch will be used.
 .It Cm up
 Short alias for
 .Cm update .
-.It Cm status Op Ar path ...
+.It Cm status Oo Fl s Ar status-codes Oc Op Ar path ...
 Show the current modification status of files in a work tree,
 using the following status codes:
 .Bl -column YXZ description
@@ -646,6 +646,20 @@ Changes created on top of staged changes are indicated
 .It MA Ta file was modified after having been staged for addition
 .El
 .Pp
+The options for
+.Cm got status
+are as follows:
+.Bl -tag -width Ds
+.It Fl s Ar status-codes
+Only show files with a modification status matching any of the
+single-character status codes contained in the
+.Ar status-codes
+argument.
+Any combination of codes from the above list of possible status codes
+may be specified.
+For staged files, status codes displayed in either column will be matched.
+.El
+.Pp
 For compatibility with
 .Xr cvs 1
 and
@@ -1955,9 +1969,12 @@ Check out a work tree from the Git repository to /usr/
 .Pp
 View local changes in a work tree directory:
 .Pp
-.Dl $ got status
 .Dl $ got diff | less
 .Pp
+In a work tree, display files in a potentially problematic state:
+.Pp
+.Dl $ got status -s 'C!~?'
+.Pp
 Interactively revert selected local changes in a work tree directory:
 .Pp
 .Dl $ got revert -p -R\ .
blob - 7d306e82e5e51906ac29b7b1df6b2cc05f281e95
blob + 93fe92b8cf1c50517bdedc66c2b0be234cb08074
--- got/got.c
+++ got/got.c
@@ -4642,7 +4642,8 @@ done:
 __dead static void
 usage_status(void)
 {
-	fprintf(stderr, "usage: %s status [path ...]\n", getprogname());
+	fprintf(stderr, "usage: %s status [-s status-codes ] [path ...]\n",
+	    getprogname());
 	exit(1);
 }
 
@@ -4654,6 +4655,18 @@ print_status(void *arg, unsigned char status, unsigned
 {
 	if (status == staged_status && (status == GOT_STATUS_DELETE))
 		status = GOT_STATUS_NO_CHANGE;
+	if (arg) {
+		char *status_codes = arg;
+		size_t ncodes = strlen(status_codes);
+		int i;
+		for (i = 0; i < ncodes ; i++) {
+			if (status == status_codes[i] ||
+			    staged_status == status_codes[i])
+				break;
+		}
+		if (i == ncodes)
+			return NULL;
+	}
 	printf("%c%c %s\n", status, staged_status, path);
 	return NULL;
 }
@@ -4664,15 +4677,35 @@ cmd_status(int argc, char *argv[])
 	const struct got_error *error = NULL;
 	struct got_repository *repo = NULL;
 	struct got_worktree *worktree = NULL;
-	char *cwd = NULL;
+	char *cwd = NULL, *status_codes = NULL;;
 	struct got_pathlist_head paths;
 	struct got_pathlist_entry *pe;
-	int ch;
+	int ch, i;
 
 	TAILQ_INIT(&paths);
 
-	while ((ch = getopt(argc, argv, "")) != -1) {
+	while ((ch = getopt(argc, argv, "s:")) != -1) {
 		switch (ch) {
+		case 's':
+			for (i = 0; i < strlen(optarg); i++) {
+				switch (optarg[i]) {
+				case GOT_STATUS_MODIFY:
+				case GOT_STATUS_ADD:
+				case GOT_STATUS_DELETE:
+				case GOT_STATUS_CONFLICT:
+				case GOT_STATUS_MISSING:
+				case GOT_STATUS_OBSTRUCTED:
+				case GOT_STATUS_UNVERSIONED:
+				case GOT_STATUS_MODE_CHANGE:
+				case GOT_STATUS_NONEXISTENT:
+					break;
+				default:
+					errx(1, "invalid status code '%c'",
+					    optarg[i]);
+				}
+			}
+			status_codes = optarg;
+			break;
 		default:
 			usage_status();
 			/* NOTREACHED */
@@ -4714,8 +4747,8 @@ cmd_status(int argc, char *argv[])
 	if (error)
 		goto done;
 
-	error = got_worktree_status(worktree, &paths, repo, print_status, NULL,
-	    check_cancelled, NULL);
+	error = got_worktree_status(worktree, &paths, repo, print_status,
+	    status_codes, check_cancelled, NULL);
 done:
 	TAILQ_FOREACH(pe, &paths, entry)
 		free((char *)pe->path);
blob - 57f0661d15b479c61bf4063f60ad7de2ec7c8499
blob + 46a185350db6563b65ec99ac16de6b202254c8ad
--- regress/cmdline/status.sh
+++ regress/cmdline/status.sh
@@ -633,7 +633,123 @@ function test_status_gitignore {
 	fi
 	test_done "$testroot" "$ret"
 }
+
+function test_status_status_code {
+	local testroot=`test_init status_status_code`
+
+	got checkout $testroot/repo $testroot/wt > /dev/null
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	echo "modified alpha" > $testroot/wt/alpha
+	(cd $testroot/wt && got rm beta >/dev/null)
+	echo "unversioned file" > $testroot/wt/foo
+	rm $testroot/wt/epsilon/zeta
+	touch $testroot/wt/beta
+	echo "new file" > $testroot/wt/new
+	(cd $testroot/wt && got add new >/dev/null)
+
+	(cd $testroot/wt && got status -s xDM \
+		> $testroot/stdout 2> $testroot/stderr)
+	ret="$?"
+	if [ "$ret" == "0" ]; then
+		echo "status succeeded unexpectedly" >&2
+		test_done "$testroot" "1"
+		return 1
+	fi
+
+	echo "got: invalid status code 'x'" > $testroot/stderr.expected
+	cmp -s $testroot/stderr.expected $testroot/stderr
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		diff -u $testroot/stderr.expected $testroot/stderr
+		test_done "$testroot" "$ret"
+		return 1
+	fi
 
+	echo 'M  alpha' > $testroot/stdout.expected
+	(cd $testroot/wt && got status -s M > $testroot/stdout)
+	cmp -s $testroot/stdout.expected $testroot/stdout
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		diff -u $testroot/stdout.expected $testroot/stdout
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	echo 'D  beta' > $testroot/stdout.expected
+	(cd $testroot/wt && got status -s D > $testroot/stdout)
+	cmp -s $testroot/stdout.expected $testroot/stdout
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		diff -u $testroot/stdout.expected $testroot/stdout
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	echo '!  epsilon/zeta' > $testroot/stdout.expected
+	echo '?  foo' >> $testroot/stdout.expected
+	(cd $testroot/wt && got status -s \!? > $testroot/stdout)
+	cmp -s $testroot/stdout.expected $testroot/stdout
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		diff -u $testroot/stdout.expected $testroot/stdout
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	echo 'A  new' > $testroot/stdout.expected
+	(cd $testroot/wt && got status -s A > $testroot/stdout)
+	cmp -s $testroot/stdout.expected $testroot/stdout
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		diff -u $testroot/stdout.expected $testroot/stdout
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	(cd $testroot/wt && got stage new > $testroot/stdout)
+
+	echo ' A new' > $testroot/stdout.expected
+	(cd $testroot/wt && got status -s A > $testroot/stdout)
+	cmp -s $testroot/stdout.expected $testroot/stdout
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		diff -u $testroot/stdout.expected $testroot/stdout
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	echo 'changed file new' > $testroot/wt/new
+
+	echo 'MA new' > $testroot/stdout.expected
+	(cd $testroot/wt && got status -s A > $testroot/stdout)
+	cmp -s $testroot/stdout.expected $testroot/stdout
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		diff -u $testroot/stdout.expected $testroot/stdout
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	echo 'M  alpha' > $testroot/stdout.expected
+	echo 'MA new' >> $testroot/stdout.expected
+	(cd $testroot/wt && got status -s M > $testroot/stdout)
+	cmp -s $testroot/stdout.expected $testroot/stdout
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		diff -u $testroot/stdout.expected $testroot/stdout
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	test_done "$testroot" "$ret"
+}
+
+
 test_parseargs "$@"
 run_test test_status_basic
 run_test test_status_subdir_no_mods
@@ -649,3 +765,4 @@ 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_status_code