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

From:
Klemens Nanni <kn@openbsd.org>
Subject:
diff: Allow diffing three or more paths at once
To:
gameoftrees@openbsd.org
Date:
Thu, 1 Apr 2021 19:52:00 +0200

Download raw body.

Thread
Do not special-case `argc == 1' any longer and handle argv[] at once.

This is the first step towards diffing an arbitrary number of paths and
automatically falling back to interpreting arguments as objects iff exactly
two were given and one of them is not a valid path.

Diffing two paths (not objects) is still not possible and will be handled
later;  this commit is to reduce churn and ease review.

---
 got/got.1 | 13 ++++++-------
 got/got.c | 43 ++++++++++++++++---------------------------
 2 files changed, 22 insertions(+), 34 deletions(-)

diff --git a/got/got.1 b/got/got.1
index 6b06d43a..e06fdfd9 100644
--- a/got/got.1
+++ b/got/got.1
@@ -799,14 +799,13 @@ This option has no effect if the specified
 .Ar commit
 is never traversed.
 .El
-.It Cm diff Oo Fl a Oc Oo Fl C Ar number Oc Oo Fl r Ar repository-path Oc Oo Fl s Oc Oo Fl w Oc Op Ar object1 Ar object2 | Ar path
-When invoked within a work tree with less than two arguments, display
-local changes in the work tree.
-If a
-.Ar path
-is specified, only show changes within this path.
+.It Cm diff Oo Fl a Oc Oo Fl C Ar number Oc Oo Fl r Ar repository-path Oc Oo Fl s Oc Oo Fl w Oc Op Ar object1 Ar object2 | Ar path ...
+Display local changes in the work tree.
+If
+.Ar path ...
+is specified, only show changes within these paths.
 .Pp
-If two arguments are provided, treat each argument as a reference, a tag
+If exactly two arguments are provided, treat each argument as a reference, a tag
 name, or an object ID SHA1 hash, and display differences between the
 corresponding objects.
 Both objects must be of the same type (blobs, trees, or commits).
diff --git a/got/got.c b/got/got.c
index 192b847b..e0319678 100644
--- a/got/got.c
+++ b/got/got.c
@@ -4078,7 +4078,7 @@ __dead static void
 usage_diff(void)
 {
 	fprintf(stderr, "usage: %s diff [-a] [-C number] [-r repository-path] "
-	    "[-s] [-w] [object1 object2 | path]\n", getprogname());
+	    "[-s] [-w] [object1 object2 | path ...]\n", getprogname());
 	exit(1);
 }
 
@@ -4294,9 +4294,11 @@ cmd_diff(int argc, char *argv[])
 	int diff_context = 3, diff_staged = 0, ignore_whitespace = 0, ch;
 	int force_text_diff = 0;
 	const char *errstr;
-	char *path = NULL;
+	struct got_pathlist_head paths;
+	struct got_pathlist_entry *pe;
 	struct got_reflist_head refs;
 
+	TAILQ_INIT(&paths);
 	TAILQ_INIT(&refs);
 
 #ifndef PROFILE
@@ -4343,7 +4345,7 @@ cmd_diff(int argc, char *argv[])
 		error = got_error_from_errno("getcwd");
 		goto done;
 	}
-	if (argc <= 1) {
+	if (argc != 2) {
 		if (repo_path)
 			errx(1,
 			    "-r option can't be used when diffing a work tree");
@@ -4359,18 +4361,12 @@ cmd_diff(int argc, char *argv[])
 			error = got_error_from_errno("strdup");
 			goto done;
 		}
-		if (argc == 1) {
-			error = got_worktree_resolve_path(&path, worktree,
-			    argv[0]);
-			if (error)
-				goto done;
-		} else {
-			path = strdup("");
-			if (path == NULL) {
-				error = got_error_from_errno("strdup");
-				goto done;
-			}
-		}
+
+		error = get_worktree_paths_from_argv(&paths, argc, argv,
+		    worktree);
+		if (error)
+			goto done;
+
 	} else if (argc == 2) {
 		if (diff_staged)
 			errx(1, "-s option can't be used when diffing "
@@ -4388,8 +4384,7 @@ cmd_diff(int argc, char *argv[])
 				goto done;
 			}
 		}
-	} else
-		usage_diff();
+	}
 
 	error = got_repo_open(&repo, repo_path, NULL);
 	free(repo_path);
@@ -4401,13 +4396,10 @@ cmd_diff(int argc, char *argv[])
 	if (error)
 		goto done;
 
-	if (argc <= 1) {
+	if (argc != 2) {
 		struct print_diff_arg arg;
-		struct got_pathlist_head paths;
 		char *id_str;
 
-		TAILQ_INIT(&paths);
-
 		error = got_object_id_str(&id_str,
 		    got_worktree_get_base_commit_id(worktree));
 		if (error)
@@ -4421,14 +4413,9 @@ cmd_diff(int argc, char *argv[])
 		arg.ignore_whitespace = ignore_whitespace;
 		arg.force_text_diff = force_text_diff;
 
-		error = got_pathlist_append(&paths, path, NULL);
-		if (error)
-			goto done;
-
 		error = got_worktree_status(worktree, &paths, repo, print_diff,
 		    &arg, check_cancelled, NULL);
 		free(id_str);
-		got_pathlist_free(&paths);
 		goto done;
 	}
 
@@ -4484,7 +4471,6 @@ done:
 	free(label2);
 	free(id1);
 	free(id2);
-	free(path);
 	if (worktree)
 		got_worktree_close(worktree);
 	if (repo) {
@@ -4493,6 +4479,9 @@ done:
 		if (error == NULL)
 			error = repo_error;
 	}
+	TAILQ_FOREACH(pe, &paths, entry)
+		free((char *)pe->path);
+	got_pathlist_free(&paths);
 	got_ref_list_free(&refs);
 	return error;
 }
-- 
2.31.0