Commit c363b2c176847929422503bc59dede412e83f0ae

Stefan Sperling 2019-08-03T14:55:49

show staged file status separately in 'got status'

diff --git a/got/got.c b/got/got.c
index 982c3c8..37d1d68 100644
--- a/got/got.c
+++ b/got/got.c
@@ -2368,6 +2368,9 @@ print_status(void *arg, unsigned char status, unsigned char staged_status,
     const char *path, struct got_object_id *blob_id,
     struct got_object_id *commit_id)
 {
+	if (status == staged_status &&
+	    (status == GOT_STATUS_ADD || status == GOT_STATUS_DELETE))
+		status = GOT_STATUS_NO_CHANGE;
 	printf("%c%c %s\n", status, staged_status, path);
 	return NULL;
 }
diff --git a/lib/worktree.c b/lib/worktree.c
index 9ca3668..eaffa11 100644
--- a/lib/worktree.c
+++ b/lib/worktree.c
@@ -1034,6 +1034,21 @@ stat_info_differs(struct got_fileindex_entry *ie, struct stat *sb)
 	    ie->size == (sb->st_size & 0xffffffff));
 }
 
+static unsigned char
+get_staged_status(struct got_fileindex_entry *ie)
+{
+	switch (got_fileindex_entry_stage_get(ie)) {
+	case GOT_FILEIDX_STAGE_ADD:
+		return GOT_STATUS_ADD;
+	case GOT_FILEIDX_STAGE_DELETE:
+		return GOT_STATUS_DELETE;
+	case GOT_FILEIDX_STAGE_MODIFY:
+		return GOT_STATUS_MODIFY;
+	default:
+		return GOT_STATUS_NO_CHANGE;
+	}
+}
+
 static const struct got_error *
 get_file_status(unsigned char *status, struct stat *sb,
     struct got_fileindex_entry *ie, const char *abspath,
@@ -1046,6 +1061,7 @@ get_file_status(unsigned char *status, struct stat *sb,
 	uint8_t fbuf[8192];
 	struct got_blob_object *blob = NULL;
 	size_t flen, blen;
+	unsigned char staged_status = get_staged_status(ie);
 
 	*status = GOT_STATUS_NO_CHANGE;
 
@@ -1076,7 +1092,12 @@ get_file_status(unsigned char *status, struct stat *sb,
 	if (!stat_info_differs(ie, sb))
 		return NULL;
 
-	memcpy(id.sha1, ie->blob_sha1, sizeof(id.sha1));
+	if (staged_status == GOT_STATUS_MODIFY ||
+	    staged_status == GOT_STATUS_ADD)
+		memcpy(id.sha1, ie->staged_blob_sha1, sizeof(id.sha1));
+	else
+		memcpy(id.sha1, ie->blob_sha1, sizeof(id.sha1));
+
 	err = got_object_open_as_blob(&blob, repo, &id, sizeof(fbuf));
 	if (err)
 		return err;
@@ -2179,21 +2200,6 @@ struct diff_dir_cb_arg {
     void *cancel_arg;
 };
 
-static unsigned char
-get_staged_status(struct got_fileindex_entry *ie)
-{
-	switch (got_fileindex_entry_stage_get(ie)) {
-	case GOT_FILEIDX_STAGE_ADD:
-		return GOT_STATUS_ADD;
-	case GOT_FILEIDX_STAGE_DELETE:
-		return GOT_STATUS_DELETE;
-	case GOT_FILEIDX_STAGE_MODIFY:
-		return GOT_STATUS_MODIFY;
-	default:
-		return GOT_STATUS_NO_CHANGE;
-	}
-}
-
 static const struct got_error *
 report_file_status(struct got_fileindex_entry *ie, const char *abspath,
     got_worktree_status_cb status_cb, void *status_arg,
@@ -2201,14 +2207,16 @@ report_file_status(struct got_fileindex_entry *ie, const char *abspath,
 {
 	const struct got_error *err = NULL;
 	unsigned char status = GOT_STATUS_NO_CHANGE;
+	unsigned char staged_status = get_staged_status(ie);
 	struct stat sb;
 	struct got_object_id blob_id, commit_id;
 
 	err = get_file_status(&status, &sb, ie, abspath, repo);
-	if (err == NULL && status != GOT_STATUS_NO_CHANGE) {
+	if (err == NULL && (status != GOT_STATUS_NO_CHANGE ||
+	    staged_status != GOT_STATUS_NO_CHANGE)) {
 		memcpy(blob_id.sha1, ie->blob_sha1, SHA1_DIGEST_LENGTH);
 		memcpy(commit_id.sha1, ie->commit_sha1, SHA1_DIGEST_LENGTH);
-		err = (*status_cb)(status_arg, status, get_staged_status(ie),
+		err = (*status_cb)(status_arg, status, staged_status,
 		    ie->path, &blob_id, &commit_id);
 	}
 	return err;
diff --git a/regress/cmdline/stage.sh b/regress/cmdline/stage.sh
index 0a71da3..5aa5444 100755
--- a/regress/cmdline/stage.sh
+++ b/regress/cmdline/stage.sh
@@ -44,4 +44,41 @@ function test_stage_basic {
 	test_done "$testroot" "$ret"
 }
 
+function test_stage_status {
+	local testroot=`test_init stage_status`
+
+	got checkout $testroot/repo $testroot/wt > /dev/null
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		test_done "$testroot" "$ret"
+		return 1
+	fi
+
+	echo "modified file" > $testroot/wt/alpha
+	(cd $testroot/wt && got rm beta > /dev/null)
+	echo "new file" > $testroot/wt/foo
+	(cd $testroot/wt && got add foo > /dev/null)
+	echo "new file" > $testroot/wt/epsilon/new
+	(cd $testroot/wt && got add epsilon/new > /dev/null)
+	echo "modified file" > $testroot/wt/epsilon/zeta
+	(cd $testroot/wt && got rm gamma/delta > /dev/null)
+
+	echo ' M alpha' > $testroot/stdout.expected
+	echo ' D beta' >> $testroot/stdout.expected
+	echo 'A  epsilon/new' >> $testroot/stdout.expected
+	echo 'M  epsilon/zeta' >> $testroot/stdout.expected
+	echo ' A foo' >> $testroot/stdout.expected
+	echo 'D  gamma/delta' >> $testroot/stdout.expected
+	(cd $testroot/wt && got stage alpha beta foo > /dev/null)
+
+	(cd $testroot/wt && got status > $testroot/stdout)
+	cmp -s $testroot/stdout.expected $testroot/stdout
+	ret="$?"
+	if [ "$ret" != "0" ]; then
+		diff -u $testroot/stdout.expected $testroot/stdout
+	fi
+	test_done "$testroot" "$ret"
+}
+
 run_test test_stage_basic
+run_test test_stage_status