Skip to content

Commit

Permalink
Add git-for-each-ref: helper for language bindings
Browse files Browse the repository at this point in the history
This adds a new command, git-for-each-ref.  You can have it iterate
over refs and have it output various aspects of the objects they
refer to.

Signed-off-by: Junio C Hamano <junkio@cox.net>
  • Loading branch information
Junio C Hamano committed Sep 16, 2006
1 parent e7676d2 commit 9f613dd
Show file tree
Hide file tree
Showing 10 changed files with 1,132 additions and 28 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ git-fetch
git-fetch-pack
git-findtags
git-fmt-merge-msg
git-for-each-ref
git-format-patch
git-fsck-objects
git-get-tar-commit-id
Expand Down
164 changes: 164 additions & 0 deletions Documentation/git-for-each-ref.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
git-for-each-ref(1)
===================

NAME
----
git-for-each-ref - Output information on each ref

SYNOPSIS
--------
'git-for-each-ref' [--count=<count>]* [--shell|--perl|--python] [--sort=<key>]* [--format=<format>] [<pattern>]

DESCRIPTION
-----------

Iterate over all refs that match `<pattern>` and show them
according to the given `<format>`, after sorting them according
to the given set of `<key>`s. If `<max>` is given, stop after
showing that many refs. The interporated values in `<format>`
can optionally be quoted as string literals in the specified
host language.

OPTIONS
-------
<count>::
By default the command shows all refs that match
`<pattern>`. This option makes it stop after showing
that many refs.

<key>::
A field name to sort on. Prefix `-` to sort in
descending order of the value. When unspecified,
`refname` is used. More than one sort keys can be
given.

<format>::
A string that interpolates `%(fieldname)` from the
object pointed at by a ref being shown. If `fieldname`
is prefixed with an asterisk (`*`) and the ref points
at a tag object, the value for the field in the object
tag refers is used. When unspecified, defaults to
`%(refname)`.

<pattern>::
If given, the name of the ref is matched against this
using fnmatch(3). Refs that do not match the pattern
are not shown.

--shell, --perl, --python::
If given, strings that substitute `%(fieldname)`
placeholders are quoted as string literals suitable for
the specified host language. This is meant to produce
a scriptlet that can directly be `eval`ed.


FIELD NAMES
-----------

Various values from structured fields in referenced objects can
be used to interpolate into the resulting output, or as sort
keys.

For all objects, the following names can be used:

refname::
The name of the ref (the part after $GIT_DIR/refs/).

objecttype::
The type of the object (`blob`, `tree`, `commit`, `tag`).

objectsize::
The size of the object (the same as `git-cat-file -s` reports).

objectname::
The object name (aka SHA-1).

In addition to the above, for commit and tag objects, the header
field names (`tree`, `parent`, `object`, `type`, and `tag`) can
be used to specify the value in the header field.

Fields that have name-email-date tuple as its value (`author`,
`committer`, and `tagger`) can be suffixed with `name`, `email`,
and `date` to extract the named component.

The first line of the message in a commit and tag object is
`subject`, the remaining lines are `body`. The whole message
is `contents`.

For sorting purposes, fields with numeric values sort in numeric
order (`objectsize`, `authordate`, `committerdate`, `taggerdate`).
All other fields are used to sort in their byte-value order.

In any case, a field name that refers to a field inapplicable to
the object referred by the ref does not cause an error. It
returns an empty string instead.


EXAMPLES
--------

Show the most recent 3 tagged commits::

------------
#!/bin/sh

git-for-each-ref --count=3 --sort='-*authordate' \
--format='From: %(*authorname) %(*authoremail)
Subject: %(*subject)
Date: %(*authordate)
Ref: %(*refname)

%(*body)
' 'refs/tags'
------------

A bit more elaborate report on tags::
------------
#!/bin/sh

fmt='
r=%(refname)
t=%(*objecttype)
T=${r#refs/tags/}

o=%(*objectname)
n=%(*authorname)
e=%(*authoremail)
s=%(*subject)
d=%(*authordate)
b=%(*body)

kind=Tag
if test "z$t" = z
then
# could be a lightweight tag
t=%(objecttype)
kind="Lightweight tag"
o=%(objectname)
n=%(authorname)
e=%(authoremail)
s=%(subject)
d=%(authordate)
b=%(body)
fi
echo "$kind $T points at a $t object $o"
if test "z$t" = zcommit
then
echo "The commit was authored by $n $e
at $d, and titled

$s

Its message reads as:
"
echo "$b" | sed -e "s/^/ /"
echo
fi
'

eval=`git-for-each-ref -s --format="$fmt" \
--sort='*objecttype' \
--sort=-taggerdate \
refs/tags`
eval "$eval"
------------
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ BUILTIN_OBJS = \
builtin-diff-stages.o \
builtin-diff-tree.o \
builtin-fmt-merge-msg.o \
builtin-for-each-ref.o \
builtin-grep.o \
builtin-init-db.o \
builtin-log.o \
Expand Down
Loading

0 comments on commit 9f613dd

Please sign in to comment.