summaryrefslogtreecommitdiff
path: root/commit.c
AgeCommit message (Collapse)AuthorFilesLines
2016-08-19Merge branch 'rs/pull-signed-tag'Libravatar Junio C Hamano1-7/+11
When "git merge-recursive" works on history with many criss-cross merges in "verbose" mode, the names the command assigns to the virtual merge bases could have overwritten each other by unintended reuse of the same piece of memory. * rs/pull-signed-tag: commit: use FLEX_ARRAY in struct merge_remote_desc merge-recursive: fix verbose output for multiple base trees commit: factor out set_merge_remote_desc() commit: use xstrdup() in get_merge_parent()
2016-08-13commit: use FLEX_ARRAY in struct merge_remote_descLibravatar René Scharfe1-2/+1
Convert the name member of struct merge_remote_desc to a FLEX_ARRAY and use FLEX_ALLOC_STR to build the struct. This halves the number of memory allocations, saves the storage for a pointer and avoids an indirection when reading the name. Suggested-by: Jeff King <peff@peff.net> Signed-off-by: Rene Scharfe <l.s.r@web.de> Reviewed-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-08-13commit: factor out set_merge_remote_desc()Libravatar René Scharfe1-7/+12
Export a helper function for allocating, populating and attaching a merge_remote_desc to a commit. Signed-off-by: Rene Scharfe <l.s.r@web.de> Reviewed-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-08-13commit: use xstrdup() in get_merge_parent()Libravatar René Scharfe1-1/+1
Handle allocation errors for the name member just like we already do for the struct merge_remote_desc itself. Signed-off-by: Rene Scharfe <l.s.r@web.de> Reviewed-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-07-28Merge branch 'js/sign-empty-commit-fix' into maintLibravatar Junio C Hamano1-1/+6
"git commit --amend --allow-empty-message -S" for a commit without any message body could have misidentified where the header of the commit object ends. * js/sign-empty-commit-fix: commit -S: avoid invalid pointer with empty message
2016-07-28Merge branch 'js/find-commit-subject-ignore-leading-blanks' into maintLibravatar Junio C Hamano1-1/+1
A helper function that takes the contents of a commit object and finds its subject line did not ignore leading blank lines, as is commonly done by other codepaths. Make it ignore leading blank lines to match. * js/find-commit-subject-ignore-leading-blanks: reset --hard: skip blank lines when reporting the commit subject sequencer: use skip_blank_lines() to find the commit subject commit -C: skip blank lines at the beginning of the message commit.c: make find_commit_subject() more robust pretty: make the skip_blank_lines() function public
2016-07-19Merge branch 'jk/printf-format'Libravatar Junio C Hamano1-10/+0
Code clean-up to avoid using a variable string that compilers may feel untrustable as printf-style format given to write_file() helper function. * jk/printf-format: commit.c: remove print_commit_list() avoid using sha1_to_hex output as printf format walker: let walker_say take arbitrary formats
2016-07-13Merge branch 'js/sign-empty-commit-fix'Libravatar Junio C Hamano1-1/+6
"git commit --amend --allow-empty-message -S" for a commit without any message body could have misidentified where the header of the commit object ends. * js/sign-empty-commit-fix: commit -S: avoid invalid pointer with empty message
2016-07-11Merge branch 'js/find-commit-subject-ignore-leading-blanks'Libravatar Junio C Hamano1-1/+1
A helper function that takes the contents of a commit object and finds its subject line did not ignore leading blank lines, as is commonly done by other codepaths. Make it ignore leading blank lines to match. * js/find-commit-subject-ignore-leading-blanks: reset --hard: skip blank lines when reporting the commit subject sequencer: use skip_blank_lines() to find the commit subject commit -C: skip blank lines at the beginning of the message commit.c: make find_commit_subject() more robust pretty: make the skip_blank_lines() function public
2016-07-08commit.c: remove print_commit_list()Libravatar Junio C Hamano1-10/+0
The helper function tries to offer a way to conveniently show the last one differently from others, presumably to allow you to say something like A, B, and C. while iterating over a list that has these three elements. However, there is only one caller, and it passes the same format string "%s\n" for both the last one and the other ones. Retire the helper function and update the caller with a simplified version. Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-06-29commit -S: avoid invalid pointer with empty messageLibravatar Johannes Schindelin1-1/+6
While it is not recommended, fsck.c says: Not having a body is not a crime [...] ... which means that we cannot assume that the commit buffer contains an empty line to separate header from body. A commit object with only a header without any body, not even without a blank line after the header, is valid. So let's tread carefully here. strstr("\n\n") may find nothing and return NULL. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-06-22commit.c: make find_commit_subject() more robustLibravatar Johannes Schindelin1-1/+1
Just like the pretty printing machinery, we should simply ignore blank lines at the beginning of the commit messages. This discrepancy was noticed when an early version of the rebase--helper produced commit objects with more than one empty line between the header and the commit message. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-02-22use st_add and st_mult for allocation size computationLibravatar Jeff King1-1/+1
If our size computation overflows size_t, we may allocate a much smaller buffer than we expected and overflow it. It's probably impossible to trigger an overflow in most of these sites in practice, but it is easy enough convert their additions and multiplications into overflow-checking variants. This may be fixing real bugs, and it makes auditing the code easier. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-02-22convert trivial cases to ALLOC_ARRAYLibravatar Jeff King1-1/+1
Each of these cases can be converted to use ALLOC_ARRAY or REALLOC_ARRAY, which has two advantages: 1. It automatically checks the array-size multiplication for overflow. 2. It always uses sizeof(*array) for the element-size, so that it can never go out of sync with the declared type of the array. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-12-11Merge branch 'rs/pop-commit' into maintLibravatar Junio C Hamano1-20/+7
Code simplification. * rs/pop-commit: use pop_commit() for consuming the first entry of a struct commit_list
2015-11-20Remove get_object_hash.Libravatar brian m. carlson1-6/+6
Convert all instances of get_object_hash to use an appropriate reference to the hash member of the oid member of struct object. This provides no functional change, as it is essentially a macro substitution. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Jeff King <peff@peff.net>
2015-11-20Convert struct object to object_idLibravatar brian m. carlson1-10/+10
struct object is one of the major data structures dealing with object IDs. Convert it to use struct object_id instead of an unsigned char array. Convert get_object_hash to refer to the new member as well. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Jeff King <peff@peff.net>
2015-11-20Add several uses of get_object_hash.Libravatar brian m. carlson1-6/+6
Convert most instances where the sha1 member of struct object is dereferenced to use get_object_hash. Most instances that are passed to functions that have versions taking struct object_id, such as get_sha1_hex/get_oid_hex, or instances that can be trivially converted to use struct object_id instead, are not converted. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Jeff King <peff@peff.net>
2015-10-30Merge branch 'rs/pop-commit'Libravatar Junio C Hamano1-20/+7
Code simplification. * rs/pop-commit: use pop_commit() for consuming the first entry of a struct commit_list
2015-10-26use pop_commit() for consuming the first entry of a struct commit_listLibravatar René Scharfe1-20/+7
Instead of open-coding the function pop_commit() just call it. This makes the intent clearer and reduces code size. Signed-off-by: Rene Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-08-03Merge branch 'jc/commit-slab'Libravatar Junio C Hamano1-8/+20
Memory use reduction when commit-slab facility is used to annotate sparsely (which is not recommended in the first place). * jc/commit-slab: commit-slab: introduce slabname##_peek() function
2015-08-03Merge branch 'bc/gpg-verify-raw'Libravatar Junio C Hamano1-15/+6
"git verify-tag" and "git verify-commit" have been taught to share more code, and then learned to optionally show the verification message from the underlying GPG implementation. * bc/gpg-verify-raw: verify-tag: add option to print raw gpg status information verify-commit: add option to print raw gpg status information gpg: centralize printing signature buffers gpg: centralize signature check verify-commit: add test for exit status on untrusted signature verify-tag: share code with verify-commit verify-tag: add tests
2015-06-25Merge branch 'jk/squelch-missing-link-warning-for-unreachable' into maintLibravatar Junio C Hamano1-2/+3
Recent "git prune" traverses young unreachable objects to safekeep old objects in the reachability chain from them, which sometimes caused error messages that are unnecessarily alarming. * jk/squelch-missing-link-warning-for-unreachable: suppress errors on missing UNINTERESTING links silence broken link warnings with revs->ignore_missing_links add quieter versions of parse_{tree,commit}
2015-06-22gpg: centralize signature checkLibravatar brian m. carlson1-2/+6
verify-commit and verify-tag both share a central codepath for verifying commits: check_signature. However, verify-tag exited successfully for untrusted signature, while verify-commit exited unsuccessfully. Centralize this signature check and make verify-commit adopt the older verify-tag behavior. This behavior is more logical anyway, as the signature is in fact valid, whether or not there's a path of trust to the author. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-22verify-tag: share code with verify-commitLibravatar brian m. carlson1-14/+1
verify-tag was executing an entirely different codepath than verify-commit, except for the underlying verify_signed_buffer. Move much of the code from check_commit_signature to a generic check_signature function and adjust both codepaths to call it. Update verify-tag to explicitly output the signature text, as we now call verify_signed_buffer with strbufs to catch the output, which prevents it from being printed automatically. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-06-11Merge branch 'jk/squelch-missing-link-warning-for-unreachable'Libravatar Junio C Hamano1-2/+3
Recent "git prune" traverses young unreachable objects to safekeep old objects in the reachability chain from them, which sometimes caused error messages that are unnecessarily alarming. * jk/squelch-missing-link-warning-for-unreachable: suppress errors on missing UNINTERESTING links silence broken link warnings with revs->ignore_missing_links add quieter versions of parse_{tree,commit}
2015-06-01add quieter versions of parse_{tree,commit}Libravatar Jeff King1-2/+3
When we call parse_commit, it will complain to stderr if the object does not exist or cannot be read. This means that we may produce useless error messages if this situation is expected (e.g., because the object is marked UNINTERESTING, or because revs->ignore_missing_links is set). We can fix this by adding a new "parse_X_gently" form that takes a flag to suppress the messages. The existing "parse_X" form is already gentle in the sense that it returns an error rather than dying, and we could in theory just add a "quiet" flag to it (with existing callers passing "0"). But doing it this way means we do not have to disturb existing callers. Note also that the new flag is "quiet_on_missing", and not just "quiet". We could add a flag to suppress _all_ errors, but besides being a more invasive change (we would have to pass the flag down to sub-functions, too), there is a good reason not to: we would never want to use it. Missing a linked object is expected in some circumstances, but it is never expected to have a malformed commit, or to get a tree when we wanted a commit. We should always complain about these corruptions. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-05-22commit-slab: introduce slabname##_peek() functionLibravatar Junio C Hamano1-8/+20
There is no API to ask "Does this commit have associated data in slab?". If an application wants to (1) parse just a few commits at the beginning of a process, (2) store data for only these commits, and then (3) start processing many commits, taking into account the data stored (for a few of them) in the slab, the application would use slabname##_at() to allocate a space to store data in (2), but there is no API other than slabname##_at() to use in step (3). This allocates and wastes new space for these commits the caller is only interested in checking if they have data stored in step (2). Introduce slabname##_peek(), which is similar to slabname##_at() but returns NULL when there is no data already associated to it in such a use case. Helped-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-03-13commit: convert parts to struct object_idLibravatar brian m. carlson1-26/+30
Convert struct commit_graft and necessary local parts of commit.c. Also, convert several constants based on the hex length of an SHA-1 to use GIT_SHA1_HEXSZ, and move several magic constants into variables for readability. Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2015-01-07Merge branch 'jc/merge-bases'Libravatar Junio C Hamano1-8/+21
The get_merge_bases*() API was easy to misuse by careless copy&paste coders, leaving object flags tainted in the commits that needed to be traversed. * jc/merge-bases: get_merge_bases(): always clean-up object flags bisect: clean flags after checking merge bases
2014-12-22Merge branch 'cc/interpret-trailers-more'Libravatar Junio C Hamano1-0/+46
"git interpret-trailers" learned to properly handle the "Conflicts:" block at the end. * cc/interpret-trailers-more: trailer: add test with an old style conflict block trailer: reuse ignore_non_trailer() to ignore conflict lines commit: make ignore_non_trailer() non static merge & sequencer: turn "Conflicts:" hint into a comment builtin/commit.c: extract ignore_non_trailer() helper function merge & sequencer: unify codepaths that write "Conflicts:" hint builtin/merge.c: drop a parameter that is never used
2014-11-10commit: make ignore_non_trailer() non staticLibravatar Christian Couder1-0/+46
Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-10-30get_merge_bases(): always clean-up object flagsLibravatar Junio C Hamano1-8/+21
The callers of get_merge_bases() can choose to leave object flags used during the merge-base traversal by passing cleanup=0 as a parameter, but in practice a very few callers can afford to do so (namely, "git merge-base"), as they need to compute merge base in preparation for other processing of their own and they need to see the object without contaminate flags. Change the function signature of get_merge_bases_many() and get_merge_bases() to drop the cleanup parameter, so that the majority of the callers do not have to say ", 1" at the end. Give a new get_merge_bases_many_dirty() API to support only a few callers that know they do not need to spend cycles cleaning up the object flags. Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-10-08Merge branch 'jc/push-cert'Libravatar Junio C Hamano1-36/+0
Allow "git push" request to be signed, so that it can be verified and audited, using the GPG signature of the person who pushed, that the tips of branches at a public repository really point the commits the pusher wanted to, without having to "trust" the server. * jc/push-cert: (24 commits) receive-pack::hmac_sha1(): copy the entire SHA-1 hash out signed push: allow stale nonce in stateless mode signed push: teach smart-HTTP to pass "git push --signed" around signed push: fortify against replay attacks signed push: add "pushee" header to push certificate signed push: remove duplicated protocol info send-pack: send feature request on push-cert packet receive-pack: GPG-validate push certificates push: the beginning of "git push --signed" pack-protocol doc: typofix for PKT-LINE gpg-interface: move parse_signature() to where it should be gpg-interface: move parse_gpg_output() to where it should be send-pack: clarify that cmds_sent is a boolean send-pack: refactor inspecting and resetting status and sending commands send-pack: rename "new_refs" to "need_pack_data" receive-pack: factor out capability string generation send-pack: factor out capability string generation send-pack: always send capabilities send-pack: refactor decision to send update per ref send-pack: move REF_STATUS_REJECT_NODELETE logic a bit higher ...
2014-09-19Merge branch 'da/styles'Libravatar Junio C Hamano1-1/+1
* da/styles: stylefix: asterisks stick to the variable, not the type
2014-09-15gpg-interface: move parse_gpg_output() to where it should beLibravatar Junio C Hamano1-36/+0
Earlier, ffb6d7d5 (Move commit GPG signature verification to commit.c, 2013-03-31) moved this helper that used to be in pretty.c (i.e. the output code path) to commit.c for better reusability. It was a good first step in the right direction, but still suffers from a myopic view that commits will be the only thing we would ever want to sign---we would actually want to be able to reuse it even wider. The function interprets what GPG said; gpg-interface is obviously a better place. Move it there. Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-09-02stylefix: asterisks stick to the variable, not the typeLibravatar David Aguilar1-1/+1
Signed-off-by: David Aguilar <davvid@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-08-27record_author_date(): use find_commit_header()Libravatar Jeff King1-14/+8
This saves us some manual parsing and makes the code more readable. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-08-27record_author_date(): fix memory leak on malformed commitLibravatar Jeff King1-1/+1
If we hit the end-of-header without finding an "author" line, we just return from the function. We should jump to the fail_exit path to clean up the buffer that we may have allocated. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-08-27commit: provide a function to find a header in a bufferLibravatar Jeff King1-0/+22
Usually when we parse a commit, we read it line by line and handle each individual line (e.g., parse_commit and parse_commit_header). Sometimes, however, we only care about extracting a single header. Code in this situation is stuck doing an ad-hoc parse of the commit buffer. Let's provide a reusable function to locate a header within the commit. The code is modeled after pretty.c's get_header, which is used to extract the encoding. Since some callers may not have the "struct commit" to go along with the buffer, we drop that parameter. The only thing lost is a warning for truncated commits, but that's OK. This shouldn't happen in practice, and even if it does, there's no particular reason that this function needs to complain about it. It either finds the header it was asked for, or it doesn't (and in the latter case, the caller will typically complain). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-07-28add object_as_type helper for casting objectsLibravatar Jeff King1-17/+2
When we call lookup_commit, lookup_tree, etc, the logic goes something like: 1. Look for an existing object struct. If we don't have one, allocate and return a new one. 2. Double check that any object we have is the expected type (and complain and return NULL otherwise). 3. Convert an object with type OBJ_NONE (from a prior call to lookup_unknown_object) to the expected type. We can encapsulate steps 2 and 3 in a helper function which checks whether we have the expected object type, converts OBJ_NONE as appropriate, and returns the object. Not only does this shorten the code, but it also provides one central location for converting OBJ_NONE objects into objects of other types. Future patches will use that to enforce type-specific invariants. Since this is a refactoring, we would want it to behave exactly as the current code. It takes a little reasoning to see that this is the case: - for lookup_{commit,tree,etc} functions, we are just pulling steps 2 and 3 into a function that does the same thing. - for the call in peel_object, we currently only do step 3 (but we want to consolidate it with the others, as mentioned above). However, step 2 is a noop here, as the surrounding conditional makes sure we have OBJ_NONE (which we want to keep to avoid an extraneous call to sha1_object_info). - for the call in lookup_commit_reference_gently, we are currently doing step 2 but not step 3. However, step 3 is a noop here. The object we got will have just come from deref_tag, which must have figured out the type for each object in order to know when to stop peeling. Therefore the type will never be OBJ_NONE. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-07-28move setting of object->type to alloc_* functionsLibravatar Jeff King1-4/+2
The "struct object" type implements basic object polymorphism. Individual instances are allocated as concrete types (or as a union type that can store any object), and a "struct object *" can be cast into its real type after examining its "type" enum. This means it is dangerous to have a type field that does not match the allocation (e.g., setting the type field of a "struct blob" to "OBJ_COMMIT" would mean that a reader might read past the allocated memory). In most of the current code this is not a problem; the first thing we do after allocating an object is usually to set its type field by passing it to create_object. However, the virtual commits we create in merge-recursive.c do not ever get their type set. This does not seem to have caused problems in practice, though (presumably because we always pass around a "struct commit" pointer and never even look at the type). We can fix this oversight and also make it harder for future code to get it wrong by setting the type directly in the object allocation functions. This will also make it easier to fix problems with commit index allocation, as we know that any object allocated by alloc_commit_node will meet the invariant that an object with an OBJ_COMMIT type field will have a unique index number. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-07-27Merge branch 'cc/replace-graft'Libravatar Junio C Hamano1-0/+34
"git replace" learned a "--graft" option to rewrite parents of a commit. * cc/replace-graft: replace: add test for --graft with a mergetag replace: check mergetags when using --graft replace: add test for --graft with signed commit replace: remove signature when using --graft contrib: add convert-grafts-to-replace-refs.sh Documentation: replace: add --graft option replace: add test for --graft replace: add --graft option replace: cleanup redirection style in tests
2014-07-27Merge branch 'jk/stable-prio-queue'Libravatar Junio C Hamano1-23/+19
* jk/stable-prio-queue: t5539: update a flaky test paint_down_to_common: use prio_queue prio-queue: make output stable with respect to insertion prio-queue: factor out compare and swap operations
2014-07-22Merge branch 'rs/code-cleaning'Libravatar Junio C Hamano1-6/+1
* rs/code-cleaning: remote-testsvn: use internal argv_array of struct child_process in cmd_import() bundle: use internal argv_array of struct child_process in create_bundle() fast-import: use hashcmp() for SHA1 hash comparison transport: simplify fetch_objs_via_rsync() using argv_array run-command: use internal argv_array of struct child_process in run_hook_ve() use commit_list_count() to count the members of commit_lists strbuf: use strbuf_addstr() for adding C strings
2014-07-22Merge branch 'jk/alloc-commit-id'Libravatar Junio C Hamano1-21/+4
Make sure all in-core commit objects are assigned a unique number so that they can be annotated using the commit-slab API. * jk/alloc-commit-id: diff-tree: avoid lookup_unknown_object object_as_type: set commit index alloc: factor out commit index add object_as_type helper for casting objects parse_object_buffer: do not set object type move setting of object->type to alloc_* functions alloc: write out allocator definitions alloc.c: remove the alloc_raw_commit_node() function
2014-07-22Merge branch 'bg/xcalloc-nmemb-then-size' into maintLibravatar Junio C Hamano1-1/+1
* bg/xcalloc-nmemb-then-size: transport-helper.c: rearrange xcalloc arguments remote.c: rearrange xcalloc arguments reflog-walk.c: rearrange xcalloc arguments pack-revindex.c: rearrange xcalloc arguments notes.c: rearrange xcalloc arguments imap-send.c: rearrange xcalloc arguments http-push.c: rearrange xcalloc arguments diff.c: rearrange xcalloc arguments config.c: rearrange xcalloc arguments commit.c: rearrange xcalloc arguments builtin/remote.c: rearrange xcalloc arguments builtin/ls-remote.c: rearrange xcalloc arguments
2014-07-21replace: remove signature when using --graftLibravatar Christian Couder1-0/+34
It could be misleading to keep a signature in a replacement commit, so let's remove it. Note that there should probably be a way to sign the replacement commit created when using --graft, but this can be dealt with in another commit or patch series. Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2014-07-21Merge branch 'cc/for-each-mergetag'Libravatar Junio C Hamano1-0/+13
* cc/for-each-mergetag: commit: add for_each_mergetag()
2014-07-17use commit_list_count() to count the members of commit_listsLibravatar René Scharfe1-6/+1
Call commit_list_count() instead of open-coding it repeatedly. Signed-off-by: Rene Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>