"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Stefan Sperling <stsp@stsp.name>
Subject:
got patch stats about conflicts and rejects
To:
gameoftrees@openbsd.org
Date:
Thu, 11 May 2023 07:34:26 +0200

Download raw body.

Thread
When 'got patch' sees merge conflicts it prints a final message saying
the patch failed to apply. This behaviour seemed somewhat unclear to me
in this particular case:

$ got patch < umb3.diff
G  Makefile
C  commands.c
G  conf.c
G  ctl.c
G  externs.h
G  if.c
G  main.c
C  ppp.c
G  sqlite3.c
A  umb.c
got: patch failed to apply
$

This left me wondering where the problem was. Other commands treat
conflicted files as an expected outcome rather than an error. So I did not
immediately understand that merge conflicts were the reason for the error
message. I see why patch does this differently but I would prefer the
following output, as implemented below.

$ got patch < umb3.diff
G  Makefile
C  commands.c
G  conf.c
G  ctl.c
G  externs.h
G  if.c
G  main.c
C  ppp.c
G  sqlite3.c
A  umb.c
Files with merge conflicts: 2
got: patch failed to apply
$

ok?

-----------------------------------------------
 make 'got patch' display statistics about files with conflicts and rejects
 
diff e423877dd3fa76444ef448d4272a9f6d3ff32b54 923b751a6de843fe88951be34e6d8a7eec656101
commit - e423877dd3fa76444ef448d4272a9f6d3ff32b54
commit + 923b751a6de843fe88951be34e6d8a7eec656101
blob - 5b1264a0869935160185d8dbf60cfca23110939d
blob + 8d34fc2c0463ba9b0482b97a427cd03c82b875d8
--- got/got.c
+++ got/got.c
@@ -8165,6 +8165,12 @@ static const struct got_error *
 	return err;
 }
 
+struct got_patch_progress_arg {
+	int did_something;
+	int conflicts;
+	int rejects;
+};
+
 static const struct got_error *
 patch_progress(void *arg, const char *old, const char *new,
     unsigned char status, const struct got_error *error, int old_from,
@@ -8172,13 +8178,24 @@ patch_progress(void *arg, const char *old, const char 
     int ws_mangled, const struct got_error *hunk_err)
 {
 	const char *path = new == NULL ? old : new;
+	struct got_patch_progress_arg *a = arg;
 
 	while (*path == '/')
 		path++;
 
-	if (status != 0)
+	if (status != GOT_STATUS_NO_CHANGE &&
+	    status != 0 /* per-hunk progress */) {
 		printf("%c  %s\n", status, path);
+		a->did_something = 1;
+	}
 
+	if (hunk_err == NULL) {
+		if (status == GOT_STATUS_CANNOT_UPDATE)
+			a->rejects++;
+		else if (status == GOT_STATUS_CONFLICT)
+			a->conflicts++;
+	}
+
 	if (error != NULL)
 		fprintf(stderr, "%s: %s\n", getprogname(), error->msg);
 
@@ -8196,6 +8213,21 @@ static const struct got_error *
 	return NULL;
 }
 
+static void
+print_patch_progress_stats(struct got_patch_progress_arg *ppa)
+{
+	if (!ppa->did_something)
+		return;
+
+	if (ppa->conflicts > 0)
+		printf("Files with merge conflicts: %d\n", ppa->conflicts);
+
+	if (ppa->rejects > 0) {
+		printf("Files where patch failed to apply: %d\n",
+		    ppa->rejects);
+	}
+}
+
 static const struct got_error *
 cmd_patch(int argc, char *argv[])
 {
@@ -8211,6 +8243,7 @@ cmd_patch(int argc, char *argv[])
 	int ch, nop = 0, strip = -1, reverse = 0;
 	int patchfd;
 	int *pack_fds = NULL;
+	struct got_patch_progress_arg ppa;
 
 	TAILQ_INIT(&refs);
 
@@ -8301,9 +8334,10 @@ cmd_patch(int argc, char *argv[])
 			goto done;
 	}
 
+	memset(&ppa, 0, sizeof(ppa));
 	error = got_patch(patchfd, worktree, repo, nop, strip, reverse,
-	    commit_id, &patch_progress, NULL, check_cancelled, NULL);
-
+	    commit_id, patch_progress, &ppa, check_cancelled, NULL);
+	print_patch_progress_stats(&ppa);
 done:
 	got_ref_list_free(&refs);
 	free(commit_id);
blob - f8f96458bc264b17a74e776857380fbf625c03d2
blob + 17db471e5c3aa81e0eb9233b406861cdccd08fcd
--- regress/cmdline/patch.sh
+++ regress/cmdline/patch.sh
@@ -202,6 +202,7 @@ EOF
 @@ -1,1 +1,2 @@ hunk failed to apply
 #  numbers
 @@ -1,9 +0,0 @@ hunk failed to apply
+Files where patch failed to apply: 2
 EOF
 
 	cmp -s $testroot/stdout.expected $testroot/stdout
@@ -561,6 +562,7 @@ EOF
 #  iota
 #  kappa
 #  lambda
+Files where patch failed to apply: 5
 EOF
 
 	cat <<EOF > $testroot/stderr.expected
@@ -1528,6 +1530,7 @@ test_patch_merge_conflict() {
 
 	echo 'C  alpha' > $testroot/stdout.expected
 	echo 'C  numbers' >> $testroot/stdout.expected
+	echo 'Files with merge conflicts: 2' >> $testroot/stdout.expected
 	cmp -s $testroot/stdout $testroot/stdout.expected
 	ret=$?
 	if [ $ret -ne 0 ]; then