diff --git a/include/git2/revwalk.h b/include/git2/revwalk.h index 0af80625e..8bfe0b502 100644 --- a/include/git2/revwalk.h +++ b/include/git2/revwalk.h @@ -216,6 +216,21 @@ GIT_EXTERN(int) git_revwalk_next(git_oid *out, git_revwalk *walk); */ GIT_EXTERN(void) git_revwalk_sorting(git_revwalk *walk, unsigned int sort_mode); +/** + * Push and hide the respective endpoints of the given range. + * + * The range should be of the form + * .. + * where each is in the form accepted by 'git_revparse_single'. + * The left-hand commit will be hidden and the right-hand commit pushed. + * + * @param walk the walker being used for the traversal + * @param range the range + * @return 0 or an error code + * + */ +GIT_EXTERN(int) git_revwalk_push_range(git_revwalk *walk, const char *range); + /** * Free a revision walker previously allocated. * diff --git a/src/revwalk.c b/src/revwalk.c index 02834ab36..c1071843b 100644 --- a/src/revwalk.c +++ b/src/revwalk.c @@ -11,6 +11,7 @@ #include "pool.h" #include "revwalk.h" +#include "git2/revparse.h" #include "merge.h" #include @@ -228,6 +229,30 @@ int git_revwalk_push_ref(git_revwalk *walk, const char *refname) return push_ref(walk, refname, 0); } +int git_revwalk_push_range(git_revwalk *walk, const char *range) +{ + git_object *left, *right; + int threedots; + int error = 0; + + if ((error = git_revparse_rangelike(&left, &right, &threedots, walk->repo, range))) + return error; + if (threedots) { + /* TODO: support "..." */ + giterr_set(GITERR_INVALID, "Symmetric differences not implemented in revwalk"); + return GIT_EINVALIDSPEC; + } + + if ((error = push_commit(walk, git_object_id(left), 1))) + goto out; + error = push_commit(walk, git_object_id(right), 0); + + out: + git_object_free(left); + git_object_free(right); + return error; +} + int git_revwalk_hide_ref(git_revwalk *walk, const char *refname) { assert(walk && refname); diff --git a/tests-clar/revwalk/basic.c b/tests-clar/revwalk/basic.c index 2f1f817c9..e82776260 100644 --- a/tests-clar/revwalk/basic.c +++ b/tests-clar/revwalk/basic.c @@ -38,6 +38,10 @@ static const int commit_sorting_time_reverse[][6] = { {4, 5, 2, 1, 3, 0} }; +static const int commit_sorting_segment[][6] = { + {1, 2, -1, -1, -1, -1} +}; + #define commit_count 6 static const int result_bytes = 24; @@ -192,3 +196,11 @@ void test_revwalk_basic__disallow_non_commit(void) cl_git_pass(git_oid_fromstr(&oid, "521d87c1ec3aef9824daf6d96cc0ae3710766d91")); cl_git_fail(git_revwalk_push(_walk, &oid)); } + +void test_revwalk_basic__push_range(void) +{ + git_revwalk_reset(_walk); + git_revwalk_sorting(_walk, 0); + cl_git_pass(git_revwalk_push_range(_walk, "9fd738e~2..9fd738e")); + cl_git_pass(test_walk_only(_walk, commit_sorting_segment, 1)); +}