Merge branch 'maint'
authorJunio C Hamano <gitster@pobox.com>
Mon, 25 Mar 2013 20:52:25 +0000 (13:52 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 25 Mar 2013 20:52:25 +0000 (13:52 -0700)
* maint:
Start preparing for 1.8.2.1
transport.c: help gcc 4.6.3 users by squelching compiler warning

95 files changed:
Documentation/RelNotes/1.8.3.txt [new file with mode: 0644]
Documentation/config.txt
Documentation/git-commit.txt
Documentation/git-count-objects.txt
Documentation/git-push.txt
Documentation/git-send-email.txt
Documentation/git-shell.txt
Documentation/git-status.txt
Documentation/gitcli.txt
Documentation/pretty-formats.txt
Documentation/user-manual.txt
GIT-VERSION-GEN
RelNotes
advice.c
advice.h
archive-zip.c
builtin/branch.c
builtin/commit.c
builtin/count-objects.c
builtin/describe.c
builtin/fetch-pack.c
builtin/fmt-merge-msg.c
builtin/index-pack.c
builtin/mailsplit.c
builtin/update-index.c
builtin/verify-tag.c
cache.h
compat/msvc.h
compat/vcbuild/include/sys/poll.h [deleted file]
compat/vcbuild/include/unistd.h
config.mak.uname
contrib/credential/gnome-keyring/git-credential-gnome-keyring.c
contrib/credential/netrc/Makefile [new file with mode: 0644]
contrib/credential/netrc/git-credential-netrc [new file with mode: 0755]
contrib/credential/netrc/test.netrc [new file with mode: 0644]
contrib/credential/netrc/test.pl [new file with mode: 0755]
contrib/credential/osxkeychain/git-credential-osxkeychain.c
contrib/credential/wincred/git-credential-wincred.c
contrib/examples/git-remote.perl
contrib/examples/git-svnimport.perl
contrib/fast-import/git-import.perl
contrib/fast-import/git-import.sh
contrib/fast-import/import-zips.py
contrib/hooks/setgitperms.perl
contrib/mw-to-git/t/install-wiki.sh
diffcore-rename.c
fetch-pack.c
fetch-pack.h
git-archimport.perl
git-compat-util.h
git-cvsexportcommit.perl
git-cvsimport.perl
git-cvsserver.perl
git-difftool.perl
git-merge-one-file.sh
git-relink.perl
git-send-email.perl
git-sh-setup.sh
git-submodule.sh
git-svn.perl
gpg-interface.c
gpg-interface.h
hash.h
imap-send.c
log-tree.c
name-hash.c
perl/Git.pm
pretty.c
remote.c
remote.h
sha1_file.c
shell.c
t/lib-git-svn.sh
t/t1509/prepare-chroot.sh
t/t2200-add-update.sh
t/t3200-branch.sh
t/t5003-archive-zip.sh
t/t5304-prune.sh
t/t5516-fetch-push.sh
t/t7060-wtstatus.sh
t/t7406-submodule-update.sh
t/t7502-commit.sh
t/t7508-status.sh
t/t7512-status-help.sh
t/t7800-difftool.sh
templates/hooks--update.sample
test-chmtime.c
test-delta.c
test-genrandom.c
test-svn-fe.c
transport.c
upload-pack.c
utf8.c
wt-status.c
wt-status.h
diff --git a/Documentation/RelNotes/1.8.3.txt b/Documentation/RelNotes/1.8.3.txt
new file mode 100644 (file)
index 0000000..23bd0c4
--- /dev/null
@@ -0,0 +1,162 @@
+Git v1.8.3 Release Notes
+========================
+
+Backward compatibility notes (for Git 2.0)
+------------------------------------------
+
+When "git push [$there]" does not say what to push, we have used the
+traditional "matching" semantics so far (all your branches were sent
+to the remote as long as there already are branches of the same name
+over there).  In Git 2.0, the default will change to the "simple"
+semantics that pushes the current branch to the branch with the same
+name, only when the current branch is set to integrate with that
+remote branch.  There is a user preference configuration variable
+"push.default" to change this.  If you are an old-timer who is used
+to the "matching" semantics, you can set it to "matching" to keep the
+traditional behaviour.  If you want to live in the future early,
+you can set it to "simple" today without waiting for Git 2.0.
+
+When "git add -u" and "git add -A", that does not specify what paths
+to add on the command line is run from inside a subdirectory, these
+commands will operate on the entire tree in Git 2.0 for consistency
+with "git commit -a" and other commands. Because there will be no
+mechanism to make "git add -u" behave as if "git add -u .", it is
+important for those who are used to "git add -u" (without pathspec)
+updating the index only for paths in the current subdirectory to start
+training their fingers to explicitly say "git add -u ." when they mean
+it before Git 2.0 comes.
+
+
+Updates since v1.8.2
+--------------------
+
+UI, Workflows & Features
+
+ * When the interactive access to git-shell is not enabled, it issues
+   a message meant to help the system admininstrator to enable it.
+   An explicit way to help the end users who connect to the service by
+   issuing custom messages to refuse such an access has been added.
+
+ * "git status" suggests users to look into using--untracked=no option
+   when it takes too long.
+
+ * "git fetch" learned to fetch a commit at the tip of an unadvertised
+   ref by specifying a raw object name from the command line when the
+   server side supports this feature.
+
+ * "git count-objects -v" learned to report leftover temporary
+   packfiles and other garbage in the object store.
+
+ * A new read-only credential helper (in contrib/) to interact with
+   the .netrc/.authinfo files has been added.
+
+ * "git send-email" can be used with the credential helper system.
+
+
+Foreign Interface
+
+
+
+Performance, Internal Implementation, etc.
+
+ * Updates for building under msvc.
+
+ * A few codepaths knew how much data they need to put in the
+   hashtables they use upfront, but still started from a small table
+   repeatedly growing and rehashing.
+
+
+Also contains minor documentation updates and code clean-ups.
+
+
+Fixes since v1.8.2
+------------------
+
+Unless otherwise noted, all the fixes since v1.8.2 in the maintenance
+track are contained in this release (see release notes to them for
+details).
+
+ * Clarify in the documentation "what" gets pushed to "where" when the
+   command line to "git push" does not say these explicitly.
+   (merge cfe1348 jc/maint-push-refspec-default-doc later to maint).
+
+ * The "--color=<when>" argument to the commands in the diff family
+   was described poorly.
+   (merge 3d0e75f jc/color-diff-doc later to maint).
+
+ * The arguments given to pre-rebase hook were not documented.
+   (merge 0414acc wk/doc-pre-rebase later to maint).
+
+ * The v4 index format was not documented.
+   (merge 647d879 nd/doc-index-format later to maint).
+
+ * The "--match=<pattern>" argument "git describe" takes uses glob
+   pattern but it wasn't obvious from the documentation.
+   (merge 5229149 gp/describe-match-uses-glob-pattern later to maint).
+
+ * Some sources failed to compile on systems that lack NI_MAXHOST in
+   their system header (e.g. z/OS).
+   (merge 3b130ade dm/ni-maxhost-may-be-missing later to maint).
+
+ * Add an example use of "--env-filter" in "filter-branch"
+   documentation.
+   (merge 21b6e4f tk/doc-filter-branch later to maint).
+
+ * "git bundle verify" did not say "records a complete history" for a
+   bundle that does not have any prerequisites.
+   (merge a02ffe0 lf/bundle-verify-list-prereqs later to maint).
+
+ * In the v1.8.0 era, we changed symbols that do not have to be global
+   to file scope static, but a few functions in graph.c were used by
+   CGit from sideways bypassing the entry points of the API the
+   in-tree users use.
+   (merge ac751a0 jk/graph-c-expose-symbols-for-cgit later to maint).
+
+ * "git update-index -h" did not do the usual "-h(elp)" thing.
+
+ * "git index-pack" had a buffer-overflow while preparing an
+   informational message when the translated version of it was too
+   long.
+   (merge 5c3459f nd/index-pack-l10n-buf-overflow later to maint).
+
+ * 'git commit -m "$msg"' used to add an extra newline even when
+   $msg already ended with one.
+   (merge 46fbf75 bc/commit-complete-lines-given-via-m-option later to maint).
+
+ * The SSL peer verification done by "git imap-send" did not ask for
+   Server Name Indication (RFC 4366), failing to connect SSL/TLS
+   sites that serve multiple hostnames on a single IP.
+   (merge 698a1ec ob/imap-send-ssl-verify later to maint).
+
+ * perl/Git.pm::cat_blob slurped everything in core only to write it
+   out to a file descriptor, which was not a very smart thing to do.
+   (merge 712c6ad jc/perl-cat-blob later to maint).
+
+ * "git branch" did not bother to check nonsense command line
+   parameters and issue errors in many cases.
+   (merge 8efb889 nd/branch-error-cases later to maint).
+
+ * Verification of signed tags were not done correctly when not in C
+   or en/US locale.
+   (merge 0174eea mg/gpg-interface-using-status later to maint).
+
+ * Some platforms and users spell UTF-8 differently; retry with the
+   most official "UTF-8" when the system does not understand the
+   user-supplied encoding name that are the common alternative
+   spellings of UTF-8.
+   (merge 5c680be jk/utf-8-can-be-spelled-differently later to maint).
+
+ * When export-subst is used, "zip" output recorded incorrect
+   size of the file.
+   (merge d3c1472 rs/zip-compresssed-size-with-export-subst later to maint).
+
+ * "git am $maildir/" applied messages in an unexpected order; sort
+   filenames read from the maildir/ in a way that is more likely to
+   sort messages in the order the writing MUA meant to, by sorting
+   numeric segment in numeric order and non-numeric segment in
+   alphabetical order.
+   (merge 18505c3 jk/mailsplit-maildir-muttsort later to maint).
+
+ * "git submodule update", when recursed into sub-submodules, did not
+   acccumulate the prefix paths.
+   (merge 75bf5e6 we/submodule-update-prefix-output later to maint).
index bbba728d09bbb578f86c1ef171d24b53c1178fa3..c1f435f6df0b2e16d50546b61c2abab50b67acc0 100644 (file)
@@ -178,6 +178,10 @@ advice.*::
                the template shown when writing commit messages in
                linkgit:git-commit[1], and in the help message shown
                by linkgit:git-checkout[1] when switching branch.
+       statusUoption::
+               Advise to consider using the `-u` option to linkgit:git-status[1]
+               when the command takes more than 2 seconds to enumerate untracked
+               files.
        commitBeforeMerge::
                Advice shown when linkgit:git-merge[1] refuses to
                merge to avoid overwriting local changes.
@@ -443,7 +447,7 @@ core.sharedRepository::
 
 core.warnAmbiguousRefs::
        If true, Git will warn you if the ref name you passed it is ambiguous
-       and might match multiple refs in the .git/refs/ tree. True by default.
+       and might match multiple refs in the repository. True by default.
 
 core.compression::
        An integer -1..9, indicating a default compression level.
@@ -2119,7 +2123,13 @@ uploadpack.hiderefs::
        are under the hierarchies listed on the value of this
        variable is excluded, and is hidden from `git ls-remote`,
        `git fetch`, etc.  An attempt to fetch a hidden ref by `git
-       fetch` will fail.
+       fetch` will fail.  See also `uploadpack.allowtipsha1inwant`.
+
+uploadpack.allowtipsha1inwant::
+       When `uploadpack.hiderefs` is in effect, allow `upload-pack`
+       to accept a fetch request that asks for an object at the tip
+       of a hidden ref (by default, such a request is rejected).
+       see also `uploadpack.hiderefs`.
 
 url.<base>.insteadOf::
        Any URL that starts with this value will be rewritten to
index 0eb79ccdba6b74aaafec8cf71461053491b8c216..24a99ccc992555e01b9ac586e7bbbd9bb8332a6c 100644 (file)
@@ -172,16 +172,25 @@ OPTIONS
        linkgit:git-commit-tree[1].
 
 --cleanup=<mode>::
-       This option sets how the commit message is cleaned up.
-       The  '<mode>' can be one of 'verbatim', 'whitespace', 'strip',
-       and 'default'. The 'default' mode will strip leading and
-       trailing empty lines and #commentary from the commit message
-       only if the message is to be edited. Otherwise only whitespace
-       removed. The 'verbatim' mode does not change message at all,
-       'whitespace' removes just leading/trailing whitespace lines
-       and 'strip' removes both whitespace and commentary. The default
-       can be changed by the 'commit.cleanup' configuration variable
-       (see linkgit:git-config[1]).
+       This option determines how the supplied commit message should be
+       cleaned up before committing.  The '<mode>' can be `strip`,
+       `whitespace`, `verbatim`, or `default`.
++
+--
+strip::
+       Strip leading and trailing empty lines, trailing whitespace, and
+       #commentary and collapse consecutive empty lines.
+whitespace::
+       Same as `strip` except #commentary is not removed.
+verbatim::
+       Do not change the message at all.
+default::
+       Same as `strip` if the message is to be edited.
+       Otherwise `whitespace`.
+--
++
+The default can be changed by the 'commit.cleanup' configuration
+variable (see linkgit:git-config[1]).
 
 -e::
 --edit::
index 23c80cea6465d23476935abcfabba8e1deb915ee..da6e72e696d4af013b3c717d31a0e98cd41922d4 100644 (file)
@@ -20,11 +20,23 @@ OPTIONS
 -------
 -v::
 --verbose::
-       In addition to the number of loose objects and disk
-       space consumed, it reports the number of in-pack
-       objects, number of packs, disk space consumed by those packs,
-       and number of objects that can be removed by running
-       `git prune-packed`.
+       Report in more detail:
++
+count: the number of loose objects
++
+size: disk space consumed by loose objects, in KiB
++
+in-pack: the number of in-pack objects
++
+size-pack: disk space consumed by the packs, in KiB
++
+prune-packable: the number of loose objects that are also present in
+the packs. These objects could be pruned using `git prune-packed`.
++
+garbage: the number of files in object database that are not valid
+loose objects nor valid packs
++
+size-garbage: disk space consumed by garbage files, in KiB
 
 GIT
 ---
index 13980257eecd3e275641c1ba3262f4d4489f77ff..577d201c006ab6c72acef9bd800aa36f6cc356d3 100644 (file)
@@ -23,6 +23,17 @@ You can make interesting things happen to a repository
 every time you push into it, by setting up 'hooks' there.  See
 documentation for linkgit:git-receive-pack[1].
 
+When the command line does not specify where to push with the
+`<repository>` argument, `branch.*.remote` configuration for the
+current branch is consulted to determine where to push.  If the
+configuration is missing, it defaults to 'origin'.
+
+When the command line does not specify what to push with `<refspec>...`
+arguments or `--all`, `--mirror`, `--tags` options, the command finds
+the default `<refspec>` by consulting `remote.*.push` configuration,
+and if it is not found, honors `push.default` configuration to decide
+what to push (See gitlink:git-config[1] for the meaning of `push.default`).
+
 
 OPTIONS[[OPTIONS]]
 ------------------
@@ -33,13 +44,10 @@ OPTIONS[[OPTIONS]]
        of a remote (see the section <<REMOTES,REMOTES>> below).
 
 <refspec>...::
+       Specify what destination ref to update with what source object.
        The format of a <refspec> parameter is an optional plus
-       `+`, followed by the source ref <src>, followed
+       `+`, followed by the source object <src>, followed
        by a colon `:`, followed by the destination ref <dst>.
-       It is used to specify with what <src> object the <dst> ref
-       in the remote repository is to be updated.  If not specified,
-       the behavior of the command is controlled by the `push.default`
-       configuration variable.
 +
 The <src> is often the name of the branch you would want to push, but
 it can be any arbitrary "SHA-1 expression", such as `master~4` or
@@ -66,10 +74,7 @@ the remote repository.
 The special refspec `:` (or `+:` to allow non-fast-forward updates)
 directs Git to push "matching" branches: for every branch that exists on
 the local side, the remote side is updated if a branch of the same name
-already exists on the remote side.  This is the default operation mode
-if no explicit refspec is found (that is neither on the command line
-nor in any Push line of the corresponding remotes file---see below) and
-no `push.default` configuration variable is set.
+already exists on the remote side.
 
 --all::
        Instead of naming each ref to push, specifies that all
index 44a1f7c4e8efbc78813de7c3ba13816e68c984cd..0cffef8aa51cc5c2f34393e39e45e84c4997b195 100644 (file)
@@ -164,8 +164,8 @@ Sending
 Furthermore, passwords need not be specified in configuration files
 or on the command line. If a username has been specified (with
 '--smtp-user' or a 'sendemail.smtpuser'), but no password has been
-specified (with '--smtp-pass' or 'sendemail.smtppass'), then the
-user is prompted for a password while the input is masked for privacy.
+specified (with '--smtp-pass' or 'sendemail.smtppass'), then
+a password is obtained using 'git-credential'.
 
 --smtp-server=<host>::
        If set, specifies the outgoing SMTP server to use (e.g.
index 9b9250600f651eac7d6e2fd6ca7ff320a64de67c..c35051ba58b63cdc489b0ee3f4ffb72631b619e3 100644 (file)
@@ -9,25 +9,81 @@ git-shell - Restricted login shell for Git-only SSH access
 SYNOPSIS
 --------
 [verse]
-'git shell' [-c <command> <argument>]
+'chsh' -s $(command -v git-shell) <user>
+'git clone' <user>`@localhost:/path/to/repo.git`
+'ssh' <user>`@localhost`
 
 DESCRIPTION
 -----------
 
-A login shell for SSH accounts to provide restricted Git access. When
-'-c' is given, the program executes <command> non-interactively;
-<command> can be one of 'git receive-pack', 'git upload-pack', 'git
-upload-archive', 'cvs server', or a command in COMMAND_DIR. The shell
-is started in interactive mode when no arguments are given; in this
-case, COMMAND_DIR must exist, and any of the executables in it can be
-invoked.
+This is a login shell for SSH accounts to provide restricted Git access.
+It permits execution only of server-side Git commands implementing the
+pull/push functionality, plus custom commands present in a subdirectory
+named `git-shell-commands` in the user's home directory.
 
-'cvs server' is a special command which executes git-cvsserver.
+COMMANDS
+--------
+
+'git shell' accepts the following commands after the '-c' option:
+
+'git receive-pack <argument>'::
+'git upload-pack <argument>'::
+'git upload-archive <argument>'::
+       Call the corresponding server-side command to support
+       the client's 'git push', 'git fetch', or 'git archive --remote'
+       request.
+'cvs server'::
+       Imitate a CVS server.  See linkgit:git-cvsserver[1].
+
+If a `~/git-shell-commands` directory is present, 'git shell' will
+also handle other, custom commands by running
+"`git-shell-commands/<command> <arguments>`" from the user's home
+directory.
+
+INTERACTIVE USE
+---------------
+
+By default, the commands above can be executed only with the '-c'
+option; the shell is not interactive.
 
-COMMAND_DIR is the path "$HOME/git-shell-commands". The user must have
-read and execute permissions to the directory in order to execute the
-programs in it. The programs are executed with a cwd of $HOME, and
-<argument> is parsed as a command-line string.
+If a `~/git-shell-commands` directory is present, 'git shell'
+can also be run interactively (with no arguments).  If a `help`
+command is present in the `git-shell-commands` directory, it is
+run to provide the user with an overview of allowed actions.  Then a
+"git> " prompt is presented at which one can enter any of the
+commands from the `git-shell-commands` directory, or `exit` to close
+the connection.
+
+Generally this mode is used as an administrative interface to allow
+users to list repositories they have access to, create, delete, or
+rename repositories, or change repository descriptions and
+permissions.
+
+If a `no-interactive-login` command exists, then it is run and the
+interactive shell is aborted.
+
+EXAMPLE
+-------
+
+To disable interactive logins, displaying a greeting instead:
++
+----------------
+$ chsh -s /usr/bin/git-shell
+$ mkdir $HOME/git-shell-commands
+$ cat >$HOME/git-shell-commands/no-interactive-login <<\EOF
+#!/bin/sh
+printf '%s\n' "Hi $USER! You've successfully authenticated, but I do not"
+printf '%s\n' "provide interactive shell access."
+exit 128
+EOF
+$ chmod +x $HOME/git-shell-commands/no-interactive-login
+----------------
+
+SEE ALSO
+--------
+ssh(1),
+linkgit:git-daemon[1],
+contrib/git-shell-commands/README
 
 GIT
 ---
index 0412c4017d07814804ab9e9adcbf2a8d0de0304f..9046df98a03fe11a203f06d79be0128309a201c5 100644 (file)
@@ -46,15 +46,21 @@ OPTIONS
        Show untracked files.
 +
 The mode parameter is optional (defaults to 'all'), and is used to
-specify the handling of untracked files; when -u is not used, the
-default is 'normal', i.e. show untracked files and directories.
+specify the handling of untracked files.
 +
 The possible options are:
 +
-       - 'no'     - Show no untracked files
-       - 'normal' - Shows untracked files and directories
+       - 'no'     - Show no untracked files.
+       - 'normal' - Shows untracked files and directories.
        - 'all'    - Also shows individual files in untracked directories.
 +
+When `-u` option is not used, untracked files and directories are
+shown (i.e. the same as specifying `normal`), to help you avoid
+forgetting to add newly created files.  Because it takes extra work
+to find untracked files in the filesystem, this mode may take some
+time in a large working tree.  You can use `no` to have `git status`
+return more quickly without showing untracked files.
++
 The default can be changed using the status.showUntrackedFiles
 configuration variable documented in linkgit:git-config[1].
 
index dc9e617a10d58769a5338d06794f338ba9970d08..9ac5088acd3e0cf9541ef097c26f19c5f462b770 100644 (file)
@@ -107,13 +107,14 @@ couple of magic command line options:
 ---------------------------------------------
 $ git describe -h
 usage: git describe [options] <committish>*
+   or: git describe [options] --dirty
 
     --contains            find the tag that comes after the commit
     --debug               debug search strategy on stderr
-    --all                 use any ref in .git/refs
-    --tags                use any tag in .git/refs/tags
-    --abbrev [<n>]        use <n> digits to display SHA-1s
-    --candidates <n>      consider <n> most recent tags (default: 10)
+    --all                 use any ref
+    --tags                use any tag, even unannotated
+    --long                always use long format
+    --abbrev[=<n>]        use <n> digits to display SHA-1s
 ---------------------------------------------
 
 --help-all::
index 105f18a6f9fd9f4a5a388cb3ec8a0e6a99f7abe3..293965524e81b240996a795498ba127f723d18eb 100644 (file)
@@ -133,6 +133,7 @@ The placeholders are:
 - '%GG': raw verification message from GPG for a signed commit
 - '%G?': show either "G" for Good or "B" for Bad for a signed commit
 - '%GS': show the name of the signer for a signed commit
+- '%GK': show the key used to sign a signed commit
 - '%gD': reflog selector, e.g., `refs/stash@{1}`
 - '%gd': shortened reflog selector, e.g., `stash@{1}`
 - '%gn': reflog identity name
index 5f36f8115ffdceec7d3f9e57c9f2c645f3936ad1..e831cc2020b2b728d972c9e33f7fef8041381547 100644 (file)
@@ -19,7 +19,7 @@ Further chapters cover more specialized topics.
 
 Comprehensive reference documentation is available through the man
 pages, or linkgit:git-help[1] command.  For example, for the command
-"git clone <repo>", you can either use:
+`git clone <repo>`, you can either use:
 
 ------------------------------------------------
 $ man git-clone
@@ -66,11 +66,11 @@ $ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
 The initial clone may be time-consuming for a large project, but you
 will only need to clone once.
 
-The clone command creates a new directory named after the project ("git"
-or "linux-2.6" in the examples above).  After you cd into this
+The clone command creates a new directory named after the project (`git`
+or `linux-2.6` in the examples above).  After you cd into this
 directory, you will see that it contains a copy of the project files,
 called the <<def_working_tree,working tree>>, together with a special
-top-level directory named ".git", which contains all the information
+top-level directory named `.git`, which contains all the information
 about the history of the project.
 
 [[how-to-check-out]]
@@ -188,7 +188,7 @@ As you can see, a commit shows who made the latest change, what they
 did, and why.
 
 Every commit has a 40-hexdigit id, sometimes called the "object name" or the
-"SHA-1 id", shown on the first line of the "git show" output.  You can usually
+"SHA-1 id", shown on the first line of the `git show` output.  You can usually
 refer to a commit by a shorter name, such as a tag or a branch name, but this
 longer name can also be useful.  Most importantly, it is a globally unique
 name for this commit: so if you tell somebody else the object name (for
@@ -268,35 +268,35 @@ Manipulating branches
 Creating, deleting, and modifying branches is quick and easy; here's
 a summary of the commands:
 
-git branch::
+`git branch`::
        list all branches
-git branch <branch>::
-       create a new branch named <branch>, referencing the same
+`git branch <branch>`::
+       create a new branch named `<branch>`, referencing the same
        point in history as the current branch
-git branch <branch> <start-point>::
-       create a new branch named <branch>, referencing
-       <start-point>, which may be specified any way you like,
+`git branch <branch> <start-point>`::
+       create a new branch named `<branch>`, referencing
+       `<start-point>`, which may be specified any way you like,
        including using a branch name or a tag name
-git branch -d <branch>::
-       delete the branch <branch>; if the branch you are deleting
+`git branch -d <branch>`::
+       delete the branch `<branch>`; if the branch you are deleting
        points to a commit which is not reachable from the current
        branch, this command will fail with a warning.
-git branch -D <branch>::
+`git branch -D <branch>`::
        even if the branch points to a commit not reachable
        from the current branch, you may know that that commit
        is still reachable from some other branch or tag.  In that
        case it is safe to use this command to force Git to delete
        the branch.
-git checkout <branch>::
-       make the current branch <branch>, updating the working
-       directory to reflect the version referenced by <branch>
-git checkout -b <new> <start-point>::
-       create a new branch <new> referencing <start-point>, and
+`git checkout <branch>`::
+       make the current branch `<branch>`, updating the working
+       directory to reflect the version referenced by `<branch>`
+`git checkout -b <new> <start-point>`::
+       create a new branch `<new>` referencing `<start-point>`, and
        check it out.
 
 The special symbol "HEAD" can always be used to refer to the current
-branch.  In fact, Git uses a file named "HEAD" in the .git directory to
-remember which branch is current:
+branch.  In fact, Git uses a file named `HEAD` in the `.git` directory
+to remember which branch is current:
 
 ------------------------------------------------
 $ cat .git/HEAD
@@ -346,7 +346,7 @@ of the HEAD in the repository that you cloned from.  That repository
 may also have had other branches, though, and your local repository
 keeps branches which track each of those remote branches, called
 remote-tracking branches, which you
-can view using the "-r" option to linkgit:git-branch[1]:
+can view using the `-r` option to linkgit:git-branch[1]:
 
 ------------------------------------------------
 $ git branch -r
@@ -364,7 +364,7 @@ In this example, "origin" is called a remote repository, or "remote"
 for short. The branches of this repository are called "remote
 branches" from our point of view. The remote-tracking branches listed
 above were created based on the remote branches at clone time and will
-be updated by "git fetch" (hence "git pull") and "git push". See
+be updated by `git fetch` (hence `git pull`) and `git push`. See
 <<Updating-a-repository-With-git-fetch>> for details.
 
 You might want to build on one of these remote-tracking branches
@@ -374,7 +374,7 @@ on a branch of your own, just as you would for a tag:
 $ git checkout -b my-todo-copy origin/todo
 ------------------------------------------------
 
-You can also check out "origin/todo" directly to examine it or
+You can also check out `origin/todo` directly to examine it or
 write a one-off patch.  See <<detached-head,detached head>>.
 
 Note that the name "origin" is just the name that Git uses by default
@@ -386,17 +386,17 @@ Naming branches, tags, and other references
 
 Branches, remote-tracking branches, and tags are all references to
 commits.  All references are named with a slash-separated path name
-starting with "refs"; the names we've been using so far are actually
+starting with `refs`; the names we've been using so far are actually
 shorthand:
 
-       - The branch "test" is short for "refs/heads/test".
-       - The tag "v2.6.18" is short for "refs/tags/v2.6.18".
-       - "origin/master" is short for "refs/remotes/origin/master".
+       - The branch `test` is short for `refs/heads/test`.
+       - The tag `v2.6.18` is short for `refs/tags/v2.6.18`.
+       - `origin/master` is short for `refs/remotes/origin/master`.
 
 The full name is occasionally useful if, for example, there ever
 exists a tag and a branch with the same name.
 
-(Newly created refs are actually stored in the .git/refs directory,
+(Newly created refs are actually stored in the `.git/refs` directory,
 under the path given by their name.  However, for efficiency reasons
 they may also be packed together in a single file; see
 linkgit:git-pack-refs[1]).
@@ -418,7 +418,7 @@ Eventually the developer cloned from will do additional work in her
 repository, creating new commits and advancing the branches to point
 at the new commits.
 
-The command "git fetch", with no arguments, will update all of the
+The command `git fetch`, with no arguments, will update all of the
 remote-tracking branches to the latest version found in her
 repository.  It will not touch any of your own branches--not even the
 "master" branch that was created for you on clone.
@@ -438,7 +438,7 @@ $ git fetch linux-nfs
 -------------------------------------------------
 
 New remote-tracking branches will be stored under the shorthand name
-that you gave "git remote add", in this case linux-nfs:
+that you gave `git remote add`, in this case `linux-nfs`:
 
 -------------------------------------------------
 $ git branch -r
@@ -446,10 +446,10 @@ linux-nfs/master
 origin/master
 -------------------------------------------------
 
-If you run "git fetch <remote>" later, the remote-tracking branches for the
-named <remote> will be updated.
+If you run `git fetch <remote>` later, the remote-tracking branches
+for the named `<remote>` will be updated.
 
-If you examine the file .git/config, you will see that Git has added
+If you examine the file `.git/config`, you will see that Git has added
 a new stanza:
 
 -------------------------------------------------
@@ -462,7 +462,7 @@ $ cat .git/config
 -------------------------------------------------
 
 This is what causes Git to track the remote's branches; you may modify
-or delete these configuration options by editing .git/config with a
+or delete these configuration options by editing `.git/config` with a
 text editor.  (See the "CONFIGURATION FILE" section of
 linkgit:git-config[1] for details.)
 
@@ -499,7 +499,7 @@ Bisecting: 3537 revisions left to test after this
 [65934a9a028b88e83e2b0f8b36618fe503349f8e] BLOCK: Make USB storage depend on SCSI rather than selecting it [try #6]
 -------------------------------------------------
 
-If you run "git branch" at this point, you'll see that Git has
+If you run `git branch` at this point, you'll see that Git has
 temporarily moved you in "(no branch)". HEAD is now detached from any
 branch and points directly to a commit (with commit id 65934...) that
 is reachable from "master" but not from v2.6.18. Compile and test it,
@@ -545,11 +545,11 @@ id, and check it out with:
 $ git reset --hard fb47ddb2db...
 -------------------------------------------------
 
-then test, run "bisect good" or "bisect bad" as appropriate, and
+then test, run `bisect good` or `bisect bad` as appropriate, and
 continue.
 
-Instead of "git bisect visualize" and then "git reset --hard
-fb47ddb2db...", you might just want to tell Git that you want to skip
+Instead of `git bisect visualize` and then `git reset --hard
+fb47ddb2db...`, you might just want to tell Git that you want to skip
 the current commit:
 
 -------------------------------------------------
@@ -561,8 +561,8 @@ bad one between some first skipped commits and a later bad commit.
 
 There are also ways to automate the bisecting process if you have a
 test script that can tell a good from a bad commit. See
-linkgit:git-bisect[1] for more information about this and other "git
-bisect" features.
+linkgit:git-bisect[1] for more information about this and other `git
+bisect` features.
 
 [[naming-commits]]
 Naming commits
@@ -591,7 +591,7 @@ $ git show HEAD~4   # the great-great-grandparent
 -------------------------------------------------
 
 Recall that merge commits may have more than one parent; by default,
-^ and ~ follow the first parent listed in the commit, but you can
+`^` and `~` follow the first parent listed in the commit, but you can
 also choose:
 
 -------------------------------------------------
@@ -640,7 +640,7 @@ running
 $ git tag stable-1 1b2e1d63ff
 -------------------------------------------------
 
-You can use stable-1 to refer to the commit 1b2e1d63ff.
+You can use `stable-1` to refer to the commit 1b2e1d63ff.
 
 This creates a "lightweight" tag.  If you would also like to include a
 comment with the tag, and possibly sign it cryptographically, then you
@@ -669,7 +669,7 @@ $ git log -S'foo()' # commits which add or remove any file data
 -------------------------------------------------
 
 And of course you can combine all of these; the following finds
-commits since v2.5 which touch the Makefile or any file under fs:
+commits since v2.5 which touch the `Makefile` or any file under `fs`:
 
 -------------------------------------------------
 $ git log v2.5.. Makefile fs/
@@ -681,7 +681,7 @@ You can also ask git log to show patches:
 $ git log -p
 -------------------------------------------------
 
-See the "--pretty" option in the linkgit:git-log[1] man page for more
+See the `--pretty` option in the linkgit:git-log[1] man page for more
 display options.
 
 Note that git log starts with the most recent commit and works
@@ -742,8 +742,8 @@ Examples
 Counting the number of commits on a branch
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-Suppose you want to know how many commits you've made on "mybranch"
-since it diverged from "origin":
+Suppose you want to know how many commits you've made on `mybranch`
+since it diverged from `origin`:
 
 -------------------------------------------------
 $ git log --pretty=oneline origin..mybranch | wc -l
@@ -780,7 +780,7 @@ $ git rev-list master
 e05db0fd4f31dde7005f075a84f96b360d05984b
 -------------------------------------------------
 
-Or you could recall that the ... operator selects all commits
+Or you could recall that the `...` operator selects all commits
 contained reachable from either one reference or the other but not
 both; so
 
@@ -880,7 +880,7 @@ Showing commits unique to a given branch
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Suppose you would like to see all the commits reachable from the branch
-head named "master" but not from any other head in your repository.
+head named `master` but not from any other head in your repository.
 
 We can list all the heads in this repository with
 linkgit:git-show-ref[1]:
@@ -894,7 +894,7 @@ a07157ac624b2524a059a3414e99f6f44bebc1e7 refs/heads/master
 1e87486ae06626c2f31eaa63d26fc0fd646c8af2 refs/heads/tutorial-fixes
 -------------------------------------------------
 
-We can get just the branch-head names, and remove "master", with
+We can get just the branch-head names, and remove `master`, with
 the help of the standard utilities cut and grep:
 
 -------------------------------------------------
@@ -939,7 +939,7 @@ is preceded by `project/`.  The output file format is inferred from
 the output file extension if possible, see linkgit:git-archive[1] for
 details.
 
-Versions of Git older than 1.7.7 don't know about the 'tar.gz' format,
+Versions of Git older than 1.7.7 don't know about the `tar.gz` format,
 you'll need to use gzip explicitly:
 
 -------------------------------------------------
@@ -1062,7 +1062,7 @@ at step 3, Git maintains a snapshot of the tree's contents in a
 special staging area called "the index."
 
 At the beginning, the content of the index will be identical to
-that of the HEAD.  The command "git diff --cached", which shows
+that of the HEAD.  The command `git diff --cached`, which shows
 the difference between the HEAD and the index, should therefore
 produce no output at that point.
 
@@ -1101,7 +1101,7 @@ $ git diff
 
 shows the difference between the working tree and the index file.
 
-Note that "git add" always adds just the current contents of a file
+Note that `git add` always adds just the current contents of a file
 to the index; further changes to the same file will be ignored unless
 you run `git add` on the file again.
 
@@ -1172,8 +1172,9 @@ annoying to have these untracked files lying around; e.g. they make
 `git add .` practically useless, and they keep showing up in the output of
 `git status`.
 
-You can tell Git to ignore certain files by creating a file called .gitignore
-in the top level of your working directory, with contents such as:
+You can tell Git to ignore certain files by creating a file called
+`.gitignore` in the top level of your working directory, with contents
+such as:
 
 -------------------------------------------------
 # Lines starting with '#' are considered comments.
@@ -1197,10 +1198,10 @@ for other users who clone your repository.
 
 If you wish the exclude patterns to affect only certain repositories
 (instead of every repository for a given project), you may instead put
-them in a file in your repository named .git/info/exclude, or in any file
-specified by the `core.excludesfile` configuration variable.  Some Git
-commands can also take exclude patterns directly on the command line.
-See linkgit:gitignore[5] for the details.
+them in a file in your repository named `.git/info/exclude`, or in any
+file specified by the `core.excludesfile` configuration variable.
+Some Git commands can also take exclude patterns directly on the
+command line.  See linkgit:gitignore[5] for the details.
 
 [[how-to-merge]]
 How to merge
@@ -1213,10 +1214,10 @@ linkgit:git-merge[1]:
 $ git merge branchname
 -------------------------------------------------
 
-merges the development in the branch "branchname" into the current
+merges the development in the branch `branchname` into the current
 branch.
 
-A merge is made by combining the changes made in "branchname" and the
+A merge is made by combining the changes made in `branchname` and the
 changes made up to the latest commit in your current branch since
 their histories forked. The work tree is overwritten by the result of
 the merge when this combining is done cleanly, or overwritten by a
@@ -1338,7 +1339,7 @@ that part is not conflicting and is not shown.  Same for stage 3).
 
 The diff above shows the differences between the working-tree version of
 file.txt and the stage 2 and stage 3 versions.  So instead of preceding
-each line by a single "+" or "-", it now uses two columns: the first
+each line by a single `+` or `-`, it now uses two columns: the first
 column is used for differences between the first parent and the working
 directory copy, and the second for differences between the second parent
 and the working directory copy.  (See the "COMBINED DIFF FORMAT" section
@@ -1613,7 +1614,7 @@ dangling tree b24c2473f1fd3d91352a624795be026d64c8841f
 
 You will see informational messages on dangling objects. They are objects
 that still exist in the repository but are no longer referenced by any of
-your branches, and can (and will) be removed after a while with "gc".
+your branches, and can (and will) be removed after a while with `gc`.
 You can run `git fsck --no-dangling` to suppress these messages, and still
 view real errors.
 
@@ -1625,9 +1626,9 @@ Recovering lost changes
 Reflogs
 ^^^^^^^
 
-Say you modify a branch with +linkgit:git-reset[1] \--hard+, and then
-realize that the branch was the only reference you had to that point in
-history.
+Say you modify a branch with <<fixing-mistakes,`git reset --hard`>>,
+and then realize that the branch was the only reference you had to
+that point in history.
 
 Fortunately, Git also keeps a log, called a "reflog", of all the
 previous values of each branch.  So in this case you can still find the
@@ -1638,8 +1639,8 @@ $ git log master@{1}
 -------------------------------------------------
 
 This lists the commits reachable from the previous version of the
-"master" branch head.  This syntax can be used with any Git command
-that accepts a commit, not just with git log.  Some other examples:
+`master` branch head.  This syntax can be used with any Git command
+that accepts a commit, not just with `git log`.  Some other examples:
 
 -------------------------------------------------
 $ git show master@{2}          # See where the branch pointed 2,
@@ -1743,8 +1744,8 @@ one step:
 $ git pull origin master
 -------------------------------------------------
 
-In fact, if you have "master" checked out, then this branch has been
-configured by "git clone" to get changes from the HEAD branch of the
+In fact, if you have `master` checked out, then this branch has been
+configured by `git clone` to get changes from the HEAD branch of the
 origin repository.  So often you can
 accomplish the above with just a simple
 
@@ -1759,11 +1760,11 @@ the current branch.
 More generally, a branch that is created from a remote-tracking branch
 will pull
 by default from that branch.  See the descriptions of the
-branch.<name>.remote and branch.<name>.merge options in
+`branch.<name>.remote` and `branch.<name>.merge` options in
 linkgit:git-config[1], and the discussion of the `--track` option in
 linkgit:git-checkout[1], to learn how to control these defaults.
 
-In addition to saving you keystrokes, "git pull" also helps you by
+In addition to saving you keystrokes, `git pull` also helps you by
 producing a default commit message documenting the branch and
 repository that you pulled from.
 
@@ -1771,7 +1772,7 @@ repository that you pulled from.
 <<fast-forwards,fast-forward>>; instead, your branch will just be
 updated to point to the latest commit from the upstream branch.)
 
-The `git pull` command can also be given "." as the "remote" repository,
+The `git pull` command can also be given `.` as the "remote" repository,
 in which case it just merges in a branch from the current repository; so
 the commands
 
@@ -1796,7 +1797,7 @@ $ git format-patch origin
 -------------------------------------------------
 
 will produce a numbered series of files in the current directory, one
-for each patch in the current branch but not in origin/HEAD.
+for each patch in the current branch but not in `origin/HEAD`.
 
 `git format-patch` can include an initial "cover letter". You can insert
 commentary on individual patches after the three dash line which
@@ -1818,7 +1819,7 @@ Importing patches to a project
 Git also provides a tool called linkgit:git-am[1] (am stands for
 "apply mailbox"), for importing such an emailed series of patches.
 Just save all of the patch-containing messages, in order, into a
-single mailbox file, say "patches.mbox", then run
+single mailbox file, say `patches.mbox`, then run
 
 -------------------------------------------------
 $ git am -3 patches.mbox
@@ -1826,7 +1827,7 @@ $ git am -3 patches.mbox
 
 Git will apply each patch in order; if any conflicts are found, it
 will stop, and you can fix the conflicts as described in
-"<<resolving-a-merge,Resolving a merge>>".  (The "-3" option tells
+"<<resolving-a-merge,Resolving a merge>>".  (The `-3` option tells
 Git to perform a merge; if you would prefer it just to abort and
 leave your tree and index untouched, you may omit that option.)
 
@@ -1902,7 +1903,7 @@ We explain how to do this in the following sections.
 Setting up a public repository
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-Assume your personal repository is in the directory ~/proj.  We
+Assume your personal repository is in the directory `~/proj`.  We
 first create a new clone of the repository and tell `git daemon` that it
 is meant to be public:
 
@@ -1912,10 +1913,10 @@ $ touch proj.git/git-daemon-export-ok
 -------------------------------------------------
 
 The resulting directory proj.git contains a "bare" git repository--it is
-just the contents of the ".git" directory, without any files checked out
+just the contents of the `.git` directory, without any files checked out
 around it.
 
-Next, copy proj.git to the server where you plan to host the
+Next, copy `proj.git` to the server where you plan to host the
 public repository.  You can use scp, rsync, or whatever is most
 convenient.
 
@@ -1926,8 +1927,8 @@ Exporting a Git repository via the Git protocol
 This is the preferred method.
 
 If someone else administers the server, they should tell you what
-directory to put the repository in, and what git:// URL it will appear
-at.  You can then skip to the section
+directory to put the repository in, and what `git://` URL it will
+appear at.  You can then skip to the section
 "<<pushing-changes-to-a-public-repository,Pushing changes to a public
 repository>>", below.
 
@@ -1962,7 +1963,7 @@ $ mv hooks/post-update.sample hooks/post-update
 (For an explanation of the last two lines, see
 linkgit:git-update-server-info[1] and linkgit:githooks[5].)
 
-Advertise the URL of proj.git.  Anybody else should then be able to
+Advertise the URL of `proj.git`.  Anybody else should then be able to
 clone or pull from that URL, for example with a command line like:
 
 -------------------------------------------------
@@ -1985,8 +1986,8 @@ access, which you will need to update the public repository with the
 latest changes created in your private repository.
 
 The simplest way to do this is using linkgit:git-push[1] and ssh; to
-update the remote branch named "master" with the latest state of your
-branch named "master", run
+update the remote branch named `master` with the latest state of your
+branch named `master`, run
 
 -------------------------------------------------
 $ git push ssh://yourserver.com/~you/proj.git master:master
@@ -2002,7 +2003,7 @@ As with `git fetch`, `git push` will complain if this does not result in a
 <<fast-forwards,fast-forward>>; see the following section for details on
 handling this case.
 
-Note that the target of a "push" is normally a
+Note that the target of a `push` is normally a
 <<def_bare_repository,bare>> repository.  You can also push to a
 repository that has a checked-out working tree, but a push to update the
 currently checked-out branch is denied by default to prevent confusion.
@@ -2030,9 +2031,9 @@ which lets you do the same push with just
 $ git push public-repo master
 -------------------------------------------------
 
-See the explanations of the remote.<name>.url, branch.<name>.remote,
-and remote.<name>.push options in linkgit:git-config[1] for
-details.
+See the explanations of the `remote.<name>.url`,
+`branch.<name>.remote`, and `remote.<name>.push` options in
+linkgit:git-config[1] for details.
 
 [[forcing-push]]
 What to do when a push fails
@@ -2167,7 +2168,7 @@ linkgit:git-fetch[1] to keep them up-to-date; see
 
 Now create the branches in which you are going to work; these start out
 at the current tip of origin/master branch, and should be set up (using
-the --track option to linkgit:git-branch[1]) to merge changes in from
+the `--track` option to linkgit:git-branch[1]) to merge changes in from
 Linus by default.
 
 -------------------------------------------------
