commit - a7f506998d573165fb10a8552b2f48c72094001d
commit + 0ed6ed4ca7635b211a4b7a02bacfdec1255dc4bd
blob - 3bcc62f94215ced3a11d5b3b47ed4887026df706
blob + 5afbf1c50c8cbb247a5f9977463af9933c693768
--- got/got.1
+++ got/got.1
.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
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
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);
__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);
}
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
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;
break;
case 'v':
verbose = 1;
+ break;
+ case 'f':
+ first_parent_traversal = 1;
break;
default:
usage();
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
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
/* 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
}
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;
}
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;
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;
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) {