Commit 4b91f058f673a3392481753a89f606317ade480f

Etienne Samson 2019-08-21T19:43:06

revwalk: expose more ways of scheduling commits Before we can tweak the revwalk to be more efficent when negotiating, we need to add an "insertion mode" option. Since there's already an implicit set of those, make it visible, at least privately.

diff --git a/src/revwalk.c b/src/revwalk.c
index 935bd4d..38f4083 100644
--- a/src/revwalk.c
+++ b/src/revwalk.c
@@ -38,7 +38,7 @@ git_commit_list_node *git_revwalk__commit_lookup(
 	return commit;
 }
 
-static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting, int from_glob)
+int git_revwalk__push_commit(git_revwalk *walk, const git_oid *oid, const git_revwalk__push_options *opts)
 {
 	git_oid commit_id;
 	int error;
@@ -54,7 +54,7 @@ static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting,
 
 	if (error == GIT_ENOTFOUND || error == GIT_EINVALIDSPEC || error == GIT_EPEEL) {
 		/* If this comes from e.g. push_glob("tags"), ignore this */
-		if (from_glob)
+		if (opts->from_glob)
 			return 0;
 
 		git_error_set(GIT_ERROR_INVALID, "object is not a committish");
@@ -74,14 +74,14 @@ static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting,
 	if (commit->uninteresting)
 		return 0;
 
-	if (uninteresting) {
+	if (opts->uninteresting) {
 		walk->limited = 1;
 		walk->did_hide = 1;
 	} else {
 		walk->did_push = 1;
 	}
 
-	commit->uninteresting = uninteresting;
+	commit->uninteresting = opts->uninteresting;
 	list = walk->user_input;
 	if (git_commit_list_insert(commit, &list) == NULL) {
 		git_error_set_oom();
@@ -95,29 +95,36 @@ static int push_commit(git_revwalk *walk, const git_oid *oid, int uninteresting,
 
 int git_revwalk_push(git_revwalk *walk, const git_oid *oid)
 {
+	git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
+
 	assert(walk && oid);
-	return push_commit(walk, oid, 0, false);
+
+	return git_revwalk__push_commit(walk, oid, &opts);
 }
 
 
 int git_revwalk_hide(git_revwalk *walk, const git_oid *oid)
 {
+	git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
 	assert(walk && oid);
-	return push_commit(walk, oid, 1, false);
+
+	opts.uninteresting = 1;
+	return git_revwalk__push_commit(walk, oid, &opts);
 }
 
-static int push_ref(git_revwalk *walk, const char *refname, int hide, int from_glob)
+int git_revwalk__push_ref(git_revwalk *walk, const char *refname, const git_revwalk__push_options *opts)
 {
 	git_oid oid;
 
 	if (git_reference_name_to_id(&oid, walk->repo, refname) < 0)
 		return -1;
 
-	return push_commit(walk, &oid, hide, from_glob);
+	return git_revwalk__push_commit(walk, &oid, opts);
 }
 
-static int push_glob(git_revwalk *walk, const char *glob, int hide)
+int git_revwalk__push_glob(git_revwalk *walk, const char *glob, const git_revwalk__push_options *given_opts)
 {
+	git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
 	int error = 0;
 	git_buf buf = GIT_BUF_INIT;
 	git_reference *ref;
@@ -126,6 +133,9 @@ static int push_glob(git_revwalk *walk, const char *glob, int hide)
 
 	assert(walk && glob);
 
+	if (given_opts)
+		memcpy(&opts, given_opts, sizeof(opts));
+
 	/* refs/ is implied if not given in the glob */
 	if (git__prefixcmp(glob, GIT_REFS_DIR) != 0)
 		git_buf_joinpath(&buf, GIT_REFS_DIR, glob);
@@ -141,8 +151,9 @@ static int push_glob(git_revwalk *walk, const char *glob, int hide)
 	if ((error = git_reference_iterator_glob_new(&iter, walk->repo, buf.ptr)) < 0)
 		goto out;
 
+	opts.from_glob = true;
 	while ((error = git_reference_next(&ref, iter)) == 0) {
-		error = push_ref(walk, git_reference_name(ref), hide, true);
+		error = git_revwalk__push_ref(walk, git_reference_name(ref), &opts);
 		git_reference_free(ref);
 		if (error < 0)
 			break;
@@ -158,36 +169,49 @@ out:
 
 int git_revwalk_push_glob(git_revwalk *walk, const char *glob)
 {
+	git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
 	assert(walk && glob);
-	return push_glob(walk, glob, 0);
+
+	return git_revwalk__push_glob(walk, glob, &opts);
 }
 
 int git_revwalk_hide_glob(git_revwalk *walk, const char *glob)
 {
+	git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
 	assert(walk && glob);
-	return push_glob(walk, glob, 1);
+
+	opts.uninteresting = 1;
+	return git_revwalk__push_glob(walk, glob, &opts);
 }
 
 int git_revwalk_push_head(git_revwalk *walk)
 {
+	git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
 	assert(walk);
-	return push_ref(walk, GIT_HEAD_FILE, 0, false);
+
+	return git_revwalk__push_ref(walk, GIT_HEAD_FILE, &opts);
 }
 
 int git_revwalk_hide_head(git_revwalk *walk)
 {
+	git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
 	assert(walk);
-	return push_ref(walk, GIT_HEAD_FILE, 1, false);
+
+	opts.uninteresting = 1;
+	return git_revwalk__push_ref(walk, GIT_HEAD_FILE, &opts);
 }
 
 int git_revwalk_push_ref(git_revwalk *walk, const char *refname)
 {
+	git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
 	assert(walk && refname);
-	return push_ref(walk, refname, 0, false);
+
+	return git_revwalk__push_ref(walk, refname, &opts);
 }
 
 int git_revwalk_push_range(git_revwalk *walk, const char *range)
 {
+	git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
 	git_revspec revspec;
 	int error = 0;
 
@@ -207,10 +231,12 @@ int git_revwalk_push_range(git_revwalk *walk, const char *range)
 		goto out;
 	}
 
-	if ((error = push_commit(walk, git_object_id(revspec.from), 1, false)))
+	opts.uninteresting = 1;
+	if ((error = git_revwalk__push_commit(walk, git_object_id(revspec.from), &opts)))
 		goto out;
 
-	error = push_commit(walk, git_object_id(revspec.to), 0, false);
+	opts.uninteresting = 0;
+	error = git_revwalk__push_commit(walk, git_object_id(revspec.to), &opts);
 
 out:
 	git_object_free(revspec.from);
@@ -220,8 +246,10 @@ out:
 
 int git_revwalk_hide_ref(git_revwalk *walk, const char *refname)
 {
+	git_revwalk__push_options opts = GIT_REVWALK__PUSH_OPTIONS_INIT;
 	assert(walk && refname);
-	return push_ref(walk, refname, 1, false);
+	opts.uninteresting = 1;
+	return git_revwalk__push_ref(walk, refname, &opts);
 }
 
 static int revwalk_enqueue_timesort(git_revwalk *walk, git_commit_list_node *commit)
diff --git a/src/revwalk.h b/src/revwalk.h
index 923a2bc..852ab8b 100644
--- a/src/revwalk.h
+++ b/src/revwalk.h
@@ -50,4 +50,23 @@ struct git_revwalk {
 
 git_commit_list_node *git_revwalk__commit_lookup(git_revwalk *walk, const git_oid *oid);
 
+typedef struct {
+	int uninteresting;
+	int from_glob;
+} git_revwalk__push_options;
+
+#define GIT_REVWALK__PUSH_OPTIONS_INIT { 0 }
+
+int git_revwalk__push_commit(git_revwalk *walk,
+	const git_oid *oid,
+	const git_revwalk__push_options *opts);
+
+int git_revwalk__push_ref(git_revwalk *walk,
+	const char *refname,
+	const git_revwalk__push_options *opts);
+
+int git_revwalk__push_glob(git_revwalk *walk,
+	const char *glob,
+	const git_revwalk__push_options *given_opts);
+
 #endif