@@ -2186,7 +2187,7 @@ Important note!  If you have any local changes in these branches, then
 this merge will create a commit object in the history (with no local
 changes Git will simply do a "fast-forward" merge).  Many people dislike
 the "noise" that this creates in the Linux history, so you should avoid
-doing this capriciously in the "release" branch, as these noisy commits
+doing this capriciously in the `release` branch, as these noisy commits
 will become part of the permanent history when you ask Linus to pull
 from the release branch.
 
@@ -2228,7 +2229,7 @@ patches), and create a new branch from a recent stable tag of
 Linus's branch. Picking a stable base for your branch will:
 1) help you: by avoiding inclusion of unrelated and perhaps lightly
 tested changes
-2) help future bug hunters that use "git bisect" to find problems
+2) help future bug hunters that use `git bisect` to find problems
 
 -------------------------------------------------
 $ git checkout -b speed-up-spinlocks v2.6.35
@@ -2253,9 +2254,9 @@ It is unlikely that you would have any conflicts here ... but you might if you
 spent a while on this step and had also pulled new versions from upstream.
 
 Some time later when enough time has passed and testing done, you can pull the
-same branch into the "release" tree ready to go upstream.  This is where you
+same branch into the `release` tree ready to go upstream.  This is where you
 see the value of keeping each patch (or patch series) in its own branch.  It
-means that the patches can be moved into the "release" tree in any order.
+means that the patches can be moved into the `release` tree in any order.
 
 -------------------------------------------------
 $ git checkout release && git pull . speed-up-spinlocks
@@ -2288,7 +2289,7 @@ If it has been merged, then there will be no output.)
 
 Once a patch completes the great cycle (moving from test to release,
 then pulled by Linus, and finally coming back into your local
-"origin/master" branch), the branch for this change is no longer needed.
+`origin/master` branch), the branch for this change is no longer needed.
 You detect this when the output from:
 
 -------------------------------------------------
@@ -2303,8 +2304,8 @@ $ git branch -d branchname
 
 Some changes are so trivial that it is not necessary to create a separate
 branch and then merge into each of the test and release branches.  For
-these changes, just apply directly to the "release" branch, and then
-merge that into the "test" branch.
+these changes, just apply directly to the `release` branch, and then
+merge that into the `test` branch.
 
 After pushing your work to `mytree`, you can use
 linkgit:git-request-pull[1] to prepare a "please pull" request message
@@ -2337,7 +2338,7 @@ origin)
        fi
        ;;
 *)
-       echo "Usage: $0 origin|test|release" 1>&2
+       echo "usage: $0 origin|test|release" 1>&2
        exit 1
        ;;
 esac
@@ -2351,7 +2352,7 @@ pname=$0
 
 usage()
 {
-       echo "Usage: $pname branch test|release" 1>&2
+       echo "usage: $pname branch test|release" 1>&2
        exit 1
 }
 
@@ -2475,8 +2476,8 @@ you are rewriting history.
 Keeping a patch series up to date using git rebase
 --------------------------------------------------
 
-Suppose that you create a branch "mywork" on a remote-tracking branch
-"origin", and create some commits on top of it:
+Suppose that you create a branch `mywork` on a remote-tracking branch
+`origin`, and create some commits on top of it:
 
 -------------------------------------------------
 $ git checkout -b mywork origin
@@ -2488,7 +2489,7 @@ $ git commit
 -------------------------------------------------
 
 You have performed no merges into mywork, so it is just a simple linear
-sequence of patches on top of "origin":
+sequence of patches on top of `origin`:
 
 ................................................
  o--o--O <-- origin
@@ -2497,7 +2498,7 @@ sequence of patches on top of "origin":
 ................................................
 
 Some more interesting work has been done in the upstream project, and
-"origin" has advanced:
+`origin` has advanced:
 
 ................................................
  o--o--O--o--o--o <-- origin
@@ -2505,7 +2506,7 @@ Some more interesting work has been done in the upstream project, and
          a--b--c <-- mywork
 ................................................
 
-At this point, you could use "pull" to merge your changes back in;
+At this point, you could use `pull` to merge your changes back in;
 the result would create a new merge commit, like this:
 
 ................................................
@@ -2524,7 +2525,7 @@ $ git rebase origin
 -------------------------------------------------
 
 This will remove each of your commits from mywork, temporarily saving
-them as patches (in a directory named ".git/rebase-apply"), update mywork to
+them as patches (in a directory named `.git/rebase-apply`), update mywork to
 point at the latest version of origin, then apply each of the saved
 patches to the new mywork.  The result will look like:
 
@@ -2795,10 +2796,10 @@ arbitrary name:
 $ git fetch origin todo:my-todo-work
 -------------------------------------------------
 
-The first argument, "origin", just tells Git to fetch from the
+The first argument, `origin`, just tells Git to fetch from the
 repository you originally cloned from.  The second argument tells Git
-to fetch the branch named "todo" from the remote repository, and to
-store it locally under the name refs/heads/my-todo-work.
+to fetch the branch named `todo` from the remote repository, and to
+store it locally under the name `refs/heads/my-todo-work`.
 
 You can also fetch branches from other repositories; so
 
@@ -2806,8 +2807,8 @@ You can also fetch branches from other repositories; so
 $ git fetch git://example.com/proj.git master:example-master
 -------------------------------------------------
 
-will create a new branch named "example-master" and store in it the
-branch named "master" from the repository at the given URL.  If you
+will create a new branch named `example-master` and store in it the
+branch named `master` from the repository at the given URL.  If you
 already have a branch named example-master, it will attempt to
 <<fast-forwards,fast-forward>> to the commit given by example.com's
 master branch.  In more detail:
@@ -2816,7 +2817,7 @@ master branch.  In more detail:
 git fetch and fast-forwards
 ---------------------------
 
-In the previous example, when updating an existing branch, "git fetch"
+In the previous example, when updating an existing branch, `git fetch`
 checks to make sure that the most recent commit on the remote
 branch is a descendant of the most recent commit on your copy of the
 branch before updating your copy of the branch to point at the new
@@ -2842,11 +2843,11 @@ resulting in a situation like:
             o--o--o <-- new head of the branch
 ................................................
 
-In this case, "git fetch" will fail, and print out a warning.
+In this case, `git fetch` will fail, and print out a warning.
 
 In that case, you can still force Git to update to the new head, as
 described in the following section.  However, note that in the
