summaryrefslogtreecommitdiff
path: root/contrib
Commit message (Collapse)AuthorAgeFilesLines
* Spelling fixesvs/typofixesVille Skyttä2017-06-273-3/+3
| | | | | Signed-off-by: Ville Skyttä <ville.skytta@iki.fi> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* Merge branch 'ab/free-and-null'Junio C Hamano2017-06-241-0/+15
|\ | | | | | | | | | | | | | | | | | | | | | | | | | | A common pattern to free a piece of memory and assign NULL to the pointer that used to point at it has been replaced with a new FREE_AND_NULL() macro. * ab/free-and-null: *.[ch] refactoring: make use of the FREE_AND_NULL() macro coccinelle: make use of the "expression" FREE_AND_NULL() rule coccinelle: add a rule to make "expression" code use FREE_AND_NULL() coccinelle: make use of the "type" FREE_AND_NULL() rule coccinelle: add a rule to make "type" code use FREE_AND_NULL() git-compat-util: add a FREE_AND_NULL() wrapper around free(ptr); ptr = NULL
| * coccinelle: add a rule to make "expression" code use FREE_AND_NULL()Ævar Arnfjörð Bjarmason2017-06-161-0/+7
| | | | | | | | | | | | | | | | | | A follow-up to the existing "type" rule added in an earlier change. This catches some occurrences that are missed by the previous rule. Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * coccinelle: add a rule to make "type" code use FREE_AND_NULL()Ævar Arnfjörð Bjarmason2017-06-161-0/+8
| | | | | | | | | | Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* | Merge branch 'jk/diff-highlight-module'Junio C Hamano2017-06-245-19/+82
|\ \ | |/ |/| | | | | | | | | | | The 'diff-highlight' program (in contrib/) has been restructured for easier reuse by an external project 'diff-so-fancy'. * jk/diff-highlight-module: diff-highlight: split code into module
| * diff-highlight: split code into modulejk/diff-highlight-moduleJeff King2017-06-155-19/+82
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The diff-so-fancy project is also written in perl, and most of its users pipe diffs through both diff-highlight and diff-so-fancy. It would be nice if this could be done in a single script. So let's pull most of diff-highlight's code into its own module which can be used by diff-so-fancy. In addition, we'll abstract a few basic items like reading from stdio so that a script using the module can do more processing before or after diff-highlight handles the lines. See the README update for more details. One small downside is that the diff-highlight script must now be built using the Makefile. There are ways around this, but it quickly gets into perl arcana. Let's go with the simple solution. As a bonus, our Makefile now respects the PERL_PATH variable if it is set. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * Merge branch 'rf/completion-config-commit' into maintJunio C Hamano2017-06-131-0/+3
| |\ | | | | | | | | | | | | | | | | | | Completion update. * rf/completion-config-commit: completion: add completions for git config commit
| * \ Merge branch 'jk/url-insteadof-config' into maintJunio C Hamano2017-06-051-0/+10
| |\ \ | | | | | | | | | | | | | | | | | | | | | | | | | | | | The interaction of "url.*.insteadOf" and custom URL scheme's whitelisting is now documented better. * jk/url-insteadof-config: docs/config: mention protocol implications of url.insteadOf
| * \ \ Merge branch 'tg/stash-push-fixup' into maintJunio C Hamano2017-06-041-1/+4
| |\ \ \ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The shell completion script (in contrib/) learned "git stash" has a new "push" subcommand. * tg/stash-push-fixup: completion: add git stash push
* | \ \ \ Merge branch 'rf/completion'Junio C Hamano2017-06-131-1/+28
|\ \ \ \ \ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Completion updates. * rf/completion: completion: add git config credentialCache.ignoreSIGHUP completion: add git config credential completions completion: add git config advice completions completion: add git config am.threeWay completion completion: add git config core completions completion: add git config gc completions
| * | | | | completion: add git config credentialCache.ignoreSIGHUPrf/completionRikard Falkeborn2017-06-021-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Signed-off-by: Rikard Falkeborn <rikard.falkeborn@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * | | | | completion: add git config credential completionsRikard Falkeborn2017-06-021-0/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Add missing completions for git config credential: * credential.helper * credential.useHttpPath * credential.username Signed-off-by: Rikard Falkeborn <rikard.falkeborn@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * | | | | completion: add git config advice completionsRikard Falkeborn2017-06-021-1/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Add missing completions for git config advice: * advice.amWorkDir * advice.pushAlreadyExists * advice.pushFetchFirst * advice.pushNeedsForce * advice.pushNonFFCurrent * advice.pushNonFFMatching * advice.pushUpdateRejected * advice.rmHints * advice.statusUoption Remove completion for git config advice.pushNonFastForward, since it was renamed to pushUpdateRejected in 1184564eac8e. The config still works, but is no longer part of the documentation. Signed-off-by: Rikard Falkeborn <rikard.falkeborn@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * | | | | completion: add git config am.threeWay completionRikard Falkeborn2017-06-021-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Signed-off-by: Rikard Falkeborn <rikard.falkeborn@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * | | | | completion: add git config core completionsRikard Falkeborn2017-06-021-0/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Add missing completions for git config core: * core.checkStat * core.commentChar * core.hideDotFiles * core.hooksPath * core.packedRefsTimeout * core.precomposeUnicode * core.protectHFS * core.protectNTFS * core.splitIndex * core.sshCommand Note that some configs are only used for some platforms (hideDotFiles on Windows and precomposeUnicode on Mac). Signed-off-by: Rikard Falkeborn <rikard.falkeborn@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * | | | | completion: add git config gc completionsRikard Falkeborn2017-06-021-0/+4
| | |_|_|/ | |/| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Add missing completion for git config gc options: * gc.aggressiveDepth * gc.autoDetach * gc.logExpiry * gc.worktreePruneExpire Signed-off-by: Rikard Falkeborn <rikard.falkeborn@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* | | | | Merge branch 'jk/url-insteadof-config'Junio C Hamano2017-06-041-0/+10
|\ \ \ \ \ | | |_|_|/ | |/| | | | | | | | | | | | | | | | | | | | | | | | | | | | The interaction of "url.*.insteadOf" and custom URL scheme's whitelisting is now documented better. * jk/url-insteadof-config: docs/config: mention protocol implications of url.insteadOf
| * | | | docs/config: mention protocol implications of url.insteadOfjk/url-insteadof-configJeff King2017-06-011-0/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | If a URL rewrite switches the protocol to something nonstandard (like "persistent-https" for "https"), the user may be bitten by the fact that the default protocol restrictions are different between the two. Let's drop a note in insteadOf that points the user in the right direction. It would be nice if we could make this work out of the box, but we can't without knowing the security implications of the user's rewrite. Only the documentation for a particular remote helper can advise one way or the other. Since we do include the persistent-https helper in contrib/ (and since it was the helper in the real-world case that inspired that patch), let's also drop a note there. Suggested-by: Elliott Cable <me@ell.io> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* | | | | Merge branch 'rf/completion-config-commit'Junio C Hamano2017-06-041-0/+3
|\ \ \ \ \ | | |/ / / | |/| | | | | | | | | | | | | | | | | | | | | | | Completion update. * rf/completion-config-commit: completion: add completions for git config commit
| * | | | completion: add completions for git config commitrf/completion-config-commitRikard Falkeborn2017-05-301-0/+3
| |/ / / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Add missing completions for git config: * commit.cleanup * commit.gpgSign * commit.verbose Signed-off-by: Rikard Falkeborn <rikard.falkeborn@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* | | | Merge branch 'tg/stash-push-fixup'Junio C Hamano2017-05-291-1/+4
|\ \ \ \ | | |_|/ | |/| | | | | | | | | | | | | | | | | | | | | | The shell completion script (in contrib/) learned "git stash" has a new "push" subcommand. * tg/stash-push-fixup: completion: add git stash push
| * | | completion: add git stash pushtg/stash-push-fixupThomas Gummerer2017-05-171-1/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When introducing git stash push in f5727e26e4 ("stash: introduce push verb", 2017-02-19), I forgot to add it to the completion code. Add it now. Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com> Reviewed-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* | | | Merge branch 'js/eol-on-ourselves'Junio C Hamano2017-05-292-0/+2
|\ \ \ \ | | |_|/ | |/| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Make sure our tests would pass when the sources are checked out with "platform native" line ending convention by default on Windows. Some "text" files out tests use and the test scripts themselves that are meant to be run with /bin/sh, ought to be checked out with eol=LF even on Windows. * js/eol-on-ourselves: t4051: mark supporting files as requiring LF-only line endings Fix the remaining tests that failed with core.autocrlf=true t3901: move supporting files into t/t3901/ completion: mark bash script as LF-only git-new-workdir: mark script as LF-only Fix build with core.autocrlf=true
| * | | completion: mark bash script as LF-onlyJohannes Schindelin2017-05-101-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Without this change, the completion script does not work, as Bash expects its scripts to have line feeds as end-of-line markers (this is particularly prominent in quoted multi-line strings, where carriage returns would slip into the strings as verbatim characters otherwise). This change is required to let t9902-completion pass when Git's source code is checked out with `core.autocrlf = true`. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Reviewed-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * | | git-new-workdir: mark script as LF-onlyJohannes Schindelin2017-05-101-0/+1
| | |/ | |/| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Bash does not handle scripts with CR/LF line endings correctly, therefore they *have* to be forced to LF-only line endings. Funnily enough, this fixes t3000-ls-files-others and t1021-rerere-in-workdir when git.git was checked out with core.autocrlf=true, as these test still use git-new-workdir (once `git worktree` is no longer marked as experimental, both scripts probably want to be ported to using that command instead). Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Reviewed-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* | | Merge branch 'ab/clone-no-tags'Junio C Hamano2017-05-161-0/+1
|\ \ \ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | "git clone" learned the "--no-tags" option not to fetch all tags initially, and also set up the tagopt not to follow any tags in subsequent fetches. * ab/clone-no-tags: tests: rename a test having to do with shallow submodules clone: add a --no-tags option to clone without tags tests: change "cd ... && git fetch" to "cd &&\n\tgit fetch"
| * | | clone: add a --no-tags option to clone without tagsÆvar Arnfjörð Bjarmason2017-05-011-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Add a --no-tags option to clone without fetching any tags. Without this change there's no easy way to clone a repository without also fetching its tags. When supplying --single-branch the primary remote branch will be cloned, but in addition tags will be followed & retrieved. Now --no-tags can be added --single-branch to clone a repository without tags, and which only tracks a single upstream branch. This option works without --single-branch as well, and will do a normal clone but not fetch any tags. Many git commands pay some fixed overhead as a function of the number of references. E.g. creating ~40k tags in linux.git will cause a command like `git log -1 >/dev/null` to run in over a second instead of in a matter of milliseconds, in addition numerous other things will slow down, e.g. "git log <TAB>" with the bash completion will slowly show ~40k references instead of 1. The user might want to avoid all of that overhead to simply use a repository like that to browse the "master" branch, or something like a CI tool might want to keep that one branch up-to-date without caring about any other references. Without this change the only way of accomplishing this was either by manually tweaking the config in a fresh repository: git init git && cat >git/.git/config <<EOF && [remote "origin"] url = git@github.com:git/git.git tagOpt = --no-tags fetch = +refs/heads/master:refs/remotes/origin/master [branch "master"] remote = origin merge = refs/heads/master EOF cd git && git pull Which requires hardcoding the "master" name, which may not be the main --single-branch would have retrieved, or alternatively by setting tagOpt=--no-tags right after cloning & deleting any existing tags: git clone --single-branch git@github.com:git/git.git && cd git && git config remote.origin.tagOpt --no-tags && git tag -l | xargs git tag -d Which of course was also subtly buggy if --branch was pointed at a tag, leaving the user in a detached head: git clone --single-branch --branch v2.12.0 git@github.com:git/git.git && cd git && git config remote.origin.tagOpt --no-tags && git tag -l | xargs git tag -d Now all this complexity becomes the much simpler: git clone --single-branch --no-tags git@github.com:git/git.git Or in the case of cloning a single tag "branch": git clone --single-branch --branch v2.12.0 --no-tags git@github.com:git/git.git Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* | | | Merge branch 'sk/status-short-branch-color-config'Junio C Hamano2017-05-161-0/+2
|\ \ \ \ | |_|/ / |/| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The colors in which "git status --short --branch" showed the names of the current branch and its remote-tracking branch are now configurable. * sk/status-short-branch-color-config: status: add color config slots for branch info in "--short --branch" status: fix missing newline when comment chars are disabled
| * | | status: add color config slots for branch info in "--short --branch"sk/status-short-branch-color-configStephen Kent2017-04-281-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Add color config slots to be used in the status short-format when displaying local and remote tracking branch information. [jc: rebased on top of Peff's fix to 'git status' and tweaked the test to check both local and remote-tracking branch output] Signed-off-by: Stephen Kent <smkent@smkent.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* | | | Merge branch 'jk/complete-checkout-sans-dwim-remote'Junio C Hamano2017-05-011-1/+10
|\ \ \ \ | |/ / / |/| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Completion for "git checkout <branch>" that auto-creates the branch out of a remote tracking branch can now be disabled, as this completion often gets in the way when completing to checkout an existing local branch that happens to share the same prefix with bunch of remote tracking branches. * jk/complete-checkout-sans-dwim-remote: completion: optionally disable checkout DWIM
| * | | completion: optionally disable checkout DWIMjk/complete-checkout-sans-dwim-remoteJeff King2017-04-231-1/+10
| |/ / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When we complete branch names for "git checkout", we also complete remote branch names that could trigger the DWIM behavior. Depending on your workflow and project, this can be either convenient or annoying. For instance, my clone of gitster.git contains 74 local "jk/*" branches, but origin contains another 147. When I want to checkout a local branch but can't quite remember the name, tab completion shows me 251 entries. And worse, for a topic that has been picked up for pu, the upstream branch name is likely to be similar to mine, leading to a high probability that I pick the wrong one and accidentally create a new branch. This patch adds a way for the user to tell the completion code not to include DWIM suggestions for checkout. This can already be done by typing: git checkout --no-guess jk/<TAB> but that's rather cumbersome. The downside, of course, is that you no longer get completion support when you _do_ want to invoke the DWIM behavior. But depending on your workflow, that may not be a big loss (for instance, in git.git I am much more likely to want to detach, so I'd type "git checkout origin/jk/<TAB>" anyway). Signed-off-by: Jeff King <peff@peff.net> Reviewed-by: SZEDER Gábor <szeder.dev@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* | | completion: expand "push --delete <remote> <ref>" for refs on that <remote>ab/completion-push-delete-refÆvar Arnfjörð Bjarmason2017-04-231-0/+1
|/ / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Change the completion of "push --delete <remote> <ref>" to complete refs on that <remote>, not all refs. Before this cloning git.git and doing "git push --delete origin p<TAB>" will complete nothing, since a fresh clone of git.git will have no "pu" branch, whereas origin/p<TAB> will uselessly complete origin/pu, but fully qualified references aren't accepted by "--delete". Now p<TAB> will complete as "pu". The completion of giving --delete later, e.g. "git push origin --delete p<TAB>" remains unchanged, this is a bug, but is a general existing limitation of the bash completion, and not how git-push is documented, so I'm not fixing that case, but adding a failing TODO test for it. The testing code was supplied by SZEDER Gábor in <20170421122832.24617-1-szeder.dev@gmail.com> with minor setup modifications on my part. Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Reviewed-by: SZEDER Gábor <szeder.dev@gmail.com> Test-code-by: SZEDER Gábor <szeder.dev@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* | Merge branch 'jc/bs-t-is-not-a-tab-for-sed'Junio C Hamano2017-04-161-2/+2
|\ \ | | | | | | | | | | | | | | | | | | Code cleanup. * jc/bs-t-is-not-a-tab-for-sed: contrib/git-resurrect.sh: do not write \t for HT in sed scripts
| * | contrib/git-resurrect.sh: do not write \t for HT in sed scriptsjc/bs-t-is-not-a-tab-for-sedJunio C Hamano2017-03-311-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | Just like we did in 0d1d6e50 ("t/t7003: replace \t with literal tab in sed expression", 2010-08-12), avoid writing "\t" for HT in sed scripts, which is not portable. Signed-off-by: Junio C Hamano <gitster@pobox.com>
* | | Merge branch 'ab/ref-filter-no-contains'Junio C Hamano2017-04-111-2/+2
|\ \ \ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | "git tag/branch/for-each-ref" family of commands long allowed to filter the refs by "--contains X" (show only the refs that are descendants of X), "--merged X" (show only the refs that are ancestors of X), "--no-merged X" (show only the refs that are not ancestors of X). One curious omission, "--no-contains X" (show only the refs that are not descendants of X) has been added to them. * ab/ref-filter-no-contains: tag: add tests for --with and --without ref-filter: reflow recently changed branch/tag/for-each-ref docs ref-filter: add --no-contains option to tag/branch/for-each-ref tag: change --point-at to default to HEAD tag: implicitly supply --list given another list-like option tag: change misleading --list <pattern> documentation parse-options: add OPT_NONEG to the "contains" option tag: add more incompatibles mode tests for-each-ref: partly change <object> to <commit> in help tag tests: fix a typo in a test description tag: remove a TODO item from the test suite ref-filter: add test for --contains on a non-commit ref-filter: make combining --merged & --no-merged an error tag doc: reword --[no-]merged to talk about commits, not tips tag doc: split up the --[no-]merged documentation tag doc: move the description of --[no-]merged earlier
| * | | ref-filter: add --no-contains option to tag/branch/for-each-refÆvar Arnfjörð Bjarmason2017-03-241-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Change the tag, branch & for-each-ref commands to have a --no-contains option in addition to their longstanding --contains options. This allows for finding the last-good rollout tag given a known-bad <commit>. Given a hypothetically bad commit cf5c7253e0, the git version to revert to can be found with this hacky two-liner: (git tag -l 'v[0-9]*'; git tag -l --contains cf5c7253e0 'v[0-9]*') | sort | uniq -c | grep -E '^ *1 ' | awk '{print $2}' | tail -n 10 With this new --no-contains option the same can be achieved with: git tag -l --no-contains cf5c7253e0 'v[0-9]*' | sort | tail -n 10 As the filtering machinery is shared between the tag, branch & for-each-ref commands, implement this for those commands too. A practical use for this with "branch" is e.g. finding branches which were branched off between v2.8.0 and v2.10.0: git branch --contains v2.8.0 --no-contains v2.10.0 The "describe" command also has a --contains option, but its semantics are unrelated to what tag/branch/for-each-ref use --contains for. A --no-contains option for "describe" wouldn't make any sense, other than being exactly equivalent to not supplying --contains at all, which would be confusing at best. Add a --without option to "tag" as an alias for --no-contains, for consistency with --with and --contains. The --with option is undocumented, and possibly the only user of it is Junio (<xmqqefy71iej.fsf@gitster.mtv.corp.google.com>). But it's trivial to support, so let's do that. The additions to the the test suite are inverse copies of the corresponding --contains tests. With this change --no-contains for tag, branch & for-each-ref is just as well tested as the existing --contains option. In addition to those tests, add a test for "tag" which asserts that --no-contains won't find tree/blob tags, which is slightly unintuitive, but consistent with how --contains works & is documented. Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* | | | Merge branch 'sg/completion-ctags'Junio C Hamano2017-03-301-6/+66
|\ \ \ \ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Command line completion updates. * sg/completion-ctags: completion: offer ctags symbol names for 'git log -S', '-G' and '-L:' completion: extract completing ctags symbol names into helper function completion: put matching ctags symbol names directly into COMPREPLY
| * | | | completion: offer ctags symbol names for 'git log -S', '-G' and '-L:'sg/completion-ctagsSZEDER Gábor2017-03-231-0/+28
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Just like in the case of search patterns for 'git grep', see 29eec71f2 (completion: match ctags symbol names in grep patterns, 2011-10-21)), a common thing to look for using 'git log -S', '-G' and '-L:' is the name of a symbol. Teach the completion for 'git log' to offer ctags symbol names after these options, both in stuck and in unstuck forms. Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * | | | completion: extract completing ctags symbol names into helper functionSZEDER Gábor2017-03-231-4/+29
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The previous commit doubled the number of __git_match_ctag()'s positional parameters, and, to keep the position of existing parameters for the sake of backwards compatibility, the prefix, current word and suffix parameters ended up in different order than in other functions accepting the same parameters. Then there is a condition checking the existence of the tag file before invoking this function. We could still live with this if there were only a single callsite, but the next commit will add a few more, so it's worth providing a cleaner interface. Add the wrapper function __git_complete_symbol(), which encompasses the condition for checking the presence of the tag file and filling COMPREPLY, and accepts '--opt=val'-style options with default values that keep callsites simpler. Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * | | | completion: put matching ctags symbol names directly into COMPREPLYSZEDER Gábor2017-03-231-3/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The one-liner awk script in __git_match_ctag() listing ctags symbol names for 'git grep <TAB>' is already smart enough to list only symbol names matching the current word to be completed. Extend this helper function to accept prefix and suffix parameters to be prepended and appended, respectively, to each listed symbol name in the awk script, so its output won't require any additional processing or filtering in the completion script before being handed over to Bash. Use the faster __gitcomp_direct() helper instead of __gitcomp_nl() to fill the fully processed matching symbol names into Bash's COMPREPLY array. Right after 'git grep <TAB>' in current git.git with 14k+ symbol names in the tag file, best of five: Before: $ time __gitcomp_nl "$(__git_match_ctag "" tags)" real 0m0.178s user 0m0.176s sys 0m0.000s After: $ time __gitcomp_direct "$(__git_match_ctag "" tags "" " ")" real 0m0.058s user 0m0.048s sys 0m0.008s Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
* | | | | Merge branch 'sg/completion-refs-speedup'Junio C Hamano2017-03-302-71/+190
|\ \ \ \ \ | |/ / / / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The refs completion for large number of refs has been sped up, partly by giving up disambiguating ambiguous refs and partly by eliminating most of the shell processing between 'git for-each-ref' and 'ls-remote' and Bash's completion facility. * sg/completion-refs-speedup: completion: speed up branch and tag completion completion: fill COMPREPLY directly when completing fetch refspecs completion: fill COMPREPLY directly when completing refs completion: let 'for-each-ref' sort remote branches for 'checkout' DWIMery completion: let 'for-each-ref' filter remote branches for 'checkout' DWIMery completion: let 'for-each-ref' strip the remote name from remote branches completion: let 'for-each-ref' and 'ls-remote' filter matching refs completion: don't disambiguate short refs completion: don't disambiguate tags and branches completion: support excluding full refs completion: support completing fully qualified non-fast-forward refspecs completion: support completing full refs after '--option=refs/<TAB>' completion: wrap __git_refs() for better option parsing completion: remove redundant __gitcomp_nl() options from _git_commit()
| * | | | completion: speed up branch and tag completionsg/completion-refs-speedupSZEDER Gábor2017-03-231-6/+19
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Modify __git_heads() and __git_tags() and the few callsites they have, so we can let 'git for-each-ref' do all the hard work and these functions' output won't need any further processing or filtering before being handed over to Bash, resulting in faster branch and tag completion. These are some of the same tricks used in the previous commits to speed up refs completion, namely: - Extend both functions to accept prefix, current word and suffix positional parameters, all optional and all empty by default to keep the parameterless behavior unaltered. - Specify appropriate globbing patterns to 'git for-each-ref' to list only branches or tags matching the given current word parameter. - Modify the 'git for-each-ref --format=<...>' to include the given prefix and suffix. - Adjust all callsites to specify the proper prefix, current word and suffix parameters, and to fill COMPREPLY using __gitcomp_direct(). Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * | | | completion: fill COMPREPLY directly when completing fetch refspecsSZEDER Gábor2017-03-231-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The __git_complete_fetch_refspecs() has to iterate over __git_refs()'s output anyway to turn the listed matching refs into refspecs, and it knows about the prefix and suffix that has to be added to each refspec. Modify this function to add the prefix and suffix to each refspec while iterating and feed the result, since it doesn't need further processing, to the new __gitcomp_direct() helper added in the previous commit, because it should be faster when there are a lot of refspecs to list. Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * | | | completion: fill COMPREPLY directly when completing refsSZEDER Gábor2017-03-232-14/+49
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | __gitcomp_nl() iterates over all the possible completion words it gets as argument - filtering matching words, - appending a trailing space to each matching word (in all but two cases), - prepending a prefix to each matching word (when completing words after e.g. '--option=<TAB>' or 'master..<TAB>'), and - adding each matching word to the COMPREPLY array. This takes a while when a lot of refs are passed to __gitcomp_nl(). The previous changes in this series ensure that __git_refs() lists only refs matching the current word to be completed, making a second filtering in __gitcomp_nl() redundant. Adding the necessary prefix and suffix could be done in __git_refs() as well: - When refs come from 'git for-each-ref', then that prefix and suffix could be added much more efficiently using a 'git for-each-ref' format containing said prefix and suffix. Care should be taken, though, because that prefix might contain 'for-each-ref' format specifiers as part of the left hand side of a '..' range or '...' symmetric difference notation or fetch/push/etc. refspec, e.g. 'git log "evil-%(refname)..br<TAB>'. Doubling every '%' in the prefix will prevent 'git for-each-ref' from interpolating any of those contained specifiers. - When refs come from 'git ls-remote', then that prefix and suffix can be added in the shell loop that has to process 'git ls-remote's output anyway. - Finally, the prefix and suffix can be added to that handful of potentially matching symbolic and pseudo refs right away in the shell loop listing them. And then all what is still left to do is to assign a bunch of newline-separated words to a shell array, which can be done without a shell loop iterating over each word, basically making all of __gitcomp_nl() unnecessary for refs completion. Add the helper function __gitcomp_direct() to fill the COMPREPLY array with prefiltered and preprocessed words without any additional processing, without a shell loop, with just one single compound assignment. Modify __git_refs() to accept prefix and suffix parameters and add them to each and every listed ref as described above. Modify __git_complete_refs() to pass the prefix and suffix parameters to __git_refs() and to feed __git_refs()'s output to __gitcomp_direct() instead of __gitcomp_nl(). This speeds up refs completion when there are a lot of refs matching the current word to be completed. Listing all branches for completion in a repo with 100k local branches, all packed, best of five: On Linux, near the beginning of this series, for reference: $ time __git_complete_refs real 0m2.028s user 0m1.692s sys 0m0.344s Before this patch: real 0m1.135s user 0m1.112s sys 0m0.024s After: real 0m0.367s user 0m0.352s sys 0m0.020s On Windows, near the beginning: real 0m13.078s user 0m1.609s sys 0m0.060s Before this patch: real 0m2.093s user 0m1.641s sys 0m0.060s After: real 0m0.683s user 0m0.203s sys 0m0.076s Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * | | | completion: let 'for-each-ref' sort remote branches for 'checkout' DWIMerySZEDER Gábor2017-03-231-1/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When listing unique remote branches for 'git checkout's tracking DWIMery, __git_refs() runs the classic '... |sort |uniq -u' pattern to filter out duplicate remote branches. Let 'git for-each-ref' do the sorting, sparing the overhead of fork()+exec()ing 'sort' and a stage in the pipeline where potentially relatively large amount of data can be passed between two subsequent pipeline stages. This speeds up refs completion for 'git checkout' a bit when a lot of remote branches match the current word to be completed. Listing a single local and 100k remote branches, all packed, best of five: On Linux, before: $ time __git_complete_refs --track real 0m1.856s user 0m1.816s sys 0m0.060s After: real 0m1.550s user 0m1.512s sys 0m0.060s On Windows, before: real 0m3.128s user 0m2.155s sys 0m0.183s After: real 0m2.781s user 0m1.826s sys 0m0.136s Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * | | | completion: let 'for-each-ref' filter remote branches for 'checkout' DWIMerySZEDER Gábor2017-03-231-9/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The code listing unique remote branches for 'git checkout's tracking DWIMery outputs only remote branches that match the current word to be completed, but the filtering is done in a shell loop iterating over all remote refs. Let 'git for-each-ref' do the filtering, as it can do so much more efficiently and we can remove that shell loop entirely. This speeds up refs completion for 'git checkout' considerably when there are a lot of non-matching remote refs to be filtered out. Uniquely completing a branch in a repository with 100k remote branches, all packed, best of five: On Linux, before: $ time __git_complete_refs --cur=maste --track real 0m1.993s user 0m1.740s sys 0m0.304s After: real 0m0.266s user 0m0.248s sys 0m0.012s On Windows, before: real 0m6.187s user 0m3.358s sys 0m2.121s After: real 0m0.750s user 0m0.015s sys 0m0.090s Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * | | | completion: let 'for-each-ref' strip the remote name from remote branchesSZEDER Gábor2017-03-231-4/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The code listing unique remote branches for 'git checkout's tracking DWIMery uses a shell parameter expansion in a loop iterating over each listed ref to remove the remote's name from the remote branches, i.e. the leading path component from the short ref. When listing refs from a configured remote repository, '| sed s///' is used for the same purpose. Let 'git for-each-ref' strip one more leading path component from the refs, i.e. use the format 'refname:strip=3' instead of '=2', making that parameter expansion and 'sed' execution unnecessary. This speeds up refs completion for 'git checkout'. Uniquely completing a branch for 'git checkout maste<TAB>' in a repo with 100k remote branches, all packed, best of five: On Linux, near the beginning of this series, for reference: $ time __git_complete_refs --cur=maste --track real 0m8.185s user 0m6.896s sys 0m1.616s Before this patch: real 0m2.714s user 0m2.344s sys 0m0.436s After: real 0m1.993s user 0m1.740s sys 0m0.304s On Windows, near the beginning: real 1m8.421s user 0m7.591s sys 0m3.557s Before this patch: real 0m8.191s user 0m4.638s sys 0m2.918s After: real 0m6.187s user 0m3.358s sys 0m2.121s Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * | | | completion: let 'for-each-ref' and 'ls-remote' filter matching refsSZEDER Gábor2017-03-231-11/+30
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When completing refs, several __git_refs() code paths list all the refs from the refs/{heads,tags,remotes}/ hierarchy and then __gitcomp_nl() iterates over those refs in a shell loop to filter out refs not matching the current ref to be completed. This comes with a considerable performance penalty when a repository contains a lot of refs but the current ref can be uniquely completed or when only a handful of refs match the current ref. Reduce the number of iterations in __gitcomp_nl() from the number of refs to the number of matching refs by specifying appropriate globbing patterns to 'git for-each-ref' and 'git ls-remote' to list only those refs that match the current ref to be completed. However, do so only when the ref to match is explicitly given as parameter, because the current word on the command line might contain a prefix like '--option=' or 'branch..'. The __git_complete_refs() and __git_complete_fetch_refspecs() helpers introduced previously in this patch series already call __git_refs() specifying this current ref parameter, so all their callsites, i.e. all places in the completion script doing refs completion, can benefit from this optimization. Furthermore, list only those symbolic and pseudo refs that match the current ref to be completed. Though it doesn't matter at all in itself performance-wise, it will allow us further significant optimizations later in this series. This speeds up refs completion considerably when there are a lot of non-matching refs to be filtered out. Uniquely completing a branch in a repository with 100k local branches, all packed, best of five: On Linux, before: $ time __git_complete_refs --cur=maste real 0m0.831s user 0m0.808s sys 0m0.028s After: real 0m0.119s user 0m0.104s sys 0m0.008s On Windows, before: real 0m1.480s user 0m1.031s sys 0m0.060s After: real 0m0.377s user 0m0.015s sys 0m0.030s Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * | | | completion: don't disambiguate short refsSZEDER Gábor2017-03-231-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When the completion script lists short refs it does so using the 'git for-each-ref' format 'refname:short', which makes sure that all listed refs are unambiguous. While disambiguating refs is technically correct in this case, as opposed to the cases discussed in the previous patch, this disambiguation involves several stat() syscalls for each ref, thus, unfortunately, comes at a steep cost especially on Windows and/or when there are a lot of refs to be listed. A user of Git for Windows reported[1] 'git checkout <TAB>' taking ~11 seconds in a repository with just about 4000 refs. However, it's questionable whether ambiguous refs are really that bad to justify that much extra cost: - Ambiguous refs are not that common, - even if a repository contains ambiguous refs, they only hurt when the user actually happens to want to do something with one of the ambiguous refs, and - the issue can be easily circumvented by renaming those ambiguous refs. - On the other hand, apparently not that many refs are needed to make refs completion unacceptably slow on Windows, - and this slowness bites each and every time the user attempts refs completion, even when the repository doesn't contain any ambiguous refs. - Furthermore, circumventing the issue might not be possible or might be considerably more difficult and requires various trade-offs (e.g. working in a repository with only a few selected important refs while keeping a separate repository with all refs for reference). Arguably, in this case the benefits of technical correctness are rather minor compared to the price we pay for it, and we are better off opting for performance over correctness. Use the 'git for-each-ref' format 'refname:strip=2' to list short refs to spare the substantial cost of disambiguating. This speeds up refs completion considerably. Uniquely completing a branch in a repository with 100k local branches, all packed, best of five: On Linux, before: $ time __git_complete_refs --cur=maste real 0m1.662s user 0m1.368s sys 0m0.296s After: real 0m0.831s user 0m0.808s sys 0m0.028s On Windows, before: real 0m12.457s user 0m1.016s sys 0m0.092s After: real 0m1.480s user 0m1.031s sys 0m0.060s [1] - https://github.com/git-for-windows/git/issues/524 Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
| * | | | completion: don't disambiguate tags and branchesSZEDER Gábor2017-03-231-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When the completion script has to list only tags or only branches, it uses the 'git for-each-ref' format 'refname:short', which makes sure that all listed tags and branches are unambiguous. However, disambiguating tags and branches in these cases is wrong, because: - __git_tags(), the helper function listing possible tagname arguments for 'git tag', lists an ambiguous tag 'refs/tags/ambiguous' as 'tags/ambiguous'. Its only consumer, 'git tag' expects its tagname argument to be under 'refs/tags/', thus it interprets that abgiguous tag as 'refs/tags/tags/ambiguous'. Clearly wrong. - __git_heads() lists possible branchname arguments for 'git branch' and possible 'branch.<branchname>' configuration subsections. Both of these expect branchnames to be under 'refs/heads/' and misinterpret a disambiguated branchname like 'heads/ambiguous'. Furthermore, disambiguation involves several stat() syscalls for each tag or branch, thus comes at a steep cost especially on Windows and/or when there are a lot of tags or branches to be listed. Use the 'git for-each-ref' format 'refname:strip=2' instead of 'refname:short' to avoid harmful disambiguation of tags and branches in __git_tags() and __git_heads(). Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>