Home Explore Blog CI



git

4th chunk of `Documentation/MyFirstObjectWalk.adoc`
fcc3d1c8b18243102d2da63f25bd552061bdcaf4d519b50c0000000100000fa0


[NOTE]
====
Instead of using the shorthand `add_head_to_pending()`, you could do
something like this:

----
	struct setup_revision_opt opt;

	memset(&opt, 0, sizeof(opt));
	opt.def = "HEAD";
	opt.revarg_opt = REVARG_COMMITTISH;
	setup_revisions(argc, argv, rev, &opt);
----

Using a `setup_revision_opt` gives you finer control over your walk's starting
point.
====

Then let's invoke `final_rev_info_setup()` after the call to
`repo_init_revisions()`:

----
int cmd_walken(int argc, const char **argv, const char *prefix)
{
	...

	final_rev_info_setup(&rev);

	...
}
----

Later, we may wish to add more arguments to `final_rev_info_setup()`. But for
now, this is all we need.

==== Preparing `rev_info` For the Walk

Now that `rev` is all initialized and configured, we've got one more setup step
before we get rolling. We can do this in a helper, which will both prepare the
`rev_info` for the walk, and perform the walk itself. Let's start the helper
with the call to `prepare_revision_walk()`, which can return an error without
dying on its own:

----
static void walken_commit_walk(struct rev_info *rev)
{
	if (prepare_revision_walk(rev))
		die(_("revision walk setup failed"));
}
----

NOTE: `die()` prints to `stderr` and exits the program. Since it will print to
`stderr` it's likely to be seen by a human, so we will localize it.

==== Performing the Walk!

Finally! We are ready to begin the walk itself. Now we can see that `rev_info`
can also be used as an iterator; we move to the next item in the walk by using
`get_revision()` repeatedly. Add the listed variable declarations at the top and
the walk loop below the `prepare_revision_walk()` call within your
`walken_commit_walk()`:

----
#include "pretty.h"

...

static void walken_commit_walk(struct rev_info *rev)
{
	struct commit *commit;
	struct strbuf prettybuf = STRBUF_INIT;

	...

	while ((commit = get_revision(rev))) {
		strbuf_reset(&prettybuf);
		pp_commit_easy(CMIT_FMT_ONELINE, commit, &prettybuf);
		puts(prettybuf.buf);
	}
	strbuf_release(&prettybuf);
}
----

NOTE: `puts()` prints a `char*` to `stdout`. Since this is the part of the
command we expect to be machine-parsed, we're sending it directly to stdout.

Give it a shot.

----
$ make
$ ./bin-wrappers/git walken
----

You should see all of the subject lines of all the commits in
your tree's history, in order, ending with the initial commit, "Initial revision
of "git", the information manager from hell". Congratulations! You've written
your first revision walk. You can play with printing some additional fields
from each commit if you're curious; have a look at the functions available in
`commit.h`.

=== Adding a Filter

Next, let's try to filter the commits we see based on their author. This is
equivalent to running `git log --author=<pattern>`. We can add a filter by
modifying `rev_info.grep_filter`, which is a `struct grep_opt`.

First some setup. Add `grep_config()` to `git_walken_config()`:

----
static int git_walken_config(const char *var, const char *value,
			     const struct config_context *ctx, void *cb)
{
	grep_config(var, value, ctx, cb);
	return git_default_config(var, value, ctx, cb);
}
----

Next, we can modify the `grep_filter`. This is done with convenience functions
found in `grep.h`. For fun, we're filtering to only commits from folks using a
`gmail.com` email address - a not-very-precise guess at who may be working on
Git as a hobby. Since we're checking the author, which is a specific line in the
header, we'll use the `append_header_grep_pattern()` helper. We can use
the `enum grep_header_field` to indicate which part of the commit header we want
to search.

In `final_rev_info_setup()`, add your filter line:

----
static void final_rev_info_setup(int argc, const char **argv,
		const char *prefix, struct rev_info *rev)
{
	...

	append_header_grep_pattern(&rev->grep_filter, GREP_HEADER_AUTHOR,
		"gmail");
	compile_grep_patterns(&rev->grep_filter);

	...
}
----

`append_header_grep_pattern()` adds your new

Title: Performing a Revision Walk and Adding a Filter in Git
Summary
This section discusses performing a revision walk in Git, including preparing the `rev_info` object, performing the walk, and printing commit information, as well as adding a filter to the walk based on the author's email address using `grep_config` and `append_header_grep_pattern`.