-situation above this may mean losing the commits labeled "a" and "b",
+situation above this may mean losing the commits labeled `a` and `b`,
 unless you've already created a reference of your own pointing to
 them.
 
@@ -2861,7 +2862,7 @@ descendant of the old head, you may force the update with:
 $ git fetch git://example.com/proj.git +master:refs/remotes/example/master
 -------------------------------------------------
 
-Note the addition of the "+" sign.  Alternatively, you can use the "-f"
+Note the addition of the `+` sign.  Alternatively, you can use the `-f`
 flag to force updates of all the fetched branches, as in:
 
 -------------------------------------------------
@@ -2875,7 +2876,7 @@ may be lost, as we saw in the previous section.
 Configuring remote-tracking branches
 ------------------------------------
 
-We saw above that "origin" is just a shortcut to refer to the
+We saw above that `origin` is just a shortcut to refer to the
 repository that you originally cloned from.  This information is
 stored in Git configuration variables, which you can see using
 linkgit:git-config[1]:
@@ -2984,7 +2985,7 @@ Commit Object
 ~~~~~~~~~~~~~
 
 The "commit" object links a physical state of a tree with a description
-of how we got there and why.  Use the --pretty=raw option to
+of how we got there and why.  Use the `--pretty=raw` option to
 linkgit:git-show[1] or linkgit:git-log[1] to examine your favorite
 commit:
 
@@ -3026,7 +3027,7 @@ of the tree referred to by this commit with the trees associated with
 its parents.  In particular, Git does not attempt to record file renames
 explicitly, though it can identify cases where the existence of the same
 file data at changing paths suggests a rename.  (See, for example, the
--M option to linkgit:git-diff[1]).
+`-M` option to linkgit:git-diff[1]).
 
 A commit is usually created by linkgit:git-commit[1], which creates a
 commit whose parent is normally the current HEAD, and whose tree is
@@ -3077,7 +3078,7 @@ Blob Object
 ~~~~~~~~~~~
 
 You can use linkgit:git-show[1] to examine the contents of a blob; take,
-for example, the blob in the entry for "COPYING" from the tree above:
+for example, the blob in the entry for `COPYING` from the tree above:
 
 ------------------------------------------------
 $ git show 6ff87c4664
@@ -3160,14 +3161,14 @@ nLE/L9aUXdWeTFPron96DLA=
 See the linkgit:git-tag[1] command to learn how to create and verify tag
 objects.  (Note that linkgit:git-tag[1] can also be used to create
 "lightweight tags", which are not tag objects at all, but just simple
-references whose names begin with "refs/tags/").
+references whose names begin with `refs/tags/`).
 
 [[pack-files]]
 How Git stores objects efficiently: pack files
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Newly created objects are initially created in a file named after the
-object's SHA-1 hash (stored in .git/objects).
+object's SHA-1 hash (stored in `.git/objects`).
 
 Unfortunately this system becomes inefficient once a project has a
 lot of objects.  Try this on an old project:
@@ -3208,9 +3209,9 @@ $ git prune
 
 to remove any of the "loose" objects that are now contained in the
 pack.  This will also remove any unreferenced objects (which may be
-created when, for example, you use "git reset" to remove a commit).
+created when, for example, you use `git reset` to remove a commit).
 You can verify that the loose objects are gone by looking at the
-.git/objects directory or by running
+`.git/objects` directory or by running
 
 ------------------------------------------------
 $ git count-objects
@@ -3237,7 +3238,7 @@ branch still exists, as does everything it pointed to. The branch
 pointer itself just doesn't, since you replaced it with another one.
 
 There are also other situations that cause dangling objects. For
-example, a "dangling blob" may arise because you did a "git add" of a
+example, a "dangling blob" may arise because you did a `git add` of a
 file, but then, before you actually committed it and made it part of the
 bigger picture, you changed something else in that file and committed
 that *updated* thing--the old state that you added originally ends up
@@ -3280,14 +3281,14 @@ $ git show <dangling-blob/tree-sha-goes-here>
 ------------------------------------------------
 
 to show what the contents of the blob were (or, for a tree, basically
-what the "ls" for that directory was), and that may give you some idea
+what the `ls` for that directory was), and that may give you some idea
 of what the operation was that left that dangling object.
 
 Usually, dangling blobs and trees aren't very interesting. They're
 almost always the result of either being a half-way mergebase (the blob
 will often even have the conflict markers from a merge in it, if you
 have had conflicting merges that you fixed up by hand), or simply
-because you interrupted a "git fetch" with ^C or something like that,
+because you interrupted a `git fetch` with ^C or something like that,
 leaving _some_ of the new objects in the object database, but just
 dangling and useless.
 
@@ -3298,16 +3299,16 @@ state, you can just prune all unreachable objects:
 $ git prune
 ------------------------------------------------
 
-and they'll be gone. But you should only run "git prune" on a quiescent
+and they'll be gone. But you should only run `git prune` on a quiescent
 repository--it's kind of like doing a filesystem fsck recovery: you
 don't want to do that while the filesystem is mounted.
 
