mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-29 12:24:11 +00:00
Merge pull request #2094 from libgit2/cmn/push-non-commit
Add flexibility to the revwalk API
This commit is contained in:
commit
df70de071a
@ -87,7 +87,7 @@ GIT_EXTERN(void) git_revwalk_reset(git_revwalk *walker);
|
|||||||
/**
|
/**
|
||||||
* Mark a commit to start traversal from.
|
* Mark a commit to start traversal from.
|
||||||
*
|
*
|
||||||
* The given OID must belong to a commit on the walked
|
* The given OID must belong to a committish on the walked
|
||||||
* repository.
|
* repository.
|
||||||
*
|
*
|
||||||
* The given commit will be used as one of the roots
|
* The given commit will be used as one of the roots
|
||||||
@ -110,6 +110,9 @@ GIT_EXTERN(int) git_revwalk_push(git_revwalk *walk, const git_oid *id);
|
|||||||
* A leading 'refs/' is implied if not present as well as a trailing
|
* A leading 'refs/' is implied if not present as well as a trailing
|
||||||
* '/\*' if the glob lacks '?', '\*' or '['.
|
* '/\*' if the glob lacks '?', '\*' or '['.
|
||||||
*
|
*
|
||||||
|
* Any references matching this glob which do not point to a
|
||||||
|
* committish will be ignored.
|
||||||
|
*
|
||||||
* @param walk the walker being used for the traversal
|
* @param walk the walker being used for the traversal
|
||||||
* @param glob the glob pattern references should match
|
* @param glob the glob pattern references should match
|
||||||
* @return 0 or an error code
|
* @return 0 or an error code
|
||||||
@ -127,7 +130,7 @@ GIT_EXTERN(int) git_revwalk_push_head(git_revwalk *walk);
|
|||||||
/**
|
/**
|
||||||
* Mark a commit (and its ancestors) uninteresting for the output.
|
* Mark a commit (and its ancestors) uninteresting for the output.
|
||||||
*
|
*
|
||||||
* The given OID must belong to a commit on the walked
|
* The given OID must belong to a committish on the walked
|
||||||
* repository.
|
* repository.
|
||||||
*
|
*
|
||||||
* The resolved commit and all its parents will be hidden from the
|
* The resolved commit and all its parents will be hidden from the
|
||||||
@ -149,6 +152,9 @@ GIT_EXTERN(int) git_revwalk_hide(git_revwalk *walk, const git_oid *commit_id);
|
|||||||
* A leading 'refs/' is implied if not present as well as a trailing
|
* A leading 'refs/' is implied if not present as well as a trailing
|
||||||
* '/\*' if the glob lacks '?', '\*' or '['.
|
* '/\*' if the glob lacks '?', '\*' or '['.
|
||||||
*
|
*
|
||||||
|
* Any references matching this glob which do not point to a
|
||||||
|
* committish will be ignored.
|
||||||
|
*
|
||||||
* @param walk the walker being used for the traversal
|
* @param walk the walker being used for the traversal
|
||||||
* @param glob the glob pattern references should match
|
* @param glob the glob pattern references should match
|
||||||
* @return 0 or an error code
|
* @return 0 or an error code
|
||||||
@ -166,7 +172,7 @@ GIT_EXTERN(int) git_revwalk_hide_head(git_revwalk *walk);
|
|||||||
/**
|
/**
|
||||||
* Push the OID pointed to by a reference
|
* Push the OID pointed to by a reference
|
||||||
*
|
*
|
||||||
* The reference must point to a commit.
|
* The reference must point to a committish.
|
||||||
*
|
*
|
||||||
* @param walk the walker being used for the traversal
|
* @param walk the walker being used for the traversal
|
||||||
* @param refname the reference to push
|
* @param refname the reference to push
|
||||||
@ -177,7 +183,7 @@ GIT_EXTERN(int) git_revwalk_push_ref(git_revwalk *walk, const char *refname);
|
|||||||
/**
|
/**
|
||||||
* Hide the OID pointed to by a reference
|
* Hide the OID pointed to by a reference
|
||||||
*
|
*
|
||||||
* The reference must point to a commit.
|
* The reference must point to a committish.
|
||||||
*
|
*
|
||||||
* @param walk the walker being used for the traversal
|
* @param walk the walker being used for the traversal
|
||||||
* @param refname the reference to hide
|
* @param refname the reference to hide
|
||||||
|
@ -490,8 +490,7 @@ static int handle_grep_syntax(git_object **out, git_repository *repo, const git_
|
|||||||
git_revwalk_sorting(walk, GIT_SORT_TIME);
|
git_revwalk_sorting(walk, GIT_SORT_TIME);
|
||||||
|
|
||||||
if (spec_oid == NULL) {
|
if (spec_oid == NULL) {
|
||||||
// TODO: @carlosmn: The glob should be refs/* but this makes git_revwalk_next() fails
|
if ((error = git_revwalk_push_glob(walk, "refs/*")) < 0)
|
||||||
if ((error = git_revwalk_push_glob(walk, GIT_REFS_HEADS_DIR "*")) < 0)
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
} else if ((error = git_revwalk_push(walk, spec_oid)) < 0)
|
} else if ((error = git_revwalk_push(walk, spec_oid)) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
@ -110,25 +110,34 @@ static int process_commit_parents(git_revwalk *walk, git_commit_list_node *commi
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting)
|
static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting, int from_glob)
|
||||||
{
|
{
|
||||||
|
git_oid commit_id;
|
||||||
int error;
|
int error;
|
||||||
git_object *obj;
|
git_object *obj, *oobj;
|
||||||
git_otype type;
|
|
||||||
git_commit_list_node *commit;
|
git_commit_list_node *commit;
|
||||||
|
|
||||||
if ((error = git_object_lookup(&obj, walk->repo, oid, GIT_OBJ_ANY)) < 0)
|
if ((error = git_object_lookup(&oobj, walk->repo, oid, GIT_OBJ_ANY)) < 0)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
type = git_object_type(obj);
|
error = git_object_peel(&obj, oobj, GIT_OBJ_COMMIT);
|
||||||
git_object_free(obj);
|
git_object_free(oobj);
|
||||||
|
|
||||||
if (type != GIT_OBJ_COMMIT) {
|
if (error == GIT_ENOTFOUND) {
|
||||||
giterr_set(GITERR_INVALID, "Object is no commit object");
|
/* If this comes from e.g. push_glob("tags"), ignore this */
|
||||||
|
if (from_glob)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
giterr_set(GITERR_INVALID, "Object is not a committish");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (error < 0)
|
||||||
|
return error;
|
||||||
|
|
||||||
commit = git_revwalk__commit_lookup(walk, oid);
|
git_oid_cpy(&commit_id, git_object_id(obj));
|
||||||
|
git_object_free(obj);
|
||||||
|
|
||||||
|
commit = git_revwalk__commit_lookup(walk, &commit_id);
|
||||||
if (commit == NULL)
|
if (commit == NULL)
|
||||||
return -1; /* error already reported by failed lookup */
|
return -1; /* error already reported by failed lookup */
|
||||||
|
|
||||||
@ -146,24 +155,24 @@ static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting)
|
|||||||
int git_revwalk_push(git_revwalk *walk, const git_oid *oid)
|
int git_revwalk_push(git_revwalk *walk, const git_oid *oid)
|
||||||
{
|
{
|
||||||
assert(walk && oid);
|
assert(walk && oid);
|
||||||
return push_commit(walk, oid, 0);
|
return push_commit(walk, oid, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int git_revwalk_hide(git_revwalk *walk, const git_oid *oid)
|
int git_revwalk_hide(git_revwalk *walk, const git_oid *oid)
|
||||||
{
|
{
|
||||||
assert(walk && oid);
|
assert(walk && oid);
|
||||||
return push_commit(walk, oid, 1);
|
return push_commit(walk, oid, 1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int push_ref(git_revwalk *walk, const char *refname, int hide)
|
static int push_ref(git_revwalk *walk, const char *refname, int hide, int from_glob)
|
||||||
{
|
{
|
||||||
git_oid oid;
|
git_oid oid;
|
||||||
|
|
||||||
if (git_reference_name_to_id(&oid, walk->repo, refname) < 0)
|
if (git_reference_name_to_id(&oid, walk->repo, refname) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return push_commit(walk, &oid, hide);
|
return push_commit(walk, &oid, hide, from_glob);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct push_cb_data {
|
struct push_cb_data {
|
||||||
@ -171,17 +180,12 @@ struct push_cb_data {
|
|||||||
int hide;
|
int hide;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int push_glob_cb(const char *refname, void *data_)
|
|
||||||
{
|
|
||||||
struct push_cb_data *data = (struct push_cb_data *)data_;
|
|
||||||
return push_ref(data->walk, refname, data->hide);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int push_glob(git_revwalk *walk, const char *glob, int hide)
|
static int push_glob(git_revwalk *walk, const char *glob, int hide)
|
||||||
{
|
{
|
||||||
int error = 0;
|
int error = 0;
|
||||||
git_buf buf = GIT_BUF_INIT;
|
git_buf buf = GIT_BUF_INIT;
|
||||||
struct push_cb_data data;
|
git_reference *ref;
|
||||||
|
git_reference_iterator *iter;
|
||||||
size_t wildcard;
|
size_t wildcard;
|
||||||
|
|
||||||
assert(walk && glob);
|
assert(walk && glob);
|
||||||
@ -199,12 +203,20 @@ static int push_glob(git_revwalk *walk, const char *glob, int hide)
|
|||||||
if (!glob[wildcard])
|
if (!glob[wildcard])
|
||||||
git_buf_put(&buf, "/*", 2);
|
git_buf_put(&buf, "/*", 2);
|
||||||
|
|
||||||
data.walk = walk;
|
if ((error = git_reference_iterator_glob_new(&iter, walk->repo, buf.ptr)) < 0)
|
||||||
data.hide = hide;
|
goto out;
|
||||||
|
|
||||||
error = git_reference_foreach_glob(
|
while ((error = git_reference_next(&ref, iter)) == 0) {
|
||||||
walk->repo, git_buf_cstr(&buf), push_glob_cb, &data);
|
error = push_ref(walk, git_reference_name(ref), hide, true);
|
||||||
|
git_reference_free(ref);
|
||||||
|
if (error < 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
git_reference_iterator_free(iter);
|
||||||
|
|
||||||
|
if (error == GIT_ITEROVER)
|
||||||
|
error = 0;
|
||||||
|
out:
|
||||||
git_buf_free(&buf);
|
git_buf_free(&buf);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@ -224,19 +236,19 @@ int git_revwalk_hide_glob(git_revwalk *walk, const char *glob)
|
|||||||
int git_revwalk_push_head(git_revwalk *walk)
|
int git_revwalk_push_head(git_revwalk *walk)
|
||||||
{
|
{
|
||||||
assert(walk);
|
assert(walk);
|
||||||
return push_ref(walk, GIT_HEAD_FILE, 0);
|
return push_ref(walk, GIT_HEAD_FILE, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_revwalk_hide_head(git_revwalk *walk)
|
int git_revwalk_hide_head(git_revwalk *walk)
|
||||||
{
|
{
|
||||||
assert(walk);
|
assert(walk);
|
||||||
return push_ref(walk, GIT_HEAD_FILE, 1);
|
return push_ref(walk, GIT_HEAD_FILE, 1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_revwalk_push_ref(git_revwalk *walk, const char *refname)
|
int git_revwalk_push_ref(git_revwalk *walk, const char *refname)
|
||||||
{
|
{
|
||||||
assert(walk && refname);
|
assert(walk && refname);
|
||||||
return push_ref(walk, refname, 0);
|
return push_ref(walk, refname, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_revwalk_push_range(git_revwalk *walk, const char *range)
|
int git_revwalk_push_range(git_revwalk *walk, const char *range)
|
||||||
@ -253,10 +265,10 @@ int git_revwalk_push_range(git_revwalk *walk, const char *range)
|
|||||||
return GIT_EINVALIDSPEC;
|
return GIT_EINVALIDSPEC;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((error = push_commit(walk, git_object_id(revspec.from), 1)))
|
if ((error = push_commit(walk, git_object_id(revspec.from), 1, false)))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
error = push_commit(walk, git_object_id(revspec.to), 0);
|
error = push_commit(walk, git_object_id(revspec.to), 0, false);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
git_object_free(revspec.from);
|
git_object_free(revspec.from);
|
||||||
@ -267,7 +279,7 @@ out:
|
|||||||
int git_revwalk_hide_ref(git_revwalk *walk, const char *refname)
|
int git_revwalk_hide_ref(git_revwalk *walk, const char *refname)
|
||||||
{
|
{
|
||||||
assert(walk && refname);
|
assert(walk && refname);
|
||||||
return push_ref(walk, refname, 1);
|
return push_ref(walk, refname, 1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int revwalk_enqueue_timesort(git_revwalk *walk, git_commit_list_node *commit)
|
static int revwalk_enqueue_timesort(git_revwalk *walk, git_commit_list_node *commit)
|
||||||
|
@ -252,3 +252,41 @@ void test_revwalk_basic__push_range(void)
|
|||||||
cl_git_pass(git_revwalk_push_range(_walk, "9fd738e~2..9fd738e"));
|
cl_git_pass(git_revwalk_push_range(_walk, "9fd738e~2..9fd738e"));
|
||||||
cl_git_pass(test_walk_only(_walk, commit_sorting_segment, 1));
|
cl_git_pass(test_walk_only(_walk, commit_sorting_segment, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_revwalk_basic__push_mixed(void)
|
||||||
|
{
|
||||||
|
git_oid oid;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
revwalk_basic_setup_walk(NULL);
|
||||||
|
|
||||||
|
git_revwalk_reset(_walk);
|
||||||
|
git_revwalk_sorting(_walk, 0);
|
||||||
|
cl_git_pass(git_revwalk_push_glob(_walk, "tags"));
|
||||||
|
|
||||||
|
while (git_revwalk_next(&oid, _walk) == 0) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* git rev-list --count --glob=tags #=> 9 */
|
||||||
|
cl_assert_equal_i(9, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_revwalk_basic__push_all(void)
|
||||||
|
{
|
||||||
|
git_oid oid;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
revwalk_basic_setup_walk(NULL);
|
||||||
|
|
||||||
|
git_revwalk_reset(_walk);
|
||||||
|
git_revwalk_sorting(_walk, 0);
|
||||||
|
cl_git_pass(git_revwalk_push_glob(_walk, "*"));
|
||||||
|
|
||||||
|
while (git_revwalk_next(&oid, _walk) == 0) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* git rev-list --count --all #=> 15 */
|
||||||
|
cl_assert_equal_i(15, i);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user