Commit Diff


commit - a7f506998d573165fb10a8552b2f48c72094001d
commit + 0ed6ed4ca7635b211a4b7a02bacfdec1255dc4bd
blob - 3bcc62f94215ced3a11d5b3b47ed4887026df706
blob + 5afbf1c50c8cbb247a5f9977463af9933c693768
--- got/got.1
+++ got/got.1
@@ -84,7 +84,7 @@ was specified use the base name of the
 .Ar path prefix .
 .\".It Cm status
 .\"Show current status of files.
-.It Cm log [ Fl p ] [ Fl c Ar commit ] [ Fl l Ar N ] [ Fl v ] [ Ar repository-path ]
+.It Cm log [ Fl p ] [ Fl c Ar commit ] [ Fl l Ar N ] [ Fl v ] [Fl f ] [ Ar repository-path ]
 Display history of the repository.
 If the
 .Fl p
@@ -105,6 +105,11 @@ commits.
 The
 .Fl v
 option enables verbose output.
+The
+.Fl f
+option restricts history traversal to the first parent of each commit.
+This shows the linear history of the current branch only, omitting any
+commits merged from other branches.
 If the
 .Ar repository path
 is omitted, use the current working directory.
blob - 62e4d6ab75e22830b973ee01eaacf12b6d95eac7
blob + 59821dd13e5b1d23f8d1fc933cc8c4b435d9c713
--- got/got.c
+++ got/got.c
@@ -375,13 +375,15 @@ print_commit(struct got_commit_object *commit, struct 
 
 static const struct got_error *
 print_commits(struct got_object *root_obj, struct got_object_id *root_id,
-    struct got_repository *repo, int show_patch, int limit, int verbose)
+    struct got_repository *repo, int show_patch, int limit, int verbose,
+    int first_parent_traversal)
 {
 	const struct got_error *err;
 	struct got_commit_graph *graph;
 	int ncommits;
 
-	err = got_commit_graph_open(&graph, root_id, repo);
+	err = got_commit_graph_open(&graph, root_id, first_parent_traversal,
+	    repo);
 	if (err)
 		return err;
 	err = got_commit_graph_iter_start(graph, root_id);
@@ -425,7 +427,7 @@ print_commits(struct got_object *root_obj, struct got_
 __dead static void
 usage_log(void)
 {
-	fprintf(stderr, "usage: %s log [-p] [-c commit] [ -l N ] "
+	fprintf(stderr, "usage: %s log [-pf] [-c commit] [ -l N ] "
 	    "[repository-path]\n", getprogname());
 	exit(1);
 }
@@ -440,7 +442,7 @@ cmd_log(int argc, char *argv[])
 	char *repo_path = NULL;
 	char *start_commit = NULL;
 	int ch;
-	int show_patch = 0, limit = 0, verbose = 0;
+	int show_patch = 0, limit = 0, verbose = 0, first_parent_traversal = 0;
 	const char *errstr;
 
 #ifndef PROFILE
@@ -448,7 +450,7 @@ cmd_log(int argc, char *argv[])
 		err(1, "pledge");
 #endif
 
-	while ((ch = getopt(argc, argv, "pc:l:v")) != -1) {
+	while ((ch = getopt(argc, argv, "pc:l:vf")) != -1) {
 		switch (ch) {
 		case 'p':
 			show_patch = 1;
@@ -463,6 +465,9 @@ cmd_log(int argc, char *argv[])
 			break;
 		case 'v':
 			verbose = 1;
+			break;
+		case 'f':
+			first_parent_traversal = 1;
 			break;
 		default:
 			usage();
@@ -511,7 +516,7 @@ cmd_log(int argc, char *argv[])
 		return error;
 	if (got_object_get_type(obj) == GOT_OBJ_TYPE_COMMIT)
 		error = print_commits(obj, id, repo, show_patch, limit,
-		    verbose);
+		    verbose, first_parent_traversal);
 	else
 		error = got_error(GOT_ERR_OBJ_TYPE);
 	got_object_close(obj);
blob - a480124dc389f0f0d1ba76dbb7d7361d8b73df5a
blob + 80e6b815ba4e77ffee25babcd23898cd5f4379db
--- include/got_commit_graph.h
+++ include/got_commit_graph.h
@@ -17,7 +17,7 @@
 struct got_commit_graph;
 
 const struct got_error *got_commit_graph_open(struct got_commit_graph **,
-    struct got_object_id *commit_id, struct got_repository *repo);
+    struct got_object_id *commit_id, int, struct got_repository *repo);
 void got_commit_graph_close(struct got_commit_graph *);
 
 const struct got_error *
blob - 5a88b2248a11ae2e2409eb51fe432efd450af467
blob + 9e8852e024353a395aff616e5276a04585dd2240
--- lib/commit_graph.c
+++ lib/commit_graph.c
@@ -64,6 +64,9 @@ struct got_commit_graph {
 	/* The commit at which traversal began (youngest commit in node_ids). */
 	struct got_commit_graph_node *head_node;
 
+	int flags;
+#define GOT_COMMIT_GRAPH_FIRST_PARENT_TRAVERSAL		0x01
+
 	/*
 	 * A set of object IDs of known parent commits which we have not yet
 	 * traversed. Each commit ID in this set represents a branch in commit
@@ -216,6 +219,41 @@ add_vertex(struct got_object_id_queue *ids, struct got
 	}
 
 	SIMPLEQ_INSERT_TAIL(ids, qid, entry);
+	return NULL;
+}
+
+static const struct got_error *
+advance_open_branches(struct got_commit_graph *graph,
+    struct got_commit_graph_node *node,
+    struct got_object_id *commit_id, struct got_commit_object *commit)
+{
+	const struct got_error *err;
+	struct got_object_qid *qid;
+
+	err = got_object_idset_remove(graph->open_branches, commit_id);
+	if (err && err->code != GOT_ERR_NO_OBJ)
+		return err;
+
+	if (graph->flags & GOT_COMMIT_GRAPH_FIRST_PARENT_TRAVERSAL) {
+		qid = SIMPLEQ_FIRST(&commit->parent_ids);
+		if (qid == NULL)
+			return NULL;
+		err = got_object_idset_add(NULL, graph->open_branches, qid->id,
+		    node);
+		if (err && err->code != GOT_ERR_OBJ_EXISTS)
+			return err;
+		return NULL;
+	}
+
+	SIMPLEQ_FOREACH(qid, &commit->parent_ids, entry) {
+		if (got_object_idset_get(graph->node_ids, qid->id))
+			continue; /* parent already traversed */
+		err = got_object_idset_add(NULL, graph->open_branches,
+		    qid->id, node);
+		if (err && err->code != GOT_ERR_OBJ_EXISTS)
+			return err;
+	}
+
 	return NULL;
 }
 
@@ -248,20 +286,8 @@ add_node(struct got_commit_graph_node **new_node,
 	err = got_object_idset_add((void **)(&existing_node),
 	    graph->node_ids, &node->id, node);
 	if (err == NULL) {
-		struct got_object_qid *qid;
-
 		add_node_to_iter_list(graph, node, child_node);
-		err = got_object_idset_remove(graph->open_branches, commit_id);
-		if (err && err->code != GOT_ERR_NO_OBJ)
-			return err;
-		SIMPLEQ_FOREACH(qid, &commit->parent_ids, entry) {
-			if (got_object_idset_get(graph->node_ids, qid->id))
-				continue; /* parent already traversed */
-			err = got_object_idset_add(NULL, graph->open_branches,
-			    qid->id, node);
-			if (err && err->code != GOT_ERR_OBJ_EXISTS)
-				return err;
-		}
+		err = advance_open_branches(graph, node, commit_id, commit);
 		*new_node = node;
 	} else if (err->code == GOT_ERR_OBJ_EXISTS) {
 		err = NULL;
@@ -296,7 +322,8 @@ add_node(struct got_commit_graph_node **new_node,
 
 const struct got_error *
 got_commit_graph_open(struct got_commit_graph **graph,
-    struct got_object_id *commit_id, struct got_repository *repo)
+    struct got_object_id *commit_id, int first_parent_traversal,
+    struct got_repository *repo)
 {
 	const struct got_error *err = NULL;
 	struct got_commit_object *commit;
@@ -313,6 +340,9 @@ got_commit_graph_open(struct got_commit_graph **graph,
 		return got_error_from_errno();
 	}
 
+	if (first_parent_traversal)
+		(*graph)->flags |= GOT_COMMIT_GRAPH_FIRST_PARENT_TRAVERSAL;
+
 	err = add_node(&(*graph)->head_node, *graph, commit_id, commit, NULL);
 	got_object_commit_close(commit);
 	if (err) {