-(The same is true of "git fsck" itself, btw, but since
+(The same is true of `git fsck` itself, btw, but since
 `git fsck` never actually *changes* the repository, it just reports
 on what it found, `git fsck` itself is never 'dangerous' to run.
 Running it while somebody is actually changing the repository can cause
 confusing and scary messages, but it won't actually do anything bad. In
-contrast, running "git prune" while somebody is actively changing the
+contrast, running `git prune` while somebody is actively changing the
 repository is a *BAD* idea).
 
 [[recovering-from-repository-corruption]]
@@ -3345,7 +3346,7 @@ missing blob 4b9458b3786228369c63936db65827de3cc06200
 Now you know that blob 4b9458b3 is missing, and that the tree 2d9263c6
 points to it.  If you could find just one copy of that missing blob
 object, possibly in some other repository, you could move it into
-.git/objects/4b/9458b3... and be done.  Suppose you can't.  You can
+`.git/objects/4b/9458b3...` and be done.  Suppose you can't.  You can
 still examine the tree that pointed to it with linkgit:git-ls-tree[1],
 which might output something like:
 
@@ -3360,10 +3361,10 @@ $ git ls-tree 2d9263c6d23595e7cb2a21e5ebbb53655278dff8
 ------------------------------------------------
 
 So now you know that the missing blob was the data for a file named
-"myfile".  And chances are you can also identify the directory--let's
-say it's in "somedirectory".  If you're lucky the missing copy might be
+`myfile`.  And chances are you can also identify the directory--let's
+say it's in `somedirectory`.  If you're lucky the missing copy might be
 the same as the copy you have checked out in your working tree at
-"somedirectory/myfile"; you can test whether that's right with
+`somedirectory/myfile`; you can test whether that's right with
 linkgit:git-hash-object[1]:
 
 ------------------------------------------------
@@ -3418,7 +3419,7 @@ $ git hash-object -w <recreated-file>
 
 and your repository is good again!
 
-(Btw, you could have ignored the fsck, and started with doing a
+(Btw, you could have ignored the `fsck`, and started with doing a
 
 ------------------------------------------------
 $ git log --raw --all
@@ -3432,7 +3433,7 @@ just missing one particular blob version.
 The index
 -----------
 
-The index is a binary file (generally kept in .git/index) containing a
+The index is a binary file (generally kept in `.git/index`) containing a
 sorted list of path names, each with permissions and the SHA-1 of a blob
 object; linkgit:git-ls-files[1] can show you the contents of the index:
 
@@ -3572,7 +3573,7 @@ $ ls -a
 
 The `git submodule add <repo> <path>` command does a couple of things:
 
-- It clones the submodule from <repo> to the given <path> under the
+- It clones the submodule from `<repo>` to the given `<path>` under the
   current directory and by default checks out the master branch.
 - It adds the submodule's clone path to the linkgit:gitmodules[5] file and
   adds this file to the index, ready to be committed.
@@ -3700,11 +3701,11 @@ Unable to checkout '261dfac35cb99d380eb966e102c1197139f7fa24' in submodule path
 
 In older Git versions it could be easily forgotten to commit new or modified
 files in a submodule, which silently leads to similar problems as not pushing
-the submodule changes. Starting with Git 1.7.0 both "git status" and "git diff"
+the submodule changes. Starting with Git 1.7.0 both `git status` and `git diff`
 in the superproject show submodules as modified when they contain new or
-modified files to protect against accidentally committing such a state. "git
-diff" will also add a "-dirty" to the work tree side when generating patch
-output or used with the --submodule option:
+modified files to protect against accidentally committing such a state. `git
+diff` will also add a `-dirty` to the work tree side when generating patch
+output or used with the `--submodule` option:
 
 -------------------------------------------------
 $ git diff
@@ -3880,7 +3881,7 @@ or, if you want to check out all of the index, use `-a`.
 
 NOTE! `git checkout-index` normally refuses to overwrite old files, so
 if you have an old version of the tree already checked out, you will
-need to use the "-f" flag ('before' the "-a" flag or the filename) to
+need to use the `-f` flag ('before' the `-a` flag or the filename) to
 'force' the checkout.
 
 
@@ -3891,7 +3892,7 @@ from one representation to the other:
 Tying it all together
 ~~~~~~~~~~~~~~~~~~~~~
 
-To commit a tree you have instantiated with "git write-tree", you'd
+To commit a tree you have instantiated with `git write-tree`, you'd
 create a "commit" object that refers to that tree and the history
 behind it--most notably the "parent" commits that preceded it in
 history.
@@ -4152,8 +4153,9 @@ As a result, the general consistency of an object can always be tested
 independently of the contents or the type of the object: all objects can
 be validated by verifying that (a) their hashes match the content of the
 file and (b) the object successfully inflates to a stream of bytes that
-forms a sequence of <ascii type without space> {plus} <space> {plus} <ascii decimal
-size> {plus} <byte\0> {plus} <binary object data>.
+forms a sequence of
+`<ascii type without space> + <space> + <ascii decimal size> +
+<byte\0> + <binary object data>`.
 
 The structured objects can further have their structure and
 connectivity to other objects verified. This is generally done with
@@ -4632,10 +4634,10 @@ Think about how to create a clear chapter dependency graph that will
 allow people to get to important topics without necessarily reading
 everything in between.
 
-Scan Documentation/ for other stuff left out; in particular:
+Scan `Documentation/` for other stuff left out; in particular:
 
 - howto's
-- some of technical/?
+- some of `technical/`?
 - hooks
 - list of commands in linkgit:git[1]
 
index f189b7889e7b19fd1e8a5412c899d8b70fab9d9d..6722e621d119dbefeda2e8ea02dfcc0ebb2b4a5a 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v1.8.2
+DEF_VER=v1.8.2.GIT
 
 LF='
 '
index 7a99a15f2fd9141247b100eb9a5d0b9b88b0f2b9..80b7e388ad321ea679e2b14ce4f18972da35156c 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/1.8.2.1.txt
\ No newline at end of file
+Documentation/RelNotes/1.8.3.txt
\ No newline at end of file
index 780f58da0f5b508eaa278c98dd15bdf6f919c468..3bc86260b8a2a809a379c91627f919ef0a529aa1 100644 (file)
--- a/advice.c
+++ b/advice.c
@@ -8,6 +8,7 @@ int advice_push_already_exists = 1;
 int advice_push_fetch_first = 1;
 int advice_push_needs_force = 1;
 int advice_status_hints = 1;
+int advice_status_u_option = 1;
 int advice_commit_before_merge = 1;
 int advice_resolve_conflict = 1;
 int advice_implicit_identity = 1;
@@ -25,6 +26,7 @@ static struct {
        { "pushfetchfirst", &advice_push_fetch_first },
        { "pushneedsforce", &advice_push_needs_force },
        { "statushints", &advice_status_hints },
+       { "statusuoption", &advice_status_u_option },
        { "commitbeforemerge", &advice_commit_before_merge },
        { "resolveconflict", &advice_resolve_conflict },
        { "implicitidentity", &advice_implicit_identity },
index fad36df467f065bf7ff7a82d9d447ee4ac5cecb9..af0c983c686b9ca5be2e8631562e60bd19656c22 100644 (file)
--- a/advice.h
+++ b/advice.h
@@ -11,6 +11,7 @@ extern int advice_push_already_exists;
 extern int advice_push_fetch_first;
 extern int advice_push_needs_force;
 extern int advice_status_hints;
+extern int advice_status_u_option;
 extern int advice_commit_before_merge;
 extern int advice_resolve_conflict;
 extern int advice_implicit_identity;
index d3aef532b7e4b844f2ac9995b2e987d378737079..a8d119305ff5c0161e7239a8ad70a92c76122631 100644 (file)
@@ -240,7 +240,6 @@ static int write_zip_entry(struct archiver_args *args,
                        (mode & 0111) ? ((mode) << 16) : 0;
                if (S_ISREG(mode) && args->compression_level != 0 && size > 0)
                        method = 8;
-               compressed_size = (method == 0) ? size : 0;
 
                if (S_ISREG(mode) && type == OBJ_BLOB && !args->convert &&
                    size > big_file_threshold) {
@@ -259,6 +258,7 @@ static int write_zip_entry(struct archiver_args *args,
                        crc = crc32(crc, buffer, size);
                        out = buffer;
                }
+               compressed_size = (method == 0) ? size : 0;
        } else {
                return error("unsupported file mode: 0%o (SHA1: %s)", mode,
                                sha1_to_hex(sha1));
index 6371bf96c4841ca263f6bee8a844743c058a5561..00d17d25d1866323f9e1dffcb334a573f5de5221 100644 (file)
@@ -889,6 +889,17 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
        } else if (new_upstream) {
                struct branch *branch = branch_get(argv[0]);
 
+               if (argc > 1)
+                       die(_("too many branches to set new upstream"));
+
+               if (!branch) {
+                       if (!argc || !strcmp(argv[0], "HEAD"))
+                               die(_("could not set upstream of HEAD to %s when "
+                                     "it does not point to any branch."),
+                                   new_upstream);
+                       die(_("no such branch '%s'"), argv[0]);
+               }
+
                if (!ref_exists(branch->refname))
                        die(_("branch '%s' does not exist"), branch->name);
 
@@ -901,6 +912,16 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
                struct branch *branch = branch_get(argv[0]);
                struct strbuf buf = STRBUF_INIT;
 
+               if (argc > 1)
+                       die(_("too many branches to unset upstream"));
+
+               if (!branch) {
+                       if (!argc || !strcmp(argv[0], "HEAD"))
+                               die(_("could not unset upstream of HEAD when "
+                                     "it does not point to any branch."));
+                       die(_("no such branch '%s'"), argv[0]);
+               }
+
                if (!branch_has_merge_config(branch)) {
                        die(_("Branch '%s' has no upstream information"), branch->name);
                }
@@ -916,6 +937,12 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
                int branch_existed = 0, remote_tracking = 0;
                struct strbuf buf = STRBUF_INIT;
 
+               if (!strcmp(argv[0], "HEAD"))
+                       die(_("it does not make sense to create 'HEAD' manually"));
+
+               if (!branch)
+                       die(_("no such branch '%s'"), argv[0]);
+
                if (kinds != REF_LOCAL_BRANCH)
                        die(_("-a and -r options to 'git branch' do not make sense with a branch name"));
 
index 3348aa14e9d5a76fa06e43625c5d74cb047accb6..d21d07a1a8e9fbc365a4555a0f9e81d0c1f2a7d0 100644 (file)
@@ -124,8 +124,10 @@ static int opt_parse_m(const struct option *opt, const char *arg, int unset)
        if (unset)
                strbuf_setlen(buf, 0);
        else {
+               if (buf->len)
+                       strbuf_addch(buf, '\n');
                strbuf_addstr(buf, arg);
-               strbuf_addstr(buf, "\n\n");
+               strbuf_complete_line(buf);
        }
        return 0;
 }
index 9afaa88f776468a0de33dd153eadae7621cf6267..3a01a8d08591d93426d436ce2e1e17fccd3ebf78 100644 (file)
@@ -9,11 +9,22 @@
 #include "builtin.h"
 #include "parse-options.h"
 
+static unsigned long garbage;
+static off_t size_garbage;
+
+static void real_report_garbage(const char *desc, const char *path)
+{
+       struct stat st;
+       if (!stat(path, &st))
+               size_garbage += st.st_size;
+       warning("%s: %s", desc, path);
+       garbage++;
+}
+
 static void count_objects(DIR *d, char *path, int len, int verbose,
                          unsigned long *loose,
                          off_t *loose_size,
-                         unsigned long *packed_loose,
-                         unsigned long *garbage)
+                         unsigned long *packed_loose)
 {
        struct dirent *ent;
        while ((ent = readdir(d)) != NULL) {
@@ -46,9 +57,11 @@ static void count_objects(DIR *d, char *path, int len, int verbose,
                }
                if (bad) {
                        if (verbose) {
-                               error("garbage found: %.*s/%s",
-                                     len + 2, path, ent->d_name);
-                               (*garbage)++;
+                               struct strbuf sb = STRBUF_INIT;
+                               strbuf_addf(&sb, "%.*s/%s",
+                                           len + 2, path, ent->d_name);
+                               report_garbage("garbage found", sb.buf);
+                               strbuf_release(&sb);
                        }
                        continue;
                }
@@ -76,7 +89,7 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)
        const char *objdir = get_object_directory();
        int len = strlen(objdir);
        char *path = xmalloc(len + 50);
-       unsigned long loose = 0, packed = 0, packed_loose = 0, garbage = 0;
+       unsigned long loose = 0, packed = 0, packed_loose = 0;
        off_t loose_size = 0;
        struct option opts[] = {
                OPT__VERBOSE(&verbose, N_("be verbose")),
@@ -87,6 +100,8 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)
        /* we do not take arguments other than flags for now */
        if (argc)
                usage_with_options(count_objects_usage, opts);
+       if (verbose)
+               report_garbage = real_report_garbage;
        memcpy(path, objdir, len);
        if (len && objdir[len-1] != '/')
                path[len++] = '/';
@@ -97,7 +112,7 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)
                if (!d)
                        continue;
                count_objects(d, path, len, verbose,
-                             &loose, &loose_size, &packed_loose, &garbage);
+                             &loose, &loose_size, &packed_loose);
                closedir(d);
        }
        if (verbose) {
@@ -122,6 +137,7 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)
                printf("size-pack: %lu\n", (unsigned long) (size_pack / 1024));
                printf("prune-packable: %lu\n", packed_loose);
                printf("garbage: %lu\n", garbage);
+               printf("size-garbage: %lu\n", (unsigned long) (size_garbage / 1024));
        }
        else
                printf("%lu objects, %lu kilobytes\n",
index 04c185b1fbdc51ba9958fdb83d1c6616bcb0c18e..ca084c675ef80deaac7a3f8615c1ea3329a97421 100644 (file)
@@ -402,8 +402,8 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
        struct option options[] = {
                OPT_BOOLEAN(0, "contains",   &contains, N_("find the tag that comes after the commit")),
                OPT_BOOLEAN(0, "debug",      &debug, N_("debug search strategy on stderr")),
-               OPT_BOOLEAN(0, "all",        &all, N_("use any ref in .git/refs")),
-               OPT_BOOLEAN(0, "tags",       &tags, N_("use any tag in .git/refs/tags")),
+               OPT_BOOLEAN(0, "all",        &all, N_("use any ref")),
+               OPT_BOOLEAN(0, "tags",       &tags, N_("use any tag, even unannotated")),
                OPT_BOOLEAN(0, "long",       &longformat, N_("always use long format")),
                OPT__ABBREV(&abbrev),
                OPT_SET_INT(0, "exact-match", &max_candidates,
index 940ae35dc2ce4923a248896eb764f145312d71b4..670e81fd995953bff9c29cc6fab99d03f1fee8b7 100644 (file)
@@ -7,12 +7,31 @@ static const char fetch_pack_usage[] =
 "[--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] "
 "[--no-progress] [-v] [<host>:]<directory> [<refs>...]";
 
+static void add_sought_entry_mem(struct ref ***sought, int *nr, int *alloc,
+                                const char *name, int namelen)
+{
+       struct ref *ref = xcalloc(1, sizeof(*ref) + namelen + 1);
+
+       memcpy(ref->name, name, namelen);
+       ref->name[namelen] = '\0';
+       (*nr)++;
+       ALLOC_GROW(*sought, *nr, *alloc);
+       (*sought)[*nr - 1] = ref;
+}
+
+static void add_sought_entry(struct ref ***sought, int *nr, int *alloc,
+                            const char *string)
+{
+       add_sought_entry_mem(sought, nr, alloc, string, strlen(string));
+}
+
 int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
 {
        int i, ret;
        struct ref *ref = NULL;
        const char *dest = NULL;
-       struct string_list sought = STRING_LIST_INIT_DUP;
+       struct ref **sought = NULL;
+       int nr_sought = 0, alloc_sought = 0;
        int fd[2];
        char *pack_lockfile = NULL;
        char **pack_lockfile_ptr = NULL;
@@ -94,7 +113,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
         * refs from the standard input:
         */
        for (; i < argc; i++)
-               string_list_append(&sought, xstrdup(argv[i]));
+               add_sought_entry(&sought, &nr_sought, &alloc_sought, argv[i]);
        if (args.stdin_refs) {
                if (args.stateless_rpc) {
                        /* in stateless RPC mode we use pkt-line to read
@@ -107,14 +126,14 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
                                        break;
                                if (line[n-1] == '\n')
                                        n--;
-                               string_list_append(&sought, xmemdupz(line, n));
+                               add_sought_entry_mem(&sought, &nr_sought,  &alloc_sought, line, n);
                        }
                }
                else {
                        /* read from stdin one ref per line, until EOF */
                        struct strbuf line = STRBUF_INIT;
                        while (strbuf_getline(&line, stdin, '\n') != EOF)
-                               string_list_append(&sought, strbuf_detach(&line, NULL));
+                               add_sought_entry(&sought, &nr_sought, &alloc_sought, line.buf);
                        strbuf_release(&line);
                }
        }
@@ -131,7 +150,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
        get_remote_heads(fd[0], &ref, 0, NULL);
 
        ref = fetch_pack(&args, fd, conn, ref, dest,
-                        &sought, pack_lockfile_ptr);
+                        sought, nr_sought, pack_lockfile_ptr);
        if (pack_lockfile) {
                printf("lock %s\n", pack_lockfile);
                fflush(stdout);
@@ -141,7 +160,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
        if (finish_connect(conn))
                return 1;
 
-       ret = !ref || sought.nr;
+       ret = !ref;
 
        /*
         * If the heads to pull were given, we should have consumed
@@ -149,8 +168,13 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
         * remote no-such-ref' would silently succeed without issuing
         * an error.
         */
-       for (i = 0; i < sought.nr; i++)
-               error("no such remote ref %s", sought.items[i].string);
+       for (i = 0; i < nr_sought; i++) {
+               if (!sought[i] || sought[i]->matched)
+                       continue;
+               error("no such remote ref %s", sought[i]->name);
+               ret = 1;
+       }
+
        while (ref) {
                printf("%s %s\n",
                       sha1_to_hex(ref->old_sha1), ref->name);
index b49612f0ce02e0c8503bee77477800297e84065d..265a9253bfd7cacd730789212fdb5284fcd270ac 100644 (file)
@@ -492,7 +492,7 @@ static void fmt_merge_msg_sigs(struct strbuf *out)
 
                if (size == len)
                        ; /* merely annotated */
-               else if (verify_signed_buffer(buf, len, buf + len, size - len, &sig)) {
+               else if (verify_signed_buffer(buf, len, buf + len, size - len, &sig, NULL)) {
                        if (!sig.len)
                                strbuf_addstr(&sig, "gpg verification failed.\n");
                }
index 43d364b8d5e5b0cb4b78be517e78d64c96da4304..ef62124aa491a9ac1e430d5baa3cf448902ac9c4 100644 (file)
@@ -1099,7 +1099,7 @@ static void conclude_pack(int fix_thin_pack, const char *curr_pack, unsigned cha
        if (fix_thin_pack) {
                struct sha1file *f;
                unsigned char read_sha1[20], tail_sha1[20];
-               char msg[48];
+               struct strbuf msg = STRBUF_INIT;
                int nr_unresolved = nr_deltas - nr_resolved_deltas;
                int nr_objects_initial = nr_objects;
                if (nr_unresolved <= 0)
@@ -1109,9 +1109,10 @@ static void conclude_pack(int fix_thin_pack, const char *curr_pack, unsigned cha
                                   * sizeof(*objects));
                f = sha1fd(output_fd, curr_pack);
                fix_unresolved_deltas(f, nr_unresolved);
-               sprintf(msg, _("completed with %d local objects"),
-                       nr_objects - nr_objects_initial);
-               stop_progress_msg(&progress, msg);
+               strbuf_addf(&msg, _("completed with %d local objects"),
+                           nr_objects - nr_objects_initial);
+               stop_progress_msg(&progress, msg.buf);
+               strbuf_release(&msg);
                sha1close(f, tail_sha1, 0);
                hashcpy(read_sha1, pack_sha1);
                fixup_pack_header_footer(output_fd, pack_sha1,
index 2d4327801e4f7766328389311c87dd63d4c5f8e4..06296d4bdf607431bfcb38f0bc6720f555d6917a 100644 (file)
@@ -130,6 +130,27 @@ static int populate_maildir_list(struct string_list *list, const char *path)
        return 0;
 }
 
+static int maildir_filename_cmp(const char *a, const char *b)
+{
+       while (*a && *b) {
+               if (isdigit(*a) && isdigit(*b)) {
+                       long int na, nb;
+                       na = strtol(a, (char **)&a, 10);
+                       nb = strtol(b, (char **)&b, 10);
+                       if (na != nb)
+                               return na - nb;
+                       /* strtol advanced our pointers */
+               }
+               else {
+                       if (*a != *b)
+                               return (unsigned char)*a - (unsigned char)*b;
+                       a++;
+                       b++;
+               }
+       }
+       return (unsigned char)*a - (unsigned char)*b;
+}
+
 static int split_maildir(const char *maildir, const char *dir,
        int nr_prec, int skip)
 {
@@ -139,6 +160,8 @@ static int split_maildir(const char *maildir, const char *dir,
        int i;
        struct string_list list = STRING_LIST_INIT_DUP;
 
+       list.cmp = maildir_filename_cmp;
+
        if (populate_maildir_list(&list, maildir) < 0)
                goto out;
 
index ada1dff846f2b77d5f71d69db57a7eca5033b943..5c7762eef404e7ea21d88991a81407f1cb99f306 100644 (file)
@@ -796,7 +796,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
        };
 
        if (argc == 2 && !strcmp(argv[1], "-h"))
-               usage(update_index_usage[0]);
+               usage_with_options(update_index_usage, options);
 
        git_config(git_default_config, NULL);
 
index a8eee886a5281965a0660308df9e94d14c1cb2b8..9cdf332333b95b3ab2ea6e133f345105bd67d019 100644 (file)
@@ -29,7 +29,7 @@ static int run_gpg_verify(const char *buf, unsigned long size, int verbose)
        if (size == len)
                return error("no signature found");
 
-       return verify_signed_buffer(buf, len, buf + len, size - len, NULL);
+       return verify_signed_buffer(buf, len, buf + len, size - len, NULL, NULL);
 }
 
 static int verify_tag(const char *name, int verbose)
diff --git a/cache.h b/cache.h
index e493563f4c07e6adcd00a1b2476926d69a4a67f8..c56315ccc3605654ff4a08a8b74cc8f25cfb2b41 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -1017,7 +1017,8 @@ struct ref {
                force:1,
                forced_update:1,
                merge:1,
-               deletion:1;
+               deletion:1,
+               matched:1;
        enum {
                REF_STATUS_NONE = 0,
                REF_STATUS_OK,
@@ -1057,6 +1058,9 @@ extern const char *parse_feature_value(const char *feature_list, const char *fea
 
 extern struct packed_git *parse_pack_index(unsigned char *sha1, const char *idx_path);
 
+/* A hook for count-objects to report invalid files in pack directory */
+extern void (*report_garbage)(const char *desc, const char *path);
+
 extern void prepare_packed_git(void);
 extern void reprepare_packed_git(void);
 extern void install_packed_git(struct packed_git *pack);
index aa4b56315ae2488ea656d695f0f660e4dbd745ef..96b6d605dad3872f02933581e501ee4380cb8f68 100644 (file)
@@ -12,6 +12,8 @@
 #define __attribute__(x)
 #define strncasecmp  _strnicmp
 #define ftruncate    _chsize
+#define strtoull     _strtoui64
+#define strtoll      _strtoi64
 
 static __inline int strcasecmp (const char *s1, const char *s2)
 {
diff --git a/compat/vcbuild/include/sys/poll.h b/compat/vcbuild/include/sys/poll.h
deleted file mode 100644 (file)
index 0d8552a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-/* Intentionally empty file to support building git with MSVC */
index b14fcf94da405c6f3267437e59936d598168e00f..c65c2cd566b51473da12786f28074040c410f343 100644 (file)
@@ -49,6 +49,9 @@ typedef int64_t off64_t;
 #define INTMAX_MAX  _I64_MAX
 #define UINTMAX_MAX _UI64_MAX
 
+#define UINT32_MAX 0xffffffff  /* 4294967295U */
+
+#define STDIN_FILENO  0
 #define STDOUT_FILENO 1
 #define STDERR_FILENO 2
 
index e09af8fc13ec4c3c6fa326e8208c98be52347a10..9080054f7617017a67ca0ae8414f829a01d3d546 100644 (file)
@@ -326,7 +326,6 @@ ifeq ($(uname_S),Windows)
        # NEEDS_LIBICONV = YesPlease
        NO_ICONV = YesPlease
        NO_STRTOUMAX = YesPlease
-       NO_STRTOULL = YesPlease
        NO_MKDTEMP = YesPlease
        NO_MKSTEMPS = YesPlease
        SNPRINTF_RETURNS_BOGUS = YesPlease
@@ -343,6 +342,9 @@ ifeq ($(uname_S),Windows)
        NO_CURL = YesPlease
        NO_PYTHON = YesPlease
        BLK_SHA1 = YesPlease
+       ETAGS_TARGET = ETAGS
+       NO_INET_PTON = YesPlease
+       NO_INET_NTOP = YesPlease
        NO_POSIX_GOODIES = UnfortunatelyYes
        NATIVE_CRLF = YesPlease
        DEFAULT_HELP_FORMAT = html
index 41f61c5db3378d234b2d1f5e67d0fc180bea678a..f2cdefee605aebe6c577129ae2c8cd76a3555a96 100644 (file)
@@ -401,7 +401,7 @@ static void usage(const char *name)
        const char *basename = strrchr(name,'/');
 
        basename = (basename) ? basename + 1 : name;
-       fprintf(stderr, "Usage: %s <", basename);
+       fprintf(stderr, "usage: %s <", basename);
        while(try_op->name) {
                fprintf(stderr,"%s",(try_op++)->name);
                if(try_op->name)
diff --git a/contrib/credential/netrc/Makefile b/contrib/credential/netrc/Makefile
new file mode 100644 (file)
index 0000000..51b7613
--- /dev/null
@@ -0,0 +1,5 @@
+test:
+       ./test.pl
+
+testverbose:
+       ./test.pl -d -v
diff --git a/contrib/credential/netrc/git-credential-netrc b/contrib/credential/netrc/git-credential-netrc
new file mode 100755 (executable)
index 0000000..6c51c43
--- /dev/null
@@ -0,0 +1,421 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Getopt::Long;
+use File::Basename;
+
+my $VERSION = "0.1";
+
+my %options = (
+              help => 0,
+              debug => 0,
+              verbose => 0,
+              insecure => 0,
+              file => [],
+
+              # identical token maps, e.g. host -> host, will be inserted later
+              tmap => {
+                       port => 'protocol',
+                       machine => 'host',
+                       path => 'path',
+                       login => 'username',
+                       user => 'username',
+                       password => 'password',
+                      }
+             );
+
+# Map each credential protocol token to itself on the netrc side.
+foreach (values %{$options{tmap}}) {
+       $options{tmap}->{$_} = $_;
+}
+
+# Now, $options{tmap} has a mapping from the netrc format to the Git credential
+# helper protocol.
+
+# Next, we build the reverse token map.
+
+# When $rmap{foo} contains 'bar', that means that what the Git credential helper
+# protocol calls 'bar' is found as 'foo' in the netrc/authinfo file.  Keys in
+# %rmap are what we expect to read from the netrc/authinfo file.
+
+my %rmap;
+foreach my $k (keys %{$options{tmap}}) {
+       push @{$rmap{$options{tmap}->{$k}}}, $k;
+}
+
+Getopt::Long::Configure("bundling");
+
+# TODO: maybe allow the token map $options{tmap} to be configurable.
+GetOptions(\%options,
+           "help|h",
+           "debug|d",
+           "insecure|k",
+           "verbose|v",
+           "file|f=s@",
+          );
+
+if ($options{help}) {
+       my $shortname = basename($0);
+       $shortname =~ s/git-credential-//;
+
+       print <<EOHIPPUS;
+
+$0 [-f AUTHFILE1] [-f AUTHFILEN] [-d] [-v] [-k] get
+
+Version $VERSION by tzz\@lifelogs.com.  License: BSD.
+
+Options:
+
+  -f|--file AUTHFILE : specify netrc-style files.  Files with the .gpg extension
+                       will be decrypted by GPG before parsing.  Multiple -f
+                       arguments are OK.  They are processed in order, and the
+                       first matching entry found is returned via the credential
+                       helper protocol (see below).
+
+                       When no -f option is given, .authinfo.gpg, .netrc.gpg,
+                      .authinfo, and .netrc files in your home directory are used
+                      in this order.
+
+  -k|--insecure      : ignore bad file ownership or permissions
+
+  -d|--debug         : turn on debugging (developer info)
+
+  -v|--verbose       : be more verbose (show files and information found)
+
+To enable this credential helper:
+
+  git config credential.helper '$shortname -f AUTHFILE1 -f AUTHFILE2'
+
+(Note that Git will prepend "git-credential-" to the helper name and look for it
+in the path.)
+
+...and if you want lots of debugging info:
+
+  git config credential.helper '$shortname -f AUTHFILE -d'
+
+...or to see the files opened and data found:
+
+  git config credential.helper '$shortname -f AUTHFILE -v'
+
+Only "get" mode is supported by this credential helper.  It opens every AUTHFILE
+and looks for the first entry that matches the requested search criteria:
+
+ 'port|protocol':
+   The protocol that will be used (e.g., https). (protocol=X)
+
+ 'machine|host':
+   The remote hostname for a network credential. (host=X)
+
+ 'path':
+   The path with which the credential will be used. (path=X)
+
+ 'login|user|username':
+   The credential’s username, if we already have one. (username=X)
+
+Thus, when we get this query on STDIN:
+
+host=github.com
+protocol=https
+username=tzz
+
+this credential helper will look for the first entry in every AUTHFILE that
+matches
+
+machine github.com port https login tzz
+
+OR
+
+machine github.com protocol https login tzz
+
+OR... etc. acceptable tokens as listed above.  Any unknown tokens are
+simply ignored.
+
+Then, the helper will print out whatever tokens it got from the entry, including
+"password" tokens, mapping back to Git's helper protocol; e.g. "port" is mapped
+back to "protocol".  Any redundant entry tokens (part of the original query) are
+skipped.
+
+Again, note that only the first matching entry from all the AUTHFILEs, processed
+in the sequence given on the command line, is used.
+
+Netrc/authinfo tokens can be quoted as 'STRING' or "STRING".
+
+No caching is performed by this credential helper.
+
+EOHIPPUS
+
+       exit 0;
+}
+
+my $mode = shift @ARGV;
+
+# Credentials must get a parameter, so die if it's missing.
+die "Syntax: $0 [-f AUTHFILE1] [-f AUTHFILEN] [-d] get" unless defined $mode;
+
+# Only support 'get' mode; with any other unsupported ones we just exit.
+exit 0 unless $mode eq 'get';
+
+my $files = $options{file};
+
+# if no files were given, use a predefined list.
+# note that .gpg files come first
+unless (scalar @$files) {
+       my @candidates = qw[
+                                  ~/.authinfo.gpg
+                                  ~/.netrc.gpg
+                                  ~/.authinfo
+                                  ~/.netrc
+                         ];
+
+       $files = $options{file} = [ map { glob $_ } @candidates ];
+}
+
+my $query = read_credential_data_from_stdin();
+
+FILE:
+foreach my $file (@$files) {
+       my $gpgmode = $file =~ m/\.gpg$/;
+       unless (-r $file) {
+               log_verbose("Unable to read $file; skipping it");
+               next FILE;
+       }
+
+       # the following check is copied from Net::Netrc, for non-GPG files
+       # OS/2 and Win32 do not handle stat in a way compatible with this check :-(
+       unless ($gpgmode || $options{insecure} ||
+               $^O eq 'os2'
+               || $^O eq 'MSWin32'
+               || $^O eq 'MacOS'
+               || $^O =~ /^cygwin/) {
+               my @stat = stat($file);
+
+               if (@stat) {
+                       if ($stat[2] & 077) {
+                               log_verbose("Insecure $file (mode=%04o); skipping it",
+                                           $stat[2] & 07777);
+                               next FILE;
+                       }
+
+                       if ($stat[4] != $<) {
+                               log_verbose("Not owner of $file; skipping it");
+                               next FILE;
+                       }
+               }
+       }
+
+       my @entries = load_netrc($file, $gpgmode);
+
+       unless (scalar @entries) {
+               if ($!) {
+                       log_verbose("Unable to open $file: $!");
+               } else {
+                       log_verbose("No netrc entries found in $file");
+               }
+
+               next FILE;
+       }
+
+       my $entry = find_netrc_entry($query, @entries);
+       if ($entry) {
+               print_credential_data($entry, $query);
+               # we're done!
+               last FILE;
+       }
+}
+
+exit 0;
+
+sub load_netrc {
+       my $file = shift @_;
+       my $gpgmode = shift @_;
+
+       my $io;
+       if ($gpgmode) {
+               my @cmd = (qw(gpg --decrypt), $file);
+               log_verbose("Using GPG to open $file: [@cmd]");
+               open $io, "-|", @cmd;
+       } else {
+               log_verbose("Opening $file...");
+               open $io, '<', $file;
+       }
+
+       # nothing to do if the open failed (we log the error later)
+       return unless $io;
+
+       # Net::Netrc does this, but the functionality is merged with the file
+       # detection logic, so we have to extract just the part we need
+       my @netrc_entries = net_netrc_loader($io);
+
+       # these entries will use the credential helper protocol token names
+       my @entries;
+
+       foreach my $nentry (@netrc_entries) {
+               my %entry;
+               my $num_port;
+
+               if (!defined $nentry->{machine}) {
+                       next;
+               }
+               if (defined $nentry->{port} && $nentry->{port} =~ m/^\d+$/) {
+                       $num_port = $nentry->{port};
+                       delete $nentry->{port};
+               }
+
+               # create the new entry for the credential helper protocol
+               $entry{$options{tmap}->{$_}} = $nentry->{$_} foreach keys %$nentry;
+
+               # for "host X port Y" where Y is an integer (captured by
+               # $num_port above), set the host to "X:Y"
+               if (defined $entry{host} && defined $num_port) {
+                       $entry{host} = join(':', $entry{host}, $num_port);
+               }
+
+               push @entries, \%entry;
+       }
+
+       return @entries;
+}
+
+sub net_netrc_loader {
+       my $fh = shift @_;
+       my @entries;
+       my ($mach, $macdef, $tok, @tok);
+
+    LINE:
+       while (<$fh>) {
+               undef $macdef if /\A\n\Z/;
+
+               if ($macdef) {
+                       next LINE;
+               }
+
+               s/^\s*//;
+               chomp;
+
+               while (length && s/^("((?:[^"]+|\\.)*)"|((?:[^\\\s]+|\\.)*))\s*//) {
+                       (my $tok = $+) =~ s/\\(.)/$1/g;
+                       push(@tok, $tok);
+               }
+
+           TOKEN:
+               while (@tok) {
+                       if ($tok[0] eq "default") {
+                               shift(@tok);
+                               $mach = { machine => undef };
+                               next TOKEN;
+                       }
+
+                       $tok = shift(@tok);
+
+                       if ($tok eq "machine") {
+                               my $host = shift @tok;
+                               $mach = { machine => $host };
+                               push @entries, $mach;
+                       } elsif (exists $options{tmap}->{$tok}) {
+                               unless ($mach) {
+                                       log_debug("Skipping token $tok because no machine was given");
+                                       next TOKEN;
+                               }
+
+                               my $value = shift @tok;
+                               unless (defined $value) {
+                                       log_debug("Token $tok had no value, skipping it.");
+                                       next TOKEN;
+                               }
+
+                               # Following line added by rmerrell to remove '/' escape char in .netrc
+                               $value =~ s/\/\\/\\/g;
+                               $mach->{$tok} = $value;
+                       } elsif ($tok eq "macdef") { # we ignore macros
+                               next TOKEN unless $mach;
+                               my $value = shift @tok;
+                               $macdef = 1;
+                       }
+               }
+       }
+
+       return @entries;
+}
+
+sub read_credential_data_from_stdin {
+       # the query: start with every token with no value
+       my %q = map { $_ => undef } values(%{$options{tmap}});
+
+       while (<STDIN>) {
+               next unless m/^([^=]+)=(.+)/;
+
+               my ($token, $value) = ($1, $2);
+               die "Unknown search token $token" unless exists $q{$token};
+               $q{$token} = $value;
+               log_debug("We were given search token $token and value $value");
+       }
+
+       foreach (sort keys %q) {
+               log_debug("Searching for %s = %s", $_, $q{$_} || '(any value)');
+       }
+
+       return \%q;
+}
+
+# takes the search tokens and then a list of entries
+# each entry is a hash reference
+sub find_netrc_entry {
+       my $query = shift @_;
+
+    ENTRY:
+       foreach my $entry (@_)
+       {
+               my $entry_text = join ', ', map { "$_=$entry->{$_}" } keys %$entry;
+               foreach my $check (sort keys %$query) {
+                       if (defined $query->{$check}) {
+                               log_debug("compare %s [%s] to [%s] (entry: %s)",
+                                         $check,
+                                         $entry->{$check},
+                                         $query->{$check},
+                                         $entry_text);
+                               unless ($query->{$check} eq $entry->{$check}) {
+                                       next ENTRY;
+                               }
+                       } else {
+                               log_debug("OK: any value satisfies check $check");
+                       }
+               }
+
+               return $entry;
+       }
+
+       # nothing was found
+       return;
+}
+
+sub print_credential_data {
+       my $entry = shift @_;
+       my $query = shift @_;
+
+       log_debug("entry has passed all the search checks");
+ TOKEN:
+       foreach my $git_token (sort keys %$entry) {
+               log_debug("looking for useful token $git_token");
+               # don't print unknown (to the credential helper protocol) tokens
+               next TOKEN unless exists $query->{$git_token};
+
+               # don't print things asked in the query (the entry matches them)
+               next TOKEN if defined $query->{$git_token};
+
+               log_debug("FOUND: $git_token=$entry->{$git_token}");
+               printf "%s=%s\n", $git_token, $entry->{$git_token};
+       }
+}
+sub log_verbose {
+       return unless $options{verbose};
+       printf STDERR @_;
+       printf STDERR "\n";
+}
+
+sub log_debug {
+       return unless $options{debug};
+       printf STDERR @_;
+       printf STDERR "\n";
+}
diff --git a/contrib/credential/netrc/test.netrc b/contrib/credential/netrc/test.netrc
new file mode 100644 (file)
index 0000000..ba119a9
--- /dev/null
@@ -0,0 +1,13 @@
+machine imap login tzz@lifelogs.com port imaps password letmeknow
+machine imap login bob port imaps password bobwillknow
+
+# comment test
+
+machine imap2 login tzz port 1099 password tzzknow
+machine imap2 login bob password bobwillknow
+
+# another command
+
+machine github.com
+  multilinetoken anothervalue
+  login carol password carolknows
diff --git a/contrib/credential/netrc/test.pl b/contrib/credential/netrc/test.pl
new file mode 100755 (executable)
index 0000000..169b646
--- /dev/null
@@ -0,0 +1,106 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+use Test;
+use IPC::Open2;
+
+BEGIN { plan tests => 15 }
+
+my @global_credential_args = @ARGV;
+my $netrc = './test.netrc';
+print "# Testing insecure file, nothing should be found\n";
+chmod 0644, $netrc;
+my $cred = run_credential(['-f', $netrc, 'get'],
+                         { host => 'github.com' });
+
+ok(scalar keys %$cred, 0, "Got 0 keys from insecure file");
+
+print "# Testing missing file, nothing should be found\n";
+chmod 0644, $netrc;
+$cred = run_credential(['-f', '///nosuchfile///', 'get'],
+                      { host => 'github.com' });
+
+ok(scalar keys %$cred, 0, "Got 0 keys from missing file");
+
+chmod 0600, $netrc;
+
+print "# Testing with invalid data\n";
+$cred = run_credential(['-f', $netrc, 'get'],
+                      "bad data");
+ok(scalar keys %$cred, 4, "Got first found keys with bad data");
+
+print "# Testing netrc file for a missing corovamilkbar entry\n";
+$cred = run_credential(['-f', $netrc, 'get'],
+                      { host => 'corovamilkbar' });
+
+ok(scalar keys %$cred, 0, "Got no corovamilkbar keys");
+
+print "# Testing netrc file for a github.com entry\n";
+$cred = run_credential(['-f', $netrc, 'get'],
+                      { host => 'github.com' });
+
+ok(scalar keys %$cred, 2, "Got 2 Github keys");
+
+ok($cred->{password}, 'carolknows', "Got correct Github password");
+ok($cred->{username}, 'carol', "Got correct Github username");
+
+print "# Testing netrc file for a username-specific entry\n";
+$cred = run_credential(['-f', $netrc, 'get'],
+                      { host => 'imap', username => 'bob' });
+
+ok(scalar keys %$cred, 2, "Got 2 username-specific keys");
+
+ok($cred->{password}, 'bobwillknow', "Got correct user-specific password");
+ok($cred->{protocol}, 'imaps', "Got correct user-specific protocol");
+
+print "# Testing netrc file for a host:port-specific entry\n";
+$cred = run_credential(['-f', $netrc, 'get'],
+                      { host => 'imap2:1099' });
+
+ok(scalar keys %$cred, 2, "Got 2 host:port-specific keys");
+
+ok($cred->{password}, 'tzzknow', "Got correct host:port-specific password");
+ok($cred->{username}, 'tzz', "Got correct host:port-specific username");
+
+print "# Testing netrc file that 'host:port kills host' entry\n";
+$cred = run_credential(['-f', $netrc, 'get'],
+                      { host => 'imap2' });
+
+ok(scalar keys %$cred, 2, "Got 2 'host:port kills host' keys");
+
+ok($cred->{password}, 'bobwillknow', "Got correct 'host:port kills host' password");
+ok($cred->{username}, 'bob', "Got correct 'host:port kills host' username");
+
+sub run_credential
+{
+       my $args = shift @_;
+       my $data = shift @_;
+       my $pid = open2(my $chld_out, my $chld_in,
+                       './git-credential-netrc', @global_credential_args,
+                       @$args);
+
+       die "Couldn't open pipe to netrc credential helper: $!" unless $pid;
+
+       if (ref $data eq 'HASH')
+       {
+               print $chld_in "$_=$data->{$_}\n" foreach sort keys %$data;
+       }
+       else
+       {
+               print $chld_in "$data\n";
+       }
+
+       close $chld_in;
+       my %ret;
+
+       while (<$chld_out>)
+       {
+               chomp;
+               next unless m/^([^=]+)=(.+)/;
+
+               $ret{$1} = $2;
+       }
+
+       return \%ret;
+}
index 6beed123ab1f46f43b35059384d6ecfdc571ee7c..3940202b36ce00a77bdc2e17a6002dac158afcb6 100644 (file)
@@ -154,7 +154,7 @@ static void read_credential(void)
 int main(int argc, const char **argv)
 {
        const char *usage =
-               "Usage: git credential-osxkeychain <get|store|erase>";
+               "usage: git credential-osxkeychain <get|store|erase>";
 
        if (!argv[1])
                die(usage);
index dac19eac81665b4f809688255b2eb9aca6874f20..a1d38f035bea404aa9a5fa37518f0af21143dbf0 100644 (file)
@@ -259,7 +259,7 @@ static void read_credential(void)
 int main(int argc, char *argv[])
 {
        const char *usage =
-           "Usage: git credential-wincred <get|store|erase>\n";
+           "usage: git credential-wincred <get|store|erase>\n";
 
        if (!argv[1])
                die(usage);
index b17952a785d9e45dea8a71c211f76f0271e659da..d42df7b4188672e01dd7c95d5dcd73939f0fd600 100755 (executable)
@@ -347,7 +347,7 @@ sub rm_remote {
 }
 
 sub add_usage {
-       print STDERR "Usage: git remote add [-f] [-t track]* [-m master] <name> <url>\n";
+       print STDERR "usage: git remote add [-f] [-t track]* [-m master] <name> <url>\n";
        exit(1);
 }
 
@@ -380,7 +380,7 @@ sub add_usage {
                }
        }
        if ($i >= @ARGV) {
-               print STDERR "Usage: git remote show <remote>\n";
+               print STDERR "usage: git remote show <remote>\n";
                exit(1);
        }
        my $status = 0;
@@ -410,7 +410,7 @@ sub add_usage {
                }
        }
        if ($i >= @ARGV) {
-               print STDERR "Usage: git remote prune <remote>\n";
+               print STDERR "usage: git remote prune <remote>\n";
                exit(1);
        }
        my $status = 0;
@@ -458,13 +458,13 @@ sub add_usage {
 }
 elsif ($ARGV[0] eq 'rm') {
        if (@ARGV <= 1) {
-               print STDERR "Usage: git remote rm <remote>\n";
+               print STDERR "usage: git remote rm <remote>\n";
                exit(1);
        }
        exit(rm_remote($ARGV[1]));
 }
 else {
-       print STDERR "Usage: git remote\n";
+       print STDERR "usage: git remote\n";
        print STDERR "       git remote add <name> <url>\n";
        print STDERR "       git remote rm <name>\n";
        print STDERR "       git remote show <name>\n";
index b09ff8f12f7e5b5b6faeaf857d7c61973de8590e..c414f0d9c7ecfac7074d0e052c19f73cae4344d1 100755 (executable)
@@ -36,7 +36,7 @@
 
 sub usage() {
        print STDERR <<END;
-Usage: ${\basename $0}     # fetch/update GIT from SVN
+usage: ${\basename $0}     # fetch/update GIT from SVN
        [-o branch-for-HEAD] [-h] [-v] [-l max_rev] [-R repack_each_revs]
        [-C GIT_repository] [-t tagname] [-T trunkname] [-b branchname]
        [-d|-D] [-i] [-u] [-r] [-I ignorefilename] [-s start_chg]
index f9fef6db28dbba0ef67589f05eeb937760d2facf..0891b9e366725cc7bbf9ce996839fdf182a6422c 100755 (executable)
@@ -7,7 +7,7 @@
 use strict;
 use File::Find;
 
-my $USAGE = 'Usage: git-import branch import-message';
+my $USAGE = 'usage: git-import branch import-message';
 my $branch = shift or die "$USAGE\n";
 my $message = shift or die "$USAGE\n";
 
index 0ca7718d0518db2e559ecd17eb6f7f57338b80fd..f8d803c5e2bea65f1fb458d23f80bd7717f2a8c9 100755 (executable)
@@ -5,7 +5,7 @@
 # but is meant to be a simple fast-import example.
 
 if [ -z "$1" -o -z "$2" ]; then
-       echo "Usage: git-import branch import-message"
+       echo "usage: git-import branch import-message"
        exit 1
 fi
 
index 5cec9b012994de61ba6ed1e4c17992edbfd8a07d..d12c2962230b80b5e6310ade8424d9b60cc37d20 100755 (executable)
 from zipfile import ZipFile
 
 if hexversion < 0x01060000:
-        # The limiter is the zipfile module
-        sys.stderr.write("import-zips.py: requires Python 1.6.0 or later.\n")
-        sys.exit(1)
+    # The limiter is the zipfile module
+    stderr.write("import-zips.py: requires Python 1.6.0 or later.\n")
+    exit(1)
 
 if len(argv) < 2:
-       print 'Usage:', argv[0], '<zipfile>...'
-       exit(1)
+    print 'usage:', argv[0], '<zipfile>...'
+    exit(1)
 
 branch_ref = 'refs/heads/import-zips'
 committer_name = 'Z Ip Creator'
 
 fast_import = popen('git fast-import --quiet', 'w')
 def printlines(list):
-       for str in list:
-               fast_import.write(str + "\n")
+    for str in list:
+        fast_import.write(str + "\n")
 
 for zipfile in argv[1:]:
-       commit_time = 0
-       next_mark = 1
-       common_prefix = None
-       mark = dict()
-
-       zip = ZipFile(zipfile, 'r')
-       for name in zip.namelist():
-               if name.endswith('/'):
-                       continue
-               info = zip.getinfo(name)
-
-               if commit_time < info.date_time:
-                       commit_time = info.date_time
-               if common_prefix == None:
-                       common_prefix = name[:name.rfind('/') + 1]
-               else:
-                       while not name.startswith(common_prefix):
-                               last_slash = common_prefix[:-1].rfind('/') + 1
-                               common_prefix = common_prefix[:last_slash]
-
-               mark[name] = ':' + str(next_mark)
-               next_mark += 1
-
-               printlines(('blob', 'mark ' + mark[name], \
-                                       'data ' + str(info.file_size)))
-               fast_import.write(zip.read(name) + "\n")
-
-       committer = committer_name + ' <' + committer_email + '> %d +0000' % \
-               mktime(commit_time + (0, 0, 0))
-
-       printlines(('commit ' + branch_ref, 'committer ' + committer, \
-               'data <<EOM', 'Imported from ' + zipfile + '.', 'EOM', \
-               '', 'deleteall'))
-
-       for name in mark.keys():
-               fast_import.write('M 100644 ' + mark[name] + ' ' +
-                       name[len(common_prefix):] + "\n")
-
-       printlines(('',  'tag ' + path.basename(zipfile), \
-               'from ' + branch_ref, 'tagger ' + committer, \
-               'data <<EOM', 'Package ' + zipfile, 'EOM', ''))
+    commit_time = 0
+    next_mark = 1
+    common_prefix = None
+    mark = dict()
+
+    zip = ZipFile(zipfile, 'r')
+    for name in zip.namelist():
+        if name.endswith('/'):
+            continue
+        info = zip.getinfo(name)
+
+        if commit_time < info.date_time:
+            commit_time = info.date_time
+        if common_prefix == None:
+            common_prefix = name[:name.rfind('/') + 1]
+        else:
+            while not name.startswith(common_prefix):
+                last_slash = common_prefix[:-1].rfind('/') + 1
+                common_prefix = common_prefix[:last_slash]
+
+        mark[name] = ':' + str(next_mark)
+        next_mark += 1
+
+        printlines(('blob', 'mark ' + mark[name], \
+                    'data ' + str(info.file_size)))
+        fast_import.write(zip.read(name) + "\n")
+
+    committer = committer_name + ' <' + committer_email + '> %d +0000' % \
+        mktime(commit_time + (0, 0, 0))
+
+    printlines(('commit ' + branch_ref, 'committer ' + committer, \
+        'data <<EOM', 'Imported from ' + zipfile + '.', 'EOM', \
+        '', 'deleteall'))
+
+    for name in mark.keys():
+        fast_import.write('M 100644 ' + mark[name] + ' ' +
+            name[len(common_prefix):] + "\n")
+
+    printlines(('',  'tag ' + path.basename(zipfile), \
+        'from ' + branch_ref, 'tagger ' + committer, \
+        'data <<EOM', 'Package ' + zipfile, 'EOM', ''))
 
 if fast_import.close():
-       exit(1)
+    exit(1)
index a577ad095f1cfea1c11efe53c4cd82625e508594..2770a1b1d205ee6b6edaec291a7dce3fc417027f 100644 (file)
@@ -24,7 +24,7 @@
 use File::Basename;
 
 my $usage =
-"Usage: setgitperms.perl [OPTION]... <--read|--write>
+"usage: setgitperms.perl [OPTION]... <--read|--write>
 This program uses a file `.gitmeta` to store/restore permissions and uid/gid
 info for all files/dirs tracked by git in the repository.
 
index c6d6fa3aefafa8f782be20b7919f2acfc7667a6f..70a53f67fd06bd2ce6f2f544655b03b99c6b2ee9 100755 (executable)
@@ -15,7 +15,7 @@ fi
 
 . "$WIKI_TEST_DIR"/test-gitmw-lib.sh
 usage () {
-       echo "Usage: "
+       echo "usage: "
        echo "  ./install-wiki.sh <install | delete | --help>"
        echo "          install | -i :  Install a wiki on your computer."
        echo "          delete | -d : Delete the wiki and all its pages and "
index 512d0ac5fd2bc0acfb57147a6eb77f61f92b7c7e..6c7a72fbe74e8dd6fca07d2555cdea62c16b8b1e 100644 (file)
@@ -389,6 +389,7 @@ static int find_exact_renames(struct diff_options *options)
        struct hash_table file_table;
 
        init_hash(&file_table);
+       preallocate_hash(&file_table, rename_src_nr + rename_dst_nr);
        for (i = 0; i < rename_src_nr; i++)
                insert_file_table(&file_table, -1, i, rename_src[i].p->one);
 
index 6d8926a5504a6cd93e19860f85d58816bdd5c222..cef8fde61bf4516f95ae13b05f73cb26a268f90c 100644 (file)
@@ -36,7 +36,7 @@ static int marked;
 #define MAX_IN_VAIN 256
 
 static struct commit_list *rev_list;
-static int non_common_revs, multi_ack, use_sideband;
+static int non_common_revs, multi_ack, use_sideband, allow_tip_sha1_in_want;
 
 static void rev_list_push(struct commit *commit, int mark)
 {
@@ -520,47 +520,37 @@ static void mark_recent_complete_commits(struct fetch_pack_args *args,
        }
 }
 
-static int non_matching_ref(struct string_list_item *item, void *unused)
-{
-       if (item->util) {
-               item->util = NULL;
-               return 0;
-       }
-       else
-               return 1;
-}
-
 static void filter_refs(struct fetch_pack_args *args,
-                       struct ref **refs, struct string_list *sought)
+                       struct ref **refs,
+                       struct ref **sought, int nr_sought)
 {
        struct ref *newlist = NULL;
        struct ref **newtail = &newlist;
        struct ref *ref, *next;
-       int sought_pos;
+       int i;
 
-       sought_pos = 0;
+       i = 0;
        for (ref = *refs; ref; ref = next) {
                int keep = 0;
                next = ref->next;
+
                if (!memcmp(ref->name, "refs/", 5) &&
                    check_refname_format(ref->name + 5, 0))
                        ; /* trash */
                else {
-                       while (sought_pos < sought->nr) {
-                               int cmp = strcmp(ref->name, sought->items[sought_pos].string);
+                       while (i < nr_sought) {
+                               int cmp = strcmp(ref->name, sought[i]->name);
                                if (cmp < 0)
                                        break; /* definitely do not have it */
                                else if (cmp == 0) {
                                        keep = 1; /* definitely have it */
-                                       sought->items[sought_pos++].util = "matched";
-                                       break;
+                                       sought[i]->matched = 1;
                                }
-                               else
-                                       sought_pos++; /* might have it; keep looking */
+                               i++;
                        }
                }
 
-               if (! keep && args->fetch_all &&
+               if (!keep && args->fetch_all &&
                    (!args->depth || prefixcmp(ref->name, "refs/tags/")))
                        keep = 1;
 
@@ -573,7 +563,21 @@ static void filter_refs(struct fetch_pack_args *args,
                }
        }
 
-       filter_string_list(sought, 0, non_matching_ref, NULL);
+       /* Append unmatched requests to the list */
+       if (allow_tip_sha1_in_want) {
+               for (i = 0; i < nr_sought; i++) {
+                       ref = sought[i];
+                       if (ref->matched)
+                               continue;
+                       if (get_sha1_hex(ref->name, ref->old_sha1))
+                               continue;
+
+                       ref->matched = 1;
+                       *newtail = ref;
+                       ref->next = NULL;
+                       newtail = &ref->next;
+               }
+       }
        *refs = newlist;
 }
 
@@ -583,7 +587,8 @@ static void mark_alternate_complete(const struct ref *ref, void *unused)
 }
 
 static int everything_local(struct fetch_pack_args *args,
-                           struct ref **refs, struct string_list *sought)
+                           struct ref **refs,
+                           struct ref **sought, int nr_sought)
 {
        struct ref *ref;
        int retval;
@@ -637,7 +642,7 @@ static int everything_local(struct fetch_pack_args *args,
                }
        }
 
-       filter_refs(args, refs, sought);
+       filter_refs(args, refs, sought, nr_sought);
 
        for (retval = 1, ref = *refs; ref ; ref = ref->next) {
                const unsigned char *remote = ref->old_sha1;
@@ -767,10 +772,17 @@ static int get_pack(struct fetch_pack_args *args,
        return 0;
 }
 
+static int cmp_ref_by_name(const void *a_, const void *b_)
+{
+       const struct ref *a = *((const struct ref **)a_);
+       const struct ref *b = *((const struct ref **)b_);
+       return strcmp(a->name, b->name);
+}
+
 static struct ref *do_fetch_pack(struct fetch_pack_args *args,
                                 int fd[2],
                                 const struct ref *orig_ref,
-                                struct string_list *sought,
+                                struct ref **sought, int nr_sought,
                                 char **pack_lockfile)
 {
        struct ref *ref = copy_ref_list(orig_ref);
@@ -779,6 +791,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
        int agent_len;
 
        sort_ref_list(&ref, ref_compare_name);
+       qsort(sought, nr_sought, sizeof(*sought), cmp_ref_by_name);
 
        if (is_repository_shallow() && !server_supports("shallow"))
                die("Server does not support shallow clients");
@@ -808,6 +821,11 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
                        fprintf(stderr, "Server supports side-band\n");
                use_sideband = 1;
        }
+       if (server_supports("allow-tip-sha1-in-want")) {
+               if (args->verbose)
+                       fprintf(stderr, "Server supports allow-tip-sha1-in-want\n");
+               allow_tip_sha1_in_want = 1;
+       }
        if (!server_supports("thin-pack"))
                args->use_thin_pack = 0;
        if (!server_supports("no-progress"))
@@ -827,7 +845,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
                                agent_len, agent_feature);
        }
 
-       if (everything_local(args, &ref, sought)) {
+       if (everything_local(args, &ref, sought, nr_sought)) {
                packet_flush(fd[1]);
                goto all_done;
        }
@@ -890,11 +908,32 @@ static void fetch_pack_setup(void)
        did_setup = 1;
 }
 
+static int remove_duplicates_in_refs(struct ref **ref, int nr)
+{
+       struct string_list names = STRING_LIST_INIT_NODUP;
+       int src, dst;
+
+       for (src = dst = 0; src < nr; src++) {
+               struct string_list_item *item;
+               item = string_list_insert(&names, ref[src]->name);
+               if (item->util)
+                       continue; /* already have it */
+               item->util = ref[src];
+               if (src != dst)
+                       ref[dst] = ref[src];
+               dst++;
+       }
+       for (src = dst; src < nr; src++)
+               ref[src] = NULL;
+       string_list_clear(&names, 0);
+       return dst;
+}
+
 struct ref *fetch_pack(struct fetch_pack_args *args,
                       int fd[], struct child_process *conn,
                       const struct ref *ref,
                       const char *dest,
-                      struct string_list *sought,
+                      struct ref **sought, int nr_sought,
                       char **pack_lockfile)
 {
        struct stat st;
@@ -906,16 +945,14 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
                        st.st_mtime = 0;
        }
 
-       if (sought->nr) {
-               sort_string_list(sought);
-               string_list_remove_duplicates(sought, 0);
-       }
+       if (nr_sought)
+               nr_sought = remove_duplicates_in_refs(sought, nr_sought);
 
        if (!ref) {
                packet_flush(fd[1]);
                die("no matching remote head");
        }
-       ref_cpy = do_fetch_pack(args, fd, ref, sought, pack_lockfile);
+       ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought, pack_lockfile);
 
        if (args->depth > 0) {
                static struct lock_file lock;
index cb148719bfd3bace27a0ca9611f1c38066fb6ed4..dc5266c970655a9fe4f971a0132c14e1cf731acc 100644 (file)
@@ -20,17 +20,16 @@ struct fetch_pack_args {
 };
 
 /*
- * sought contains the full names of remote references that should be
- * updated from.  On return, the names that were found on the remote
- * will have been removed from the list.  The util members of the
- * string_list_items are used internally; they must be NULL on entry
- * (and will be NULL on exit).
+ * sought represents remote references that should be updated from.
+ * On return, the names that were found on the remote will have been
+ * marked as such.
  */
 struct ref *fetch_pack(struct fetch_pack_args *args,
                       int fd[], struct child_process *conn,
                       const struct ref *ref,
                       const char *dest,
-                      struct string_list *sought,
+                      struct ref **sought,
+                      int nr_sought,
                       char **pack_lockfile);
 
 #endif
index bc32f18d6d9cbf915eb7797817390adbbc111506..9cb123a07df88c975cf1b0d6c5832cb410175dd0 100755 (executable)
@@ -75,7 +75,7 @@ =head1 Devel Notes
 
 sub usage() {
     print STDERR <<END;
-Usage: git archimport     # fetch/update GIT from Arch
+usage: git archimport     # fetch/update GIT from Arch
        [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ] [ -D depth ] [ -t tempdir ]
        repository/arch-branch [ repository/arch-branch] ...
 END
index e715285e7c2e0a3d0b959505921b344dda55089d..90e037203879f6ba91403ae5371f18910206b580 100644 (file)
@@ -86,6 +86,9 @@
 #define _SGI_SOURCE 1
 
 #ifdef WIN32 /* Both MinGW and MSVC */
+# if defined (_MSC_VER)
+#  define _WIN32_WINNT 0x0502
+# endif
 #define WIN32_LEAN_AND_MEAN  /* stops windows.h including winsock.h */
 #include <winsock2.h>
 #include <windows.h>
index e6bf25232c4ec27fc98f78e076678ae4d0a524c1..d13f02da95f3b9b3921c3ccff9e3b6a7511cd666 100755 (executable)
 
 sub usage {
        print STDERR <<END;
-Usage: GIT_DIR=/path/to/.git git cvsexportcommit [-h] [-p] [-v] [-c] [-f] [-u] [-k] [-w cvsworkdir] [-m msgprefix] [ parent ] commit
+usage: GIT_DIR=/path/to/.git git cvsexportcommit [-h] [-p] [-v] [-c] [-f] [-u] [-k] [-w cvsworkdir] [-m msgprefix] [ parent ] commit
 END
        exit(1);
 }
index 344f1206d111a57ec529c34785ff8b1a6537e4d1..73d367cea8f130bc7721803e397df710e7cfff58 100755 (executable)
@@ -38,7 +38,7 @@ (;$)
        my $msg = shift;
        print(STDERR "Error: $msg\n") if $msg;
        print STDERR <<END;
-Usage: git cvsimport     # fetch/update GIT from CVS
+usage: git cvsimport     # fetch/update GIT from CVS
        [-o branch-for-HEAD] [-h] [-v] [-d CVSROOT] [-A author-conv-file]
        [-p opts-for-cvsps] [-P file] [-C GIT_repository] [-z fuzz] [-i] [-k]
        [-u] [-s subst] [-a] [-m] [-M regex] [-S regex] [-L commitlimit]
index 36790749830251854fa475f2bd8d33ece07203f6..f1c3f49a836a8cf7f980bd3bc99d4fe9c2d49b65 100755 (executable)
 $log->info("--------------- STARTING -----------------");
 
 my $usage =
-    "Usage: git cvsserver [options] [pserver|server] [<directory> ...]\n".
+    "usage: git cvsserver [options] [pserver|server] [<directory> ...]\n".
     "    --base-path <path>  : Prepend to requested CVSROOT\n".
     "                          Can be read from GIT_CVSSERVER_BASE_PATH\n".
     "    --strict-paths      : Don't allow recursing into subdirectories\n".
index 0a90de414646b901e13abbf89aa78ae71e8b12f0..12231fbc6708971f6350006c710124bd369de7ab 100755 (executable)
@@ -336,7 +336,7 @@ sub main
        }
        if ($opts{gui}) {
                my $guitool = Git::config('diff.guitool');
-               if (length($guitool) > 0) {
+               if (defined($guitool) && length($guitool) > 0) {
                        $ENV{GIT_DIFF_TOOL} = $guitool;
                }
        }
index f612cb847aca981e16cb6006fa08d870497c6263..3373c040d4aae221386fac5ec2cd9a29344c1840 100755 (executable)
@@ -18,7 +18,7 @@
 
 USAGE='<orig blob> <our blob> <their blob> <path>'
 USAGE="$USAGE <orig mode> <our mode> <their mode>"
-LONG_USAGE="Usage: git merge-one-file $USAGE
+LONG_USAGE="usage: git merge-one-file $USAGE
 
 Blob ids and modes should be empty for missing files."
 
index f29285c411a6dc9b58cffb47b91577bb2d023bc6..236a3521a19260f5f49b81a39d7193a68b25b64b 100755 (executable)
@@ -163,7 +163,7 @@ ($$)
 
 
 sub usage() {
-       print("Usage: git relink [--safe] <dir>... <master_dir> \n");
+       print("usage: git relink [--safe] <dir>... <master_dir> \n");
        print("All directories should contain a .git/objects/ subdirectory.\n");
        print("Options\n");
        print("\t--safe\t" .
index be809e5b59394a4fd2f4f2b73cad6bac47a39600..c3501d987e66d330189f156590316d335b580aaf 100755 (executable)
@@ -1045,6 +1045,47 @@ sub maildomain {
        return maildomain_net() || maildomain_mta() || 'localhost.localdomain';
 }
 
+sub smtp_host_string {
+       if (defined $smtp_server_port) {
+               return "$smtp_server:$smtp_server_port";
+       } else {
+               return $smtp_server;
+       }
+}
+
+# Returns 1 if authentication succeeded or was not necessary
+# (smtp_user was not specified), and 0 otherwise.
+
+sub smtp_auth_maybe {
+       if (!defined $smtp_authuser || $auth) {
+               return 1;
+       }
+
+       # Workaround AUTH PLAIN/LOGIN interaction defect
+       # with Authen::SASL::Cyrus
+       eval {
+               require Authen::SASL;
+               Authen::SASL->import(qw(Perl));
+       };
+
+       # TODO: Authentication may fail not because credentials were
+       # invalid but due to other reasons, in which we should not
+       # reject credentials.
+       $auth = Git::credential({
+               'protocol' => 'smtp',
+               'host' => smtp_host_string(),
+               'username' => $smtp_authuser,
+               # if there's no password, "git credential fill" will
+               # give us one, otherwise it'll just pass this one.
+               'password' => $smtp_authpass
+       }, sub {
+               my $cred = shift;
+               return !!$smtp->auth($cred->{'username'}, $cred->{'password'});
+       });
+
+       return $auth;
+}
+
 # Returns 1 if the message was sent, and 0 otherwise.
 # In actuality, the whole program dies when there
 # is an error sending a message.
@@ -1155,9 +1196,7 @@ sub send_message {
                else {
                        require Net::SMTP;
                        $smtp_domain ||= maildomain();
-                       $smtp ||= Net::SMTP->new((defined $smtp_server_port)
-                                                ? "$smtp_server:$smtp_server_port"
-                                                : $smtp_server,
+                       $smtp ||= Net::SMTP->new(smtp_host_string(),
                                                 Hello => $smtp_domain,
                                                 Debug => $debug_net_smtp);
                        if ($smtp_encryption eq 'tls' && $smtp) {
@@ -1185,31 +1224,7 @@ sub send_message {
                            defined $smtp_server_port ? " port=$smtp_server_port" : "";
                }
 
-               if (defined $smtp_authuser) {
-                       # Workaround AUTH PLAIN/LOGIN interaction defect
-                       # with Authen::SASL::Cyrus
-                       eval {
-                               require Authen::SASL;
-                               Authen::SASL->import(qw(Perl));
-                       };
-
-                       if (!defined $smtp_authpass) {
-
-                               system "stty -echo";
-
-                               do {
-                                       print "Password: ";
-                                       $_ = <STDIN>;
-                                       print "\n";
-                               } while (!defined $_);
-
-                               chomp($smtp_authpass = $_);
-
-                               system "stty echo";
-                       }
-
-                       $auth ||= $smtp->auth( $smtp_authuser, $smtp_authpass ) or die $smtp->message;
-               }
+               smtp_auth_maybe or die $smtp->message;
 
                $smtp->mail( $raw_from ) or die $smtp->message;
                $smtp->to( @recipients ) or die $smtp->message;
index 795edd2852aa1c680c3db1776bb84aca7662899d..9cfbe7f1435e073eeb39ab2190eda2d2dda300a5 100644 (file)
@@ -84,14 +84,14 @@ if test -n "$OPTIONS_SPEC"; then
 else
        dashless=$(basename "$0" | sed -e 's/-/ /')
        usage() {
-               die "Usage: $dashless $USAGE"
+               die "usage: $dashless $USAGE"
        }
 
        if [ -z "$LONG_USAGE" ]
        then
-               LONG_USAGE="Usage: $dashless $USAGE"
+               LONG_USAGE="usage: $dashless $USAGE"
        else
-               LONG_USAGE="Usage: $dashless $USAGE
+               LONG_USAGE="usage: $dashless $USAGE
 
 $LONG_USAGE"
        fi
index 004c034bc09449416ff6d66b7570d48b651f96cb..ab29bfeb738d1b8f452c558ba6f6d7aa4e854b3d 100755 (executable)
@@ -622,7 +622,7 @@ cmd_update()
                die_if_unmatched "$mode"
                if test "$stage" = U
                then
-                       echo >&2 "Skipping unmerged submodule $sm_path"
+                       echo >&2 "Skipping unmerged submodule $prefix$sm_path"
                        continue
                fi
                name=$(module_name "$sm_path") || exit
@@ -637,7 +637,7 @@ cmd_update()
 
                if test "$update_module" = "none"
                then
-                       echo "Skipping submodule '$sm_path'"
+                       echo "Skipping submodule '$prefix$sm_path'"
                        continue
                fi
 
@@ -646,7 +646,7 @@ cmd_update()
                        # Only mention uninitialized submodules when its
                        # path have been specified
                        test "$#" != "0" &&
-                       say "$(eval_gettext "Submodule path '\$sm_path' not initialized
+                       say "$(eval_gettext "Submodule path '\$prefix\$sm_path' not initialized
 Maybe you want to use 'update --init'?")"
                        continue
                fi
@@ -659,7 +659,7 @@ Maybe you want to use 'update --init'?")"
                else
                        subsha1=$(clear_local_git_env; cd "$sm_path" &&
                                git rev-parse --verify HEAD) ||
-                       die "$(eval_gettext "Unable to find current revision in submodule path '\$sm_path'")"
+                       die "$(eval_gettext "Unable to find current revision in submodule path '\$prefix\$sm_path'")"
                fi
 
                if test -n "$remote"
@@ -692,7 +692,7 @@ Maybe you want to use 'update --init'?")"
                                (clear_local_git_env; cd "$sm_path" &&
                                        ( (rev=$(git rev-list -n 1 $sha1 --not --all 2>/dev/null) &&
                                         test -z "$rev") || git-fetch)) ||
-                               die "$(eval_gettext "Unable to fetch in submodule path '\$sm_path'")"
+                               die "$(eval_gettext "Unable to fetch in submodule path '\$prefix\$sm_path'")"
                        fi
 
                        # Is this something we just cloned?
@@ -706,20 +706,20 @@ Maybe you want to use 'update --init'?")"
                        case "$update_module" in
                        rebase)
                                command="git rebase"
-                               die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$sm_path'")"
-                               say_msg="$(eval_gettext "Submodule path '\$sm_path': rebased into '\$sha1'")"
+                               die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$prefix\$sm_path'")"
+                               say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': rebased into '\$sha1'")"
                                must_die_on_failure=yes
                                ;;
                        merge)
                                command="git merge"
-                               die_msg="$(eval_gettext "Unable to merge '\$sha1' in submodule path '\$sm_path'")"
-                               say_msg="$(eval_gettext "Submodule path '\$sm_path': merged in '\$sha1'")"
+                               die_msg="$(eval_gettext "Unable to merge '\$sha1' in submodule path '\$prefix\$sm_path'")"
+                               say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': merged in '\$sha1'")"
                                must_die_on_failure=yes
                                ;;
                        *)
                                command="git checkout $subforce -q"
-                               die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$sm_path'")"
-                               say_msg="$(eval_gettext "Submodule path '\$sm_path': checked out '\$sha1'")"
+                               die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$prefix\$sm_path'")"
+                               say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': checked out '\$sha1'")"
                                ;;
                        esac
 
@@ -737,11 +737,16 @@ Maybe you want to use 'update --init'?")"
 
                if test -n "$recursive"
                then
-                       (clear_local_git_env; cd "$sm_path" && eval cmd_update "$orig_flags")
+                       (
+                               prefix="$prefix$sm_path/"
+                               clear_local_git_env
+                               cd "$sm_path" &&
+                               eval cmd_update "$orig_flags"
+                       )
                        res=$?
                        if test $res -gt 0
                        then
-                               die_msg="$(eval_gettext "Failed to recurse into submodule path '\$sm_path'")"
+                               die_msg="$(eval_gettext "Failed to recurse into submodule path '\$prefix\$sm_path'")"
                                if test $res -eq 1
                                then
                                        err="${err};$die_msg"
index b46795f5935dd3d61a2f3e45f979aec04d12afcb..6c7bd95032b890d2f79cff0d18ac6aa688a74757 100755 (executable)
@@ -382,7 +382,7 @@ sub usage {
        my $fd = $exit ? \*STDERR : \*STDOUT;
        print $fd <<"";
 git-svn - bidirectional operations between a single Subversion tree and git
-Usage: git svn <command> [options] [arguments]\n
+usage: git svn <command> [options] [arguments]\n
 
        print $fd "Available commands:\n" unless $cmd;
 
@@ -534,7 +534,7 @@ sub cmd_fetch {
        }
        my ($remote) = @_;
        if (@_ > 1) {
-               die "Usage: $0 fetch [--all] [--parent] [svn-remote]\n";
+               die "usage: $0 fetch [--all] [--parent] [svn-remote]\n";
        }
        $Git::SVN::no_reuse_existing = undef;
        if ($_fetch_parent) {
@@ -1404,7 +1404,7 @@ sub cmd_multi_fetch {
 # this command is special because it requires no metadata
 sub cmd_commit_diff {
        my ($ta, $tb, $url) = @_;
-       my $usage = "Usage: $0 commit-diff -r<revision> ".
+       my $usage = "usage: $0 commit-diff -r<revision> ".
                    "<tree-ish> <tree-ish> [<URL>]";
        fatal($usage) if (!defined $ta || !defined $tb);
        my $svn_path = '';
index 45590330aa3131da69174899783913cee9a44c31..8b0e87436b687ce26e3e4987129a2fc171069280 100644 (file)
@@ -96,15 +96,18 @@ int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *sig
 /*
  * Run "gpg" to see if the payload matches the detached signature.
  * gpg_output, when set, receives the diagnostic output from GPG.
+ * gpg_status, when set, receives the status output from GPG.
  */
 int verify_signed_buffer(const char *payload, size_t payload_size,
                         const char *signature, size_t signature_size,
-                        struct strbuf *gpg_output)
+                        struct strbuf *gpg_output, struct strbuf *gpg_status)
 {
        struct child_process gpg;
-       const char *args_gpg[] = {NULL, "--verify", "FILE", "-", NULL};
+       const char *args_gpg[] = {NULL, "--status-fd=1", "--verify", "FILE", "-", NULL};
        char path[PATH_MAX];
        int fd, ret;
+       struct strbuf buf = STRBUF_INIT;
+       struct strbuf *pbuf = &buf;
 
        args_gpg[0] = gpg_program;
        fd = git_mkstemp(path, PATH_MAX, ".git_vtag_tmpXXXXXX");
@@ -119,9 +122,10 @@ int verify_signed_buffer(const char *payload, size_t payload_size,
        memset(&gpg, 0, sizeof(gpg));
        gpg.argv = args_gpg;
        gpg.in = -1;
+       gpg.out = -1;
        if (gpg_output)
                gpg.err = -1;
-       args_gpg[2] = path;
+       args_gpg[3] = path;
        if (start_command(&gpg)) {
                unlink(path);
                return error(_("could not run gpg."));
@@ -134,9 +138,17 @@ int verify_signed_buffer(const char *payload, size_t payload_size,
                strbuf_read(gpg_output, gpg.err, 0);
                close(gpg.err);
        }
+       if (gpg_status)
+               pbuf = gpg_status;
+       strbuf_read(pbuf, gpg.out, 0);
+       close(gpg.out);
+
        ret = finish_command(&gpg);
 
        unlink_or_warn(path);
 
+       ret |= !strstr(pbuf->buf, "\n[GNUPG:] GOODSIG ");
+       strbuf_release(&buf); /* no matter it was used or not */
+
        return ret;
 }
index b9c36088cea3c1d419c23354e095320ebebd90a4..cf9902184272d20c6d5826cf9f10dcaebeb3e6e8 100644 (file)
@@ -2,7 +2,7 @@
 #define GPG_INTERFACE_H
 
 extern int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const char *signing_key);
-extern int verify_signed_buffer(const char *payload, size_t payload_size, const char *signature, size_t signature_size, struct strbuf *gpg_output);
+extern int verify_signed_buffer(const char *payload, size_t payload_size, const char *signature, size_t signature_size, struct strbuf *gpg_output, struct strbuf *gpg_status);
 extern int git_gpg_config(const char *, const char *, void *);
 extern void set_signing_key(const char *);
 extern const char *get_signing_key(void);
diff --git a/hash.h b/hash.h
index b875ce67c49eb39a8ca8ad6a688a334985db0534..1d43ac0ba0120e947e40476946360efbdee80a93 100644 (file)
--- a/hash.h
+++ b/hash.h
@@ -40,4 +40,11 @@ static inline void init_hash(struct hash_table *table)
        table->array = NULL;
 }
 
+static inline void preallocate_hash(struct hash_table *table, unsigned int elts)
+{
+       assert(table->size == 0 && table->nr == 0 && table->array == NULL);
+       table->size = elts * 2;
+       table->array = xcalloc(sizeof(struct hash_table_entry), table->size);
+}
+
 #endif
index 43ac4e0bdfdba8850eff176b53d6bd071e8f424c..d9bcfb44dc334d86363fd60b576fcc2e2121f971 100644 (file)
@@ -304,6 +304,17 @@ static int ssl_socket_connect(struct imap_socket *sock, int use_tls_only, int ve
                return -1;
        }
 
+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+       /*
+        * SNI (RFC4366)
+        * OpenSSL does not document this function, but the implementation
+        * returns 1 on success, 0 on failure after calling SSLerr().
+        */
+       ret = SSL_set_tlsext_host_name(sock->ssl, server.host);
+       if (ret != 1)
+               warning("SSL_set_tlsext_host_name(%s) failed.", server.host);
+#endif
+
        ret = SSL_connect(sock->ssl);
        if (ret <= 0) {
                socket_perror("SSL_connect", sock, ret);
index 5dc45c4812bdfd0d7a6b71d529eaa37df8178186..3d888238711364338a83e7d81bf27f555352bdca 100644 (file)
@@ -444,7 +444,7 @@ static void show_signature(struct rev_info *opt, struct commit *commit)
 
        status = verify_signed_buffer(payload.buf, payload.len,
                                      signature.buf, signature.len,
-                                     &gpg_output);
+                                     &gpg_output, NULL);
        if (status && !gpg_output.len)
                strbuf_addstr(&gpg_output, "No signature\n");
 
@@ -508,20 +508,17 @@ static void show_one_mergetag(struct rev_info *opt,
        gpg_message_offset = verify_message.len;
 
        payload_size = parse_signature(extra->value, extra->len);
-       if ((extra->len <= payload_size) ||
-           (verify_signed_buffer(extra->value, payload_size,
-                                 extra->value + payload_size,
-                                 extra->len - payload_size,
-                                 &verify_message) &&
-            verify_message.len <= gpg_message_offset)) {
-               strbuf_addstr(&verify_message, "No signature\n");
-               status = -1;
-       }
-       else if (strstr(verify_message.buf + gpg_message_offset,
-                       ": Good signature from "))
-               status = 0;
-       else
-               status = -1;
+       status = -1;
+       if (extra->len > payload_size)
+               if (verify_signed_buffer(extra->value, payload_size,
+                                        extra->value + payload_size,
+                                        extra->len - payload_size,
+                                        &verify_message, NULL)) {
+                       if (verify_message.len <= gpg_message_offset)
+                               strbuf_addstr(&verify_message, "No signature\n");
+                       else
+                               status = 0;
+               }
 
        show_sig_lines(opt, status, verify_message.buf);
        strbuf_release(&verify_message);
index 942c45962252eba4c6f88b4f4f7593c9247749ae..9bac31a6ab7aa80586828e7f48ab829e5b77a740 100644 (file)
@@ -92,6 +92,8 @@ static void lazy_init_name_hash(struct index_state *istate)
 
        if (istate->name_hash_initialized)
                return;
+       if (istate->cache_nr)
+               preallocate_hash(&istate->name_hash, istate->cache_nr);
        for (nr = 0; nr < istate->cache_nr; nr++)
                hash_index_entry(istate, istate->cache[nr]);
        istate->name_hash_initialized = 1;
index a56d1e76f797cdba83510a5488945425f1936c2d..96cac39a4c8ebc0ce4e111271429fdf68b03bf97 100644 (file)
@@ -60,6 +60,7 @@ =head1 SYNOPSIS
                 version exec_path html_path hash_object git_cmd_try
                 remote_refs prompt
                 get_tz_offset
+                credential credential_read credential_write
                 temp_acquire temp_release temp_reset temp_path);
 
 
@@ -269,13 +270,13 @@ sub command {
 
        if (not defined wantarray) {
                # Nothing to pepper the possible exception with.
-               _cmd_close($fh, $ctx);
+               _cmd_close($ctx, $fh);
 
        } elsif (not wantarray) {
                local $/;
                my $text = <$fh>;
                try {
-                       _cmd_close($fh, $ctx);
+                       _cmd_close($ctx, $fh);
                } catch Git::Error::Command with {
                        # Pepper with the output:
                        my $E = shift;
@@ -288,7 +289,7 @@ sub command {
                my @lines = <$fh>;
                defined and chomp for @lines;
                try {
-                       _cmd_close($fh, $ctx);
+                       _cmd_close($ctx, $fh);
                } catch Git::Error::Command with {
                        my $E = shift;
                        $E->{'-outputref'} = \@lines;
@@ -315,7 +316,7 @@ sub command_oneline {
        my $line = <$fh>;
        defined $line and chomp $line;
        try {
-               _cmd_close($fh, $ctx);
+               _cmd_close($ctx, $fh);
        } catch Git::Error::Command with {
                # Pepper with the output:
                my $E = shift;
@@ -383,7 +384,7 @@ sub command_input_pipe {
 sub command_close_pipe {
        my ($self, $fh, $ctx) = _maybe_self(@_);
        $ctx ||= '<unknown>';
-       _cmd_close($fh, $ctx);
+       _cmd_close($ctx, $fh);
 }
 
 =item command_bidi_pipe ( COMMAND [, ARGUMENTS... ] )
@@ -420,7 +421,7 @@ sub command_bidi_pipe {
 is:
 
        my ($pid, $in, $out, $ctx) = $r->command_bidi_pipe('cat-file --batch-check');
-       print "000000000\n" $out;
+       print $out "000000000\n";
        while (<$in>) { ... }
        $r->command_close_bidi_pipe($pid, $in, $out, $ctx);
 
@@ -428,23 +429,26 @@ sub command_bidi_pipe {
 currently it is simply the command name but in future the context might
 have more complicated structure.
 
+C<PIPE_IN> and C<PIPE_OUT> may be C<undef> if they have been closed prior to
+calling this function.  This may be useful in a query-response type of
+commands where caller first writes a query and later reads response, eg:
+
+       my ($pid, $in, $out, $ctx) = $r->command_bidi_pipe('cat-file --batch-check');
+       print $out "000000000\n";
+       close $out;
+       while (<$in>) { ... }
+       $r->command_close_bidi_pipe($pid, $in, undef, $ctx);
+
+This idiom may prevent potential dead locks caused by data sent to the output
+pipe not being flushed and thus not reaching the executed command.
+
 =cut
 
 sub command_close_bidi_pipe {
        local $?;
-       my ($pid, $in, $out, $ctx) = @_;
-       foreach my $fh ($in, $out) {
-               unless (close $fh) {
-                       if ($!) {
-                               carp "error closing pipe: $!";
-                       } elsif ($? >> 8) {
-                               throw Git::Error::Command($ctx, $? >>8);
-                       }
-               }
-       }
-
+       my ($self, $pid, $in, $out, $ctx) = _maybe_self(@_);
+       _cmd_close($ctx, (grep { defined } ($in, $out)));
        waitpid $pid, 0;
-
        if ($? >> 8) {
                throw Git::Error::Command($ctx, $? >>8);
        }
@@ -965,20 +969,22 @@ sub cat_blob {
        my $size = $1;
 
        my $blob;
-       my $bytesRead = 0;
+       my $bytesLeft = $size;
 
        while (1) {
-               my $bytesLeft = $size - $bytesRead;
                last unless $bytesLeft;
 
                my $bytesToRead = $bytesLeft < 1024 ? $bytesLeft : 1024;
-               my $read = read($in, $blob, $bytesToRead, $bytesRead);
+               my $read = read($in, $blob, $bytesToRead);
                unless (defined($read)) {
                        $self->_close_cat_blob();
                        throw Error::Simple("in pipe went bad");
                }
-
-               $bytesRead += $read;
+               unless (print $fh $blob) {
+                       $self->_close_cat_blob();
+                       throw Error::Simple("couldn't write to passed in filehandle");
+               }
+               $bytesLeft -= $read;
        }
 
        # Skip past the trailing newline.
@@ -993,11 +999,6 @@ sub cat_blob {
                throw Error::Simple("didn't find newline after blob");
        }
 
-       unless (print $fh $blob) {
-               $self->_close_cat_blob();
-               throw Error::Simple("couldn't write to passed in filehandle");
-       }
-
        return $size;
 }
 
@@ -1023,6 +1024,156 @@ sub _close_cat_blob {
 }
 
 
+=item credential_read( FILEHANDLE )
+
+Reads credential key-value pairs from C<FILEHANDLE>.  Reading stops at EOF or
+when an empty line is encountered.  Each line must be of the form C<key=value>
+with a non-empty key.  Function returns hash with all read values.  Any white
+space (other than new-line character) is preserved.
+
+=cut
+
+sub credential_read {
+       my ($self, $reader) = _maybe_self(@_);
+       my %credential;
+       while (<$reader>) {
+               chomp;
+               if ($_ eq '') {
+                       last;
+               } elsif (!/^([^=]+)=(.*)$/) {
+                       throw Error::Simple("unable to parse git credential data:\n$_");
+               }
+               $credential{$1} = $2;
+       }
+       return %credential;
+}
+
+=item credential_write( FILEHANDLE, CREDENTIAL_HASHREF )
+
+Writes credential key-value pairs from hash referenced by
+C<CREDENTIAL_HASHREF> to C<FILEHANDLE>.  Keys and values cannot contain
+new-lines or NUL bytes characters, and key cannot contain equal signs nor be
+empty (if they do Error::Simple is thrown).  Any white space is preserved.  If
+value for a key is C<undef>, it will be skipped.
+
+If C<'url'> key exists it will be written first.  (All the other key-value
+pairs are written in sorted order but you should not depend on that).  Once
+all lines are written, an empty line is printed.
+
+=cut
+
+sub credential_write {
+       my ($self, $writer, $credential) = _maybe_self(@_);
+       my ($key, $value);
+
+       # Check if $credential is valid prior to writing anything
+       while (($key, $value) = each %$credential) {
+               if (!defined $key || !length $key) {
+                       throw Error::Simple("credential key empty or undefined");
+               } elsif ($key =~ /[=\n\0]/) {
+                       throw Error::Simple("credential key contains invalid characters: $key");
+               } elsif (defined $value && $value =~ /[\n\0]/) {
+                       throw Error::Simple("credential value for key=$key contains invalid characters: $value");
+               }
+       }
+
+       for $key (sort {
+               # url overwrites other fields, so it must come first
+               return -1 if $a eq 'url';
+               return  1 if $b eq 'url';
+               return $a cmp $b;
+       } keys %$credential) {
+               if (defined $credential->{$key}) {
+                       print $writer $key, '=', $credential->{$key}, "\n";
+               }
+       }
+       print $writer "\n";
+}
+
+sub _credential_run {
+       my ($self, $credential, $op) = _maybe_self(@_);
+       my ($pid, $reader, $writer, $ctx) = command_bidi_pipe('credential', $op);
+
+       credential_write $writer, $credential;
+       close $writer;
+
+       if ($op eq "fill") {
+               %$credential = credential_read $reader;
+       }
+       if (<$reader>) {
+               throw Error::Simple("unexpected output from git credential $op response:\n$_\n");
+       }
+
+       command_close_bidi_pipe($pid, $reader, undef, $ctx);
+}
+
+=item credential( CREDENTIAL_HASHREF [, OPERATION ] )
+
+=item credential( CREDENTIAL_HASHREF, CODE )
+
+Executes C<git credential> for a given set of credentials and specified
+operation.  In both forms C<CREDENTIAL_HASHREF> needs to be a reference to
+a hash which stores credentials.  Under certain conditions the hash can
+change.
+
+In the first form, C<OPERATION> can be C<'fill'>, C<'approve'> or C<'reject'>,
+and function will execute corresponding C<git credential> sub-command.  If
+it's omitted C<'fill'> is assumed.  In case of C<'fill'> the values stored in
+C<CREDENTIAL_HASHREF> will be changed to the ones returned by the C<git
+credential fill> command.  The usual usage would look something like:
+
+       my %cred = (
+               'protocol' => 'https',
+               'host' => 'example.com',
+               'username' => 'bob'
+       );
+       Git::credential \%cred;
+       if (try_to_authenticate($cred{'username'}, $cred{'password'})) {
+               Git::credential \%cred, 'approve';
+               ... do more stuff ...
+       } else {
+               Git::credential \%cred, 'reject';
+       }
+
+In the second form, C<CODE> needs to be a reference to a subroutine.  The
+function will execute C<git credential fill> to fill the provided credential
+hash, then call C<CODE> with C<CREDENTIAL_HASHREF> as the sole argument.  If
+C<CODE>'s return value is defined, the function will execute C<git credential
+approve> (if return value yields true) or C<git credential reject> (if return
+value is false).  If the return value is undef, nothing at all is executed;
+this is useful, for example, if the credential could neither be verified nor
+rejected due to an unrelated network error.  The return value is the same as
+what C<CODE> returns.  With this form, the usage might look as follows:
+
+       if (Git::credential {
+               'protocol' => 'https',
+               'host' => 'example.com',
+               'username' => 'bob'
+       }, sub {
+               my $cred = shift;
+               return !!try_to_authenticate($cred->{'username'},
+                                            $cred->{'password'});
+       }) {
+               ... do more stuff ...
+       }
+
+=cut
+
+sub credential {
+       my ($self, $credential, $op_or_code) = (_maybe_self(@_), 'fill');
+
+       if ('CODE' eq ref $op_or_code) {
+               _credential_run $credential, 'fill';
+               my $ret = $op_or_code->($credential);
+               if (defined $ret) {
+                       _credential_run $credential, $ret ? 'approve' : 'reject';
+               }
+               return $ret;
+       } else {
+               _credential_run $credential, $op_or_code;
+       }
+}
+
 { # %TEMP_* Lexical Context
 
 my (%TEMP_FILEMAP, %TEMP_FILES);
@@ -1378,9 +1529,11 @@ sub _setup_git_cmd_env {
 
 # Close pipe to a subprocess.
 sub _cmd_close {
-       my ($fh, $ctx) = @_;
-       if (not close $fh) {
-               if ($!) {
+       my $ctx = shift @_;
+       foreach my $fh (@_) {
+               if (close $fh) {
+                       # nop
+               } elsif ($!) {
                        # It's just close, no point in fatalities
                        carp "error closing pipe: $!";
                } elsif ($? >> 8) {
index eae57ad9d7f3b06a5a76f9d934825f9824def477..b57adefdd296f7cdf410bdf87dd48e192d31353e 100644 (file)
--- a/pretty.c
+++ b/pretty.c
@@ -759,8 +759,10 @@ struct format_commit_context {
        unsigned commit_signature_parsed:1;
        struct {
                char *gpg_output;
+               char *gpg_status;
                char good_bad;
                char *signer;
+               char *key;
        } signature;
        char *message;
        size_t width, indent1, indent2;
@@ -948,13 +950,13 @@ static struct {
        char result;
        const char *check;
 } signature_check[] = {
-       { 'G', ": Good signature from " },
-       { 'B', ": BAD signature from " },
+       { 'G', "\n[GNUPG:] GOODSIG " },
+       { 'B', "\n[GNUPG:] BADSIG " },
 };
 
 static void parse_signature_lines(struct format_commit_context *ctx)
 {
-       const char *buf = ctx->signature.gpg_output;
+       const char *buf = ctx->signature.gpg_status;
        int i;
 
        for (i = 0; i < ARRAY_SIZE(signature_check); i++) {
@@ -964,6 +966,8 @@ static void parse_signature_lines(struct format_commit_context *ctx)
                        continue;
                ctx->signature.good_bad = signature_check[i].result;
                found += strlen(signature_check[i].check);
+               ctx->signature.key = xmemdupz(found, 16);
+               found += 17;
                next = strchrnul(found, '\n');
                ctx->signature.signer = xmemdupz(found, next - found);
                break;
@@ -975,6 +979,7 @@ static void parse_commit_signature(struct format_commit_context *ctx)
        struct strbuf payload = STRBUF_INIT;
        struct strbuf signature = STRBUF_INIT;
        struct strbuf gpg_output = STRBUF_INIT;
+       struct strbuf gpg_status = STRBUF_INIT;
        int status;
 
        ctx->commit_signature_parsed = 1;
@@ -984,13 +989,15 @@ static void parse_commit_signature(struct format_commit_context *ctx)
                goto out;
        status = verify_signed_buffer(payload.buf, payload.len,
                                      signature.buf, signature.len,
-                                     &gpg_output);
+                                     &gpg_output, &gpg_status);
        if (status && !gpg_output.len)
                goto out;
        ctx->signature.gpg_output = strbuf_detach(&gpg_output, NULL);
+       ctx->signature.gpg_status = strbuf_detach(&gpg_status, NULL);
        parse_signature_lines(ctx);
 
  out:
+       strbuf_release(&gpg_status);
        strbuf_release(&gpg_output);
        strbuf_release(&payload);
        strbuf_release(&signature);
@@ -1200,6 +1207,10 @@ static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
                        if (c->signature.signer)
                                strbuf_addstr(sb, c->signature.signer);
                        break;
+               case 'K':
+                       if (c->signature.key)
+                               strbuf_addstr(sb, c->signature.key);
+                       break;
                }
                return 2;
        }
index e53a6eb7769e2884f77819c73423c31e49b0114e..174e48eb7414a0bce0fb1720967e2343985d87ea 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -15,6 +15,7 @@ static struct refspec s_tag_refspec = {
        0,
        1,
        0,
+       0,
        "refs/tags/*",
        "refs/tags/*"
 };
@@ -538,7 +539,7 @@ static struct refspec *parse_refspec_internal(int nr_refspec, const char **refsp
 
                /*
                 * Before going on, special case ":" (or "+:") as a refspec
-                * for matching refs.
+                * for pushing matching refs.
                 */
                if (!fetch && rhs == lhs && rhs[1] == '\0') {
                        rs[i].matching = 1;
@@ -565,26 +566,25 @@ static struct refspec *parse_refspec_internal(int nr_refspec, const char **refsp
                flags = REFNAME_ALLOW_ONELEVEL | (is_glob ? REFNAME_REFSPEC_PATTERN : 0);
 
                if (fetch) {
-                       /*
-                        * LHS
-                        * - empty is allowed; it means HEAD.
-                        * - otherwise it must be a valid looking ref.
-                        */
+                       unsigned char unused[40];
+
+                       /* LHS */
                        if (!*rs[i].src)
-                               ; /* empty is ok */
-                       else if (check_refname_format(rs[i].src, flags))
+                               ; /* empty is ok; it means "HEAD" */
+                       else if (llen == 40 && !get_sha1_hex(rs[i].src, unused))
+                               rs[i].exact_sha1 = 1; /* ok */
+                       else if (!check_refname_format(rs[i].src, flags))
+                               ; /* valid looking ref is ok */
+                       else
                                goto invalid;
-                       /*
-                        * RHS
-                        * - missing is ok, and is same as empty.
-                        * - empty is ok; it means not to store.
-                        * - otherwise it must be a valid looking ref.
-                        */
+                       /* RHS */
                        if (!rs[i].dst)
-                               ; /* ok */
+                               ; /* missing is ok; it is the same as empty */
                        else if (!*rs[i].dst)
-                               ; /* ok */
-                       else if (check_refname_format(rs[i].dst, flags))
+                               ; /* empty is ok; it means "do not store" */
+                       else if (!check_refname_format(rs[i].dst, flags))
+                               ; /* valid looking ref is ok */
+                       else
                                goto invalid;
                } else {
                        /*
@@ -1466,7 +1466,12 @@ int get_fetch_map(const struct ref *remote_refs,
        } else {
                const char *name = refspec->src[0] ? refspec->src : "HEAD";
 
-               ref_map = get_remote_ref(remote_refs, name);
+               if (refspec->exact_sha1) {
+                       ref_map = alloc_ref(name);
+                       get_sha1_hex(name, ref_map->old_sha1);
+               } else {
+                       ref_map = get_remote_ref(remote_refs, name);
+               }
                if (!missing_ok && !ref_map)
                        die("Couldn't find remote ref %s", name);
                if (ref_map) {
index 251d8fd9654f23e7a131765742803492fb0d9041..f7b08f15de3f87ce75d16c81d08e84c47f028877 100644 (file)
--- a/remote.h
+++ b/remote.h
@@ -62,6 +62,7 @@ struct refspec {
        unsigned force : 1;
        unsigned pattern : 1;
        unsigned matching : 1;
+       unsigned exact_sha1 : 1;
 
        char *src;
        char *dst;
index 40b23297b2e1e60a3719e9c67256303e39456604..16967d3b9a86dc481a5161f0a98220e05790ca01 100644 (file)
@@ -21,6 +21,7 @@
 #include "sha1-lookup.h"
 #include "bulk-checkin.h"
 #include "streaming.h"
+#include "dir.h"
 
 #ifndef O_NOATIME
 #if defined(__linux__) && (defined(__i386__) || defined(__PPC__))
@@ -1000,6 +1001,63 @@ void install_packed_git(struct packed_git *pack)
        packed_git = pack;
 }
 
+void (*report_garbage)(const char *desc, const char *path);
+
+static void report_helper(const struct string_list *list,
+                         int seen_bits, int first, int last)
+{
+       const char *msg;
+       switch (seen_bits) {
+       case 0:
+               msg = "no corresponding .idx nor .pack";
+               break;
+       case 1:
+               msg = "no corresponding .idx";
+               break;
+       case 2:
+               msg = "no corresponding .pack";
+               break;
+       default:
+               return;
+       }
+       for (; first < last; first++)
+               report_garbage(msg, list->items[first].string);
+}
+
+static void report_pack_garbage(struct string_list *list)
+{
+       int i, baselen = -1, first = 0, seen_bits = 0;
+
+       if (!report_garbage)
+               return;
+
+       sort_string_list(list);
+
+       for (i = 0; i < list->nr; i++) {
+               const char *path = list->items[i].string;
+               if (baselen != -1 &&
+                   strncmp(path, list->items[first].string, baselen)) {
+                       report_helper(list, seen_bits, first, i);
+                       baselen = -1;
+                       seen_bits = 0;
+               }
+               if (baselen == -1) {
+                       const char *dot = strrchr(path, '.');
+                       if (!dot) {
+                               report_garbage("garbage found", path);
+                               continue;
+                       }
+                       baselen = dot - path + 1;
+                       first = i;
+               }
+               if (!strcmp(path + baselen, "pack"))
+                       seen_bits |= 1;
+               else if (!strcmp(path + baselen, "idx"))
+                       seen_bits |= 2;
+       }
+       report_helper(list, seen_bits, first, list->nr);
+}
+
 static void prepare_packed_git_one(char *objdir, int local)
 {
        /* Ensure that this buffer is large enough so that we can
@@ -1009,6 +1067,7 @@ static void prepare_packed_git_one(char *objdir, int local)
        int len;
        DIR *dir;
        struct dirent *de;
+       struct string_list garbage = STRING_LIST_INIT_DUP;
 
        sprintf(path, "%s/pack", objdir);
        len = strlen(path);
@@ -1024,29 +1083,49 @@ static void prepare_packed_git_one(char *objdir, int local)
                int namelen = strlen(de->d_name);
                struct packed_git *p;
 
-               if (!has_extension(de->d_name, ".idx"))
+               if (len + namelen + 1 > sizeof(path)) {
+                       if (report_garbage) {
+                               struct strbuf sb = STRBUF_INIT;
+                               strbuf_addf(&sb, "%.*s/%s", len - 1, path, de->d_name);
+                               report_garbage("path too long", sb.buf);
+                               strbuf_release(&sb);
+                       }
                        continue;
+               }
 
-               if (len + namelen + 1 > sizeof(path))
+               if (is_dot_or_dotdot(de->d_name))
                        continue;
 
-               /* Don't reopen a pack we already have. */
                strcpy(path + len, de->d_name);
-               for (p = packed_git; p; p = p->next) {
-                       if (!memcmp(path, p->pack_name, len + namelen - 4))
-                               break;
+
+               if (has_extension(de->d_name, ".idx")) {
+                       /* Don't reopen a pack we already have. */
+                       for (p = packed_git; p; p = p->next) {
+                               if (!memcmp(path, p->pack_name, len + namelen - 4))
+                                       break;
+                       }
+                       if (p == NULL &&
+                           /*
+                            * See if it really is a valid .idx file with
+                            * corresponding .pack file that we can map.
+                            */
+                           (p = add_packed_git(path, len + namelen, local)) != NULL)
+                               install_packed_git(p);
                }
-               if (p)
-                       continue;
-               /* See if it really is a valid .idx file with corresponding
-                * .pack file that we can map.
-                */
-               p = add_packed_git(path, len + namelen, local);
-               if (!p)
+
+               if (!report_garbage)
                        continue;
-               install_packed_git(p);
+
+               if (has_extension(de->d_name, ".idx") ||
+                   has_extension(de->d_name, ".pack") ||
+                   has_extension(de->d_name, ".keep"))
+                       string_list_append(&garbage, path);
+               else
+                       report_garbage("garbage found", path);
        }
        closedir(dir);
+       report_pack_garbage(&garbage);
+       string_list_clear(&garbage, 0);
 }
 
 static int sort_pack(const void *a_, const void *b_)
diff --git a/shell.c b/shell.c
index 84b237fef352e2f94f853897dbb5f2364d50962d..1429870a8f29d3d8b8e4d1d7ba3e228d15a73759 100644 (file)
--- a/shell.c
+++ b/shell.c
@@ -6,6 +6,7 @@
 
 #define COMMAND_DIR "git-shell-commands"
 #define HELP_COMMAND COMMAND_DIR "/help"
+#define NOLOGIN_COMMAND COMMAND_DIR "/no-interactive-login"
 
 static int do_generic_cmd(const char *me, char *arg)
 {
@@ -65,6 +66,18 @@ static void run_shell(void)
 {
        int done = 0;
        static const char *help_argv[] = { HELP_COMMAND, NULL };
+
+       if (!access(NOLOGIN_COMMAND, F_OK)) {
+               /* Interactive login disabled. */
+               const char *argv[] = { NOLOGIN_COMMAND, NULL };
+               int status;
+
+               status = run_command_v_opt(argv, 0);
+               if (status < 0)
+                       exit(127);
+               exit(status);
+       }
+
        /* Print help if enabled */
        run_command_v_opt(help_argv, RUN_SILENT_EXEC_FAILURE);
 
index 199f22c231b5ac1479929a89cdf988ac7aff4268..c5e55b190bfbb06eef5a03d701b956e32ad22048 100644 (file)
@@ -148,7 +148,7 @@ stop_httpd () {
 convert_to_rev_db () {
        "$PERL_PATH" -w -- - "$@" <<\EOF
 use strict;
-@ARGV == 2 or die "Usage: convert_to_rev_db <input> <output>";
+@ARGV == 2 or die "usage: convert_to_rev_db <input> <output>";
 open my $wr, '+>', $ARGV[1] or die "$!: couldn't open: $ARGV[1]";
 open my $rd, '<', $ARGV[0] or die "$!: couldn't open: $ARGV[0]";
 my $size = (stat($rd))[7];
index c5334a8fa416aedd66a12416c75e85dbd9b6ac70..62691172e34f0d7b5bdfff2920bab4261f9d3b5c 100755 (executable)
@@ -14,7 +14,7 @@ xmkdir() {
 
 R="$1"
 
-[ -n "$R" ] || die "Usage: prepare-chroot.sh <root>"
+[ -n "$R" ] || die "usage: prepare-chroot.sh <root>"
 [ -x git ] || die "This script needs to be executed at git source code's top directory"
 [ -x /bin/busybox ] || die "You need busybox"
 
index 4cdebda6a5c9b893f46e99b5b565cc4b70efb2db..c317254b9a82befd3400d300f85ecfd661d1a948 100755 (executable)
@@ -80,6 +80,22 @@ test_expect_success 'change gets noticed' '
 
 '
 
+# Note that this is scheduled to change in Git 2.0, when
+# "git add -u" will become full-tree by default.
+test_expect_success 'non-limited update in subdir leaves root alone' '
+       (
+               cd dir1 &&
+               echo even more >>sub2 &&
+               git add -u
+       ) &&
+       cat >expect <<-\EOF &&
+       check
+       top
+       EOF
+       git diff-files --name-only >actual &&
+       test_cmp expect actual
+'
+
 test_expect_success SYMLINKS 'replace a file with a symlink' '
 
        rm foo &&
index f3e0e4a38c3188760df8cb5bd4c096e2209fed9f..12f1e4a63c33b2f394ea37db71e1cd4467cee8f5 100755 (executable)
@@ -42,6 +42,10 @@ test_expect_success \
     'git branch a/b/c should create a branch' \
     'git branch a/b/c && test_path_is_file .git/refs/heads/a/b/c'
 
+test_expect_success \
+    'git branch HEAD should fail' \
+    'test_must_fail git branch HEAD'
+
 cat >expect <<EOF
 $_z40 $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000        branch: Created from master
 EOF
@@ -388,6 +392,14 @@ test_expect_success \
     'git tag foobar &&
      test_must_fail git branch --track my11 foobar'
 
+test_expect_success '--set-upstream-to fails on multiple branches' \
+    'test_must_fail git branch --set-upstream-to master a b c'
+
+test_expect_success '--set-upstream-to fails on detached HEAD' \
+    'git checkout HEAD^{} &&
+     test_must_fail git branch --set-upstream-to master &&
+     git checkout -'
+
 test_expect_success 'use --set-upstream-to modify HEAD' \
     'test_config branch.master.remote foo &&
      test_config branch.master.merge foo &&
@@ -417,6 +429,15 @@ test_expect_success 'test --unset-upstream on HEAD' \
      test_must_fail git branch --unset-upstream
 '
 
+test_expect_success '--unset-upstream should fail on multiple branches' \
+    'test_must_fail git branch --unset-upstream a b c'
+
+test_expect_success '--unset-upstream should fail on detached HEAD' \
+    'git checkout HEAD^{} &&
+     test_must_fail git branch --unset-upstream &&
+     git checkout -
+'
+
 test_expect_success 'test --unset-upstream on a particular branch' \
     'git branch my15
      git branch --set-upstream-to master my14 &&
index 7cfe9ca3dacb1488aa44ea3643e1333d346feac7..6a33606d28eba61281252cf28f6d5820dc452f1d 100755 (executable)
@@ -76,6 +76,12 @@ test_expect_success \
      git update-ref HEAD $(TZ=GMT GIT_COMMITTER_DATE="2005-05-27 22:00:00" \
      git commit-tree $treeid </dev/null)'
 
+test_expect_success 'setup export-subst' '
+       echo "substfile?" export-subst >>.git/info/attributes &&
+       git log --max-count=1 "--pretty=format:A${SUBSTFORMAT}O" HEAD \
+               >a/substfile1
+'
+
 test_expect_success \
     'create bare clone' \
     'git clone --bare . bare.git &&
index d645328609c9ec63782a0b9f80c31a73ef745802..e4bb3a14570780b41ce4ebea9e47870d4cbcb127 100755 (executable)
@@ -195,4 +195,30 @@ test_expect_success 'gc: prune old objects after local clone' '
        )
 '
 
+test_expect_success 'garbage report in count-objects -v' '
+       : >.git/objects/pack/foo &&
+       : >.git/objects/pack/foo.bar &&
+       : >.git/objects/pack/foo.keep &&
+       : >.git/objects/pack/foo.pack &&
+       : >.git/objects/pack/fake.bar &&
+       : >.git/objects/pack/fake.keep &&
+       : >.git/objects/pack/fake.pack &&
+       : >.git/objects/pack/fake.idx &&
+       : >.git/objects/pack/fake2.keep &&
+       : >.git/objects/pack/fake3.idx &&
+       git count-objects -v 2>stderr &&
+       grep "index file .git/objects/pack/fake.idx is too small" stderr &&
+       grep "^warning:" stderr | sort >actual &&
+       cat >expected <<\EOF &&
+warning: garbage found: .git/objects/pack/fake.bar
+warning: garbage found: .git/objects/pack/foo
+warning: garbage found: .git/objects/pack/foo.bar
+warning: no corresponding .idx nor .pack: .git/objects/pack/fake2.keep
+warning: no corresponding .idx: .git/objects/pack/foo.keep
+warning: no corresponding .idx: .git/objects/pack/foo.pack
+warning: no corresponding .pack: .git/objects/pack/fake3.idx
+EOF
+       test_cmp expected actual
+'
+
 test_done
index c31e5c1c525eea5a9f4677b03c5d7314d70c6136..6fd125aecf128a6c4a2ae8b986d5a311c6d0c133 100755 (executable)
@@ -1043,4 +1043,38 @@ do
        '
 done
 
+test_expect_success 'fetch exact SHA1' '
+       mk_test heads/master hidden/one &&
+       git push testrepo master:refs/hidden/one &&
+       (
+               cd testrepo &&
+               git config transfer.hiderefs refs/hidden
+       ) &&
+       check_push_result $the_commit hidden/one &&
+
+       mk_child child &&
+       (
+               cd child &&
+
+               # make sure $the_commit does not exist here
+               git repack -a -d &&
+               git prune &&
+               test_must_fail git cat-file -t $the_commit &&
+
+               # fetching the hidden object should fail by default
+               test_must_fail git fetch -v ../testrepo $the_commit:refs/heads/copy &&
+               test_must_fail git rev-parse --verify refs/heads/copy &&
+
+               # the server side can allow it to succeed
+               (
+                       cd ../testrepo &&
+                       git config uploadpack.allowtipsha1inwant true
+               ) &&
+
+               git fetch -v ../testrepo $the_commit:refs/heads/copy &&
+               result=$(git rev-parse --verify refs/heads/copy) &&
+               test "$the_commit" = "$result"
+       )
+'
+
 test_done
index f4f38a5e7387694e16ff6f4a54020843630c2ac7..52ef06b0005aabf2a201d20dbb5f232e3a26766a 100755 (executable)
@@ -5,6 +5,7 @@ test_description='basic work tree status reporting'
 . ./test-lib.sh
 
 test_expect_success setup '
+       git config --global advice.statusuoption false &&
        test_commit A &&
        test_commit B oneside added &&
        git checkout A^0 &&
index 4975ec07ce614c8473f7f5638a008d7058730f06..1a3d20bdc36c63c5261090d76858d43bd7f64113 100755 (executable)
@@ -643,7 +643,8 @@ test_expect_success 'submodule update places git-dir in superprojects git-dir re
        rm -rf super_update_r2 &&
        git clone super_update_r super_update_r2 &&
        (cd super_update_r2 &&
-        git submodule update --init --recursive &&
+        git submodule update --init --recursive >actual &&
+        test_i18ngrep "Submodule path .submodule/subsubmodule.: checked out" actual &&
         (cd submodule/subsubmodule &&
          git log > ../../expected
         ) &&
index cbd7a45927eb2d4b04649f21f82192091782ce90..f9b44b72449d258647c5278c52e5c792ee10445e 100755 (executable)
@@ -177,12 +177,20 @@ test_expect_success 'verbose respects diff config' '
        git config --unset color.diff
 '
 
+mesg_with_comment_and_newlines='
+# text
+
+'
+
+test_expect_success 'prepare file with comment line and trailing newlines'  '
+       printf "%s" "$mesg_with_comment_and_newlines" >expect
+'
+
 test_expect_success 'cleanup commit messages (verbatim option,-t)' '
 
        echo >>negative &&
-       { echo;echo "# text";echo; } >expect &&
-       git commit --cleanup=verbatim -t expect -a &&
-       git cat-file -p HEAD |sed -e "1,/^\$/d" |head -n 3 >actual &&
+       git commit --cleanup=verbatim --no-status -t expect -a &&
+       git cat-file -p HEAD |sed -e "1,/^\$/d" >actual &&
        test_cmp expect actual
 
 '
@@ -199,7 +207,7 @@ test_expect_success 'cleanup commit messages (verbatim option,-F)' '
 test_expect_success 'cleanup commit messages (verbatim option,-m)' '
 
        echo >>negative &&
-       git commit --cleanup=verbatim -m "$(cat expect)" -a &&
+       git commit --cleanup=verbatim -m "$mesg_with_comment_and_newlines" -a &&
        git cat-file -p HEAD |sed -e "1,/^\$/d">actual &&
        test_cmp expect actual
 
@@ -255,32 +263,40 @@ test_expect_success 'cleanup commit message (fail on invalid cleanup mode config
 test_expect_success 'cleanup commit message (no config and no option uses default)' '
        echo content >>file &&
        git add file &&
-       test_set_editor "$TEST_DIRECTORY"/t7500/add-content-and-comment &&
-       git commit --no-status &&
+       (
+         test_set_editor "$TEST_DIRECTORY"/t7500/add-content-and-comment &&
+         git commit --no-status
+       ) &&
        commit_msg_is "commit message"
 '
 
 test_expect_success 'cleanup commit message (option overrides default)' '
        echo content >>file &&
        git add file &&
-       test_set_editor "$TEST_DIRECTORY"/t7500/add-content-and-comment &&
-       git commit --cleanup=whitespace --no-status &&
+       (
+         test_set_editor "$TEST_DIRECTORY"/t7500/add-content-and-comment &&
+         git commit --cleanup=whitespace --no-status
+       ) &&
        commit_msg_is "commit message # comment"
 '
 
 test_expect_success 'cleanup commit message (config overrides default)' '
        echo content >>file &&
        git add file &&
-       test_set_editor "$TEST_DIRECTORY"/t7500/add-content-and-comment &&
-       git -c commit.cleanup=whitespace commit --no-status &&
+       (
+         test_set_editor "$TEST_DIRECTORY"/t7500/add-content-and-comment &&
+         git -c commit.cleanup=whitespace commit --no-status
+       ) &&
        commit_msg_is "commit message # comment"
 '
 
 test_expect_success 'cleanup commit message (option overrides config)' '
        echo content >>file &&
        git add file &&
-       test_set_editor "$TEST_DIRECTORY"/t7500/add-content-and-comment &&
-       git -c commit.cleanup=whitespace commit --cleanup=default &&
+       (
+         test_set_editor "$TEST_DIRECTORY"/t7500/add-content-and-comment &&
+         git -c commit.cleanup=whitespace commit --cleanup=default
+       ) &&
        commit_msg_is "commit message"
 '
 
index a79c032ffd941a68e737b844ea5b28fffe58686c..aecb4d1e5fdc1e966aad07ee1f1e7af834388bb2 100755 (executable)
@@ -8,6 +8,7 @@ test_description='git status'
 . ./test-lib.sh
 
 test_expect_success 'status -h in broken repository' '
+       git config --global advice.statusuoption false &&
        mkdir broken &&
        test_when_finished "rm -fr broken" &&
        (
index d2da89a5f572134c55c690b1439ffde66ecdd6cb..9d4610629d725c22b9de5187abf71b2b8544292d 100755 (executable)
@@ -14,6 +14,7 @@ test_description='git status advice'
 set_fake_editor
 
 test_expect_success 'prepare for conflicts' '
+       git config --global advice.statusuoption false &&
        test_commit init main.txt init &&
        git branch conflicts &&
        test_commit on_master main.txt on_master &&
index eb1d3f85b59b2e74231f0285fc4e90d95d0658fa..3aab6e15000f57e76d05f70920525d5734e20ef7 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# Copyright (c) 2009, 2010 David Aguilar
+# Copyright (c) 2009, 2010, 2012, 2013 David Aguilar
 #
 
 test_description='git-difftool
@@ -10,43 +10,25 @@ Testing basic diff tool invocation
 
 . ./test-lib.sh
 
-remove_config_vars()
+difftool_test_setup ()
 {
-       # Unset all config variables used by git-difftool
-       git config --unset diff.tool
-       git config --unset diff.guitool
-       git config --unset difftool.test-tool.cmd
-       git config --unset difftool.prompt
-       git config --unset merge.tool
-       git config --unset mergetool.test-tool.cmd
-       git config --unset mergetool.prompt
-       return 0
+       test_config diff.tool test-tool &&
+       test_config difftool.test-tool.cmd 'cat "$LOCAL"' &&
+       test_config difftool.bogus-tool.cmd false
 }
 
-restore_test_defaults()
-{
-       # Restores the test defaults used by several tests
-       remove_config_vars
-       unset GIT_DIFF_TOOL
-       unset GIT_DIFFTOOL_PROMPT
-       unset GIT_DIFFTOOL_NO_PROMPT
-       git config diff.tool test-tool &&
-       git config difftool.test-tool.cmd 'cat $LOCAL'
-       git config difftool.bogus-tool.cmd false
-}
-
-prompt_given()
+prompt_given ()
 {
        prompt="$1"
        test "$prompt" = "Launch 'test-tool' [Y/n]: branch"
 }
 
-stdin_contains()
+stdin_contains ()
 {
        grep >/dev/null "$1"
 }
 
-stdin_doesnot_contain()
+stdin_doesnot_contain ()
 {
        ! stdin_contains "$1"
 }
@@ -65,249 +47,237 @@ test_expect_success PERL 'setup' '
 
 # Configure a custom difftool.<tool>.cmd and use it
 test_expect_success PERL 'custom commands' '
-       restore_test_defaults &&
-       git config difftool.test-tool.cmd "cat \$REMOTE" &&
+       difftool_test_setup &&
+       test_config difftool.test-tool.cmd "cat \"\$REMOTE\"" &&
+       echo master >expect &&
+       git difftool --no-prompt branch >actual &&
+       test_cmp expect actual &&
 
-       diff=$(git difftool --no-prompt branch) &&
-       test "$diff" = "master" &&
-
-       restore_test_defaults &&
-       diff=$(git difftool --no-prompt branch) &&
-       test "$diff" = "branch"
+       test_config difftool.test-tool.cmd "cat \"\$LOCAL\"" &&
+       echo branch >expect &&
+       git difftool --no-prompt branch >actual &&
+       test_cmp expect actual
 '
 
-# Ensures that a custom difftool.<tool>.cmd overrides built-ins
-test_expect_success PERL 'custom commands override built-ins' '
-       restore_test_defaults &&
-       git config difftool.defaults.cmd "cat \$REMOTE" &&
-
-       diff=$(git difftool --tool defaults --no-prompt branch) &&
-       test "$diff" = "master" &&
-
-       git config --unset difftool.defaults.cmd
+test_expect_success PERL 'custom tool commands override built-ins' '
+       test_config difftool.vimdiff.cmd "cat \"\$REMOTE\"" &&
+       echo master >expect &&
+       git difftool --tool vimdiff --no-prompt branch >actual &&
+       test_cmp expect actual
 '
 
-# Ensures that git-difftool ignores bogus --tool values
 test_expect_success PERL 'difftool ignores bad --tool values' '
-       diff=$(git difftool --no-prompt --tool=bad-tool branch)
-       test "$?" = 1 &&
-       test "$diff" = ""
+       : >expect &&
+       test_expect_code 1 \
+               git difftool --no-prompt --tool=bad-tool branch >actual &&
+       test_cmp expect actual
 '
 
 test_expect_success PERL 'difftool forwards arguments to diff' '
+       difftool_test_setup &&
        >for-diff &&
        git add for-diff &&
        echo changes>for-diff &&
        git add for-diff &&
-       diff=$(git difftool --cached --no-prompt -- for-diff) &&
-       test "$diff" = "" &&
+       : >expect &&
+       git difftool --cached --no-prompt -- for-diff >actual &&
+       test_cmp expect actual &&
        git reset -- for-diff &&
        rm for-diff
 '
 
 test_expect_success PERL 'difftool honors --gui' '
-       git config merge.tool bogus-tool &&
-       git config diff.tool bogus-tool &&
-       git config diff.guitool test-tool &&
-
-       diff=$(git difftool --no-prompt --gui branch) &&
-       test "$diff" = "branch" &&
+       difftool_test_setup &&
+       test_config merge.tool bogus-tool &&
+       test_config diff.tool bogus-tool &&
+       test_config diff.guitool test-tool &&
 
-       restore_test_defaults
+       echo branch >expect &&
+       git difftool --no-prompt --gui branch >actual &&
+       test_cmp expect actual
 '
 
 test_expect_success PERL 'difftool --gui last setting wins' '
-       git config diff.guitool bogus-tool &&
-       git difftool --no-prompt --gui --no-gui &&
+       difftool_test_setup &&
+       : >expect &&
+       git difftool --no-prompt --gui --no-gui >actual &&
+       test_cmp expect actual &&
 
-       git config merge.tool bogus-tool &&
-       git config diff.tool bogus-tool &&
-       git config diff.guitool test-tool &&
-       diff=$(git difftool --no-prompt --no-gui --gui branch) &&
-       test "$diff" = "branch" &&
-
-       restore_test_defaults
+       test_config merge.tool bogus-tool &&
+       test_config diff.tool bogus-tool &&
+       test_config diff.guitool test-tool &&
+       echo branch >expect &&
+       git difftool --no-prompt --no-gui --gui branch >actual &&
+       test_cmp expect actual
 '
 
 test_expect_success PERL 'difftool --gui works without configured diff.guitool' '
-       git config diff.tool test-tool &&
-
-       diff=$(git difftool --no-prompt --gui branch) &&
-       test "$diff" = "branch" &&
-
-       restore_test_defaults
+       difftool_test_setup &&
+       echo branch >expect &&
+       git difftool --no-prompt --gui branch >actual &&
+       test_cmp expect actual
 '
 
 # Specify the diff tool using $GIT_DIFF_TOOL
 test_expect_success PERL 'GIT_DIFF_TOOL variable' '
-       test_might_fail git config --unset diff.tool &&
-       GIT_DIFF_TOOL=test-tool &&
-       export GIT_DIFF_TOOL &&
-
-       diff=$(git difftool --no-prompt branch) &&
-       test "$diff" = "branch" &&
-
-       restore_test_defaults
+       difftool_test_setup &&
+       git config --unset diff.tool &&
+       echo branch >expect &&
+       GIT_DIFF_TOOL=test-tool git difftool --no-prompt branch >actual &&
+       test_cmp expect actual
 '
 
 # Test the $GIT_*_TOOL variables and ensure
 # that $GIT_DIFF_TOOL always wins unless --tool is specified
 test_expect_success PERL 'GIT_DIFF_TOOL overrides' '
-       git config diff.tool bogus-tool &&
-       git config merge.tool bogus-tool &&
-
-       GIT_DIFF_TOOL=test-tool &&
-       export GIT_DIFF_TOOL &&
-
-       diff=$(git difftool --no-prompt branch) &&
-       test "$diff" = "branch" &&
+       difftool_test_setup &&
+       test_config diff.tool bogus-tool &&
+       test_config merge.tool bogus-tool &&
 
-       GIT_DIFF_TOOL=bogus-tool &&
-       export GIT_DIFF_TOOL &&
+       echo branch >expect &&
+       GIT_DIFF_TOOL=test-tool git difftool --no-prompt branch >actual &&
+       test_cmp expect actual &&
 
-       diff=$(git difftool --no-prompt --tool=test-tool branch) &&
-       test "$diff" = "branch" &&
-
-       restore_test_defaults
+       test_config diff.tool bogus-tool &&
+       test_config merge.tool bogus-tool &&
+       GIT_DIFF_TOOL=bogus-tool \
+               git difftool --no-prompt --tool=test-tool branch >actual &&
+       test_cmp expect actual
 '
 
 # Test that we don't have to pass --no-prompt to difftool
 # when $GIT_DIFFTOOL_NO_PROMPT is true
 test_expect_success PERL 'GIT_DIFFTOOL_NO_PROMPT variable' '
-       GIT_DIFFTOOL_NO_PROMPT=true &&
-       export GIT_DIFFTOOL_NO_PROMPT &&
-
-       diff=$(git difftool branch) &&
-       test "$diff" = "branch" &&
-
-       restore_test_defaults
+       difftool_test_setup &&
+       echo branch >expect &&
+       GIT_DIFFTOOL_NO_PROMPT=true git difftool branch >actual &&
+       test_cmp expect actual
 '
 
 # git-difftool supports the difftool.prompt variable.
 # Test that GIT_DIFFTOOL_PROMPT can override difftool.prompt = false
 test_expect_success PERL 'GIT_DIFFTOOL_PROMPT variable' '
-       git config difftool.prompt false &&
-       GIT_DIFFTOOL_PROMPT=true &&
-       export GIT_DIFFTOOL_PROMPT &&
-
-       prompt=$(echo | git difftool branch | tail -1) &&
-       prompt_given "$prompt" &&
-
-       restore_test_defaults
+       difftool_test_setup &&
+       test_config difftool.prompt false &&
+       echo >input &&
+       GIT_DIFFTOOL_PROMPT=true git difftool branch <input >output &&
+       prompt=$(tail -1 <output) &&
+       prompt_given "$prompt"
 '
 
 # Test that we don't have to pass --no-prompt when difftool.prompt is false
 test_expect_success PERL 'difftool.prompt config variable is false' '
-       git config difftool.prompt false &&
-
-       diff=$(git difftool branch) &&
-       test "$diff" = "branch" &&
-
-       restore_test_defaults
+       difftool_test_setup &&
+       test_config difftool.prompt false &&
+       echo branch >expect &&
+       git difftool branch >actual &&
+       test_cmp expect actual
 '
 
 # Test that we don't have to pass --no-prompt when mergetool.prompt is false
 test_expect_success PERL 'difftool merge.prompt = false' '
+       difftool_test_setup &&
        test_might_fail git config --unset difftool.prompt &&
-       git config mergetool.prompt false &&
-
-       diff=$(git difftool branch) &&
-       test "$diff" = "branch" &&
-
-       restore_test_defaults
+       test_config mergetool.prompt false &&
+       echo branch >expect &&
+       git difftool branch >actual &&
+       test_cmp expect actual
 '
 
 # Test that the -y flag can override difftool.prompt = true
 test_expect_success PERL 'difftool.prompt can overridden with -y' '
-       git config difftool.prompt true &&
-
-       diff=$(git difftool -y branch) &&
-       test "$diff" = "branch" &&
-
-       restore_test_defaults
+       difftool_test_setup &&
+       test_config difftool.prompt true &&
+       echo branch >expect &&
+       git difftool -y branch >actual &&
+       test_cmp expect actual
 '
 
 # Test that the --prompt flag can override difftool.prompt = false
 test_expect_success PERL 'difftool.prompt can overridden with --prompt' '
-       git config difftool.prompt false &&
-
-       prompt=$(echo | git difftool --prompt branch | tail -1) &&
-       prompt_given "$prompt" &&
-
-       restore_test_defaults
+       difftool_test_setup &&
+       test_config difftool.prompt false &&
+       echo >input &&
+       git difftool --prompt branch <input >output &&
+       prompt=$(tail -1 <output) &&
+       prompt_given "$prompt"
 '
 
 # Test that the last flag passed on the command-line wins
 test_expect_success PERL 'difftool last flag wins' '
-       diff=$(git difftool --prompt --no-prompt branch) &&
-       test "$diff" = "branch" &&
-
-       restore_test_defaults &&
-
-       prompt=$(echo | git difftool --no-prompt --prompt branch | tail -1) &&
-       prompt_given "$prompt" &&
-
-       restore_test_defaults
+       difftool_test_setup &&
+       echo branch >expect &&
+       git difftool --prompt --no-prompt branch >actual &&
+       test_cmp expect actual &&
+       echo >input &&
+       git difftool --no-prompt --prompt branch <input >output &&
+       prompt=$(tail -1 <output) &&
+       prompt_given "$prompt"
 '
 
 # git-difftool falls back to git-mergetool config variables
 # so test that behavior here
 test_expect_success PERL 'difftool + mergetool config variables' '
-       remove_config_vars &&
-       git config merge.tool test-tool &&
-       git config mergetool.test-tool.cmd "cat \$LOCAL" &&
-
-       diff=$(git difftool --no-prompt branch) &&
-       test "$diff" = "branch" &&
+       test_config merge.tool test-tool &&
+       test_config mergetool.test-tool.cmd "cat \$LOCAL" &&
+       echo branch >expect &&
+       git difftool --no-prompt branch >actual &&
+       test_cmp expect actual &&
 
        # set merge.tool to something bogus, diff.tool to test-tool
-       git config merge.tool bogus-tool &&
-       git config diff.tool test-tool &&
-
-       diff=$(git difftool --no-prompt branch) &&
-       test "$diff" = "branch" &&
-
-       restore_test_defaults
+       test_config merge.tool bogus-tool &&
+       test_config diff.tool test-tool &&
+       git difftool --no-prompt branch >actual &&
+       test_cmp expect actual
 '
 
 test_expect_success PERL 'difftool.<tool>.path' '
-       git config difftool.tkdiff.path echo &&
-       diff=$(git difftool --tool=tkdiff --no-prompt branch) &&
-       git config --unset difftool.tkdiff.path &&
-       lines=$(echo "$diff" | grep file | wc -l) &&
-       test "$lines" -eq 1 &&
-
-       restore_test_defaults
+       test_config difftool.tkdiff.path echo &&
+       git difftool --tool=tkdiff --no-prompt branch >output &&
+       lines=$(grep file output | wc -l) &&
+       test "$lines" -eq 1
 '
 
 test_expect_success PERL 'difftool --extcmd=cat' '
-       diff=$(git difftool --no-prompt --extcmd=cat branch) &&
-       test "$diff" = branch"$LF"master
+       echo branch >expect &&
+       echo master >>expect &&
+       git difftool --no-prompt --extcmd=cat branch >actual &&
+       test_cmp expect actual
 '
 
 test_expect_success PERL 'difftool --extcmd cat' '
-       diff=$(git difftool --no-prompt --extcmd cat branch) &&
-       test "$diff" = branch"$LF"master
+       echo branch >expect &&
+       echo master >>expect &&
+       git difftool --no-prompt --extcmd=cat branch >actual &&
+       test_cmp expect actual
 '
 
 test_expect_success PERL 'difftool -x cat' '
-       diff=$(git difftool --no-prompt -x cat branch) &&
-       test "$diff" = branch"$LF"master
+       echo branch >expect &&
+       echo master >>expect &&
+       git difftool --no-prompt -x cat branch >actual &&
+       test_cmp expect actual
 '
 
 test_expect_success PERL 'difftool --extcmd echo arg1' '
-       diff=$(git difftool --no-prompt --extcmd sh\ -c\ \"echo\ \$1\" branch) &&
-       test "$diff" = file
+       echo file >expect &&
+       git difftool --no-prompt \
+               --extcmd sh\ -c\ \"echo\ \$1\" branch >actual &&
+       test_cmp expect actual
 '
 
 test_expect_success PERL 'difftool --extcmd cat arg1' '
-       diff=$(git difftool --no-prompt --extcmd sh\ -c\ \"cat\ \$1\" branch) &&
-       test "$diff" = master
+       echo master >expect &&
+       git difftool --no-prompt \
+               --extcmd sh\ -c\ \"cat\ \$1\" branch >actual &&
+       test_cmp expect actual
 '
 
 test_expect_success PERL 'difftool --extcmd cat arg2' '
-       diff=$(git difftool --no-prompt --extcmd sh\ -c\ \"cat\ \$2\" branch) &&
-       test "$diff" = branch
+       echo branch >expect &&
+       git difftool --no-prompt \
+               --extcmd sh\ -c\ \"cat\ \$2\" branch >actual &&
+       test_cmp expect actual
 '
 
 # Create a second file on master and a different version on branch
@@ -324,26 +294,26 @@ test_expect_success PERL 'setup with 2 files different' '
 '
 
 test_expect_success PERL 'say no to the first file' '
-       diff=$( (echo n; echo) | git difftool -x cat branch ) &&
-
-       echo "$diff" | stdin_contains m2 &&
-       echo "$diff" | stdin_contains br2 &&
-       echo "$diff" | stdin_doesnot_contain master &&
-       echo "$diff" | stdin_doesnot_contain branch
+       (echo n && echo) >input &&
+       git difftool -x cat branch <input >output &&
+       stdin_contains m2 <output &&
+       stdin_contains br2 <output &&
+       stdin_doesnot_contain master <output &&
+       stdin_doesnot_contain branch <output
 '
 
 test_expect_success PERL 'say no to the second file' '
-       diff=$( (echo; echo n) | git difftool -x cat branch ) &&
-
-       echo "$diff" | stdin_contains master &&
-       echo "$diff" | stdin_contains branch &&
-       echo "$diff" | stdin_doesnot_contain m2 &&
-       echo "$diff" | stdin_doesnot_contain br2
+       (echo && echo n) >input &&
+       git difftool -x cat branch <input >output &&
+       stdin_contains master <output &&
+       stdin_contains branch  <output &&
+       stdin_doesnot_contain m2 <output &&
+       stdin_doesnot_contain br2 <output
 '
 
 test_expect_success PERL 'difftool --tool-help' '
-       tool_help=$(git difftool --tool-help) &&
-       echo "$tool_help" | stdin_contains tool
+       git difftool --tool-help >output &&
+       stdin_contains tool <output
 '
 
 test_expect_success PERL 'setup change in subdirectory' '
@@ -359,29 +329,29 @@ test_expect_success PERL 'setup change in subdirectory' '
 '
 
 test_expect_success PERL 'difftool -d' '
-       diff=$(git difftool -d --extcmd ls branch) &&
-       echo "$diff" | stdin_contains sub &&
-       echo "$diff" | stdin_contains file
+       git difftool -d --extcmd ls branch >output &&
+       stdin_contains sub <output &&
+       stdin_contains file <output
 '
 
 test_expect_success PERL 'difftool --dir-diff' '
-       diff=$(git difftool --dir-diff --extcmd ls branch) &&
-       echo "$diff" | stdin_contains sub &&
-       echo "$diff" | stdin_contains file
+       git difftool --dir-diff --extcmd ls branch >output &&
+       stdin_contains sub <output &&
+       stdin_contains file <output
 '
 
 test_expect_success PERL 'difftool --dir-diff ignores --prompt' '
-       diff=$(git difftool --dir-diff --prompt --extcmd ls branch) &&
-       echo "$diff" | stdin_contains sub &&
-       echo "$diff" | stdin_contains file
+       git difftool --dir-diff --prompt --extcmd ls branch >output &&
+       stdin_contains sub <output &&
+       stdin_contains file <output
 '
 
 test_expect_success PERL 'difftool --dir-diff from subdirectory' '
        (
                cd sub &&
-               diff=$(git difftool --dir-diff --extcmd ls branch) &&
-               echo "$diff" | stdin_contains sub &&
-               echo "$diff" | stdin_contains file
+               git difftool --dir-diff --extcmd ls branch >output &&
+               stdin_contains sub <output &&
+               stdin_contains file <output
        )
 '
 
index 71ab04edc09be7aeefa1e8a0f609a974ffd55a9f..d84758373da1d3121ec907435ae5d598c5c14b26 100755 (executable)
@@ -38,7 +38,7 @@ if [ -z "$GIT_DIR" ]; then
 fi
 
 if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
-       echo "Usage: $0 <ref> <oldrev> <newrev>" >&2
+       echo "usage: $0 <ref> <oldrev> <newrev>" >&2
        exit 1
 fi
 
index 92713d16da5431e9c8395967ab0e116402dfed67..02b42badd550a4b775aab084b38a63c2f4f561a9 100644 (file)
@@ -114,6 +114,6 @@ int main(int argc, const char *argv[])
        return 0;
 
 usage:
-       fprintf(stderr, "Usage: %s %s\n", argv[0], usage_str);
+       fprintf(stderr, "usage: %s %s\n", argv[0], usage_str);
        return -1;
 }
index af40a3c49ee0df5f0caaebae8e9bc6e9ffdb092b..4595cd6433f9fd543791ee5a8a59a9112b50c046 100644 (file)
@@ -23,7 +23,7 @@ int main(int argc, char *argv[])
        unsigned long from_size, data_size, out_size;
 
        if (argc != 5 || (strcmp(argv[1], "-d") && strcmp(argv[1], "-p"))) {
-               fprintf(stderr, "Usage: %s\n", usage_str);
+               fprintf(stderr, "usage: %s\n", usage_str);
                return 1;
        }
 
index b3c28d9a1c1102f2862af68b0bda7e9b0424f5cc..54824d075421e792f337beb5cdce170a33b00e68 100644 (file)
@@ -12,7 +12,7 @@ int main(int argc, char *argv[])
        unsigned char *c;
 
        if (argc < 2 || argc > 3) {
-               fprintf(stderr, "Usage: %s <seed_string> [<size>]\n", argv[0]);
+               fprintf(stderr, "usage: %s <seed_string> [<size>]\n", argv[0]);
                return 1;
        }
 
index 0f2d9a4a3d8ea732c7c61e3818bd0bbe417c76b0..120ec96b0dbd94e7be9ffc81d0fb87ccbd30a7df 100644 (file)
@@ -24,7 +24,7 @@ static int apply_delta(int argc, char *argv[])
                die_errno("cannot open preimage");
        if (buffer_init(&delta, argv[3]))
                die_errno("cannot open delta");
-       if (svndiff0_apply(&delta, (off_t) strtoull(argv[4], NULL, 0),
+       if (svndiff0_apply(&delta, (off_t) strtoumax(argv[4], NULL, 0),
                                        &preimage_view, stdout))
                return 1;
        if (buffer_deinit(&preimage))
index e6f9346c762416b9c0e97f9023062f99e4542dbc..42a61b30b3778181a06afad8afcd5bfcfc56f05a 100644 (file)
@@ -519,11 +519,9 @@ static int fetch_refs_via_pack(struct transport *transport,
                               int nr_heads, struct ref **to_fetch)
 {
        struct git_transport_data *data = transport->data;
-       struct string_list sought = STRING_LIST_INIT_DUP;
        const struct ref *refs;
        char *dest = xstrdup(transport->url);
        struct fetch_pack_args args;
-       int i;
        struct ref *refs_tmp = NULL;
 
        memset(&args, 0, sizeof(args));
@@ -537,9 +535,6 @@ static int fetch_refs_via_pack(struct transport *transport,
        args.no_progress = !transport->progress;
        args.depth = data->options.depth;
 
-       for (i = 0; i < nr_heads; i++)
-               string_list_append(&sought, to_fetch[i]->name);
-
        if (!data->got_remote_heads) {
                connect_setup(transport, 0, 0);
                get_remote_heads(data->fd[0], &refs_tmp, 0, NULL);
@@ -548,7 +543,8 @@ static int fetch_refs_via_pack(struct transport *transport,
 
        refs = fetch_pack(&args, data->fd, data->conn,
                          refs_tmp ? refs_tmp : transport->remote_refs,
-                         dest, &sought, &transport->pack_lockfile);
+                         dest, to_fetch, nr_heads,
+                         &transport->pack_lockfile);
        close(data->fd[0]);
        close(data->fd[1]);
        if (finish_connect(data->conn))
@@ -558,7 +554,6 @@ static int fetch_refs_via_pack(struct transport *transport,
 
        free_refs(refs_tmp);
 
-       string_list_clear(&sought, 0);
        free(dest);
        return (refs ? 0 : -1);
 }
index 30146a04f7a271ffaa033c0c6567ad1036f4bc49..35605310d2da35fd49cf1eff17aaced395328470 100644 (file)
@@ -26,6 +26,7 @@ static const char upload_pack_usage[] = "git upload-pack [--strict] [--timeout=<
 #define SHALLOW                (1u << 16)
 #define NOT_SHALLOW    (1u << 17)
 #define CLIENT_SHALLOW (1u << 18)
+#define HIDDEN_REF     (1u << 19)
 
 static unsigned long oldest_have;
 
@@ -33,6 +34,7 @@ static int multi_ack;
 static int no_done;
 static int use_thin_pack, use_ofs_delta, use_include_tag;
 static int no_progress, daemon_mode;
+static int allow_tip_sha1_in_want;
 static int shallow_nr;
 static struct object_array have_obj;
 static struct object_array want_obj;
@@ -487,6 +489,12 @@ static int get_common_commits(void)
        }
 }
 
+static int is_our_ref(struct object *o)
+{
+       return o->flags &
+               ((allow_tip_sha1_in_want ? HIDDEN_REF : 0) | OUR_REF);
+}
+
 static void check_non_tip(void)
 {
        static const char *argv[] = {
@@ -523,7 +531,7 @@ static void check_non_tip(void)
                o = get_indexed_object(--i);
                if (!o)
                        continue;
-               if (!(o->flags & OUR_REF))
+               if (!is_our_ref(o))
                        continue;
                memcpy(namebuf + 1, sha1_to_hex(o->sha1), 40);
                if (write_in_full(cmd.in, namebuf, 42) < 0)
@@ -532,7 +540,7 @@ static void check_non_tip(void)
        namebuf[40] = '\n';
        for (i = 0; i < want_obj.nr; i++) {
                o = want_obj.objects[i].item;
-               if (o->flags & OUR_REF)
+               if (is_our_ref(o))
                        continue;
                memcpy(namebuf, sha1_to_hex(o->sha1), 40);
                if (write_in_full(cmd.in, namebuf, 41) < 0)
@@ -566,7 +574,7 @@ static void check_non_tip(void)
        /* Pick one of them (we know there at least is one) */
        for (i = 0; i < want_obj.nr; i++) {
                o = want_obj.objects[i].item;
-               if (!(o->flags & OUR_REF))
+               if (!is_our_ref(o))
                        die("git upload-pack: not our ref %s",
                            sha1_to_hex(o->sha1));
        }
@@ -646,7 +654,7 @@ static void receive_needs(void)
                            sha1_to_hex(sha1_buf));
                if (!(o->flags & WANTED)) {
                        o->flags |= WANTED;
-                       if (!(o->flags & OUR_REF))
+                       if (!is_our_ref(o))
                                has_non_tip = 1;
                        add_object_array(o, NULL, &want_obj);
                }
@@ -732,8 +740,10 @@ static int mark_our_ref(const char *refname, const unsigned char *sha1, int flag
 {
        struct object *o = lookup_unknown_object(sha1);
 
-       if (ref_is_hidden(refname))
+       if (ref_is_hidden(refname)) {
+               o->flags |= HIDDEN_REF;
                return 1;
+       }
        if (!o)
                die("git upload-pack: cannot find object %s:", sha1_to_hex(sha1));
        o->flags |= OUR_REF;
@@ -752,9 +762,10 @@ static int send_ref(const char *refname, const unsigned char *sha1, int flag, vo
                return 0;
 
        if (capabilities)
-               packet_write(1, "%s %s%c%s%s agent=%s\n",
+               packet_write(1, "%s %s%c%s%s%s agent=%s\n",
                             sha1_to_hex(sha1), refname_nons,
                             0, capabilities,
+                            allow_tip_sha1_in_want ? " allow-tip-sha1-in-want" : "",
                             stateless_rpc ? " no-done" : "",
                             git_user_agent_sanitized());
        else
@@ -788,6 +799,8 @@ static void upload_pack(void)
 
 static int upload_pack_config(const char *var, const char *value, void *unused)
 {
+       if (!strcmp("uploadpack.allowtipsha1inwant", var))
+               allow_tip_sha1_in_want = git_config_bool(var, value);
        return parse_hide_refs_config(var, value, "uploadpack");
 }
 
diff --git a/utf8.c b/utf8.c
index 1087870c51caff3dd86a852ec5e8bf5875f6d797..8f6e84b7b3cf589f437a81ee81fd0228b2faf2f2 100644 (file)
--- a/utf8.c
+++ b/utf8.c
@@ -507,9 +507,25 @@ char *reencode_string(const char *in, const char *out_encoding, const char *in_e
 
        if (!in_encoding)
                return NULL;
+
        conv = iconv_open(out_encoding, in_encoding);
-       if (conv == (iconv_t) -1)
-               return NULL;
+       if (conv == (iconv_t) -1) {
+               /*
+                * Some platforms do not have the variously spelled variants of
+                * UTF-8, so let's fall back to trying the most official
+                * spelling. We do so only as a fallback in case the platform
+                * does understand the user's spelling, but not our official
+                * one.
+                */
+               if (is_encoding_utf8(in_encoding))
+                       in_encoding = "UTF-8";
+               if (is_encoding_utf8(out_encoding))
+                       out_encoding = "UTF-8";
+               conv = iconv_open(out_encoding, in_encoding);
+               if (conv == (iconv_t) -1)
+                       return NULL;
+       }
+
        out = reencode_string_iconv(in, strlen(in), conv);
        iconv_close(conv);
        return out;
index 75558177860d14120636859e2dcc29b48b72a721..54f4391f9cc86d3d485ed80383cb142b1f25b1e7 100644 (file)
@@ -499,9 +499,14 @@ static void wt_status_collect_untracked(struct wt_status *s)
 {
        int i;
        struct dir_struct dir;
+       struct timeval t_begin;
 
        if (!s->show_untracked_files)
                return;
+
+       if (advice_status_u_option)
+               gettimeofday(&t_begin, NULL);
+
        memset(&dir, 0, sizeof(dir));
        if (s->show_untracked_files != SHOW_ALL_UNTRACKED_FILES)
                dir.flags |=
@@ -533,6 +538,14 @@ static void wt_status_collect_untracked(struct wt_status *s)
        }
 
        free(dir.entries);
+
+       if (advice_status_u_option) {
+               struct timeval t_end;
+               gettimeofday(&t_end, NULL);
+               s->untracked_in_ms =
+                       (uint64_t)t_end.tv_sec * 1000 + t_end.tv_usec / 1000 -
+                       ((uint64_t)t_begin.tv_sec * 1000 + t_begin.tv_usec / 1000);
+       }
 }
 
 void wt_status_collect(struct wt_status *s)
@@ -1100,6 +1113,18 @@ void wt_status_print(struct wt_status *s)
                wt_status_print_other(s, &s->untracked, _("Untracked files"), "add");
                if (s->show_ignored_files)
                        wt_status_print_other(s, &s->ignored, _("Ignored files"), "add -f");
+               if (advice_status_u_option && 2000 < s->untracked_in_ms) {
+                       status_printf_ln(s, GIT_COLOR_NORMAL, "");
+                       status_printf_ln(s, GIT_COLOR_NORMAL,
+                                _("It took %.2f seconds to enumerate untracked files."
+                                  "  'status -uno'"),
+                                s->untracked_in_ms / 1000.0);
+                       status_printf_ln(s, GIT_COLOR_NORMAL,
+                                _("may speed it up, but you have to be careful not"
+                                  " to forget to add"));
+                       status_printf_ln(s, GIT_COLOR_NORMAL,
+                                _("new files yourself (see 'git help status')."));
+               }
        } else if (s->commitable)
                status_printf_ln(s, GIT_COLOR_NORMAL, _("Untracked files not listed%s"),
                        advice_status_hints
index 81e1dcf84dbfbea76657d3b4c65e3e63890396e9..74208c06fd08b49041489c869d3c5f16804493da 100644 (file)
@@ -69,6 +69,7 @@ struct wt_status {
        struct string_list change;
        struct string_list untracked;
        struct string_list ignored;
+       uint32_t untracked_in_ms;
 };
 
 struct wt_status_state {