commit 0ed6ed4ca7635b211a4b7a02bacfdec1255dc4bd from: Stefan Sperling date: Wed Jun 13 16:29:04 2018 UTC got log: allow first-parent traversal with the commit graph 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) {