Commit Diff


commit - f8d1f275c50bc69aed2c12b2efacf5923c9c4a4b
commit + 6bad629b50d093da48f6347e1dd806d56bf05a1e
blob - 1f262f0cc13c58a418ead0547d47fa568730d0be
blob + 374ed5e84b7472ab124872d9e03621f6e9df94da
--- got/got.1
+++ got/got.1
@@ -109,8 +109,19 @@ Update the work tree to the specified
 .Ar commit .
 The expected argument is a SHA1 hash which corresponds to a commit object.
 .El
-.\".It Cm status
-.\"Show current status of files.
+.It Cm status [ Ar worktree-path ]
+Show the current modification status of files in a worktree,
+using the following status codes:
+.Bl -column YXZ description
+.It M Ta modified file
+.It ! Ta versioned file was expected on disk but is missing
+.It ? Ta unversioned item not tracked by
+.Nm
+.El
+.Pp
+If the
+.Ar work tree path
+is omitted, use the current working directory.
 .It Cm log [ Fl c Ar commit ] [ Fl C Ar number ] [ Fl f ] [ Fl l Ar N ] [ Fl p ] [ Fl r Ar repository-path ] [ path ]
 Display history of a repository.
 If a
blob - bedd053bfd85bcf4daedb8cabb19a4ef5b948f82
blob + 21e4910f5bcd87ece0560e051f115d801f404a25
--- got/got.c
+++ got/got.c
@@ -75,6 +75,7 @@ __dead static void	usage_log(void);
 __dead static void	usage_diff(void);
 __dead static void	usage_blame(void);
 __dead static void	usage_tree(void);
+__dead static void	usage_status(void);
 
 static const struct got_error*		cmd_checkout(int, char *[]);
 static const struct got_error*		cmd_update(int, char *[]);
@@ -82,9 +83,7 @@ static const struct got_error*		cmd_log(int, char *[])
 static const struct got_error*		cmd_diff(int, char *[]);
 static const struct got_error*		cmd_blame(int, char *[]);
 static const struct got_error*		cmd_tree(int, char *[]);
-#ifdef notyet
 static const struct got_error*		cmd_status(int, char *[]);
-#endif
 
 static struct cmd got_commands[] = {
 	{ "checkout",	cmd_checkout,	usage_checkout,
@@ -99,10 +98,8 @@ static struct cmd got_commands[] = {
 	    " show when lines in a file were changed" },
 	{ "tree",	cmd_tree,	usage_tree,
 	    " list files and directories in repository" },
-#ifdef notyet
 	{ "status",	cmd_status,	usage_status,
 	    "show modification status of files" },
-#endif
 };
 
 int
@@ -218,7 +215,7 @@ checkout_progress(void *arg, unsigned char status, con
 }
 
 static const struct got_error *
-checkout_cancel(void *arg)
+check_cancelled(void *arg)
 {
 	if (sigint_received || sigpipe_received)
 		return got_error(GOT_ERR_CANCELLED);
@@ -410,7 +407,7 @@ cmd_checkout(int argc, char *argv[])
 	}
 
 	error = got_worktree_checkout_files(worktree, repo,
-	    checkout_progress, worktree_path, checkout_cancel, NULL);
+	    checkout_progress, worktree_path, check_cancelled, NULL);
 	if (error != NULL)
 		goto done;
 
@@ -535,7 +532,7 @@ cmd_update(int argc, char *argv[])
 	}
 
 	error = got_worktree_checkout_files(worktree, repo,
-	    update_progress, &did_something, checkout_cancel, NULL);
+	    update_progress, &did_something, check_cancelled, NULL);
 	if (error != NULL)
 		goto done;
 
@@ -1349,83 +1346,74 @@ done:
 	return error;
 }
 
