From c7c833947ec7ac446761242c02d32916661daeb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Rub=C3=A9n?= Date: Fri, 21 Feb 2014 00:22:07 +0100 Subject: [PATCH 1/4] Add option to limit blame to first parent --- examples/blame.c | 5 +++++ include/git2/blame.h | 2 ++ src/blame_git.c | 6 ++++-- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/examples/blame.c b/examples/blame.c index 1f5db69a1..f04c41772 100644 --- a/examples/blame.c +++ b/examples/blame.c @@ -31,6 +31,7 @@ struct opts { int M; int start_line; int end_line; + int F; }; static void parse_opts(struct opts *o, int argc, char *argv[]); @@ -52,6 +53,7 @@ int main(int argc, char *argv[]) parse_opts(&o, argc, argv); if (o.M) blameopts.flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES; if (o.C) blameopts.flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_COPIES; + if (o.F) blameopts.flags |= GIT_BLAME_FIRST_PARENT; /** Open the repository. */ check_lg2(git_repository_open_ext(&repo, ".", 0, NULL), "Couldn't open repository", NULL); @@ -146,6 +148,7 @@ static void usage(const char *msg, const char *arg) fprintf(stderr, " -L process only line range n-m, counting from 1\n"); fprintf(stderr, " -M find line moves within and across files\n"); fprintf(stderr, " -C find line copies within and across files\n"); + fprintf(stderr, " -F only care about the first parent\n"); fprintf(stderr, "\n"); exit(1); } @@ -174,6 +177,8 @@ static void parse_opts(struct opts *o, int argc, char *argv[]) o->M = 1; else if (!strcasecmp(a, "-C")) o->C = 1; + else if (!strcasecmp(a, "-F")) + o->F = 1; else if (!strcasecmp(a, "-L")) { i++; a = argv[i]; if (i >= argc) fatal("Not enough arguments to -L", NULL); diff --git a/include/git2/blame.h b/include/git2/blame.h index b98c6f0d7..873a94ddd 100644 --- a/include/git2/blame.h +++ b/include/git2/blame.h @@ -40,6 +40,8 @@ typedef enum { * commit (like `git blame -CCC`). Implies SAME_COMMIT_COPIES. * NOT IMPLEMENTED. */ GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES = (1<<3), + + GIT_BLAME_FIRST_PARENT = (1<<4), } git_blame_flag_t; /** diff --git a/src/blame_git.c b/src/blame_git.c index 800f1f039..c275293c3 100644 --- a/src/blame_git.c +++ b/src/blame_git.c @@ -485,12 +485,14 @@ static void pass_blame(git_blame *blame, git_blame__origin *origin, uint32_t opt git_blame__origin *sg_buf[16]; git_blame__origin *porigin, **sg_origin = sg_buf; - GIT_UNUSED(opt); - num_parents = git_commit_parentcount(commit); if (!git_oid_cmp(git_commit_id(commit), &blame->options.oldest_commit)) /* Stop at oldest specified commit */ num_parents = 0; + else if (opt & GIT_BLAME_FIRST_PARENT) + /* Limit search to the first parent */ + num_parents = 1; + if (!num_parents) { git_oid_cpy(&blame->options.oldest_commit, git_commit_id(commit)); goto finish; From 9e3b901aeb3c3dc4b0bb442745ca59bb7e894f76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Rub=C3=A9n?= Date: Mon, 24 Feb 2014 00:09:29 +0100 Subject: [PATCH 2/4] Add unit test --- tests/blame/simple.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/blame/simple.c b/tests/blame/simple.c index 79bd56b83..18b3457af 100644 --- a/tests/blame/simple.c +++ b/tests/blame/simple.c @@ -303,3 +303,18 @@ void test_blame_simple__can_restrict_to_newish_commits(void) check_blame_hunk_index(g_repo, g_blame, 0, 1, 1, 1, "be3563a", "branch_file.txt"); check_blame_hunk_index(g_repo, g_blame, 1, 2, 1, 0, "a65fedf", "branch_file.txt"); } + +void test_blame_simple__can_restrict_to_first_parent_commits(void) +{ + git_blame_options opts = GIT_BLAME_OPTIONS_INIT; + opts.flags |= GIT_BLAME_FIRST_PARENT; + + cl_git_pass(git_repository_open(&g_repo, cl_fixture("blametest.git"))); + + cl_git_pass(git_blame_file(&g_blame, g_repo, "b.txt", &opts)); + cl_assert_equal_i(4, git_blame_get_hunk_count(g_blame)); + check_blame_hunk_index(g_repo, g_blame, 0, 1, 4, 0, "da237394", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 1, 5, 1, 0, "b99f7ac0", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 2, 6, 5, 0, "63d671eb", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 3, 11, 5, 0, "bc7c5ac2", "b.txt"); +} From 899bd19a62c10be929103542aabbf8585de8aecd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Rub=C3=A9n?= Date: Mon, 24 Feb 2014 21:20:57 +0100 Subject: [PATCH 3/4] Document enumerator and rewording --- examples/blame.c | 2 +- include/git2/blame.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/blame.c b/examples/blame.c index f04c41772..6bc0581ac 100644 --- a/examples/blame.c +++ b/examples/blame.c @@ -148,7 +148,7 @@ static void usage(const char *msg, const char *arg) fprintf(stderr, " -L process only line range n-m, counting from 1\n"); fprintf(stderr, " -M find line moves within and across files\n"); fprintf(stderr, " -C find line copies within and across files\n"); - fprintf(stderr, " -F only care about the first parent\n"); + fprintf(stderr, " -F follow only the first parent commits\n"); fprintf(stderr, "\n"); exit(1); } diff --git a/include/git2/blame.h b/include/git2/blame.h index 873a94ddd..4ad51ee50 100644 --- a/include/git2/blame.h +++ b/include/git2/blame.h @@ -40,7 +40,8 @@ typedef enum { * commit (like `git blame -CCC`). Implies SAME_COMMIT_COPIES. * NOT IMPLEMENTED. */ GIT_BLAME_TRACK_COPIES_ANY_COMMIT_COPIES = (1<<3), - + /** Restrict the search of commits to those reachable following only the + * first parents. */ GIT_BLAME_FIRST_PARENT = (1<<4), } git_blame_flag_t; From 0276f0f55bf24dc5e0f49612106c1091381033f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Rub=C3=A9n?= Date: Wed, 26 Feb 2014 19:22:19 +0100 Subject: [PATCH 4/4] Reset num_parents to 1 only for merge commits Also, correct test case to account for the boundary flag --- src/blame_git.c | 2 +- tests/blame/simple.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/blame_git.c b/src/blame_git.c index c275293c3..72afb852b 100644 --- a/src/blame_git.c +++ b/src/blame_git.c @@ -489,7 +489,7 @@ static void pass_blame(git_blame *blame, git_blame__origin *origin, uint32_t opt if (!git_oid_cmp(git_commit_id(commit), &blame->options.oldest_commit)) /* Stop at oldest specified commit */ num_parents = 0; - else if (opt & GIT_BLAME_FIRST_PARENT) + else if (opt & GIT_BLAME_FIRST_PARENT && num_parents > 1) /* Limit search to the first parent */ num_parents = 1; diff --git a/tests/blame/simple.c b/tests/blame/simple.c index 18b3457af..11ff4cd19 100644 --- a/tests/blame/simple.c +++ b/tests/blame/simple.c @@ -314,7 +314,7 @@ void test_blame_simple__can_restrict_to_first_parent_commits(void) cl_git_pass(git_blame_file(&g_blame, g_repo, "b.txt", &opts)); cl_assert_equal_i(4, git_blame_get_hunk_count(g_blame)); check_blame_hunk_index(g_repo, g_blame, 0, 1, 4, 0, "da237394", "b.txt"); - check_blame_hunk_index(g_repo, g_blame, 1, 5, 1, 0, "b99f7ac0", "b.txt"); + check_blame_hunk_index(g_repo, g_blame, 1, 5, 1, 1, "b99f7ac0", "b.txt"); check_blame_hunk_index(g_repo, g_blame, 2, 6, 5, 0, "63d671eb", "b.txt"); check_blame_hunk_index(g_repo, g_blame, 3, 11, 5, 0, "bc7c5ac2", "b.txt"); }