-#ifdef notyet
-static const struct got_error *
-cmd_status(int argc __unused, char *argv[] __unused)
-{
-	git_repository *repo = NULL;
-	git_status_list *status;
-	git_status_options statusopts;
-	size_t i;
+__dead static void
+usage_status(void)
+{
+	fprintf(stderr, "usage: %s status [worktree-path]\n", getprogname());
+	exit(1);
+}
 
-	git_libgit2_init();
-
-	if (git_repository_open_ext(&repo, ".", 0, NULL))
-		errx(1, "git_repository_open: %s", giterr_last()->message);
-
-	if (git_repository_is_bare(repo))
-		errx(1, "bar repository");
-
-	if (git_status_init_options(&statusopts, GIT_STATUS_OPTIONS_VERSION))
-		errx(1, "git_status_init_options: %s", giterr_last()->message);
+static void
+print_status(void *arg, unsigned char status, const char *path)
+{
+	printf("%c  %s\n", status, path);
+}
 
-	statusopts.show  = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
-	statusopts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED |
-	    GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX |
-	    GIT_STATUS_OPT_SORT_CASE_SENSITIVELY;
+static const struct got_error *
+cmd_status(int argc, char *argv[])
+{
+	const struct got_error *error = NULL;
+	struct got_repository *repo = NULL;
+	struct got_worktree *worktree = NULL;
+	char *worktree_path = NULL;
+	int ch;
 
-	if (git_status_list_new(&status, repo, &statusopts))
-		errx(1, "git_status_list_new: %s", giterr_last()->message);
-
-	for (i = 0; i < git_status_list_entrycount(status); i++) {
-		const git_status_entry *se;
-
-		se = git_status_byindex(status, i);
-		switch (se->status) {
-		case GIT_STATUS_WT_NEW:
-			printf("? %s\n", se->index_to_workdir->new_file.path);
-			break;
-		case GIT_STATUS_WT_MODIFIED:
-			printf("M %s\n", se->index_to_workdir->new_file.path);
-			break;
-		case GIT_STATUS_WT_DELETED:
-			printf("R %s\n", se->index_to_workdir->new_file.path);
-			break;
-		case GIT_STATUS_WT_RENAMED:
-			printf("m %s -> %s\n",
-			    se->index_to_workdir->old_file.path,
-			    se->index_to_workdir->new_file.path);
-			break;
-		case GIT_STATUS_WT_TYPECHANGE:
-			printf("t %s\n", se->index_to_workdir->new_file.path);
-			break;
-		case GIT_STATUS_INDEX_NEW:
-			printf("A %s\n", se->head_to_index->new_file.path);
-			break;
-		case GIT_STATUS_INDEX_MODIFIED:
-			printf("M %s\n", se->head_to_index->old_file.path);
-			break;
-		case GIT_STATUS_INDEX_DELETED:
-			printf("R %s\n", se->head_to_index->old_file.path);
-			break;
-		case GIT_STATUS_INDEX_RENAMED:
-			printf("m %s -> %s\n",
-			    se->head_to_index->old_file.path,
-			    se->head_to_index->new_file.path);
-			break;
-		case GIT_STATUS_INDEX_TYPECHANGE:
-			printf("t %s\n", se->head_to_index->old_file.path);
-			break;
-		case GIT_STATUS_CURRENT:
+	while ((ch = getopt(argc, argv, "")) != -1) {
+		switch (ch) {
 		default:
-			break;
+			usage();
+			/* NOTREACHED */
 		}
 	}
 
-	git_status_list_free(status);
-	git_repository_free(repo);
-	git_libgit2_shutdown();
+	argc -= optind;
+	argv += optind;
 
-	return 0;
-}
+#ifndef PROFILE
+	if (pledge("stdio rpath wpath cpath flock proc exec sendfd unveil",
+	    NULL) == -1)
+		err(1, "pledge");
 #endif
+	if (argc == 0) {
+		worktree_path = getcwd(NULL, 0);
+		if (worktree_path == NULL) {
+			error = got_error_from_errno();
+			goto done;
+		}
+	} else if (argc == 1) {
+		worktree_path = realpath(argv[0], NULL);
+		if (worktree_path == NULL) {
+			error = got_error_from_errno();
+			goto done;
+		}
+	} else
+		usage_status();
+
+	error = got_worktree_open(&worktree, worktree_path);
+	if (error != NULL)
+		goto done;
+
+	error = got_repo_open(&repo, got_worktree_get_repo_path(worktree));
+	if (error != NULL)
+		goto done;
+
+	error = apply_unveil(got_repo_get_path(repo), worktree_path);
+	if (error)
+		goto done;
+
+	error = got_worktree_status(worktree, repo, print_status, NULL,
+	    check_cancelled, NULL);
+done:
+	free(worktree_path);
+	return error;
+}