Merge branch 'bc/solaris'
authorJunio C Hamano <gitster@pobox.com>
Sat, 13 Jun 2009 19:48:34 +0000 (12:48 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sat, 13 Jun 2009 19:48:34 +0000 (12:48 -0700)
* bc/solaris:
configure: test whether -lresolv is needed
Makefile: insert SANE_TOOL_PATH to PATH before /bin or /usr/bin
git-compat-util.h: avoid using c99 flex array feature with Sun compiler 5.8
Makefile: add section for SunOS 5.7
Makefile: introduce SANE_TOOL_PATH for prepending required elements to PATH
Makefile: define __sun__ on SunOS
git-compat-util.h: tweak the way _XOPEN_SOURCE is set on Solaris
On Solaris choose the OLD_ICONV iconv() declaration based on the UNIX spec
Makefile: add NEEDS_RESOLV to optionally add -lresolv to compile arguments
Makefile: use /usr/ucb/install on SunOS platforms rather than ginstall

Conflicts:
Makefile

142 files changed:
Documentation/RelNotes-1.6.3.2.txt
Documentation/config.txt
Documentation/git-apply.txt
Documentation/git-difftool.txt
Documentation/git-mergetool.txt
Documentation/git-mktree.txt
Documentation/git-repack.txt
Documentation/git-send-email.txt
Documentation/git-show-branch.txt
Documentation/git-stash.txt
Documentation/git.txt
Documentation/gittutorial.txt
Documentation/merge-config.txt
Documentation/technical/api-parse-options.txt
Documentation/user-manual.txt
Makefile
archive.c
bisect.c
builtin-add.c
builtin-apply.c
builtin-archive.c
builtin-bisect--helper.c
builtin-blame.c
builtin-branch.c
builtin-cat-file.c
builtin-check-attr.c
builtin-checkout-index.c
builtin-checkout.c
builtin-clean.c
builtin-clone.c
builtin-commit.c
builtin-config.c
builtin-count-objects.c
builtin-describe.c
builtin-fast-export.c
builtin-fetch-pack.c
builtin-fetch.c
builtin-fmt-merge-msg.c
builtin-for-each-ref.c
builtin-fsck.c
builtin-gc.c
builtin-grep.c
builtin-help.c
builtin-log.c
builtin-ls-files.c
builtin-mailinfo.c
builtin-merge-base.c
builtin-merge-file.c
builtin-merge.c
builtin-mktree.c [new file with mode: 0644]
builtin-mv.c
builtin-name-rev.c
builtin-pack-refs.c
builtin-prune.c
builtin-push.c
builtin-receive-pack.c
builtin-remote.c
builtin-reset.c
builtin-rev-parse.c
builtin-revert.c
builtin-rm.c
builtin-send-pack.c
builtin-shortlog.c
builtin-show-branch.c
builtin-symbolic-ref.c
builtin-tag.c
builtin-update-ref.c
builtin.h
cache.h
commit.c
commit.h
compat/basename.c [new file with mode: 0644]
compat/mkstemps.c [new file with mode: 0644]
config.mak.in
configure.ac
connect.c
contrib/completion/git-completion.bash
daemon.c
diff.c
dir.c
git-add--interactive.perl
git-compat-util.h
git-cvsexportcommit.perl
git-mergetool--lib.sh
git-rebase--interactive.sh
git-send-email.perl
git-stash.sh
git-svn.perl
git.c
grep.c
hash-object.c
http-push.c
imap-send.c
ll-merge.c
merge-index.c
mktree.c [deleted file]
parse-options.c
parse-options.h
path.c
pretty.c
remote.c
remote.h
revision.c
revision.h
symlinks.c
t/lib-httpd.sh
t/t0040-parse-options.sh
t/t1010-mktree.sh [new file with mode: 0755]
t/t3700-add.sh
t/t3701-add-interactive.sh
t/t3900-i18n-commit.sh
t/t3900/EUCJP.txt [deleted file]
t/t3900/ISO-8859-1.txt [deleted file]
t/t3900/ISO8859-1.txt [new file with mode: 0644]
t/t3900/eucJP.txt [new file with mode: 0644]
t/t3901-i18n-patch.sh
t/t4020-diff-external.sh
t/t4131-apply-fake-ancestor.sh [new file with mode: 0755]
t/t5100/rfc2047-samples.mbox
t/t5100/sample.mbox
t/t5500-fetch-pack.sh
t/t5505-remote.sh
t/t6023-merge-file.sh
t/t6030-bisect-porcelain.sh
t/t6200-fmt-merge-msg.sh
t/t7002-grep.sh
t/t7500-commit.sh
t/t8003-blame.sh
t/t8005-blame-i18n.sh
t/t8005/cp1251.txt [deleted file]
t/t8005/iso8859-5.txt [new file with mode: 0644]
t/t9001-send-email.sh
t/t9120-git-svn-clone-with-percent-escapes.sh
t/t9129-git-svn-i18n-commitencoding.sh
t/t9139-git-svn-non-utf8-commitencoding.sh [new file with mode: 0755]
t/t9200-git-cvsexportcommit.sh
t/t9301-fast-export.sh
t/t9500-gitweb-standalone-no-errors.sh
t/test-lib.sh
test-parse-options.c
transport.c
xdiff/xmerge.c
index a3fceebb118301ab08597fb2d89d560ae084d547..b2f3f0293c0da729d642dc7e4645df26c86c338d 100644 (file)
@@ -8,44 +8,54 @@ Fixes since v1.6.3.1
    casting the (char *) pointer to (int *); GCC 4.4 did not like this,
    and aborted compilation.
 
- * http-push had a small use-after-free bug.
-
- * command completion code in bash did not reliably detect that we are
-   in a bare repository.
-
- * "git for-each-ref" had a segfaulting bug when dealing with a tag object
-   created by an ancient git.
-
  * Some unlink(2) failures went undiagnosed.
 
  * The "recursive" merge strategy misbehaved when faced rename/delete
    conflicts while coming up with an intermediate merge base.
 
+ * The low-level merge algorithm did not handle a degenerate case of
+   merging a file with itself using itself as the common ancestor
+   gracefully.  It should produce the file itself, but instead
+   produced an empty result.
+
  * GIT_TRACE mechanism segfaulted when tracing a shell-quoted aliases.
 
+ * OpenBSD also uses st_ctimspec in "struct stat", instead of "st_ctim".
+
+ * With NO_CROSS_DIRECTORY_HARDLINKS, "make install" can be told not to
+   create hardlinks between $(gitexecdir)/git-$builtin_commands and
+   $(bindir)/git.
+
+ * command completion code in bash did not reliably detect that we are
+   in a bare repository.
+
  * "git add ." in an empty directory complained that pathspec "." did not
    match anything, which may be technically correct, but not useful.  We
    silently make it a no-op now.
 
+ * "git add -p" (and "patch" action in "git add -i") was broken when
+   the first hunk that adds a line at the top was split into two and
+   both halves are marked to be used.
+
+ * "git blame path" misbehaved at the commit where path became file
+   from a directory with some files in it.
+
+ * "git for-each-ref" had a segfaulting bug when dealing with a tag object
+   created by an ancient git.
+
  * "git format-patch -k" still added patch numbers if format.numbered
    configuration was set.
 
- * OpenBSD also uses st_ctimspec in "struct stat", instead of "st_ctim".
+ * "git grep --color ''" did not terminate.  The command also had
+   subtle bugs with its -w option.
 
- * With NO_CROSS_DIRECTORY_HARDLINKS, "make install" can be told not to
-   create hardlinks between $(gitexecdir)/git-$builtin_commands and
-   $(bindir)/git.
+ * http-push had a small use-after-free bug.
 
  * "git push" was converting OFS_DELTA pack representation into less
    efficient REF_DELTA representation unconditionally upon transfer,
    making the transferred data unnecessarily larger.
 
+ * "git remote show origin" segfaulted when origin was still empty.
+
 Many other general usability updates around help text, diagnostic messages
 and documentation are included as well.
-
----
-exec >/var/tmp/1
-O=v1.6.3.1-51-g2a1feb9
-echo O=$(git describe maint)
-git shortlog --no-merges $O..maint
-
index 2c031620c50f8e3eaaa652aaf43ee261eab8f957..3a86d1f8f05317717d718a6db7c5e0f9acb47d6b 100644 (file)
@@ -438,6 +438,11 @@ On some file system/operating system combinations, this is unreliable.
 Set this config setting to 'rename' there; However, This will remove the
 check that makes sure that existing object files will not get overwritten.
 
+add.ignore-errors::
+       Tells 'git-add' to continue adding files when some files cannot be
+       added due to indexing errors. Equivalent to the '--ignore-errors'
+       option of linkgit:git-add[1].
+
 alias.*::
        Command aliases for the linkgit:git[1] command wrapper - e.g.
        after defining "alias.last = cat-file commit HEAD", the invocation
index 9e5baa277731adf14e47fda8c6b13a076e0873db..735374d7df7e8d0e967dce7750f41aabff9a095f 100644 (file)
@@ -3,7 +3,7 @@ git-apply(1)
 
 NAME
 ----
-git-apply - Apply a patch on a git index file and a working tree
+git-apply - Apply a patch on a git index file and/or a working tree
 
 
 SYNOPSIS
index 15b247bab4195286e55447388308473af4e2d001..96a6c51a4b83207fa23fc8f09cb02f57b1085ea4 100644 (file)
@@ -31,7 +31,7 @@ OPTIONS
        Use the diff tool specified by <tool>.
        Valid merge tools are:
        kdiff3, kompare, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff,
-       ecmerge, diffuse and opendiff
+       ecmerge, diffuse, opendiff and araxis.
 +
 If a diff tool is not specified, 'git-difftool'
 will use the configuration variable `diff.tool`.  If the
index ff9700d17a333f50d6509bc14a0bd81fad876d3b..68ed6c095664b8f06635ba7eaa85b85086b24280 100644 (file)
@@ -27,7 +27,7 @@ OPTIONS
        Use the merge resolution program specified by <tool>.
        Valid merge tools are:
        kdiff3, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff, ecmerge,
-       diffuse, tortoisemerge and opendiff
+       diffuse, tortoisemerge, opendiff and araxis.
 +
 If a merge resolution program is not specified, 'git-mergetool'
 will use the configuration variable `merge.tool`.  If the
index af19f06ed738bdecc7ab9a72a5c9a216b816f4c2..81e3326772d94464708cc2037715e1e62eae5f11 100644 (file)
@@ -8,12 +8,13 @@ git-mktree - Build a tree-object from ls-tree formatted text
 
 SYNOPSIS
 --------
-'git mktree' [-z]
+'git mktree' [-z] [--missing] [--batch]
 
 DESCRIPTION
 -----------
-Reads standard input in non-recursive `ls-tree` output format,
-and creates a tree object.  The object name of the tree object
+Reads standard input in non-recursive `ls-tree` output format, and creates
+a tree object.  The order of the tree entries is normalised by mktree so
+pre-sorting the input is not required.  The object name of the tree object
 built is written to the standard output.
 
 OPTIONS
@@ -21,6 +22,18 @@ OPTIONS
 -z::
        Read the NUL-terminated `ls-tree -z` output instead.
 
+--missing::
+       Allow missing objects.  The default behaviour (without this option)
+       is to verify that each tree entry's sha1 identifies an existing
+       object.  This option has no effect on the treatment of gitlink entries
+       (aka "submodules") which are always allowed to be missing.
+
+--batch::
+       Allow building of more than one tree object before exiting.  Each
+       tree is separated by as single blank line. The final new-line is
+       optional.  Note - if the '-z' option is used, lines are terminated
+       with NUL.
+
 Author
 ------
 Written by Junio C Hamano <gitster@pobox.com>
index aaa88526291a26db55c7ebb0833faefda9c7e5a4..c9257a10c956432fdd2e456c7f910cc2996c1534 100644 (file)
@@ -31,11 +31,14 @@ OPTIONS
        Instead of incrementally packing the unpacked objects,
        pack everything referenced into a single pack.
        Especially useful when packing a repository that is used
-       for private development and there is no need to worry
-       about people fetching via dumb protocols from it.  Use
+       for private development. Use
        with '-d'.  This will clean up the objects that `git prune`
        leaves behind, but `git fsck --full` shows as
        dangling.
++
+Note that users fetching over dumb protocols will have to fetch the
+whole new pack in order to get any contained object, no matter how many
+other objects in that pack they already have locally.
 
 -A::
        Same as `-a`, unless '-d' is used.  Then any unreachable
index f9407702794b0546f21844bafadb32b0c7984bd1..e7cb0e6c71e84c896ecf2d232c906c5cb0de6b08 100644 (file)
@@ -14,6 +14,10 @@ SYNOPSIS
 DESCRIPTION
 -----------
 Takes the patches given on the command line and emails them out.
+Patches can be specified as files, directories (which will send all
+files in the directory), or directly as a revision list.  In the
+last case, any format accepted by linkgit:git-format-patch[1] can
+be passed to git send-email.
 
 The header of the email is configurable by command line options.  If not
 specified on the command line, the user will be prompted with a ReadLine
@@ -39,6 +43,10 @@ OPTIONS
 Composing
 ~~~~~~~~~
 
+--annotate::
+       Review and edit each patch you're about to send. See the
+       CONFIGURATION section for 'sendemail.multiedit'.
+
 --bcc=<address>::
        Specify a "Bcc:" value for each email. Default is the value of
        'sendemail.bcc'.
@@ -51,11 +59,6 @@ The --bcc option must be repeated for each user you want on the bcc list.
 +
 The --cc option must be repeated for each user you want on the cc list.
 
---annotate::
-       Review each patch you're about to send in an editor. The setting
-       'sendemail.multiedit' defines if this will spawn one editor per patch
-       or one for all of them at once.
-
 --compose::
        Use $GIT_EDITOR, core.editor, $VISUAL, or $EDITOR to edit an
        introductory message for the patch series.
@@ -67,6 +70,8 @@ In-Reply-To headers specified in the message. If the body of the message
 and In-Reply-To headers will be used unless they are removed.
 +
 Missing From or In-Reply-To headers will be prompted for.
++
+See the CONFIGURATION section for 'sendemail.multiedit'.
 
 --from=<address>::
        Specify the sender of the emails.  If not specified on the command line,
@@ -138,7 +143,9 @@ user is prompted for a password while the input is masked for privacy.
 --smtp-server-port=<port>::
        Specifies a port different from the default port (SMTP
        servers typically listen to smtp port 25 and ssmtp port
-       465). This can be set with 'sendemail.smtpserverport'.
+       465); symbolic port names (e.g. "submission" instead of 465)
+       are also accepted. The port can also be set with the
+       'sendemail.smtpserverport' configuration variable.
 
 --smtp-ssl::
        Legacy alias for '--smtp-encryption ssl'.
@@ -233,6 +240,12 @@ have been specified, in which case default to 'compose'.
 --dry-run::
        Do everything except actually send the emails.
 
+--[no-]format-patch::
+       When an argument may be understood either as a reference or as a file name,
+       choose to understand it as a format-patch argument ('--format-patch')
+       or as a file name ('--no-format-patch'). By default, when such a conflict
+       occurs, git send-email will fail.
+
 --quiet::
        Make git-send-email less verbose.  One line per email should be
        all that is output.
@@ -249,12 +262,6 @@ have been specified, in which case default to 'compose'.
 Default is the value of 'sendemail.validate'; if this is not set,
 default to '--validate'.
 
---[no-]format-patch::
-       When an argument may be understood either as a reference or as a file name,
-       choose to understand it as a format-patch argument ('--format-patch')
-       or as a file name ('--no-format-patch'). By default, when such a conflict
-       occurs, git send-email will fail.
-
 
 CONFIGURATION
 -------------
index edd8f6463ebab38f950db634e28fe5f06cf3915a..89ec5364ecd447f6a7836d9c7f582dbd1d864807 100644 (file)
@@ -8,10 +8,11 @@ git-show-branch - Show branches and their commits
 SYNOPSIS
 --------
 [verse]
-'git show-branch' [--all] [--remotes] [--topo-order] [--current]
+'git show-branch' [--all] [--remotes] [--topo-order | --date-order]
+               [--current] [--color | --no-color]
                [--more=<n> | --list | --independent | --merge-base]
-               [--color | --no-color]
-               [--no-name | --sha1-name] [--topics] [<rev> | <glob>]...
+               [--no-name | --sha1-name] [--topics]
+               [<rev> | <glob>]...
 'git show-branch' (-g|--reflog)[=<n>[,<base>]] [--list] [<ref>]
 
 DESCRIPTION
@@ -58,6 +59,11 @@ OPTIONS
         appear in topological order (i.e., descendant commits
         are shown before their parents).
 
+--date-order::
+       This option is similar to '--topo-order' in the sense that no
+       parent comes before all of its children, but otherwise commits
+       are ordered according to their commit date.
+
 --sparse::
        By default, the output omits merges that are reachable
        from only one tip being shown.  This option makes them
index 051f94d26f9f057cbd4db0d6886ca1a4d33c912c..a42d4c85bddd539d46aaaafea6bf6412cd7c3436 100644 (file)
@@ -9,8 +9,8 @@ SYNOPSIS
 --------
 [verse]
 'git stash' list [<options>]
-'git stash' (show | drop | pop ) [<stash>]
-'git stash' apply [--index] [<stash>]
+'git stash' ( show | drop ) [<stash>]
+'git stash' ( pop | apply ) [--index] [<stash>]
 'git stash' branch <branchname> [<stash>]
 'git stash' [save [--keep-index] [<message>]]
 'git stash' clear
@@ -75,19 +75,27 @@ show [<stash>]::
        it will accept any format known to 'git-diff' (e.g., `git stash show
        -p stash@\{1}` to view the second most recent stash in patch form).
 
-apply [--index] [<stash>]::
+pop [<stash>]::
 
-       Restore the changes recorded in the stash on top of the current
-       working tree state.  When no `<stash>` is given, applies the latest
-       one.  The working directory must match the index.
+       Remove a single stashed state from the stash list and apply it
+       on top of the current working tree state, i.e., do the inverse
+       operation of `git stash save`. The working directory must
+       match the index.
 +
-This operation can fail with conflicts; you need to resolve them
-by hand in the working tree.
+Applying the state can fail with conflicts; in this case, it is not
+removed from the stash list. You need to resolve the conflicts by hand
+and call `git stash drop` manually afterwards.
 +
 If the `--index` option is used, then tries to reinstate not only the working
 tree's changes, but also the index's ones. However, this can fail, when you
 have conflicts (which are stored in the index, where you therefore can no
 longer apply the changes as they were originally).
++
+When no `<stash>` is given, `stash@\{0}` is assumed.
+
+apply [--index] [<stash>]::
+
+       Like `pop`, but do not remove the state from the stash list.
 
 branch <branchname> [<stash>]::
 
@@ -112,12 +120,6 @@ drop [<stash>]::
        Remove a single stashed state from the stash list. When no `<stash>`
        is given, it removes the latest one. i.e. `stash@\{0}`
 
-pop [<stash>]::
-
-       Remove a single stashed state from the stash list and apply on top
-       of the current working tree state. When no `<stash>` is given,
-       `stash@\{0}` is assumed. See also `apply`.
-
 create::
 
        Create a stash (which is a regular commit object) and return its
@@ -163,7 +165,7 @@ $ git pull
 file foobar not up to date, cannot merge.
 $ git stash
 $ git pull
-$ git stash apply
+$ git stash pop
 ----------------------------------------------------------------
 
 Interrupted workflow::
@@ -192,7 +194,7 @@ You can use 'git-stash' to simplify the above, like this:
 $ git stash
 $ edit emergency fix
 $ git commit -a -m "Fix in a hurry"
-$ git stash apply
+$ git stash pop
 # ... continue hacking ...
 ----------------------------------------------------------------
 
index 9d8f236fe84cd02550b8cf08e835b2926e6c45f0..56d47709ac9ec698405215ecac13d66d7c773848 100644 (file)
@@ -43,7 +43,12 @@ unreleased) version of git, that is available from 'master'
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
-* link:v1.6.3/git.html[documentation for release 1.6.3]
+* link:v1.6.3.2/git.html[documentation for release 1.6.3.2]
+
+* release notes for
+  link:RelNotes-1.6.3.2.txt[1.6.3.2],
+  link:RelNotes-1.6.3.1.txt[1.6.3.1],
+  link:RelNotes-1.6.3.txt[1.6.3].
 
 * release notes for
   link:RelNotes-1.6.2.5.txt[1.6.2.5],
@@ -227,6 +232,8 @@ The link:user-manual.html#git-concepts[git concepts chapter of the
 user-manual] and linkgit:gitcore-tutorial[7] both provide
 introductions to the underlying git architecture.
 
+See linkgit:gitworkflows[7] for an overview of recommended workflows.
+
 See also the link:howto-index.html[howto] documents for some useful
 examples.
 
@@ -644,7 +651,8 @@ SEE ALSO
 linkgit:gittutorial[7], linkgit:gittutorial-2[7],
 link:everyday.html[Everyday Git], linkgit:gitcvs-migration[7],
 linkgit:gitglossary[7], linkgit:gitcore-tutorial[7],
-linkgit:gitcli[7], link:user-manual.html[The Git User's Manual]
+linkgit:gitcli[7], link:user-manual.html[The Git User's Manual],
+linkgit:gitworkflows[7]
 
 GIT
 ---
index c5d5596d895755d69c8060bc38a800d7c70eda26..c7fa949c287f76c5ab8173d975f6da3dd92e6802 100644 (file)
@@ -650,6 +650,9 @@ digressions that may be interesting at this point are:
     smart enough to perform a close-to-optimal search even in the
     case of complex non-linear history with lots of merged branches.
 
+  * linkgit:gitworkflows[7]: Gives an overview of recommended
+    workflows.
+
   * link:everyday.html[Everyday GIT with 20 Commands Or So]
 
   * linkgit:gitcvs-migration[7]: Git for CVS users.
@@ -661,6 +664,7 @@ linkgit:gitcvs-migration[7],
 linkgit:gitcore-tutorial[7],
 linkgit:gitglossary[7],
 linkgit:git-help[1],
+linkgit:gitworkflows[7],
 link:everyday.html[Everyday git],
 link:user-manual.html[The Git User's Manual]
 
index 4832bc75e2604c997e004018023e3b93cb394b87..c0f96e70708cab74a13ec8696db003289f99b455 100644 (file)
@@ -23,7 +23,7 @@ merge.tool::
        Controls which merge resolution program is used by
        linkgit:git-mergetool[1].  Valid built-in values are: "kdiff3",
        "tkdiff", "meld", "xxdiff", "emerge", "vimdiff", "gvimdiff",
-       "diffuse", "ecmerge", "tortoisemerge", and
+       "diffuse", "ecmerge", "tortoisemerge", "araxis", and
        "opendiff".  Any other value is treated is custom merge tool
        and there must be a corresponding mergetool.<tool>.cmd option.
 
index b43458eae6787caab163fadab113dff61e577498..50f9e9ac1708f3f754023c1bb60416adc9c73c74 100644 (file)
@@ -60,13 +60,13 @@ Steps to parse options
 . in `cmd_foo(int argc, const char **argv, const char *prefix)`
   call
 
-       argc = parse_options(argc, argv, builtin_foo_options, builtin_foo_usage, flags);
+       argc = parse_options(argc, argv, prefix, builtin_foo_options, builtin_foo_usage, flags);
 +
 `parse_options()` will filter out the processed options of `argv[]` and leave the
 non-option arguments in `argv[]`.
 `argc` is updated appropriately because of the assignment.
 +
-You can also pass NULL instead of a usage array as fourth parameter of
+You can also pass NULL instead of a usage array as the fifth parameter of
 parse_options(), to avoid displaying a help screen with usage info and
 option list.  This should only be done if necessary, e.g. to implement
 a limited parser for only a subset of the options that needs to be run
@@ -167,6 +167,11 @@ There are some macros to easily define options:
        and the result will be put into `var`.
        See 'Option Callbacks' below for a more elaborate description.
 
+`OPT_FILENAME(short, long, &var, description)`::
+       Introduce an option with a filename argument.
+       The filename will be prefixed by passing the filename along with
+       the prefix argument of `parse_options()` to `prefix_filename()`.
+
 `OPT_ARGUMENT(long, description)`::
        Introduce a long-option argument that will be kept in `argv[]`.
 
index dbbeb7e7c7856776450bc64321ff5f1de26202bb..0b88a51d0b192a3dbc2ec0fe73a32860247377a1 100644 (file)
@@ -1520,10 +1520,10 @@ $ git commit -a -m "blorpl: typofix"
 ------------------------------------------------
 
 After that, you can go back to what you were working on with
-`git stash apply`:
+`git stash pop`:
 
 ------------------------------------------------
-$ git stash apply
+$ git stash pop
 ------------------------------------------------
 
 
index 1197b2fd4dcf5eb79f646b7486c45120440670e6..735ab079c07b73964b37dfc6c5ac4ee6d1ebcf57 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -57,6 +57,10 @@ all::
 #
 # Define NO_MKDTEMP if you don't have mkdtemp in the C library.
 #
+# Define NO_MKSTEMPS if you don't have mkstemps in the C library.
+#
+# Define NO_LIBGEN_H if you don't have libgen.h.
+#
 # Define NO_SYS_SELECT_H if you don't have sys/select.h.
 #
 # Define NO_SYMLINK_HEAD if you never want .git/HEAD to be a symbolic link.
@@ -345,7 +349,6 @@ PROGRAMS += git-index-pack$X
 PROGRAMS += git-merge-index$X
 PROGRAMS += git-merge-tree$X
 PROGRAMS += git-mktag$X
-PROGRAMS += git-mktree$X
 PROGRAMS += git-pack-redundant$X
 PROGRAMS += git-patch-id$X
 PROGRAMS += git-shell$X
@@ -599,6 +602,7 @@ BUILTIN_OBJS += builtin-merge-base.o
 BUILTIN_OBJS += builtin-merge-file.o
 BUILTIN_OBJS += builtin-merge-ours.o
 BUILTIN_OBJS += builtin-merge-recursive.o
+BUILTIN_OBJS += builtin-mktree.o
 BUILTIN_OBJS += builtin-mv.o
 BUILTIN_OBJS += builtin-name-rev.o
 BUILTIN_OBJS += builtin-pack-objects.o
@@ -645,10 +649,12 @@ EXTLIBS =
 
 ifeq ($(uname_S),Linux)
        NO_STRLCPY = YesPlease
+       NO_MKSTEMPS = YesPlease
        THREADED_DELTA_SEARCH = YesPlease
 endif
 ifeq ($(uname_S),GNU/kFreeBSD)
        NO_STRLCPY = YesPlease
+       NO_MKSTEMPS = YesPlease
        THREADED_DELTA_SEARCH = YesPlease
 endif
 ifeq ($(uname_S),UnixWare)
@@ -660,6 +666,7 @@ ifeq ($(uname_S),UnixWare)
        SHELL_PATH = /usr/local/bin/bash
        NO_IPV6 = YesPlease
        NO_HSTRERROR = YesPlease
+       NO_MKSTEMPS = YesPlease
        BASIC_CFLAGS += -Kthread
        BASIC_CFLAGS += -I/usr/local/include
        BASIC_LDFLAGS += -L/usr/local/lib
@@ -683,6 +690,7 @@ ifeq ($(uname_S),SCO_SV)
        SHELL_PATH = /usr/bin/bash
        NO_IPV6 = YesPlease
        NO_HSTRERROR = YesPlease
+       NO_MKSTEMPS = YesPlease
        BASIC_CFLAGS += -I/usr/local/include
        BASIC_LDFLAGS += -L/usr/local/lib
        NO_STRCASESTR = YesPlease
@@ -746,6 +754,7 @@ ifeq ($(uname_O),Cygwin)
        NO_D_INO_IN_DIRENT = YesPlease
        NO_STRCASESTR = YesPlease
        NO_MEMMEM = YesPlease
+       NO_MKSTEMPS = YesPlease
        NO_SYMLINK_HEAD = YesPlease
        NEEDS_LIBICONV = YesPlease
        NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes
@@ -789,11 +798,13 @@ ifeq ($(uname_S),NetBSD)
        BASIC_LDFLAGS += -L/usr/pkg/lib $(CC_LD_DYNPATH)/usr/pkg/lib
        THREADED_DELTA_SEARCH = YesPlease
        USE_ST_TIMESPEC = YesPlease
+       NO_MKSTEMPS = YesPlease
 endif
 ifeq ($(uname_S),AIX)
        NO_STRCASESTR=YesPlease
        NO_MEMMEM = YesPlease
        NO_MKDTEMP = YesPlease
+       NO_MKSTEMPS = YesPlease
        NO_STRLCPY = YesPlease
        NO_NSEC = YesPlease
        FREAD_READS_DIRECTORIES = UnfortunatelyYes
@@ -809,12 +820,14 @@ endif
 ifeq ($(uname_S),GNU)
        # GNU/Hurd
        NO_STRLCPY=YesPlease
+       NO_MKSTEMPS = YesPlease
 endif
 ifeq ($(uname_S),IRIX64)
        NO_IPV6=YesPlease
        NO_SETENV=YesPlease
        NO_STRCASESTR=YesPlease
        NO_MEMMEM = YesPlease
+       NO_MKSTEMPS = YesPlease
        NO_STRLCPY = YesPlease
        NO_SOCKADDR_STORAGE=YesPlease
        SHELL_PATH=/usr/gnu/bin/bash
@@ -827,6 +840,7 @@ ifeq ($(uname_S),HP-UX)
        NO_SETENV=YesPlease
        NO_STRCASESTR=YesPlease
        NO_MEMMEM = YesPlease
+       NO_MKSTEMPS = YesPlease
        NO_STRLCPY = YesPlease
        NO_MKDTEMP = YesPlease
        NO_UNSETENV = YesPlease
@@ -843,6 +857,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
        NO_PREAD = YesPlease
        NO_OPENSSL = YesPlease
        NO_CURL = YesPlease
+       NO_LIBGEN_H = YesPlease
        NO_SYMLINK_HEAD = YesPlease
        NO_IPV6 = YesPlease
        NO_SETENV = YesPlease
@@ -856,6 +871,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
        NO_C99_FORMAT = YesPlease
        NO_STRTOUMAX = YesPlease
        NO_MKDTEMP = YesPlease
+       NO_MKSTEMPS = YesPlease
        SNPRINTF_RETURNS_BOGUS = YesPlease
        NO_SVN_TESTS = YesPlease
        NO_PERL_MAKEMAKER = YesPlease
@@ -875,6 +891,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
 endif
 ifneq (,$(findstring arm,$(uname_M)))
        ARM_SHA1 = YesPlease
+       NO_MKSTEMPS = YesPlease
 endif
 
 -include config.mak.autogen
@@ -914,6 +931,11 @@ ifndef CC_LD_DYNPATH
        endif
 endif
 
+ifdef NO_LIBGEN_H
+       COMPAT_CFLAGS += -DNO_LIBGEN_H
+       COMPAT_OBJS += compat/basename.o
+endif
+
 ifdef NO_CURL
        BASIC_CFLAGS += -DNO_CURL
 else
@@ -1044,6 +1066,10 @@ ifdef NO_MKDTEMP
        COMPAT_CFLAGS += -DNO_MKDTEMP
        COMPAT_OBJS += compat/mkdtemp.o
 endif
+ifdef NO_MKSTEMPS
+       COMPAT_CFLAGS += -DNO_MKSTEMPS
+       COMPAT_OBJS += compat/mkstemps.o
+endif
 ifdef NO_UNSETENV
        COMPAT_CFLAGS += -DNO_UNSETENV
        COMPAT_OBJS += compat/unsetenv.o
@@ -1529,6 +1555,8 @@ test-delta$X: diff-delta.o patch-delta.o
 
 test-parse-options$X: parse-options.o
 
+test-parse-options.o: parse-options.h
+
 .PRECIOUS: $(patsubst test-%$X,test-%.o,$(TEST_PROGRAMS))
 
 test-%$X: test-%.o $(GITLIBS)
index b2b90d31700d3aa50a3ac0626c1a8561c37c49b7..0bca9ca4038ace99c32eff2e042290b03b2324b7 100644 (file)
--- a/archive.c
+++ b/archive.c
@@ -309,7 +309,7 @@ static int parse_archive_args(int argc, const char **argv,
                OPT_END()
        };
 
-       argc = parse_options(argc, argv, opts, archive_usage, 0);
+       argc = parse_options(argc, argv, NULL, opts, archive_usage, 0);
 
        if (remote)
                die("Unexpected option --remote");
index f57b62cdddb7ff96acaabdee6e4bfc551d8a195f..c43c120bdefe95bda60b913c5a52d0a942e9d3f6 100644 (file)
--- a/bisect.c
+++ b/bisect.c
@@ -553,7 +553,9 @@ struct commit_list *filter_skipped(struct commit_list *list,
        return filtered;
 }
 
-static void bisect_rev_setup(struct rev_info *revs, const char *prefix)
+static void bisect_rev_setup(struct rev_info *revs, const char *prefix,
+                            const char *bad_format, const char *good_format,
+                            int read_paths)
 {
        struct argv_array rev_argv = { NULL, 0, 0 };
        int i;
@@ -564,26 +566,24 @@ static void bisect_rev_setup(struct rev_info *revs, const char *prefix)
 
        /* rev_argv.argv[0] will be ignored by setup_revisions */
        argv_array_push(&rev_argv, xstrdup("bisect_rev_setup"));
-       argv_array_push_sha1(&rev_argv, current_bad_sha1, "%s");
+       argv_array_push_sha1(&rev_argv, current_bad_sha1, bad_format);
        for (i = 0; i < good_revs.sha1_nr; i++)
-               argv_array_push_sha1(&rev_argv, good_revs.sha1[i], "^%s");
+               argv_array_push_sha1(&rev_argv, good_revs.sha1[i],
+                                    good_format);
        argv_array_push(&rev_argv, xstrdup("--"));
-       read_bisect_paths(&rev_argv);
+       if (read_paths)
+               read_bisect_paths(&rev_argv);
        argv_array_push(&rev_argv, NULL);
 
        setup_revisions(rev_argv.argv_nr, rev_argv.argv, revs, NULL);
-       revs->limited = 1;
 }
 
-static void bisect_common(struct rev_info *revs, int *reaches, int *all)
+static void bisect_common(struct rev_info *revs)
 {
        if (prepare_revision_walk(revs))
                die("revision walk setup failed");
        if (revs->tree_objects)
                mark_edges_uninteresting(revs->commits, revs, NULL);
-
-       revs->commits = find_bisection(revs->commits, reaches, all,
-                                      !!skipped_revs.sha1_nr);
 }
 
 static void exit_if_skipped_commits(struct commit_list *tried,
@@ -750,42 +750,31 @@ static void check_merge_bases(void)
        free_commit_list(result);
 }
 
-/*
- * This function runs the command "git rev-list $_good ^$_bad"
- * and returns 1 if it produces some output, 0 otherwise.
- */
-static int check_ancestors(void)
+static int check_ancestors(const char *prefix)
 {
-       struct argv_array rev_argv = { NULL, 0, 0 };
-       struct strbuf str = STRBUF_INIT;
-       int i, result = 0;
-       struct child_process rls;
-       FILE *rls_fout;
+       struct rev_info revs;
+       struct object_array pending_copy;
+       int i, res;
 
-       argv_array_push(&rev_argv, xstrdup("rev-list"));
-       argv_array_push_sha1(&rev_argv, current_bad_sha1, "^%s");
-       for (i = 0; i < good_revs.sha1_nr; i++)
-               argv_array_push_sha1(&rev_argv, good_revs.sha1[i], "%s");
-       argv_array_push(&rev_argv, NULL);
+       bisect_rev_setup(&revs, prefix, "^%s", "%s", 0);
 
-       memset(&rls, 0, sizeof(rls));
-       rls.argv = rev_argv.argv;
-       rls.out = -1;
-       rls.git_cmd = 1;
-       if (start_command(&rls))
-               die("Could not launch 'git rev-list' command.");
-       rls_fout = fdopen(rls.out, "r");
-       while (strbuf_getline(&str, rls_fout, '\n') != EOF) {
-               strbuf_trim(&str);
-               if (*str.buf) {
-                       result = 1;
-                       break;
-               }
+       /* Save pending objects, so they can be cleaned up later. */
+       memset(&pending_copy, 0, sizeof(pending_copy));
+       for (i = 0; i < revs.pending.nr; i++)
+               add_object_array(revs.pending.objects[i].item,
+                                revs.pending.objects[i].name,
+                                &pending_copy);
+
+       bisect_common(&revs);
+       res = (revs.commits != NULL);
+
+       /* Clean up objects used, as they will be reused. */
+       for (i = 0; i < pending_copy.nr; i++) {
+               struct object *o = pending_copy.objects[i].item;
+               unparse_commit((struct commit *)o);
        }
-       fclose(rls_fout);
-       finish_command(&rls);
 
-       return result;
+       return res;
 }
 
 /*
@@ -813,7 +802,8 @@ static void check_good_are_ancestors_of_bad(const char *prefix)
        if (good_revs.sha1_nr == 0)
                return;
 
-       if (check_ancestors())
+       /* Check if all good revs are ancestor of the bad rev. */
+       if (check_ancestors(prefix))
                check_merge_bases();
 
        /* Create file BISECT_ANCESTORS_OK. */
@@ -843,10 +833,13 @@ int bisect_next_all(const char *prefix)
 
        check_good_are_ancestors_of_bad(prefix);
 
-       bisect_rev_setup(&revs, prefix);
+       bisect_rev_setup(&revs, prefix, "%s", "^%s", 1);
+       revs.limited = 1;
 
-       bisect_common(&revs, &reaches, &all);
+       bisect_common(&revs);
 
+       revs.commits = find_bisection(revs.commits, &reaches, &all,
+                                      !!skipped_revs.sha1_nr);
        revs.commits = filter_skipped(revs.commits, &tried, 0);
 
        if (!revs.commits) {
index bee45f00de7d82e07b617716033f0d5605b2a368..c1b229a9d8a026ec88cdbf0492856021cacc8097 100644 (file)
@@ -298,7 +298,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
        int add_new_files;
        int require_pathspec;
 
-       argc = parse_options(argc, argv, builtin_add_options,
+       argc = parse_options(argc, argv, prefix, builtin_add_options,
                          builtin_add_usage, PARSE_OPT_KEEP_ARGV0);
        if (patch_interactive)
                add_interactive = 1;
index 8a3771e87e1ef2ac7a1ee70133b8206f0f18cbb5..94ba2bdd5bdf0bc2f9924fc8f73c98f0bb159134 100644 (file)
@@ -320,6 +320,20 @@ static int name_terminate(const char *name, int namelen, int c, int terminate)
        return 1;
 }
 
+/* remove double slashes to make --index work with such filenames */
+static char *squash_slash(char *name)
+{
+       int i = 0, j = 0;
+
+       while (name[i]) {
+               if ((name[j++] = name[i++]) == '/')
+                       while (name[i] == '/')
+                               i++;
+       }
+       name[j] = '\0';
+       return name;
+}
+
 static char *find_name(const char *line, char *def, int p_value, int terminate)
 {
        int len;
@@ -349,7 +363,7 @@ static char *find_name(const char *line, char *def, int p_value, int terminate)
                                free(def);
                                if (root)
                                        strbuf_insert(&name, 0, root, root_len);
-                               return strbuf_detach(&name, NULL);
+                               return squash_slash(strbuf_detach(&name, NULL));
                        }
                }
                strbuf_release(&name);
@@ -369,10 +383,10 @@ static char *find_name(const char *line, char *def, int p_value, int terminate)
                        start = line;
        }
        if (!start)
-               return def;
+               return squash_slash(def);
        len = line - start;
        if (!len)
-               return def;
+               return squash_slash(def);
 
        /*
         * Generally we prefer the shorter name, especially
@@ -383,7 +397,7 @@ static char *find_name(const char *line, char *def, int p_value, int terminate)
        if (def) {
                int deflen = strlen(def);
                if (deflen < len && !strncmp(start, def, deflen))
-                       return def;
+                       return squash_slash(def);
                free(def);
        }
 
@@ -392,10 +406,10 @@ static char *find_name(const char *line, char *def, int p_value, int terminate)
                strcpy(ret, root);
                memcpy(ret + root_len, start, len);
                ret[root_len + len] = '\0';
-               return ret;
+               return squash_slash(ret);
        }
 
-       return xmemdupz(start, len);
+       return squash_slash(xmemdupz(start, len));
 }
 
 static int count_slashes(const char *cp)
@@ -3278,7 +3292,7 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
                        "apply a patch without touching the working tree"),
                OPT_BOOLEAN(0, "apply", &force_apply,
                        "also apply the patch (use with --stat/--summary/--check)"),
-               OPT_STRING(0, "build-fake-ancestor", &fake_ancestor, "file",
+               OPT_FILENAME(0, "build-fake-ancestor", &fake_ancestor,
                        "build a temporary index based on embedded index information"),
                { OPTION_CALLBACK, 'z', NULL, NULL, NULL,
                        "paths are separated with NUL character",
@@ -3313,8 +3327,9 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
        if (apply_default_whitespace)
                parse_whitespace_option(apply_default_whitespace);
 
-       argc = parse_options(argc, argv, builtin_apply_options,
+       argc = parse_options(argc, argv, prefix, builtin_apply_options,
                        apply_usage, 0);
+
        if (apply_with_reject)
                apply = apply_verbosely = 1;
        if (!force_apply && (diffstat || numstat || summary || check || fake_ancestor))
index ab50cebba0e6798996cc007ced9079c3f0b94a29..3c5a5a7822afebf87ef6eb1f89c7c54d76844161 100644 (file)
@@ -80,7 +80,8 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
                OPT_END()
        };
 
-       argc = parse_options(argc, argv, local_opts, NULL, PARSE_OPT_KEEP_ALL);
+       argc = parse_options(argc, argv, prefix, local_opts, NULL,
+                            PARSE_OPT_KEEP_ALL);
 
        if (output)
                create_output_file(output);
index cb3e15511611240cbc3ea53a1a591fdee19ba0b9..5b226399e1c30b23a7b5d226a3f45efe9dbedf45 100644 (file)
@@ -17,7 +17,8 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
                OPT_END()
        };
 
-       argc = parse_options(argc, argv, options, git_bisect_helper_usage, 0);
+       argc = parse_options(argc, argv, prefix, options,
+                            git_bisect_helper_usage, 0);
 
        if (!next_all)
                usage_with_options(git_bisect_helper_usage, options);
index cf74a926149668b7e67544aecd46a0e05d4f59d9..0c2d29a43005e0afe7c0b0754499a37156e235ef 100644 (file)
@@ -362,18 +362,28 @@ static struct origin *find_origin(struct scoreboard *sb,
                               "", &diff_opts);
        diffcore_std(&diff_opts);
 
-       /* It is either one entry that says "modified", or "created",
-        * or nothing.
-        */
        if (!diff_queued_diff.nr) {
                /* The path is the same as parent */
                porigin = get_origin(sb, parent, origin->path);
                hashcpy(porigin->blob_sha1, origin->blob_sha1);
-       }
-       else if (diff_queued_diff.nr != 1)
-               die("internal error in blame::find_origin");
-       else {
-               struct diff_filepair *p = diff_queued_diff.queue[0];
+       } else {
+               /*
+                * Since origin->path is a pathspec, if the parent
+                * commit had it as a directory, we will see a whole
+                * bunch of deletion of files in the directory that we
+                * do not care about.
+                */
+               int i;
+               struct diff_filepair *p = NULL;
+               for (i = 0; i < diff_queued_diff.nr; i++) {
+                       const char *name;
+                       p = diff_queued_diff.queue[i];
+                       name = p->one->path ? p->one->path : p->two->path;
+                       if (!strcmp(name, origin->path))
+                               break;
+               }
+               if (!p)
+                       die("internal error in blame::find_origin");
                switch (p->status) {
                default:
                        die("internal error in blame::find_origin (%c)",
@@ -2229,7 +2239,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
        save_commit_buffer = 0;
        dashdash_pos = 0;
 
-       parse_options_start(&ctx, argc, argv, PARSE_OPT_KEEP_DASHDASH |
+       parse_options_start(&ctx, argc, argv, prefix, PARSE_OPT_KEEP_DASHDASH |
                            PARSE_OPT_KEEP_ARGV0);
        for (;;) {
                switch (parse_options_step(&ctx, options, blame_opt_usage)) {
index 6aaa708473231848db8cba061f6048d41a6782af..5687d6042ced29e60aa1999dc9d73eb6c38b8e77 100644 (file)
@@ -610,7 +610,8 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
        }
        hashcpy(merge_filter_ref, head_sha1);
 
-       argc = parse_options(argc, argv, options, builtin_branch_usage, 0);
+       argc = parse_options(argc, argv, prefix, options, builtin_branch_usage,
+                            0);
        if (!!delete + !!rename + !!force_create > 1)
                usage_with_options(builtin_branch_usage, options);
 
index 43ffe7ffae90322d757e110d8693a936209236f0..590684200854ad6a71653f30d494eb191fd4a324 100644 (file)
@@ -231,7 +231,7 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
        if (argc != 3 && argc != 2)
                usage_with_options(cat_file_usage, options);
 
-       argc = parse_options(argc, argv, options, cat_file_usage, 0);
+       argc = parse_options(argc, argv, prefix, options, cat_file_usage, 0);
 
        if (opt) {
                if (argc == 1)
index 15a04b7179a09492764d43c16a3ec5ff7cdd1b61..8bd043009829fb4bb40cd2f730cbffa27c3791cf 100644 (file)
@@ -69,8 +69,8 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)
        int cnt, i, doubledash;
        const char *errstr = NULL;
 
-       argc = parse_options(argc, argv, check_attr_options, check_attr_usage,
-               PARSE_OPT_KEEP_DASHDASH);
+       argc = parse_options(argc, argv, prefix, check_attr_options,
+                            check_attr_usage, PARSE_OPT_KEEP_DASHDASH);
        if (!argc)
                usage_with_options(check_attr_usage, check_attr_options);
 
index afe35e246c5ab2b262683308def787c6abce2a83..a7a5ee10f32d52c7555f85f2dcf6c567425488dd 100644 (file)
@@ -249,7 +249,7 @@ int cmd_checkout_index(int argc, const char **argv, const char *prefix)
                die("invalid cache");
        }
 
-       argc = parse_options(argc, argv, builtin_checkout_index_options,
+       argc = parse_options(argc, argv, prefix, builtin_checkout_index_options,
                        builtin_checkout_index_usage, 0);
        state.force = force;
        state.quiet = quiet;
index b8a4b0139b3b9c2f731315413a73db30edaf9231..8a9a474218c128b7878647045ba471df9902636a 100644 (file)
@@ -605,7 +605,7 @@ int cmd_checkout(int argc, const char **argv, const char *prefix)
 
        opts.track = BRANCH_TRACK_UNSPECIFIED;
 
-       argc = parse_options(argc, argv, options, checkout_usage,
+       argc = parse_options(argc, argv, prefix, options, checkout_usage,
                             PARSE_OPT_KEEP_DASHDASH);
 
        /* --track without -b should DWIM */
index c5ad33d3e665f6d1613df2dfba235b03765565ac..1c1b6d26e9987800d2a414e49e4f371a4277b96e 100644 (file)
@@ -56,7 +56,8 @@ int cmd_clean(int argc, const char **argv, const char *prefix)
        else
                config_set = 1;
 
-       argc = parse_options(argc, argv, options, builtin_clean_usage, 0);
+       argc = parse_options(argc, argv, prefix, options, builtin_clean_usage,
+                            0);
 
        memset(&dir, 0, sizeof(dir));
        if (ignored_only)
index c935833c6ce176caf47a14b5ad1f2848f0d1ab22..5c46496a43a8fe2f91b395563b266e79a8b94429 100644 (file)
@@ -360,7 +360,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 
        junk_pid = getpid();
 
-       argc = parse_options(argc, argv, builtin_clone_options,
+       argc = parse_options(argc, argv, prefix, builtin_clone_options,
                             builtin_clone_usage, 0);
 
        if (argc == 0)
index 81371b1d2698a48dba36046d7ff9d849f830a762..41e222d267ca952c3bc0c8d6b1e19c0171df0c62 100644 (file)
@@ -88,13 +88,13 @@ static struct option builtin_commit_options[] = {
        OPT__VERBOSE(&verbose),
        OPT_GROUP("Commit message options"),
 
-       OPT_STRING('F', "file", &logfile, "FILE", "read log from file"),
+       OPT_FILENAME('F', "file", &logfile, "read log from file"),
        OPT_STRING(0, "author", &force_author, "AUTHOR", "override author for commit"),
        OPT_CALLBACK('m', "message", &message, "MESSAGE", "specify commit message", opt_parse_m),
        OPT_STRING('c', "reedit-message", &edit_message, "COMMIT", "reuse and edit message from specified commit "),
        OPT_STRING('C', "reuse-message", &use_message, "COMMIT", "reuse message from specified commit"),
        OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
-       OPT_STRING('t', "template", &template_file, "FILE", "use specified template file"),
+       OPT_FILENAME('t', "template", &template_file, "use specified template file"),
        OPT_BOOLEAN('e', "edit", &edit_flag, "force edit of commit"),
 
        OPT_GROUP("Commit contents options"),
@@ -697,9 +697,8 @@ static int parse_and_validate_options(int argc, const char *argv[],
 {
        int f = 0;
 
-       argc = parse_options(argc, argv, builtin_commit_options, usage, 0);
-       logfile = parse_options_fix_filename(prefix, logfile);
-       template_file = parse_options_fix_filename(prefix, template_file);
+       argc = parse_options(argc, argv, prefix, builtin_commit_options, usage,
+                            0);
 
        if (force_author && !strchr(force_author, '>'))
                force_author = find_author_by_nickname(force_author);
index a81bc8bbf033fac83ad6deecbf4a67ba44e06a0b..60915f91caff02997222d18bc625d242d95c6bb1 100644 (file)
@@ -316,7 +316,8 @@ int cmd_config(int argc, const char **argv, const char *unused_prefix)
 
        config_exclusive_filename = getenv(CONFIG_ENVIRONMENT);
 
-       argc = parse_options(argc, argv, builtin_config_options, builtin_config_usage,
+       argc = parse_options(argc, argv, prefix, builtin_config_options,
+                            builtin_config_usage,
                             PARSE_OPT_STOP_AT_NON_OPTION);
 
        if (use_global_config + use_system_config + !!given_config_file > 1) {
index b814fe5070873f5c87fc6bbfde480e3b0a83e397..1b0b6c84ea4279df56b82c5a406adbea59e58513 100644 (file)
@@ -83,7 +83,7 @@ int cmd_count_objects(int argc, const char **argv, const char *prefix)
                OPT_END(),
        };
 
-       argc = parse_options(argc, argv, opts, count_objects_usage, 0);
+       argc = parse_options(argc, argv, prefix, opts, count_objects_usage, 0);
        /* we do not take arguments other than flags for now */
        if (argc)
                usage_with_options(count_objects_usage, opts);
index 63c6a19da5b38bc7c00c624c080ba0afbb10ff8a..7a662980d102a275fceb8299bba0b84b41a8f9cb 100644 (file)
@@ -322,7 +322,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
                OPT_END(),
        };
 
-       argc = parse_options(argc, argv, options, describe_usage, 0);
+       argc = parse_options(argc, argv, prefix, options, describe_usage, 0);
        if (max_candidates < 0)
                max_candidates = 0;
        else if (max_candidates > MAX_TAGS)
index 6731713223d4df24614417cc4285cbee793151d3..6cef8103127a8748acb64ca7ec7a7a95fb639cd3 100644 (file)
@@ -515,7 +515,7 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
 
        init_revisions(&revs, prefix);
        argc = setup_revisions(argc, argv, &revs, NULL);
-       argc = parse_options(argc, argv, options, fast_export_usage, 0);
+       argc = parse_options(argc, argv, prefix, options, fast_export_usage, 0);
        if (argc > 1)
                usage_with_options (fast_export_usage, options);
 
index 6202462216f3b8c3cbe924d4cc002616e69d75ab..629735f54723a3bc3b24f8c91e9a6226ae28d742 100644 (file)
@@ -483,7 +483,9 @@ static int sideband_demux(int fd, void *data)
 {
        int *xd = data;
 
-       return recv_sideband("fetch-pack", xd[0], fd);
+       int ret = recv_sideband("fetch-pack", xd[0], fd);
+       close(fd);
+       return ret;
 }
 
 static int get_pack(int xd[2], char **pack_lockfile)
index 1eec64e9c4f624f035dc8c155316964c3b87470f..cd5eb9aff530fcb9629bd561bc774e2b9ad69afc 100644 (file)
@@ -639,7 +639,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
        for (i = 1; i < argc; i++)
                strbuf_addf(&default_rla, " %s", argv[i]);
 
-       argc = parse_options(argc, argv,
+       argc = parse_options(argc, argv, prefix,
                             builtin_fetch_options, builtin_fetch_usage, 0);
 
        if (argc == 0)
index a7883690d74cb1bcef7b20f27ebbea6f6c5dcc53..fbf9582e667dfd1e69027b35c3f307f3c7a08a99 100644 (file)
@@ -351,7 +351,7 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
        struct option options[] = {
                OPT_BOOLEAN(0, "log",     &merge_summary, "populate log with the shortlog"),
                OPT_BOOLEAN(0, "summary", &merge_summary, "alias for --log"),
-               OPT_STRING('F', "file",   &inpath, "file", "file to read from"),
+               OPT_FILENAME('F', "file", &inpath, "file to read from"),
                OPT_END()
        };
 
@@ -360,7 +360,8 @@ int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix)
        int ret;
 
        git_config(fmt_merge_msg_config, NULL);
-       argc = parse_options(argc, argv, options, fmt_merge_msg_usage, 0);
+       argc = parse_options(argc, argv, prefix, options, fmt_merge_msg_usage,
+                            0);
        if (argc > 0)
                usage_with_options(fmt_merge_msg_usage, options);
 
index d091e04af9549b70a1e15a4b845383056e71932e..784733b25d21f292c6ac895ba34d0a7b88b3073f 100644 (file)
@@ -905,7 +905,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
                OPT_END(),
        };
 
-       parse_options(argc, argv, opts, for_each_ref_usage, 0);
+       parse_options(argc, argv, prefix, opts, for_each_ref_usage, 0);
        if (maxcount < 0) {
                error("invalid --count argument: `%d'", maxcount);
                usage_with_options(for_each_ref_usage, opts);
index 6436bc224840f11af2f7fa26c61b62c25d78d865..7da706cac3bef05f03c09955d41b4e5077558d4f 100644 (file)
@@ -590,7 +590,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
 
        errors_found = 0;
 
-       argc = parse_options(argc, argv, fsck_opts, fsck_usage, 0);
+       argc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0);
        if (write_lost_and_found) {
                check_full = 1;
                include_reflogs = 0;
index fc556ed7f3fb68734fd783e5b38e6b050bed9c5b..7d3e9cc7a04e0aa3eb378cb54b7b71fe17981c95 100644 (file)
@@ -194,7 +194,8 @@ int cmd_gc(int argc, const char **argv, const char *prefix)
        if (pack_refs < 0)
                pack_refs = !is_bare_repository();
 
-       argc = parse_options(argc, argv, builtin_gc_options, builtin_gc_usage, 0);
+       argc = parse_options(argc, argv, prefix, builtin_gc_options,
+                            builtin_gc_usage, 0);
        if (argc > 0)
                usage_with_options(builtin_gc_usage, builtin_gc_options);
 
index 5308b346e69a50d7695b26f3b8e00bfdf71e1dd2..73fc922c4995369c0ca86c01200e2a0ea39161ab 100644 (file)
@@ -765,7 +765,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
         * unrecognized non option is the beginning of the refs list
         * that continues up to the -- (if exists), and then paths.
         */
-       argc = parse_options(argc, argv, options, grep_usage,
+       argc = parse_options(argc, argv, prefix, options, grep_usage,
                             PARSE_OPT_KEEP_DASHDASH |
                             PARSE_OPT_STOP_AT_NON_OPTION |
                             PARSE_OPT_NO_INTERNAL_HELP);
index 67dda3e6e63c9130a6f1e1c94cb35e519d765a95..6e53b23833062249485124b827da348a8be206b0 100644 (file)
@@ -80,10 +80,9 @@ static int check_emacsclient_version(void)
        ec_process.argv = argv_ec;
        ec_process.err = -1;
        ec_process.stdout_to_stderr = 1;
-       if (start_command(&ec_process)) {
-               fprintf(stderr, "Failed to start emacsclient.\n");
-               return -1;
-       }
+       if (start_command(&ec_process))
+               return error("Failed to start emacsclient.");
+
        strbuf_read(&buffer, ec_process.err, 20);
        close(ec_process.err);
 
@@ -94,20 +93,17 @@ static int check_emacsclient_version(void)
        finish_command(&ec_process);
 
        if (prefixcmp(buffer.buf, "emacsclient")) {
-               fprintf(stderr, "Failed to parse emacsclient version.\n");
                strbuf_release(&buffer);
-               return -1;
+               return error("Failed to parse emacsclient version.");
        }
 
        strbuf_remove(&buffer, 0, strlen("emacsclient"));
        version = atoi(buffer.buf);
 
        if (version < 22) {
-               fprintf(stderr,
-                       "emacsclient version '%d' too old (< 22).\n",
-                       version);
                strbuf_release(&buffer);
-               return -1;
+               return error("emacsclient version '%d' too old (< 22).",
+                       version);
        }
 
        strbuf_release(&buffer);
@@ -423,7 +419,7 @@ int cmd_help(int argc, const char **argv, const char *prefix)
        setup_git_directory_gently(&nongit);
        git_config(git_help_config, NULL);
 
-       argc = parse_options(argc, argv, builtin_help_options,
+       argc = parse_options(argc, argv, prefix, builtin_help_options,
                        builtin_help_usage, 0);
 
        if (show_all) {
index f10cfebdbbabac67dea41639289e7ad968d5bbe3..0d34050556855d6bab8b4c4121e833cc326324df 100644 (file)
@@ -18,6 +18,7 @@
 #include "shortlog.h"
 #include "remote.h"
 #include "string-list.h"
+#include "parse-options.h"
 
 /* Set a default date-time format for git log ("log.date" config variable) */
 static const char *default_date_mode = NULL;
@@ -619,7 +620,7 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
        struct shortlog log;
        struct strbuf sb = STRBUF_INIT;
        int i;
-       const char *encoding = "utf-8";
+       const char *encoding = "UTF-8";
        struct diff_options opts;
        int need_8bit_cte = 0;
        struct commit *commit = NULL;
@@ -740,27 +741,179 @@ static const char *set_outdir(const char *prefix, const char *output_directory)
                                       output_directory));
 }
 
+static const char * const builtin_format_patch_usage[] = {
+       "git format-patch [options] [<since> | <revision range>]",
+       NULL
+};
+
+static int keep_subject = 0;
+
+static int keep_callback(const struct option *opt, const char *arg, int unset)
+{
+       ((struct rev_info *)opt->value)->total = -1;
+       keep_subject = 1;
+       return 0;
+}
+
+static int subject_prefix = 0;
+
+static int subject_prefix_callback(const struct option *opt, const char *arg,
+                           int unset)
+{
+       subject_prefix = 1;
+       ((struct rev_info *)opt->value)->subject_prefix = arg;
+       return 0;
+}
+
+static int numbered_cmdline_opt = 0;
+
+static int numbered_callback(const struct option *opt, const char *arg,
+                            int unset)
+{
+       *(int *)opt->value = numbered_cmdline_opt = unset ? 0 : 1;
+       if (unset)
+               auto_number =  0;
+       return 0;
+}
+
+static int no_numbered_callback(const struct option *opt, const char *arg,
+                               int unset)
+{
+       return numbered_callback(opt, arg, 1);
+}
+
+static int output_directory_callback(const struct option *opt, const char *arg,
+                             int unset)
+{
+       const char **dir = (const char **)opt->value;
+       if (*dir)
+               die("Two output directories?");
+       *dir = arg;
+       return 0;
+}
+
+static int thread_callback(const struct option *opt, const char *arg, int unset)
+{
+       int *thread = (int *)opt->value;
+       if (unset)
+               *thread = 0;
+       else if (!arg || !strcmp(arg, "shallow"))
+               *thread = THREAD_SHALLOW;
+       else if (!strcmp(arg, "deep"))
+               *thread = THREAD_DEEP;
+       else
+               return 1;
+       return 0;
+}
+
+static int attach_callback(const struct option *opt, const char *arg, int unset)
+{
+       struct rev_info *rev = (struct rev_info *)opt->value;
+       if (unset)
+               rev->mime_boundary = NULL;
+       else if (arg)
+               rev->mime_boundary = arg;
+       else
+               rev->mime_boundary = git_version_string;
+       rev->no_inline = unset ? 0 : 1;
+       return 0;
+}
+
+static int inline_callback(const struct option *opt, const char *arg, int unset)
+{
+       struct rev_info *rev = (struct rev_info *)opt->value;
+       if (unset)
+               rev->mime_boundary = NULL;
+       else if (arg)
+               rev->mime_boundary = arg;
+       else
+               rev->mime_boundary = git_version_string;
+       rev->no_inline = 0;
+       return 0;
+}
+
+static int header_callback(const struct option *opt, const char *arg, int unset)
+{
+       add_header(arg);
+       return 0;
+}
+
+static int cc_callback(const struct option *opt, const char *arg, int unset)
+{
+       ALLOC_GROW(extra_cc, extra_cc_nr + 1, extra_cc_alloc);
+       extra_cc[extra_cc_nr++] = xstrdup(arg);
+       return 0;
+}
+
 int cmd_format_patch(int argc, const char **argv, const char *prefix)
 {
        struct commit *commit;
        struct commit **list = NULL;
        struct rev_info rev;
-       int nr = 0, total, i, j;
+       int nr = 0, total, i;
        int use_stdout = 0;
        int start_number = -1;
-       int keep_subject = 0;
        int numbered_files = 0;         /* _just_ numbers */
-       int subject_prefix = 0;
        int ignore_if_in_upstream = 0;
        int cover_letter = 0;
        int boundary_count = 0;
        int no_binary_diff = 0;
-       int numbered_cmdline_opt = 0;
        struct commit *origin = NULL, *head = NULL;
        const char *in_reply_to = NULL;
        struct patch_ids ids;
        char *add_signoff = NULL;
        struct strbuf buf = STRBUF_INIT;
+       const struct option builtin_format_patch_options[] = {
+               { OPTION_CALLBACK, 'n', "numbered", &numbered, NULL,
+                           "use [PATCH n/m] even with a single patch",
+                           PARSE_OPT_NOARG, numbered_callback },
+               { OPTION_CALLBACK, 'N', "no-numbered", &numbered, NULL,
+                           "use [PATCH] even with multiple patches",
+                           PARSE_OPT_NOARG, no_numbered_callback },
+               OPT_BOOLEAN('s', "signoff", &do_signoff, "add Signed-off-by:"),
+               OPT_BOOLEAN(0, "stdout", &use_stdout,
+                           "print patches to standard out"),
+               OPT_BOOLEAN(0, "cover-letter", &cover_letter,
+                           "generate a cover letter"),
+               OPT_BOOLEAN(0, "numbered-files", &numbered_files,
+                           "use simple number sequence for output file names"),
+               OPT_STRING(0, "suffix", &fmt_patch_suffix, "sfx",
+                           "use <sfx> instead of '.patch'"),
+               OPT_INTEGER(0, "start-number", &start_number,
+                           "start numbering patches at <n> instead of 1"),
+               { OPTION_CALLBACK, 0, "subject-prefix", &rev, "prefix",
+                           "Use [<prefix>] instead of [PATCH]",
+                           PARSE_OPT_NONEG, subject_prefix_callback },
+               { OPTION_CALLBACK, 'o', "output-directory", &output_directory,
+                           "dir", "store resulting files in <dir>",
+                           PARSE_OPT_NONEG, output_directory_callback },
+               { OPTION_CALLBACK, 'k', "keep-subject", &rev, NULL,
+                           "don't strip/add [PATCH]",
+                           PARSE_OPT_NOARG | PARSE_OPT_NONEG, keep_callback },
+               OPT_BOOLEAN(0, "no-binary", &no_binary_diff,
+                           "don't output binary diffs"),
+               OPT_BOOLEAN(0, "ignore-if-in-upstream", &ignore_if_in_upstream,
+                           "don't include a patch matching a commit upstream"),
+               OPT_GROUP("Messaging"),
+               { OPTION_CALLBACK, 0, "add-header", NULL, "header",
+                           "add email header", PARSE_OPT_NONEG,
+                           header_callback },
+               { OPTION_CALLBACK, 0, "cc", NULL, "email", "add Cc: header",
+                           PARSE_OPT_NONEG, cc_callback },
+               OPT_STRING(0, "in-reply-to", &in_reply_to, "message-id",
+                           "make first mail a reply to <message-id>"),
+               { OPTION_CALLBACK, 0, "attach", &rev, "boundary",
+                           "attach the patch", PARSE_OPT_OPTARG,
+                           attach_callback },
+               { OPTION_CALLBACK, 0, "inline", &rev, "boundary",
+                           "inline the patch",
+                           PARSE_OPT_OPTARG | PARSE_OPT_NONEG,
+                           inline_callback },
+               { OPTION_CALLBACK, 0, "thread", &thread, "style",
+                           "enable message threading, styles: shallow, deep",
+                           PARSE_OPT_OPTARG, thread_callback },
+               OPT_END()
+       };
 
        git_config(git_format_config, NULL);
        init_revisions(&rev, prefix);
@@ -783,102 +936,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
         * like "git format-patch -o a123 HEAD^.." may fail; a123 is
         * possibly a valid SHA1.
         */
-       for (i = 1, j = 1; i < argc; i++) {
-               if (!strcmp(argv[i], "--stdout"))
-                       use_stdout = 1;
-               else if (!strcmp(argv[i], "-n") ||
-                               !strcmp(argv[i], "--numbered")) {
-                       numbered = 1;
-                       numbered_cmdline_opt = 1;
-               }
-               else if (!strcmp(argv[i], "-N") ||
-                               !strcmp(argv[i], "--no-numbered")) {
-                       numbered = 0;
-                       auto_number = 0;
-               }
-               else if (!prefixcmp(argv[i], "--start-number="))
-                       start_number = strtol(argv[i] + 15, NULL, 10);
-               else if (!strcmp(argv[i], "--numbered-files"))
-                       numbered_files = 1;
-               else if (!strcmp(argv[i], "--start-number")) {
-                       i++;
-                       if (i == argc)
-                               die("Need a number for --start-number");
-                       start_number = strtol(argv[i], NULL, 10);
-               }
-               else if (!prefixcmp(argv[i], "--cc=")) {
-                       ALLOC_GROW(extra_cc, extra_cc_nr + 1, extra_cc_alloc);
-                       extra_cc[extra_cc_nr++] = xstrdup(argv[i] + 5);
-               }
-               else if (!strcmp(argv[i], "-k") ||
-                               !strcmp(argv[i], "--keep-subject")) {
-                       keep_subject = 1;
-                       rev.total = -1;
-               }
-               else if (!strcmp(argv[i], "--output-directory") ||
-                        !strcmp(argv[i], "-o")) {
-                       i++;
-                       if (argc <= i)
-                               die("Which directory?");
-                       if (output_directory)
-                               die("Two output directories?");
-                       output_directory = argv[i];
-               }
-               else if (!strcmp(argv[i], "--signoff") ||
-                        !strcmp(argv[i], "-s")) {
-                       do_signoff = 1;
-               }
-               else if (!strcmp(argv[i], "--attach")) {
-                       rev.mime_boundary = git_version_string;
-                       rev.no_inline = 1;
-               }
-               else if (!prefixcmp(argv[i], "--attach=")) {
-                       rev.mime_boundary = argv[i] + 9;
-                       rev.no_inline = 1;
-               }
-               else if (!strcmp(argv[i], "--no-attach")) {
-                       rev.mime_boundary = NULL;
-                       rev.no_inline = 0;
-               }
-               else if (!strcmp(argv[i], "--inline")) {
-                       rev.mime_boundary = git_version_string;
-                       rev.no_inline = 0;
-               }
-               else if (!prefixcmp(argv[i], "--inline=")) {
-                       rev.mime_boundary = argv[i] + 9;
-                       rev.no_inline = 0;
-               }
-               else if (!strcmp(argv[i], "--ignore-if-in-upstream"))
-                       ignore_if_in_upstream = 1;
-               else if (!strcmp(argv[i], "--thread")
-                       || !strcmp(argv[i], "--thread=shallow"))
-                       thread = THREAD_SHALLOW;
-               else if (!strcmp(argv[i], "--thread=deep"))
-                       thread = THREAD_DEEP;
-               else if (!strcmp(argv[i], "--no-thread"))
-                       thread = 0;
-               else if (!prefixcmp(argv[i], "--in-reply-to="))
-                       in_reply_to = argv[i] + 14;
-               else if (!strcmp(argv[i], "--in-reply-to")) {
-                       i++;
-                       if (i == argc)
-                               die("Need a Message-Id for --in-reply-to");
-                       in_reply_to = argv[i];
-               } else if (!prefixcmp(argv[i], "--subject-prefix=")) {
-                       subject_prefix = 1;
-                       rev.subject_prefix = argv[i] + 17;
-               } else if (!prefixcmp(argv[i], "--suffix="))
-                       fmt_patch_suffix = argv[i] + 9;
-               else if (!strcmp(argv[i], "--cover-letter"))
-                       cover_letter = 1;
-               else if (!strcmp(argv[i], "--no-binary"))
-                       no_binary_diff = 1;
-               else if (!prefixcmp(argv[i], "--add-header="))
-                       add_header(argv[i] + 13);
-               else
-                       argv[j++] = argv[i];
-       }
-       argc = j;
+       argc = parse_options(argc, argv, prefix, builtin_format_patch_options,
+                            builtin_format_patch_usage,
+                            PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN);
 
        if (do_signoff) {
                const char *committer;
index 3d59b0e140ca199997704ffcf59fbc2138345168..2312866605c4140ac4e5a9f5bb963ca5ab5c6da3 100644 (file)
@@ -486,7 +486,7 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)
                prefix_offset = strlen(prefix);
        git_config(git_default_config, NULL);
 
-       argc = parse_options(argc, argv, builtin_ls_files_options,
+       argc = parse_options(argc, argv, prefix, builtin_ls_files_options,
                        ls_files_usage, 0);
        if (show_tag || show_valid_bit) {
                tag_cached = "H ";
index 1eeeb4de6d0d54e3fd753b7f057351094e10a24e..92637ac0bae82d0b88e267b572a51a75299cda5c 100644 (file)
@@ -193,8 +193,7 @@ static void handle_content_type(struct strbuf *line)
                *content_top = boundary;
                boundary = NULL;
        }
-       if (slurp_attr(line->buf, "charset=", &charset))
-               strbuf_tolower(&charset);
+       slurp_attr(line->buf, "charset=", &charset);
 
        if (boundary) {
                strbuf_release(boundary);
@@ -481,7 +480,7 @@ static const char *guess_charset(const struct strbuf *line, const char *target_c
                if (is_utf8(line->buf))
                        return NULL;
        }
-       return "latin1";
+       return "ISO8859-1";
 }
 
 static void convert_to_utf8(struct strbuf *line, const char *charset)
@@ -494,7 +493,7 @@ static void convert_to_utf8(struct strbuf *line, const char *charset)
                        return;
        }
 
-       if (!strcmp(metainfo_charset, charset))
+       if (!strcasecmp(metainfo_charset, charset))
                return;
        out = reencode_string(line->buf, metainfo_charset, charset);
        if (!out)
@@ -550,7 +549,6 @@ static int decode_header_bq(struct strbuf *it)
                if (cp + 3 - it->buf > it->len)
                        goto decode_header_bq_out;
                strbuf_add(&charset_q, ep, cp - ep);
-               strbuf_tolower(&charset_q);
 
                encoding = cp[1];
                if (!encoding || cp[2] != '?')
@@ -944,7 +942,7 @@ int cmd_mailinfo(int argc, const char **argv, const char *prefix)
         */
        git_config(git_default_config, NULL);
 
-       def_charset = (git_commit_encoding ? git_commit_encoding : "utf-8");
+       def_charset = (git_commit_encoding ? git_commit_encoding : "UTF-8");
        metainfo_charset = def_charset;
 
        while (1 < argc && argv[1][0] == '-') {
index 03fc1c211453f1ed09ee2c6b71d438b0bfbf474f..a6ec2f7ab76db27afbb63aacf3bba60b4e73b3f6 100644 (file)
@@ -53,7 +53,7 @@ int cmd_merge_base(int argc, const char **argv, const char *prefix)
        };
 
        git_config(git_default_config, NULL);
-       argc = parse_options(argc, argv, options, merge_base_usage, 0);
+       argc = parse_options(argc, argv, prefix, options, merge_base_usage, 0);
        if (argc < 2)
                usage_with_options(merge_base_usage, options);
        rev = xmalloc(argc * sizeof(*rev));
index 96edb97a8327ba64cccf64bfa341e94d9f903e94..afd2ea7a732460c431328dbd4c0141a49d638244 100644 (file)
@@ -48,7 +48,7 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
                        merge_style = git_xmerge_style;
        }
 
-       argc = parse_options(argc, argv, options, merge_file_usage, 0);
+       argc = parse_options(argc, argv, prefix, options, merge_file_usage, 0);
        if (argc != 3)
                usage_with_options(merge_file_usage, options);
        if (quiet) {
index 0b58e5eda1f38c1560cc9dcf69be37fa5fc9886f..8d101eff0b433bd5afa6cf1e027e50447fdf5370 100644 (file)
@@ -462,7 +462,7 @@ static int git_merge_config(const char *k, const char *v, void *cb)
                argv = xrealloc(argv, sizeof(*argv) * (argc + 2));
                memmove(argv + 1, argv, sizeof(*argv) * (argc + 1));
                argc++;
-               parse_options(argc, argv, builtin_merge_options,
+               parse_options(argc, argv, NULL, builtin_merge_options,
                              builtin_merge_usage, 0);
                free(buf);
        }
@@ -855,7 +855,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
        if (diff_use_color_default == -1)
                diff_use_color_default = git_use_color_default;
 
-       argc = parse_options(argc, argv, builtin_merge_options,
+       argc = parse_options(argc, argv, prefix, builtin_merge_options,
                        builtin_merge_usage, 0);
        if (verbosity < 0)
                show_diffstat = 0;
diff --git a/builtin-mktree.c b/builtin-mktree.c
new file mode 100644 (file)
index 0000000..098395f
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * GIT - the stupid content tracker
+ *
+ * Copyright (c) Junio C Hamano, 2006, 2009
+ */
+#include "builtin.h"
+#include "quote.h"
+#include "tree.h"
+#include "parse-options.h"
+
+static struct treeent {
+       unsigned mode;
+       unsigned char sha1[20];
+       int len;
+       char name[FLEX_ARRAY];
+} **entries;
+static int alloc, used;
+
+static void append_to_tree(unsigned mode, unsigned char *sha1, char *path)
+{
+       struct treeent *ent;
+       int len = strlen(path);
+       if (strchr(path, '/'))
+               die("path %s contains slash", path);
+
+       if (alloc <= used) {
+               alloc = alloc_nr(used);
+               entries = xrealloc(entries, sizeof(*entries) * alloc);
+       }
+       ent = entries[used++] = xmalloc(sizeof(**entries) + len + 1);
+       ent->mode = mode;
+       ent->len = len;
+       hashcpy(ent->sha1, sha1);
+       memcpy(ent->name, path, len+1);
+}
+
+static int ent_compare(const void *a_, const void *b_)
+{
+       struct treeent *a = *(struct treeent **)a_;
+       struct treeent *b = *(struct treeent **)b_;
+       return base_name_compare(a->name, a->len, a->mode,
+                                b->name, b->len, b->mode);
+}
+
+static void write_tree(unsigned char *sha1)
+{
+       struct strbuf buf;
+       size_t size;
+       int i;
+
+       qsort(entries, used, sizeof(*entries), ent_compare);
+       for (size = i = 0; i < used; i++)
+               size += 32 + entries[i]->len;
+
+       strbuf_init(&buf, size);
+       for (i = 0; i < used; i++) {
+               struct treeent *ent = entries[i];
+               strbuf_addf(&buf, "%o %s%c", ent->mode, ent->name, '\0');
+               strbuf_add(&buf, ent->sha1, 20);
+       }
+
+       write_sha1_file(buf.buf, buf.len, tree_type, sha1);
+}
+
+static const char *mktree_usage[] = {
+       "git mktree [-z] [--missing] [--batch]",
+       NULL
+};
+
+static void mktree_line(char *buf, size_t len, int line_termination, int allow_missing)
+{
+       char *ptr, *ntr;
+       unsigned mode;
+       enum object_type mode_type; /* object type derived from mode */
+       enum object_type obj_type; /* object type derived from sha */
+       char *path;
+       unsigned char sha1[20];
+
+       ptr = buf;
+       /*
+        * Read non-recursive ls-tree output format:
+        *     mode SP type SP sha1 TAB name
+        */
+       mode = strtoul(ptr, &ntr, 8);
+       if (ptr == ntr || !ntr || *ntr != ' ')
+               die("input format error: %s", buf);
+       ptr = ntr + 1; /* type */
+       ntr = strchr(ptr, ' ');
+       if (!ntr || buf + len <= ntr + 40 ||
+           ntr[41] != '\t' ||
+           get_sha1_hex(ntr + 1, sha1))
+               die("input format error: %s", buf);
+
+       /* It is perfectly normal if we do not have a commit from a submodule */
+       if (S_ISGITLINK(mode))
+               allow_missing = 1;
+
+
+       *ntr++ = 0; /* now at the beginning of SHA1 */
+
+       path = ntr + 41;  /* at the beginning of name */
+       if (line_termination && path[0] == '"') {
+               struct strbuf p_uq = STRBUF_INIT;
+               if (unquote_c_style(&p_uq, path, NULL))
+                       die("invalid quoting");
+               path = strbuf_detach(&p_uq, NULL);
+       }
+
+       /*
+        * Object type is redundantly derivable three ways.
+        * These should all agree.
+        */
+       mode_type = object_type(mode);
+       if (mode_type != type_from_string(ptr)) {
+               die("entry '%s' object type (%s) doesn't match mode type (%s)",
+                       path, ptr, typename(mode_type));
+       }
+
+       /* Check the type of object identified by sha1 */
+       obj_type = sha1_object_info(sha1, NULL);
+       if (obj_type < 0) {
+               if (allow_missing) {
+                       ; /* no problem - missing objects are presumed to be of the right type */
+               } else {
+                       die("entry '%s' object %s is unavailable", path, sha1_to_hex(sha1));
+               }
+       } else {
+               if (obj_type != mode_type) {
+                       /*
+                        * The object exists but is of the wrong type.
+                        * This is a problem regardless of allow_missing
+                        * because the new tree entry will never be correct.
+                        */
+                       die("entry '%s' object %s is a %s but specified type was (%s)",
+                               path, sha1_to_hex(sha1), typename(obj_type), typename(mode_type));
+               }
+       }
+
+       append_to_tree(mode, sha1, path);
+}
+
+int cmd_mktree(int ac, const char **av, const char *prefix)
+{
+       struct strbuf sb = STRBUF_INIT;
+       unsigned char sha1[20];
+       int line_termination = '\n';
+       int allow_missing = 0;
+       int is_batch_mode = 0;
+       int got_eof = 0;
+
+       const struct option option[] = {
+               OPT_SET_INT('z', NULL, &line_termination, "input is NUL terminated", '\0'),
+               OPT_SET_INT( 0 , "missing", &allow_missing, "allow missing objects", 1),
+               OPT_SET_INT( 0 , "batch", &is_batch_mode, "allow creation of more than one tree", 1),
+               OPT_END()
+       };
+
+       ac = parse_options(ac, av, prefix, option, mktree_usage, 0);
+
+       while (!got_eof) {
+               while (1) {
+                       if (strbuf_getline(&sb, stdin, line_termination) == EOF) {
+                               got_eof = 1;
+                               break;
+                       }
+                       if (sb.buf[0] == '\0') {
+                               /* empty lines denote tree boundaries in batch mode */
+                               if (is_batch_mode)
+                                       break;
+                               die("input format error: (blank line only valid in batch mode)");
+                       }
+                       mktree_line(sb.buf, sb.len, line_termination, allow_missing);
+               }
+               if (is_batch_mode && got_eof && used < 1) {
+                       /*
+                        * Execution gets here if the last tree entry is terminated with a
+                        * new-line.  The final new-line has been made optional to be
+                        * consistent with the original non-batch behaviour of mktree.
+                        */
+                       ; /* skip creating an empty tree */
+               } else {
+                       write_tree(sha1);
+                       puts(sha1_to_hex(sha1));
+                       fflush(stdout);
+               }
+               used=0; /* reset tree entry buffer for re-use in batch mode */
+       }
+       strbuf_release(&sb);
+       exit(0);
+}
index 01270fefdfb04ed27379b1ca761a811b929ce887..8b81d4b51d78bb2aa49430102ab585afce9cccdf 100644 (file)
@@ -72,7 +72,8 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
        if (read_cache() < 0)
                die("index file corrupt");
 
-       argc = parse_options(argc, argv, builtin_mv_options, builtin_mv_usage, 0);
+       argc = parse_options(argc, argv, prefix, builtin_mv_options,
+                            builtin_mv_usage, 0);
        if (--argc < 1)
                usage_with_options(builtin_mv_usage, builtin_mv_options);
 
index 08c8aabf9428447abad7def693d7b22c5330e180..06a38ac8c10126085e6477c205d450da089faae2 100644 (file)
@@ -238,7 +238,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
        };
 
        git_config(git_default_config, NULL);
-       argc = parse_options(argc, argv, opts, name_rev_usage, 0);
+       argc = parse_options(argc, argv, prefix, opts, name_rev_usage, 0);
        if (!!all + !!transform_stdin + !!argc > 1) {
                error("Specify either a list, or --all, not both!");
                usage_with_options(name_rev_usage, opts);
index 34246df4ec946273d9f42e6f0848b02d8510beea..091860b2e370561f0811399b0d307e732e9eaac3 100644 (file)
@@ -15,7 +15,7 @@ int cmd_pack_refs(int argc, const char **argv, const char *prefix)
                OPT_BIT(0, "prune", &flags, "prune loose refs (default)", PACK_REFS_PRUNE),
                OPT_END(),
        };
-       if (parse_options(argc, argv, opts, pack_refs_usage, 0))
+       if (parse_options(argc, argv, prefix, opts, pack_refs_usage, 0))
                usage_with_options(pack_refs_usage, opts);
        return pack_refs(flags);
 }
index 145ba83651e9c8560e20d6ab449ce64783bc65f5..0ed9cce4a23aa575c1e131a808cedd4f8bb542f4 100644 (file)
@@ -142,7 +142,7 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
        save_commit_buffer = 0;
        init_revisions(&revs, prefix);
 
-       argc = parse_options(argc, argv, options, prune_usage, 0);
+       argc = parse_options(argc, argv, prefix, options, prune_usage, 0);
        while (argc--) {
                unsigned char sha1[20];
                const char *name = *argv++;
index 2eabcd3bdfb3f5d5705125a8f74d21d4ab1deafc..c869974013b5c1bb563d4f9b306820362545c9ea 100644 (file)
@@ -198,7 +198,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
                OPT_END()
        };
 
-       argc = parse_options(argc, argv, options, push_usage, 0);
+       argc = parse_options(argc, argv, prefix, options, push_usage, 0);
 
        if (tags)
                add_refspec("refs/tags/*");
index 0b08da9b595432efa231eb59d88ecd2b422eb56a..33d345dc3993d01d3cd5ae1cc0aa5ae8eda83edb 100644 (file)
@@ -192,7 +192,6 @@ static int run_receive_hook(const char *hook_name)
 static int run_update_hook(struct command *cmd)
 {
        static const char update_hook[] = "hooks/update";
-       struct child_process proc;
        const char *argv[5];
 
        if (access(update_hook, X_OK) < 0)
@@ -204,12 +203,9 @@ static int run_update_hook(struct command *cmd)
        argv[3] = sha1_to_hex(cmd->new_sha1);
        argv[4] = NULL;
 
-       memset(&proc, 0, sizeof(proc));
-       proc.argv = argv;
-       proc.no_stdin = 1;
-       proc.stdout_to_stderr = 1;
-
-       return hook_status(run_command(&proc), update_hook);
+       return hook_status(run_command_v_opt(argv, RUN_COMMAND_NO_STDIN |
+                                       RUN_COMMAND_STDOUT_TO_STDERR),
+                       update_hook);
 }
 
 static int is_ref_checked_out(const char *ref)
index 71abf68404f5b260ba96208717d89e50e778dd36..dfc0b9e706507fc557cc2b593632fda4683387bc 100644 (file)
@@ -79,7 +79,8 @@ static int add(int argc, const char **argv)
                OPT_END()
        };
 
-       argc = parse_options(argc, argv, options, builtin_remote_usage, 0);
+       argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
+                            0);
 
        if (argc < 2)
                usage_with_options(builtin_remote_usage, options);
@@ -294,17 +295,14 @@ static int get_push_ref_states(const struct ref *remote_refs,
        struct ref_states *states)
 {
        struct remote *remote = states->remote;
-       struct ref *ref, *local_refs, *push_map, **push_tail;
+       struct ref *ref, *local_refs, *push_map;
        if (remote->mirror)
                return 0;
 
        local_refs = get_local_heads();
-       ref = push_map = copy_ref_list(remote_refs);
-       while (ref->next)
-               ref = ref->next;
-       push_tail = &ref->next;
+       push_map = copy_ref_list(remote_refs);
 
-       match_refs(local_refs, push_map, &push_tail, remote->push_refspec_nr,
+       match_refs(local_refs, &push_map, remote->push_refspec_nr,
                   remote->push_refspec, MATCH_REFS_NONE);
 
        states->push.strdup_strings = 1;
@@ -986,7 +984,8 @@ static int show(int argc, const char **argv)
        struct string_list info_list = { NULL, 0, 0, 0 };
        struct show_info info;
 
-       argc = parse_options(argc, argv, options, builtin_remote_usage, 0);
+       argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
+                            0);
 
        if (argc < 1)
                return show_all();
@@ -1003,9 +1002,12 @@ static int show(int argc, const char **argv)
 
                get_remote_ref_states(*argv, &states, query_flag);
 
-               printf("* remote %s\n  URL: %s\n", *argv,
-                       states.remote->url_nr > 0 ?
-                               states.remote->url[0] : "(no URL)");
+               printf("* remote %s\n", *argv);
+               if (states.remote->url_nr) {
+                       for (i=0; i < states.remote->url_nr; i++)
+                               printf("  URL: %s\n", states.remote->url[i]);
+               } else
+                       printf("  URL: %s\n", "(no URL)");
                if (no_query)
                        printf("  HEAD branch: (not queried)\n");
                else if (!states.heads.nr)
@@ -1076,7 +1078,8 @@ static int set_head(int argc, const char **argv)
                            "delete refs/remotes/<name>/HEAD"),
                OPT_END()
        };
-       argc = parse_options(argc, argv, options, builtin_remote_usage, 0);
+       argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
+                            0);
        if (argc)
                strbuf_addf(&buf, "refs/remotes/%s/HEAD", argv[0]);
 
@@ -1130,7 +1133,8 @@ static int prune(int argc, const char **argv)
                OPT_END()
        };
 
-       argc = parse_options(argc, argv, options, builtin_remote_usage, 0);
+       argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
+                            0);
 
        if (argc < 1)
                usage_with_options(builtin_remote_usage, options);
@@ -1220,7 +1224,7 @@ static int update(int argc, const char **argv)
                OPT_END()
        };
 
-       argc = parse_options(argc, argv, options, builtin_remote_usage,
+       argc = parse_options(argc, argv, NULL, options, builtin_remote_usage,
                             PARSE_OPT_KEEP_ARGV0);
        if (argc < 2) {
                argc = 2;
@@ -1306,7 +1310,7 @@ int cmd_remote(int argc, const char **argv, const char *prefix)
        };
        int result;
 
-       argc = parse_options(argc, argv, options, builtin_remote_usage,
+       argc = parse_options(argc, argv, prefix, options, builtin_remote_usage,
                PARSE_OPT_STOP_AT_NON_OPTION);
 
        if (argc < 1)
index 7e7ebabaa865ebd749502774638efe7b6d26bec1..5fa1789d0c2b90ef9ee83d091b67292f2ff0db26 100644 (file)
@@ -203,7 +203,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 
        git_config(git_default_config, NULL);
 
-       argc = parse_options(argc, argv, options, git_reset_usage,
+       argc = parse_options(argc, argv, prefix, options, git_reset_usage,
                                                PARSE_OPT_KEEP_DASHDASH);
        reflog_action = args_to_str(argv);
        setenv("GIT_REFLOG_ACTION", reflog_action, 0);
index c5b3d6e31bc899fe511f760de33870f20dc9766f..112d622cda6f74f9752627d9adf3a1cdb04851c3 100644 (file)
@@ -318,7 +318,7 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
        int onb = 0, osz = 0, unb = 0, usz = 0;
 
        strbuf_addstr(&parsed, "set --");
-       argc = parse_options(argc, argv, parseopt_opts, parseopt_usage,
+       argc = parse_options(argc, argv, prefix, parseopt_opts, parseopt_usage,
                             PARSE_OPT_KEEP_DASHDASH);
        if (argc < 1 || strcmp(argv[0], "--"))
                usage_with_options(parseopt_usage, parseopt_opts);
@@ -393,7 +393,7 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)
        /* put an OPT_END() */
        ALLOC_GROW(opts, onb + 1, osz);
        memset(opts + onb, 0, sizeof(opts[onb]));
-       argc = parse_options(argc, argv, opts, usage,
+       argc = parse_options(argc, argv, prefix, opts, usage,
                             keep_dashdash ? PARSE_OPT_KEEP_DASHDASH : 0);
 
        strbuf_addf(&parsed, " --");
index 3f2614e1bbef009afadefff7d284225533db2a09..c87115af30abd9515599586af860ccd07b96b264 100644 (file)
@@ -60,7 +60,7 @@ static void parse_args(int argc, const char **argv)
                OPT_END(),
        };
 
-       if (parse_options(argc, argv, options, usage_str, 0) != 1)
+       if (parse_options(argc, argv, NULL, options, usage_str, 0) != 1)
                usage_with_options(usage_str, options);
        arg = argv[0];
 
@@ -323,9 +323,9 @@ static int revert_or_cherry_pick(int argc, const char **argv)
 
        encoding = get_encoding(message);
        if (!encoding)
-               encoding = "utf-8";
+               encoding = "UTF-8";
        if (!git_commit_encoding)
-               git_commit_encoding = "utf-8";
+               git_commit_encoding = "UTF-8";
        if ((reencoded_message = reencode_string(message,
                                        git_commit_encoding, encoding)))
                message = reencoded_message;
index 269d60890ac6732f05b835e88bdb60a10bb3d441..0cc491271846214d73d55a4f528c8854e0460c8f 100644 (file)
@@ -157,7 +157,8 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
 
        git_config(git_default_config, NULL);
 
-       argc = parse_options(argc, argv, builtin_rm_options, builtin_rm_usage, 0);
+       argc = parse_options(argc, argv, prefix, builtin_rm_options,
+                            builtin_rm_usage, 0);
        if (!argc)
                usage_with_options(builtin_rm_usage, builtin_rm_options);
 
index be3b0926deeb38f34b75c08bedf29fd80bac9b3c..c375a3dbde0a75af592c8881965f255f66b599d1 100644 (file)
@@ -473,7 +473,7 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
        int fd[2];
        struct child_process *conn;
        struct extra_have_objects extra_have;
-       struct ref *remote_refs, **remote_tail, *local_refs;
+       struct ref *remote_refs, *local_refs;
        int ret;
        int send_all = 0;
        const char *receivepack = "git-receive-pack";
@@ -567,13 +567,8 @@ int cmd_send_pack(int argc, const char **argv, const char *prefix)
                flags |= MATCH_REFS_MIRROR;
 
        /* match them up */
-       remote_tail = &remote_refs;
-       while (*remote_tail)
-               remote_tail = &((*remote_tail)->next);
-       if (match_refs(local_refs, remote_refs, &remote_tail,
-                      nr_refspecs, refspecs, flags)) {
+       if (match_refs(local_refs, &remote_refs, nr_refspecs, refspecs, flags))
                return -1;
-       }
 
        ret = send_pack(&args, fd, conn, remote_refs, &extra_have);
 
index b28091b4455db15e80841f2779ce0686d4f18826..6a3812ee18a2ca1bc251f67582ebaee3675d9af5 100644 (file)
@@ -263,7 +263,7 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix)
        git_config(git_default_config, NULL);
        shortlog_init(&log);
        init_revisions(&rev, prefix);
-       parse_options_start(&ctx, argc, argv, PARSE_OPT_KEEP_DASHDASH |
+       parse_options_start(&ctx, argc, argv, prefix, PARSE_OPT_KEEP_DASHDASH |
                            PARSE_OPT_KEEP_ARGV0);
 
        for (;;) {
index c8e9b3c723cb733e1d6b4cd2036f165f0a088970..01bea3b583b53f4930a1ab17d64b1b714f58099c 100644 (file)
@@ -3,11 +3,13 @@
 #include "refs.h"
 #include "builtin.h"
 #include "color.h"
+#include "parse-options.h"
 
-static const char show_branch_usage[] =
-"git show-branch [--sparse] [--current] [--all] [--remotes] [--topo-order] [--more=count | --list | --independent | --merge-base ] [--topics] [<refs>...] | --reflog[=n[,b]] <branch>";
-static const char show_branch_usage_reflog[] =
-"--reflog is incompatible with --all, --remotes, --independent or --merge-base";
+static const char* show_branch_usage[] = {
+    "git show-branch [--sparse] [--current] [--all] [--remotes] [--topo-order] [--more=count | --list | --independent | --merge-base] [--topics] [--color] [<refs>...]",
+    "--reflog[=n[,b]] [--list] [--color] <branch>",
+    NULL
+};
 
 static int showbranch_use_color = -1;
 static char column_colors[][COLOR_MAXLEN] = {
@@ -601,18 +603,25 @@ static int omit_in_dense(struct commit *commit, struct commit **rev, int n)
        return 0;
 }
 
-static void parse_reflog_param(const char *arg, int *cnt, const char **base)
+static int reflog = 0;
+
+static int parse_reflog_param(const struct option *opt, const char *arg,
+                             int unset)
 {
        char *ep;
-       *cnt = strtoul(arg, &ep, 10);
+       const char **base = (const char **)opt->value;
+       if (!arg)
+               arg = "";
+       reflog = strtoul(arg, &ep, 10);
        if (*ep == ',')
                *base = ep + 1;
        else if (*ep)
-               die("unrecognized reflog param '%s'", arg);
+               return error("unrecognized reflog param '%s'", arg);
        else
                *base = NULL;
-       if (*cnt <= 0)
-               *cnt = DEFAULT_REFLOG;
+       if (reflog <= 0)
+               reflog = DEFAULT_REFLOG;
+       return 0;
 }
 
 int cmd_show_branch(int ac, const char **av, const char *prefix)
@@ -638,8 +647,43 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
        int head_at = -1;
        int topics = 0;
        int dense = 1;
-       int reflog = 0;
        const char *reflog_base = NULL;
+       struct option builtin_show_branch_options[] = {
+               OPT_BOOLEAN('a', "all", &all_heads,
+                           "show remote-tracking and local branches"),
+               OPT_BOOLEAN('r', "remotes", &all_remotes,
+                           "show remote-tracking branches"),
+               OPT_BOOLEAN(0, "color", &showbranch_use_color,
+                           "color '*!+-' corresponding to the branch"),
+               { OPTION_INTEGER, 0, "more", &extra, "n",
+                           "show <n> more commits after the common ancestor",
+                           PARSE_OPT_OPTARG, NULL, (intptr_t)1 },
+               OPT_SET_INT(0, "list", &extra, "synonym to more=-1", -1),
+               OPT_BOOLEAN(0, "no-name", &no_name, "suppress naming strings"),
+               OPT_BOOLEAN(0, "current", &with_current_branch,
+                           "include the current branch"),
+               OPT_BOOLEAN(0, "sha1-name", &sha1_name,
+                           "name commits with their object names"),
+               OPT_BOOLEAN(0, "merge-base", &merge_base,
+                           "act like git merge-base -a"),
+               OPT_BOOLEAN(0, "independent", &independent,
+                           "show refs unreachable from any other ref"),
+               OPT_BOOLEAN(0, "topo-order", &lifo,
+                           "show commits in topological order"),
+               OPT_BOOLEAN(0, "topics", &topics,
+                           "show only commits not on the first branch"),
+               OPT_SET_INT(0, "sparse", &dense,
+                           "show merges reachable from only one tip", 0),
+               OPT_SET_INT(0, "date-order", &lifo,
+                           "show commits where no parent comes before its "
+                           "children", 0),
+               { OPTION_CALLBACK, 'g', "reflog", &reflog_base, "<n>[,<base>]",
+                           "show <n> most recent ref-log entries starting at "
+                           "base",
+                           PARSE_OPT_OPTARG | PARSE_OPT_LITERAL_ARGHELP,
+                           parse_reflog_param },
+               OPT_END()
+       };
 
        git_config(git_show_branch_config, NULL);
 
@@ -652,63 +696,18 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
                av = default_arg - 1; /* ick; we would not address av[0] */
        }
 
-       while (1 < ac && av[1][0] == '-') {
-               const char *arg = av[1];
-               if (!strcmp(arg, "--")) {
-                       ac--; av++;
-                       break;
-               }
-               else if (!strcmp(arg, "--all") || !strcmp(arg, "-a"))
-                       all_heads = all_remotes = 1;
-               else if (!strcmp(arg, "--remotes") || !strcmp(arg, "-r"))
-                       all_remotes = 1;
-               else if (!strcmp(arg, "--more"))
-                       extra = 1;
-               else if (!strcmp(arg, "--list"))
-                       extra = -1;
-               else if (!strcmp(arg, "--no-name"))
-                       no_name = 1;
-               else if (!strcmp(arg, "--current"))
-                       with_current_branch = 1;
-               else if (!strcmp(arg, "--sha1-name"))
-                       sha1_name = 1;
-               else if (!prefixcmp(arg, "--more="))
-                       extra = atoi(arg + 7);
-               else if (!strcmp(arg, "--merge-base"))
-                       merge_base = 1;
-               else if (!strcmp(arg, "--independent"))
-                       independent = 1;
-               else if (!strcmp(arg, "--topo-order"))
-                       lifo = 1;
-               else if (!strcmp(arg, "--topics"))
-                       topics = 1;
-               else if (!strcmp(arg, "--sparse"))
-                       dense = 0;
-               else if (!strcmp(arg, "--date-order"))
-                       lifo = 0;
-               else if (!strcmp(arg, "--reflog") || !strcmp(arg, "-g")) {
-                       reflog = DEFAULT_REFLOG;
-               }
-               else if (!prefixcmp(arg, "--reflog="))
-                       parse_reflog_param(arg + 9, &reflog, &reflog_base);
-               else if (!prefixcmp(arg, "-g="))
-                       parse_reflog_param(arg + 3, &reflog, &reflog_base);
-               else if (!strcmp(arg, "--color"))
-                       showbranch_use_color = 1;
-               else if (!strcmp(arg, "--no-color"))
-                       showbranch_use_color = 0;
-               else
-                       usage(show_branch_usage);
-               ac--; av++;
-       }
-       ac--; av++;
+       ac = parse_options(ac, av, prefix, builtin_show_branch_options,
+                          show_branch_usage, PARSE_OPT_STOP_AT_NON_OPTION);
+       if (all_heads)
+               all_remotes = 1;
 
        if (extra || reflog) {
                /* "listing" mode is incompatible with
                 * independent nor merge-base modes.
                 */
                if (independent || merge_base)
-                       usage(show_branch_usage);
+                       usage_with_options(show_branch_usage,
+                                          builtin_show_branch_options);
                if (reflog && ((0 < extra) || all_heads || all_remotes))
                        /*
                         * Asking for --more in reflog mode does not
@@ -716,7 +715,8 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
                         *
                         * Also --all and --remotes do not make sense either.
                         */
-                       usage(show_branch_usage_reflog);
+                       die("--reflog is incompatible with --all, --remotes, "
+                           "--independent or --merge-base");
        }
 
        /* If nothing is specified, show all branches by default */
index 6ae6bcc0e8d02d9af8a81a7d694c0bfd2c6c0514..ca855a5eb239f4dadccd53369e38db4e78b1d13f 100644 (file)
@@ -36,7 +36,8 @@ int cmd_symbolic_ref(int argc, const char **argv, const char *prefix)
        };
 
        git_config(git_default_config, NULL);
-       argc = parse_options(argc, argv, options, git_symbolic_ref_usage, 0);
+       argc = parse_options(argc, argv, prefix, options,
+                            git_symbolic_ref_usage, 0);
        if (msg &&!*msg)
                die("Refusing to perform update with empty message");
        switch (argc) {
index e54443009420d98dc281285e997b32f2a263b996..dc3db628115cc7b3c62c1d54af37c87ba126a5db 100644 (file)
@@ -387,7 +387,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
                                        "annotated tag, needs a message"),
                OPT_CALLBACK('m', NULL, &msg, "msg",
                             "message for the tag", parse_msg_arg),
-               OPT_STRING('F', NULL, &msgfile, "file", "message in a file"),
+               OPT_FILENAME('F', NULL, &msgfile, "message in a file"),
                OPT_BOOLEAN('s', NULL, &sign, "annotated and GPG-signed tag"),
                OPT_STRING('u', NULL, &keyid, "key-id",
                                        "use another key to sign the tag"),
@@ -405,8 +405,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 
        git_config(git_tag_config, NULL);
 
-       argc = parse_options(argc, argv, options, git_tag_usage, 0);
-       msgfile = parse_options_fix_filename(prefix, msgfile);
+       argc = parse_options(argc, argv, prefix, options, git_tag_usage, 0);
 
        if (keyid) {
                sign = 1;
index 378dc1b7a6bb4d56d301a34a4d44dae2f9a37e44..76ba1d5881b3cddc527bd363dec340c83dde605f 100644 (file)
@@ -23,7 +23,8 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
        };
 
        git_config(git_default_config, NULL);
-       argc = parse_options(argc, argv, options, git_update_ref_usage, 0);
+       argc = parse_options(argc, argv, prefix, options, git_update_ref_usage,
+                            0);
        if (msg && !*msg)
                die("Refusing to perform update with empty message.");
 
index 425ff8e89b361c34b3336cda58794682c66b57f3..20427d2963fa25c1177bd05ab9f8be2890b9f7ba 100644 (file)
--- a/builtin.h
+++ b/builtin.h
@@ -72,6 +72,7 @@ extern int cmd_merge_base(int argc, const char **argv, const char *prefix);
 extern int cmd_merge_ours(int argc, const char **argv, const char *prefix);
 extern int cmd_merge_file(int argc, const char **argv, const char *prefix);
 extern int cmd_merge_recursive(int argc, const char **argv, const char *prefix);
+extern int cmd_mktree(int argc, const char **argv, const char *prefix);
 extern int cmd_mv(int argc, const char **argv, const char *prefix);
 extern int cmd_name_rev(int argc, const char **argv, const char *prefix);
 extern int cmd_pack_objects(int argc, const char **argv, const char *prefix);
diff --git a/cache.h b/cache.h
index b8503ad91c3b13ccaf87a6f596d13918f7ae114b..871c9844e88c8e73aa1bab0e079d0399bef1b11d 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -614,6 +614,8 @@ extern int is_empty_blob_sha1(const unsigned char *sha1);
 
 int git_mkstemp(char *path, size_t n, const char *template);
 
+int git_mkstemps(char *path, size_t n, const char *template, int suffix_len);
+
 /*
  * NOTE NOTE NOTE!!
  *
index aa3b35b6a86891ac9d0628e20a6a46d506bf7700..8f6b703c557599921d890c3b50b66eaa397de548 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -316,6 +316,26 @@ int parse_commit(struct commit *item)
        return ret;
 }
 
+static void unparse_commit_list(struct commit_list *list)
+{
+       for (; list; list = list->next)
+               unparse_commit(list->item);
+}
+
+void unparse_commit(struct commit *item)
+{
+       item->object.flags = 0;
+       item->object.used = 0;
+       if (item->object.parsed) {
+               item->object.parsed = 0;
+               if (item->parents) {
+                       unparse_commit_list(item->parents);
+                       free_commit_list(item->parents);
+                       item->parents = NULL;
+               }
+       }
+}
+
 struct commit_list *commit_list_insert(struct commit *item, struct commit_list **list_p)
 {
        struct commit_list *new_list = xmalloc(sizeof(struct commit_list));
index ba9f63813eba004ae409eba8741266a074161239..f3eaf1d048a3e799eb571fbfe1302c08b3d394a6 100644 (file)
--- a/commit.h
+++ b/commit.h
@@ -40,6 +40,8 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size);
 
 int parse_commit(struct commit *item);
 
+void unparse_commit(struct commit *item);
+
 struct commit_list * commit_list_insert(struct commit *item, struct commit_list **list_p);
 unsigned commit_list_count(const struct commit_list *l);
 struct commit_list * insert_by_date(struct commit *item, struct commit_list **list);
diff --git a/compat/basename.c b/compat/basename.c
new file mode 100644 (file)
index 0000000..d8f8a3c
--- /dev/null
@@ -0,0 +1,15 @@
+#include "../git-compat-util.h"
+
+/* Adapted from libiberty's basename.c.  */
+char *gitbasename (char *path)
+{
+       const char *base;
+       /* Skip over the disk name in MSDOS pathnames. */
+       if (has_dos_drive_prefix(path))
+               path += 2;
+       for (base = path; *path; path++) {
+               if (is_dir_sep(*path))
+                       base = path + 1;
+       }
+       return (char *)base;
+}
diff --git a/compat/mkstemps.c b/compat/mkstemps.c
new file mode 100644 (file)
index 0000000..14179c8
--- /dev/null
@@ -0,0 +1,70 @@
+#include "../git-compat-util.h"
+
+/* Adapted from libiberty's mkstemp.c. */
+
+#undef TMP_MAX
+#define TMP_MAX 16384
+
+int gitmkstemps(char *pattern, int suffix_len)
+{
+       static const char letters[] =
+               "abcdefghijklmnopqrstuvwxyz"
+               "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+               "0123456789";
+       static const int num_letters = 62;
+       uint64_t value;
+       struct timeval tv;
+       char *template;
+       size_t len;
+       int fd, count;
+
+       len = strlen(pattern);
+
+       if (len < 6 + suffix_len) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       if (strncmp(&pattern[len - 6 - suffix_len], "XXXXXX", 6)) {
+               errno = EINVAL;
+               return -1;
+       }
+
+       /*
+        * Replace pattern's XXXXXX characters with randomness.
+        * Try TMP_MAX different filenames.
+        */
+       gettimeofday(&tv, NULL);
+       value = ((size_t)(tv.tv_usec << 16)) ^ tv.tv_sec ^ getpid();
+       template = &pattern[len - 6 - suffix_len];
+       for (count = 0; count < TMP_MAX; ++count) {
+               uint64_t v = value;
+               /* Fill in the random bits. */
+               template[0] = letters[v % num_letters]; v /= num_letters;
+               template[1] = letters[v % num_letters]; v /= num_letters;
+               template[2] = letters[v % num_letters]; v /= num_letters;
+               template[3] = letters[v % num_letters]; v /= num_letters;
+               template[4] = letters[v % num_letters]; v /= num_letters;
+               template[5] = letters[v % num_letters]; v /= num_letters;
+
+               fd = open(pattern, O_CREAT | O_EXCL | O_RDWR, 0600);
+               if (fd > 0)
+                       return fd;
+               /*
+                * Fatal error (EPERM, ENOSPC etc).
+                * It doesn't make sense to loop.
+                */
+               if (errno != EEXIST)
+                       break;
+               /*
+                * This is a random value.  It is only necessary that
+                * the next TMP_MAX values generated by adding 7777 to
+                * VALUE are different with (module 2^32).
+                */
+               value += 7777;
+       }
+       /* We return the null string if we can't find a unique file name.  */
+       pattern[0] = '\0';
+       errno = EINVAL;
+       return -1;
+}
index d0cd1558117bd944f63250f3f09d366d8875e62f..dd6045131880111bb09306cb3e48330a0e5acdac 100644 (file)
@@ -30,6 +30,7 @@ NEEDS_SSL_WITH_CRYPTO=@NEEDS_SSL_WITH_CRYPTO@
 NO_OPENSSL=@NO_OPENSSL@
 NO_CURL=@NO_CURL@
 NO_EXPAT=@NO_EXPAT@
+NO_LIBGEN_H=@NO_LIBGEN_H@
 NEEDS_LIBICONV=@NEEDS_LIBICONV@
 NEEDS_SOCKET=@NEEDS_SOCKET@
 NEEDS_RESOLV=@NEEDS_RESOLV@
@@ -47,6 +48,7 @@ NO_STRTOUMAX=@NO_STRTOUMAX@
 NO_SETENV=@NO_SETENV@
 NO_UNSETENV=@NO_UNSETENV@
 NO_MKDTEMP=@NO_MKDTEMP@
+NO_MKSTEMPS=@NO_MKSTEMPS@
 NO_ICONV=@NO_ICONV@
 OLD_ICONV=@OLD_ICONV@
 NO_DEFLATE_BOUND=@NO_DEFLATE_BOUND@
index 0a37af74a260a396bf2e4627f6e57786d3570f7f..7937e604be34eadddc314c0eff0cea226af19c9c 100644 (file)
@@ -636,6 +636,12 @@ AC_SUBST(SNPRINTF_RETURNS_BOGUS)
 ## (in default C library and libraries checked by AC_CHECK_LIB)
 AC_MSG_NOTICE([CHECKS for library functions])
 #
+# Define NO_LIBGEN_H if you don't have libgen.h.
+AC_CHECK_HEADER([libgen.h],
+[NO_LIBGEN_H=],
+[NO_LIBGEN_H=YesPlease])
+AC_SUBST(NO_LIBGEN_H)
+#
 # Define NO_STRCASESTR if you don't have strcasestr.
 GIT_CHECK_FUNC(strcasestr,
 [NO_STRCASESTR=],
@@ -686,6 +692,13 @@ GIT_CHECK_FUNC(mkdtemp,
 [NO_MKDTEMP=YesPlease])
 AC_SUBST(NO_MKDTEMP)
 #
+# Define NO_MKSTEMPS if you don't have mkstemps in the C library.
+GIT_CHECK_FUNC(mkstemps,
+[NO_MKSTEMPS=],
+[NO_MKSTEMPS=YesPlease])
+AC_SUBST(NO_MKSTEMPS)
+#
+#
 # Define NO_MMAP if you want to avoid mmap.
 #
 # Define NO_ICONV if your libc does not properly support iconv.
index f6b8ba6fec16ed2ff2de4c66e2465e79d059a817..958c831e430340435c31b640bd757d56b7cb8b71 100644 (file)
--- a/connect.c
+++ b/connect.c
@@ -579,7 +579,10 @@ struct child_process *git_connect(int fd[2], const char *url_orig,
                        git_tcp_connect(fd, host, flags);
                /*
                 * Separate original protocol components prog and path
-                * from extended components with a NUL byte.
+                * from extended host header with a NUL byte.
+                *
+                * Note: Do not add any other headers here!  Doing so
+                * will cause older git-daemon servers to crash.
                 */
                packet_write(fd[1],
                             "%s %s%chost=%s%c",
index 0c8bb536c84f04627e78f251f51aea11b2048ce5..80ab4e45eb108898eb80caa32684c3f1308ab3a8 100755 (executable)
 #       with the bash.showDirtyState variable, which defaults to true
 #       once GIT_PS1_SHOWDIRTYSTATE is enabled.
 #
+#       You can also see if currently something is stashed, by setting
+#       GIT_PS1_SHOWSTASHSTATE to a nonempty value. If something is stashed,
+#       then a '$' will be shown next to the branch name.
+#
 # To submit patches:
 #
 #    *) Read Documentation/SubmittingPatches
@@ -84,26 +88,24 @@ __git_ps1 ()
        if [ -n "$g" ]; then
                local r
                local b
-               if [ -d "$g/rebase-apply" ]; then
-                       if [ -f "$g/rebase-apply/rebasing" ]; then
-                               r="|REBASE"
-               elif [ -f "$g/rebase-apply/applying" ]; then
-                               r="|AM"
-                       else
-                               r="|AM/REBASE"
-                       fi
-                       b="$(git symbolic-ref HEAD 2>/dev/null)"
-               elif [ -f "$g/rebase-merge/interactive" ]; then
+               if [ -f "$g/rebase-merge/interactive" ]; then
                        r="|REBASE-i"
                        b="$(cat "$g/rebase-merge/head-name")"
                elif [ -d "$g/rebase-merge" ]; then
                        r="|REBASE-m"
                        b="$(cat "$g/rebase-merge/head-name")"
                else
-                       if [ -f "$g/MERGE_HEAD" ]; then
+                       if [ -d "$g/rebase-apply" ]; then
+                               if [ -f "$g/rebase-apply/rebasing" ]; then
+                                       r="|REBASE"
+                               elif [ -f "$g/rebase-apply/applying" ]; then
+                                       r="|AM"
+                               else
+                                       r="|AM/REBASE"
+                               fi
+                       elif [ -f "$g/MERGE_HEAD" ]; then
                                r="|MERGING"
-                       fi
-                       if [ -f "$g/BISECT_LOG" ]; then
+                       elif [ -f "$g/BISECT_LOG" ]; then
                                r="|BISECTING"
                        fi
 
@@ -129,6 +131,7 @@ __git_ps1 ()
 
                local w
                local i
+               local s
                local c
 
                if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then
@@ -150,14 +153,15 @@ __git_ps1 ()
                                        fi
                                fi
                        fi
+                       if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ]; then
+                               git rev-parse --verify refs/stash >/dev/null 2>&1 && s="$"
+                       fi
                fi
 
-               if [ -n "$b" ]; then
-                       if [ -n "${1-}" ]; then
-                               printf "$1" "$c${b##refs/heads/}$w$i$r"
-                       else
-                               printf " (%s)" "$c${b##refs/heads/}$w$i$r"
-                       fi
+               if [ -n "${1-}" ]; then
+                       printf "$1" "$c${b##refs/heads/}$w$i$s$r"
+               else
+                       printf " (%s)" "$c${b##refs/heads/}$w$i$s$r"
                fi
        fi
 }
@@ -923,7 +927,7 @@ _git_diff ()
 }
 
 __git_mergetools_common="diffuse ecmerge emerge kdiff3 meld opendiff
-                       tkdiff vimdiff gvimdiff xxdiff
+                       tkdiff vimdiff gvimdiff xxdiff araxis
 "
 
 _git_difftool ()
@@ -1877,10 +1881,10 @@ _git_stash ()
                save,--*)
                        __gitcomp "--keep-index"
                        ;;
-               apply,--*)
+               apply,--*|pop,--*)
                        __gitcomp "--index"
                        ;;
-               show,--*|drop,--*|pop,--*|branch,--*)
+               show,--*|drop,--*|branch,--*)
                        COMPREPLY=()
                        ;;
                show,*|apply,*|drop,*|pop,*|branch,*)
index daa4c8e8c95924c6fb446884b3ed44c454425b54..b2babcc076de65b53671157115e63e74fec83a3e 100644 (file)
--- a/daemon.c
+++ b/daemon.c
@@ -406,15 +406,15 @@ static char *xstrdup_tolower(const char *str)
 }
 
 /*
- * Separate the "extra args" information as supplied by the client connection.
+ * Read the host as supplied by the client connection.
  */
-static void parse_extra_args(char *extra_args, int buflen)
+static void parse_host_arg(char *extra_args, int buflen)
 {
        char *val;
        int vallen;
        char *end = extra_args + buflen;
 
-       while (extra_args < end && *extra_args) {
+       if (extra_args < end && *extra_args) {
                saw_extended_args = 1;
                if (strncasecmp("host=", extra_args, 5) == 0) {
                        val = extra_args + 5;
@@ -436,6 +436,8 @@ static void parse_extra_args(char *extra_args, int buflen)
                        /* On to the next one */
                        extra_args = val + vallen;
                }
+               if (extra_args < end && *extra_args)
+                       die("Invalid request");
        }
 
        /*
@@ -545,7 +547,7 @@ static int execute(struct sockaddr *addr)
        hostname = canon_hostname = ip_address = tcp_port = NULL;
 
        if (len != pktlen)
-               parse_extra_args(line + len + 1, pktlen - len - 1);
+               parse_host_arg(line + len + 1, pktlen - len - 1);
 
        for (i = 0; i < ARRAY_SIZE(daemon_service); i++) {
                struct daemon_service *s = &(daemon_service[i]);
diff --git a/diff.c b/diff.c
index dcfbcb0215766efefa786b18d793c4bf96740b8c..43835d756c2c2c7ec579e1c38804fe33a706944f 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -1964,8 +1964,16 @@ static void prep_temp_blob(const char *path, struct diff_tempfile *temp,
 {
        int fd;
        struct strbuf buf = STRBUF_INIT;
+       struct strbuf template = STRBUF_INIT;
+       char *path_dup = xstrdup(path);
+       const char *base = basename(path_dup);
 
-       fd = git_mkstemp(temp->tmp_path, PATH_MAX, ".diff_XXXXXX");
+       /* Generate "XXXXXX_basename.ext" */
+       strbuf_addstr(&template, "XXXXXX_");
+       strbuf_addstr(&template, base);
+
+       fd = git_mkstemps(temp->tmp_path, PATH_MAX, template.buf,
+                       strlen(base) + 1);
        if (fd < 0)
                die("unable to create temp-file: %s", strerror(errno));
        if (convert_to_working_tree(path,
@@ -1981,6 +1989,8 @@ static void prep_temp_blob(const char *path, struct diff_tempfile *temp,
        temp->hex[40] = 0;
        sprintf(temp->mode, "%06o", mode);
        strbuf_release(&buf);
+       strbuf_release(&template);
+       free(path_dup);
 }
 
 static struct diff_tempfile *prepare_temp_file(const char *name,
@@ -3586,6 +3596,7 @@ static char *run_textconv(const char *pgm, struct diff_filespec *spec,
        if (start_command(&child) != 0 ||
            strbuf_read(&buf, child.out, 0) < 0 ||
            finish_command(&child) != 0) {
+               strbuf_release(&buf);
                remove_tempfile();
                error("error running textconv command '%s'", pgm);
                return NULL;
diff --git a/dir.c b/dir.c
index 0e6b752cd5833bfb970619983b4efa880aaaf134..bbfcb566e63310d38848b0b76076fb051a7446c8 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -396,7 +396,7 @@ static struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathna
 
 static struct dir_entry *dir_add_ignored(struct dir_struct *dir, const char *pathname, int len)
 {
-       if (cache_name_pos(pathname, len) >= 0)
+       if (!cache_name_is_other(pathname, len))
                return NULL;
 
        ALLOC_GROW(dir->ignored, dir->ignored_nr+1, dir->ignored_alloc);
index f6e536ece314316ebb281721ed27d7519577202f..df9f231635d2bc53073375971c1383966e2a140b 100755 (executable)
@@ -767,6 +767,96 @@ sub split_hunk {
        return @split;
 }
 
+sub find_last_o_ctx {
+       my ($it) = @_;
+       my $text = $it->{TEXT};
+       my ($o_ofs, $o_cnt) = parse_hunk_header($text->[0]);
+       my $i = @{$text};
+       my $last_o_ctx = $o_ofs + $o_cnt;
+       while (0 < --$i) {
+               my $line = $text->[$i];
+               if ($line =~ /^ /) {
+                       $last_o_ctx--;
+                       next;
+               }
+               last;
+       }
+       return $last_o_ctx;
+}
+
+sub merge_hunk {
+       my ($prev, $this) = @_;
+       my ($o0_ofs, $o0_cnt, $n0_ofs, $n0_cnt) =
+           parse_hunk_header($prev->{TEXT}[0]);
+       my ($o1_ofs, $o1_cnt, $n1_ofs, $n1_cnt) =
+           parse_hunk_header($this->{TEXT}[0]);
+
+       my (@line, $i, $ofs, $o_cnt, $n_cnt);
+       $ofs = $o0_ofs;
+       $o_cnt = $n_cnt = 0;
+       for ($i = 1; $i < @{$prev->{TEXT}}; $i++) {
+               my $line = $prev->{TEXT}[$i];
+               if ($line =~ /^\+/) {
+                       $n_cnt++;
+                       push @line, $line;
+                       next;
+               }
+
+               last if ($o1_ofs <= $ofs);
+
+               $o_cnt++;
+               $ofs++;
+               if ($line =~ /^ /) {
+                       $n_cnt++;
+               }
+               push @line, $line;
+       }
+
+       for ($i = 1; $i < @{$this->{TEXT}}; $i++) {
+               my $line = $this->{TEXT}[$i];
+               if ($line =~ /^\+/) {
+                       $n_cnt++;
+                       push @line, $line;
+                       next;
+               }
+               $ofs++;
+               $o_cnt++;
+               if ($line =~ /^ /) {
+                       $n_cnt++;
+               }
+               push @line, $line;
+       }
+       my $head = ("@@ -$o0_ofs" .
+                   (($o_cnt != 1) ? ",$o_cnt" : '') .
+                   " +$n0_ofs" .
+                   (($n_cnt != 1) ? ",$n_cnt" : '') .
+                   " @@\n");
+       @{$prev->{TEXT}} = ($head, @line);
+}
+
+sub coalesce_overlapping_hunks {
+       my (@in) = @_;
+       my @out = ();
+
+       my ($last_o_ctx, $last_was_dirty);
+
+       for (grep { $_->{USE} } @in) {
+               my $text = $_->{TEXT};
+               my ($o_ofs) = parse_hunk_header($text->[0]);
+               if (defined $last_o_ctx &&
+                   $o_ofs <= $last_o_ctx &&
+                   !$_->{DIRTY} &&
+                   !$last_was_dirty) {
+                       merge_hunk($out[-1], $_);
+               }
+               else {
+                       push @out, $_;
+               }
+               $last_o_ctx = find_last_o_ctx($out[-1]);
+               $last_was_dirty = $_->{DIRTY};
+       }
+       return @out;
+}
 
 sub color_diff {
        return map {
@@ -878,7 +968,8 @@ sub edit_hunk_loop {
                my $newhunk = {
                        TEXT => $text,
                        TYPE => $hunk->[$ix]->{TYPE},
-                       USE => 1
+                       USE => 1,
+                       DIRTY => 1,
                };
                if (diff_applies($head,
                                 @{$hunk}[0..$ix-1],
@@ -1210,6 +1301,8 @@ sub patch_update_file {
                }
        }
 
+       @hunk = coalesce_overlapping_hunks(@hunk);
+
        my $n_lofs = 0;
        my @result = ();
        for (@hunk) {
index 48d99fab863eb2462a266cd1bac31d88ffd59f8d..919b7f1ade9cab3c4ba907f9506e3cb518fb9e7f 100644 (file)
 # endif
 #elif !defined(__APPLE__) && !defined(__FreeBSD__)  && !defined(__USLC__) && !defined(_M_UNIX)
 #define _XOPEN_SOURCE 600 /* glibc2 and AIX 5.3L need 500, OpenBSD needs 600 for S_ISLNK() */
+#ifndef __sun__
 #define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */
 #endif
+#endif
 #define _ALL_SOURCE 1
 #define _GNU_SOURCE 1
 #define _BSD_SOURCE 1
 #include "compat/mingw.h"
 #endif /* __MINGW32__ */
 
+#ifndef NO_LIBGEN_H
+#include <libgen.h>
+#else
+#define basename gitbasename
+extern char *gitbasename(char *);
+#endif
+
 #ifndef NO_ICONV
 #include <iconv.h>
 #endif
@@ -245,6 +254,11 @@ extern int gitsetenv(const char *, const char *, int);
 extern char *gitmkdtemp(char *);
 #endif
 
+#ifdef NO_MKSTEMPS
+#define mkstemps gitmkstemps
+extern int gitmkstemps(char *, int);
+#endif
+
 #ifdef NO_UNSETENV
 #define unsetenv gitunsetenv
 extern void gitunsetenv(const char *);
index 6d9f0ef0f989133422cf8c0302e63dab15a999d5..9ec1df95c0aa8aba01990362c49ae1c15e2e086f 100755 (executable)
       foreach my $name (keys %todo) {
        my $basename = basename($name);
 
-       $basename = "no file " . $basename if (exists($added{$basename}));
+       # CVS reports files that don't exist in the current revision as
+       # "no file $basename" in its "status" output, so we should
+       # anticipate that.  Totally unknown files will have a status
+       # "Unknown". However, if they exist in the Attic, their status
+       # will be "Up-to-date" (this means they were added once but have
+       # been removed).
+       $basename = "no file $basename" if $added{$basename};
+
        $basename =~ s/^\s+//;
        $basename =~ s/\s+$//;
 
          $fullname{$basename} = $name;
          push (@canstatusfiles2, $name);
          delete($todo{$name});
-        }
+       }
       }
       my @cvsoutput;
       @cvsoutput = xargs_safe_pipe_capture([@cvs, 'status'], @canstatusfiles2);
       foreach my $l (@cvsoutput) {
-        chomp $l;
-        if ($l =~ /^File:\s+(.*\S)\s+Status: (.*)$/) {
-         if (!exists($fullname{$1})) {
-           print STDERR "Huh? Status reported for unexpected file '$1'\n";
-         } else {
-           $cvsstat{$fullname{$1}} = $2;
-         }
-       }
+       chomp $l;
+       next unless
+           my ($file, $status) = $l =~ /^File:\s+(.*\S)\s+Status: (.*)$/;
+
+       my $fullname = $fullname{$file};
+       print STDERR "Huh? Status '$status' reported for unexpected file '$file'\n"
+           unless defined $fullname;
+
+       # This response means the file does not exist except in
+       # CVS's attic, so set the status accordingly
+       $status = "In-attic"
+           if $file =~ /^no file /
+               && $status eq 'Up-to-date';
+
+       $cvsstat{$fullname{$file}} = $status;
       }
     }
 }
 
-# ... validate new files,
+# ... Validate that new files have the correct status
 foreach my $f (@afiles) {
-    if (defined ($cvsstat{$f}) and $cvsstat{$f} ne "Unknown") {
-       $dirty = 1;
+    next unless defined(my $stat = $cvsstat{$f});
+
+    # This means the file has never been seen before
+    next if $stat eq 'Unknown';
+
+    # This means the file has been seen before but was removed
+    next if $stat eq 'In-attic';
+
+    $dirty = 1;
        warn "File $f is already known in your CVS checkout -- perhaps it has been added by another user. Or this may indicate that it exists on a different branch. If this is the case, use -f to force the merge.\n";
        warn "Status was: $cvsstat{$f}\n";
-    }
 }
+
 # ... validate known files.
 foreach my $f (@files) {
     next if grep { $_ eq $f } @afiles;
index 8b5e6a8c64238be2534689113984b7eaf07e94e2..bfb01f7842e6192e0b3fbc0e3f2ab96269578289 100644 (file)
@@ -18,6 +18,9 @@ translate_merge_tool_path () {
        emerge)
                echo emacs
                ;;
+       araxis)
+               echo compare
+               ;;
        *)
                echo "$1"
                ;;
@@ -43,7 +46,7 @@ check_unchanged () {
 valid_tool () {
        case "$1" in
        kdiff3 | tkdiff | xxdiff | meld | opendiff | \
-       emerge | vimdiff | gvimdiff | ecmerge | diffuse)
+       emerge | vimdiff | gvimdiff | ecmerge | diffuse | araxis)
                ;; # happy
        tortoisemerge)
                if ! merge_mode; then
@@ -263,6 +266,24 @@ run_merge_tool () {
                        status=1
                fi
                ;;
+       araxis)
+               if merge_mode; then
+                       touch "$BACKUP"
+                       if $base_present; then
+                               "$merge_tool_path" -wait -merge -3 -a1 \
+                                       "$BASE" "$LOCAL" "$REMOTE" "$MERGED" \
+                                       >/dev/null 2>&1
+                       else
+                               "$merge_tool_path" -wait -2 \
+                                       "$LOCAL" "$REMOTE" "$MERGED" \
+                                       >/dev/null 2>&1
+                       fi
+                       check_unchanged
+               else
+                       "$merge_tool_path" -wait -2 "$LOCAL" "$REMOTE" \
+                               >/dev/null 2>&1
+               fi
+               ;;
        *)
                merge_tool_cmd="$(get_merge_tool_cmd "$1")"
                if test -z "$merge_tool_cmd"; then
@@ -302,7 +323,7 @@ guess_merge_tool () {
                else
                        tools="opendiff kdiff3 tkdiff xxdiff meld $tools"
                fi
-               tools="$tools gvimdiff diffuse ecmerge"
+               tools="$tools gvimdiff diffuse ecmerge araxis"
        fi
        if echo "${VISUAL:-$EDITOR}" | grep emacs > /dev/null 2>&1; then
                # $EDITOR is emacs so add emerge as a candidate
index 314cd364b8f4df5e170dd0ffd9e874b3e6c2737c..f96d887d23653019e3387eced2779d50b3f09fa2 100755 (executable)
@@ -420,7 +420,7 @@ do_next () {
        NEWHEAD=$(git rev-parse HEAD) &&
        case $HEADNAME in
        refs/*)
-               message="$GIT_REFLOG_ACTION: $HEADNAME onto $SHORTONTO)" &&
+               message="$GIT_REFLOG_ACTION: $HEADNAME onto $SHORTONTO" &&
                git update-ref -m "$message" $HEADNAME $NEWHEAD $OLDHEAD &&
                git symbolic-ref HEAD $HEADNAME
                ;;
index e793935b4f2980aa1e333f7e8424b293b4b59399..4c795a4b0310aa0d8081dcaea0a9d9593643e704 100755 (executable)
@@ -538,7 +538,7 @@ ($)
 
        print C <<EOT;
 From $tpl_sender # This line is ignored.
-GIT: Lines beginning in "GIT: " will be removed.
+GIT: Lines beginning in "GIT:" will be removed.
 GIT: Consider including an overall diffstat or table of contents
 GIT: for the patch you are writing.
 GIT:
@@ -553,8 +553,6 @@ ($)
        }
        close(C);
 
-       my $editor = $ENV{GIT_EDITOR} || Git::config(@repo, "core.editor") || $ENV{VISUAL} || $ENV{EDITOR} || "vi";
-
        if ($annotate) {
                do_edit($compose_filename, @files);
        } else {
@@ -571,7 +569,7 @@ ($)
        my $in_body = 0;
        my $summary_empty = 1;
        while(<C>) {
-               next if m/^GIT: /;
+               next if m/^GIT:/;
                if ($in_body) {
                        $summary_empty = 0 unless (/^\n$/);
                } elsif (/^\n$/) {
@@ -579,7 +577,7 @@ ($)
                        if ($need_8bit_cte) {
                                print C2 "MIME-Version: 1.0\n",
                                         "Content-Type: text/plain; ",
-                                          "charset=utf-8\n",
+                                          "charset=UTF-8\n",
                                         "Content-Transfer-Encoding: 8bit\n";
                        }
                } elsif (/^MIME-Version:/i) {
@@ -768,12 +766,20 @@ sub unquote_rfc2047 {
 
 sub quote_rfc2047 {
        local $_ = shift;
-       my $encoding = shift || 'utf-8';
+       my $encoding = shift || 'UTF-8';
        s/([^-a-zA-Z0-9!*+\/])/sprintf("=%02X", ord($1))/eg;
        s/(.*)/=\?$encoding\?q\?$1\?=/;
        return $_;
 }
 
+sub is_rfc2047_quoted {
+       my $s = shift;
+       my $token = '[^][()<>@,;:"\/?.= \000-\037\177-\377]+';
+       my $encoded_text = '[!->@-~]+';
+       length($s) <= 75 &&
+       $s =~ m/^(?:"[[:ascii:]]*"|=\?$token\?$token\?$encoded_text\?=)$/o;
+}
+
 # use the simplest quoting being able to handle the recipient
 sub sanitize_address
 {
@@ -785,7 +791,7 @@ sub sanitize_address
        }
 
        # if recipient_name is already quoted, do nothing
-       if ($recipient_name =~ /^("[[:ascii:]]*"|=\?utf-8\?q\?.*\?=)$/) {
+       if (is_rfc2047_quoted($recipient_name)) {
                return $recipient;
        }
 
@@ -805,6 +811,10 @@ sub sanitize_address
 
 }
 
+# Returns 1 if the message was sent, and 0 otherwise.
+# In actuality, the whole program dies when a there
+# is an error sending a message.
+
 sub send_message
 {
        my @recipients = unique_email_list(@to);
@@ -873,7 +883,7 @@ sub send_message
                         default => $ask_default);
                die "Send this email reply required" unless defined $_;
                if (/^n/i) {
-                       return;
+                       return 0;
                } elsif (/^q/i) {
                        cleanup_compose_files();
                        exit(0);
@@ -954,7 +964,7 @@ sub send_message
                $smtp->data or die $smtp->message;
                $smtp->datasend("$header\n$message") or die $smtp->message;
                $smtp->dataend() or die $smtp->message;
-               $smtp->ok or die "Failed to send $subject\n".$smtp->message;
+               $smtp->code =~ /250|200/ or die "Failed to send $subject\n".$smtp->message;
        }
        if ($quiet) {
                printf (($dry_run ? "Dry-" : "")."Sent %s\n", $subject);
@@ -975,6 +985,8 @@ sub send_message
                        print "Result: OK\n";
                }
        }
+
+       return 1;
 }
 
 $reply_to = $initial_reply_to;
@@ -1135,10 +1147,10 @@ sub send_message
 
        @cc = (@initial_cc, @cc);
 
-       send_message();
+       my $message_was_sent = send_message();
 
        # set up for the next message
-       if ($chain_reply_to || !defined $reply_to || length($reply_to) == 0) {
+       if ($message_was_sent and $chain_reply_to || not defined $reply_to || length($reply_to) == 0) {
                $reply_to = $message_id;
                if (length $references > 0) {
                        $references .= "\n $message_id";
index b9ace9970492aaf48472904d978d809d90ca33db..e6a586720978ec516d243590b0e403ed7ecfe36c 100755 (executable)
@@ -3,8 +3,8 @@
 
 dashless=$(basename "$0" | sed -e 's/-/ /')
 USAGE="list [<options>]
-   or: $dashless (show | drop | pop ) [<stash>]
-   or: $dashless apply [--index] [<stash>]
+   or: $dashless ( show | drop ) [<stash>]
+   or: $dashless ( pop | apply ) [--index] [<stash>]
    or: $dashless branch <branchname> [<stash>]
    or: $dashless [save [--keep-index] [<message>]]
    or: $dashless clear"
index a70c7d7b2cc1e47d5293e1bd45e11d398e48c3f1..33017974d0a098bdaff707ccf0e8660aa5009079 100755 (executable)
@@ -1178,16 +1178,27 @@ sub get_commit_entry {
        }
        rename $commit_editmsg, $commit_msg or croak $!;
        {
+               require Encode;
                # SVN requires messages to be UTF-8 when entering the repo
                local $/;
                open $log_fh, '<', $commit_msg or croak $!;
                binmode $log_fh;
                chomp($log_entry{log} = <$log_fh>);
 
-               if (my $enc = Git::config('i18n.commitencoding')) {
-                       require Encode;
-                       Encode::from_to($log_entry{log}, $enc, 'UTF-8');
+               my $enc = Git::config('i18n.commitencoding') || 'UTF-8';
+               my $msg = $log_entry{log};
+
+               eval { $msg = Encode::decode($enc, $msg, 1) };
+               if ($@) {
+                       die "Could not decode as $enc:\n", $msg,
+                           "\nPerhaps you need to set i18n.commitencoding\n";
                }
+
+               eval { $msg = Encode::encode('UTF-8', $msg, 1) };
+               die "Could not encode as UTF-8:\n$msg\n" if $@;
+
+               $log_entry{log} = $msg;
+
                close $log_fh or croak $!;
        }
        unlink $commit_msg;
diff --git a/git.c b/git.c
index 5a00726d09a13d5f70ab0378e02bbbd299124d5c..7d7f949f0da85ea124f67ead6f68fdd0ddc75d20 100644 (file)
--- a/git.c
+++ b/git.c
@@ -327,6 +327,7 @@ static void handle_internal_command(int argc, const char **argv)
                { "merge-ours", cmd_merge_ours, RUN_SETUP },
                { "merge-recursive", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
                { "merge-subtree", cmd_merge_recursive, RUN_SETUP | NEED_WORK_TREE },
+               { "mktree", cmd_mktree, RUN_SETUP },
                { "mv", cmd_mv, RUN_SETUP | NEED_WORK_TREE },
                { "name-rev", cmd_name_rev, RUN_SETUP },
                { "pack-objects", cmd_pack_objects, RUN_SETUP },
diff --git a/grep.c b/grep.c
index a649f063cf28baa5b0ddce72d7d6e4d9fca6f360..92a47c71e7d93eef7dc8d6967cd071aa061218ce 100644 (file)
--- a/grep.c
+++ b/grep.c
@@ -331,7 +331,7 @@ static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,
 
        if (hit && p->word_regexp) {
                if ((pmatch[0].rm_so < 0) ||
-                   (eol - bol) <= pmatch[0].rm_so ||
+                   (eol - bol) < pmatch[0].rm_so ||
                    (pmatch[0].rm_eo < 0) ||
                    (eol - bol) < pmatch[0].rm_eo)
                        die("regexp returned nonsense");
@@ -350,6 +350,10 @@ static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,
                else
                        hit = 0;
 
+               /* Words consist of at least one character. */
+               if (pmatch->rm_so == pmatch->rm_eo)
+                       hit = 0;
+
                if (!hit && pmatch[0].rm_so + bol + 1 < eol) {
                        /* There could be more than one match on the
                         * line, and the first match might not be
@@ -360,6 +364,7 @@ static int match_one_pattern(struct grep_pat *p, char *bol, char *eol,
                        bol = pmatch[0].rm_so + bol + 1;
                        while (word_char(bol[-1]) && bol < eol)
                                bol++;
+                       eflags |= REG_NOTBOL;
                        if (bol < eol)
                                goto again;
                }
@@ -499,6 +504,8 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
 
                *eol = '\0';
                while (next_match(opt, bol, eol, ctx, &match, eflags)) {
+                       if (match.rm_so == match.rm_eo)
+                               break;
                        printf("%.*s%s%.*s%s",
                               (int)match.rm_so, bol,
                               opt->color_match,
index ebb3bedb074202a29e2356845012bd1ffae0dc19..47cf43c3cdd2bcd7638360a130fc8ef04ce132e9 100644 (file)
@@ -84,7 +84,8 @@ int main(int argc, const char **argv)
 
        git_extract_argv0_path(argv[0]);
 
-       argc = parse_options(argc, argv, hash_object_options, hash_object_usage, 0);
+       argc = parse_options(argc, argv, NULL, hash_object_options,
+                            hash_object_usage, 0);
 
        if (write_object) {
                prefix = setup_git_directory();
index 45e8a69e2d6b83f5a1564e7d1fe40d783d87ae3e..a7e28e345fb303534c4b99189096424bd7d9e887 100644 (file)
@@ -1844,7 +1844,7 @@ static int update_remote(unsigned char *sha1, struct remote_lock *lock)
        return 1;
 }
 
-static struct ref *remote_refs, **remote_tail;
+static struct ref *remote_refs;
 
 static void one_remote_ref(char *refname)
 {
@@ -1874,27 +1874,15 @@ static void one_remote_ref(char *refname)
                }
        }
 
-       *remote_tail = ref;
-       remote_tail = &ref->next;
+       ref->next = remote_refs;
+       remote_refs = ref;
 }
 
 static void get_dav_remote_heads(void)
 {
-       remote_tail = &remote_refs;
        remote_ls("refs/", (PROCESS_FILES | PROCESS_DIRS | RECURSIVE), process_ls_ref, NULL);
 }
 
-static int is_zero_sha1(const unsigned char *sha1)
-{
-       int i;
-
-       for (i = 0; i < 20; i++) {
-               if (*sha1++)
-                       return 0;
-       }
-       return 1;
-}
-
 static void add_remote_info_ref(struct remote_ls_ctx *ls)
 {
        struct strbuf *buf = (struct strbuf *)ls->userData;
@@ -2120,13 +2108,13 @@ static int delete_remote_branch(char *pattern, int force)
                /* Remote HEAD must resolve to a known object */
                if (symref)
                        return error("Remote HEAD symrefs too deep");
-               if (is_zero_sha1(head_sha1))
+               if (is_null_sha1(head_sha1))
                        return error("Unable to resolve remote HEAD");
                if (!has_sha1_file(head_sha1))
                        return error("Remote HEAD resolves to object %s\nwhich does not exist locally, perhaps you need to fetch?", sha1_to_hex(head_sha1));
 
                /* Remote branch must resolve to a known object */
-               if (is_zero_sha1(remote_ref->old_sha1))
+               if (is_null_sha1(remote_ref->old_sha1))
                        return error("Unable to resolve remote branch %s",
                                     remote_ref->name);
                if (!has_sha1_file(remote_ref->old_sha1))
@@ -2311,9 +2299,7 @@ int main(int argc, char **argv)
        }
 
        /* match them up */
-       if (!remote_tail)
-               remote_tail = &remote_refs;
-       if (match_refs(local_refs, remote_refs, &remote_tail,
+       if (match_refs(local_refs, &remote_refs,
                       nr_refspec, (const char **) refspec, push_all)) {
                rc = -1;
                goto cleanup;
@@ -2334,7 +2320,7 @@ int main(int argc, char **argv)
                if (!ref->peer_ref)
                        continue;
 
-               if (is_zero_sha1(ref->peer_ref->new_sha1)) {
+               if (is_null_sha1(ref->peer_ref->new_sha1)) {
                        if (delete_remote_branch(ref->name, 1) == -1) {
                                error("Could not remove %s", ref->name);
                                rc = -4;
@@ -2350,7 +2336,7 @@ int main(int argc, char **argv)
                }
 
                if (!force_all &&
-                   !is_zero_sha1(ref->old_sha1) &&
+                   !is_null_sha1(ref->old_sha1) &&
                    !ref->force) {
                        if (!has_sha1_file(ref->old_sha1) ||
                            !ref_newer(ref->peer_ref->new_sha1,
@@ -2400,7 +2386,7 @@ int main(int argc, char **argv)
                old_sha1_hex = NULL;
                commit_argv[1] = "--objects";
                commit_argv[2] = new_sha1_hex;
-               if (!push_all && !is_zero_sha1(ref->old_sha1)) {
+               if (!push_all && !is_null_sha1(ref->old_sha1)) {
                        old_sha1_hex = xmalloc(42);
                        sprintf(old_sha1_hex, "^%s",
                                sha1_to_hex(ref->old_sha1));
index 8154cb2116da9257ecf286c46f77fc1ed2a62afc..e4c83b9d5b989671c1accc573235479ad77a5ab7 100644 (file)
@@ -982,9 +982,7 @@ static struct store *imap_open_store(struct imap_server_conf *srvc)
        struct imap_store *ctx;
        struct imap *imap;
        char *arg, *rsp;
-       struct hostent *he;
-       struct sockaddr_in addr;
-       int s, a[2], preauth;
+       int s = -1, a[2], preauth;
        pid_t pid;
 
        ctx = xcalloc(sizeof(*ctx), 1);
@@ -1021,6 +1019,51 @@ static struct store *imap_open_store(struct imap_server_conf *srvc)
 
                imap_info("ok\n");
        } else {
+#ifndef NO_IPV6
+               struct addrinfo hints, *ai0, *ai;
+               int gai;
+               char portstr[6];
+
+               snprintf(portstr, sizeof(portstr), "%hu", srvc->port);
+
+               memset(&hints, 0, sizeof(hints));
+               hints.ai_socktype = SOCK_STREAM;
+               hints.ai_protocol = IPPROTO_TCP;
+
+               imap_info("Resolving %s... ", srvc->host);
+               gai = getaddrinfo(srvc->host, portstr, &hints, &ai);
+               if (gai) {
+                       fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(gai));
+                       goto bail;
+               }
+               imap_info("ok\n");
+
+               for (ai0 = ai; ai; ai = ai->ai_next) {
+                       char addr[NI_MAXHOST];
+
+                       s = socket(ai->ai_family, ai->ai_socktype,
+                                  ai->ai_protocol);
+                       if (s < 0)
+                               continue;
+
+                       getnameinfo(ai->ai_addr, ai->ai_addrlen, addr,
+                                   sizeof(addr), NULL, 0, NI_NUMERICHOST);
+                       imap_info("Connecting to [%s]:%s... ", addr, portstr);
+
+                       if (connect(s, ai->ai_addr, ai->ai_addrlen) < 0) {
+                               close(s);
+                               s = -1;
+                               perror("connect");
+                               continue;
+                       }
+
+                       break;
+               }
+               freeaddrinfo(ai0);
+#else /* NO_IPV6 */
+               struct hostent *he;
+               struct sockaddr_in addr;
+
                memset(&addr, 0, sizeof(addr));
                addr.sin_port = htons(srvc->port);
                addr.sin_family = AF_INET;
@@ -1040,7 +1083,12 @@ static struct store *imap_open_store(struct imap_server_conf *srvc)
                imap_info("Connecting to %s:%hu... ", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
                if (connect(s, (struct sockaddr *)&addr, sizeof(addr))) {
                        close(s);
+                       s = -1;
                        perror("connect");
+               }
+#endif
+               if (s < 0) {
+                       fputs("Error: unable to connect to server.\n", stderr);
                        goto bail;
                }
 
index 81c02ad0531e98379d8cd11dc7c2d70214d67fb4..31d6f0a2ee63e8c3cad1053f9281a0ce9917fb32 100644 (file)
@@ -175,8 +175,7 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
                { "B", temp[2] },
                { NULL }
        };
-       struct child_process child;
-       const char *args[20];
+       const char *args[] = { "sh", "-c", NULL, NULL };
        int status, fd, i;
        struct stat st;
 
@@ -191,14 +190,8 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
 
        strbuf_expand(&cmd, fn->cmdline, strbuf_expand_dict_cb, &dict);
 
-       memset(&child, 0, sizeof(child));
-       child.argv = args;
-       args[0] = "sh";
-       args[1] = "-c";
        args[2] = cmd.buf;
-       args[3] = NULL;
-
-       status = run_command(&child);
+       status = run_command_v_opt(args, 0);
        if (status < -ERR_RUN_COMMAND_FORK)
                ; /* failure in run-command */
        else
index aa9cf23a39ae271a53d1a0c05ac99be0e832b46a..19ddd03e0b2a57d03d85b1e5ca73b0bd4a0d6981 100644 (file)
@@ -3,45 +3,20 @@
 #include "exec_cmd.h"
 
 static const char *pgm;
-static const char *arguments[9];
 static int one_shot, quiet;
 static int err;
 
-static void run_program(void)
-{
-       struct child_process child;
-       memset(&child, 0, sizeof(child));
-       child.argv = arguments;
-       if (run_command(&child)) {
-               if (one_shot) {
-                       err++;
-               } else {
-                       if (!quiet)
-                               die("merge program failed");
-                       exit(1);
-               }
-       }
-}
-
 static int merge_entry(int pos, const char *path)
 {
        int found;
+       const char *arguments[] = { pgm, "", "", "", path, "", "", "", NULL };
+       char hexbuf[4][60];
+       char ownbuf[4][60];
 
        if (pos >= active_nr)
                die("git merge-index: %s not in the cache", path);
-       arguments[0] = pgm;
-       arguments[1] = "";
-       arguments[2] = "";
-       arguments[3] = "";
-       arguments[4] = path;
-       arguments[5] = "";
-       arguments[6] = "";
-       arguments[7] = "";
-       arguments[8] = NULL;
        found = 0;
        do {
-               static char hexbuf[4][60];
-               static char ownbuf[4][60];
                struct cache_entry *ce = active_cache[pos];
                int stage = ce_stage(ce);
 
@@ -55,7 +30,16 @@ static int merge_entry(int pos, const char *path)
        } while (++pos < active_nr);
        if (!found)
                die("git merge-index: %s not in the cache", path);
-       run_program();
+
+       if (run_command_v_opt(arguments, 0)) {
+               if (one_shot)
+                       err++;
+               else {
+                       if (!quiet)
+                               die("merge program failed");
+                       exit(1);
+               }
+       }
        return found;
 }
 
diff --git a/mktree.c b/mktree.c
deleted file mode 100644 (file)
index 137a095..0000000
--- a/mktree.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * GIT - the stupid content tracker
- *
- * Copyright (c) Junio C Hamano, 2006
- */
-#include "cache.h"
-#include "quote.h"
-#include "tree.h"
-#include "exec_cmd.h"
-
-static struct treeent {
-       unsigned mode;
-       unsigned char sha1[20];
-       int len;
-       char name[FLEX_ARRAY];
-} **entries;
-static int alloc, used;
-
-static void append_to_tree(unsigned mode, unsigned char *sha1, char *path)
-{
-       struct treeent *ent;
-       int len = strlen(path);
-       if (strchr(path, '/'))
-               die("path %s contains slash", path);
-
-       if (alloc <= used) {
-               alloc = alloc_nr(used);
-               entries = xrealloc(entries, sizeof(*entries) * alloc);
-       }
-       ent = entries[used++] = xmalloc(sizeof(**entries) + len + 1);
-       ent->mode = mode;
-       ent->len = len;
-       hashcpy(ent->sha1, sha1);
-       memcpy(ent->name, path, len+1);
-}
-
-static int ent_compare(const void *a_, const void *b_)
-{
-       struct treeent *a = *(struct treeent **)a_;
-       struct treeent *b = *(struct treeent **)b_;
-       return base_name_compare(a->name, a->len, a->mode,
-                                b->name, b->len, b->mode);
-}
-
-static void write_tree(unsigned char *sha1)
-{
-       struct strbuf buf;
-       size_t size;
-       int i;
-
-       qsort(entries, used, sizeof(*entries), ent_compare);
-       for (size = i = 0; i < used; i++)
-               size += 32 + entries[i]->len;
-
-       strbuf_init(&buf, size);
-       for (i = 0; i < used; i++) {
-               struct treeent *ent = entries[i];
-               strbuf_addf(&buf, "%o %s%c", ent->mode, ent->name, '\0');
-               strbuf_add(&buf, ent->sha1, 20);
-       }
-
-       write_sha1_file(buf.buf, buf.len, tree_type, sha1);
-}
-
-static const char mktree_usage[] = "git mktree [-z]";
-
-int main(int ac, char **av)
-{
-       struct strbuf sb = STRBUF_INIT;
-       struct strbuf p_uq = STRBUF_INIT;
-       unsigned char sha1[20];
-       int line_termination = '\n';
-
-       git_extract_argv0_path(av[0]);
-
-       setup_git_directory();
-
-       while ((1 < ac) && av[1][0] == '-') {
-               char *arg = av[1];
-               if (!strcmp("-z", arg))
-                       line_termination = 0;
-               else
-                       usage(mktree_usage);
-               ac--;
-               av++;
-       }
-
-       while (strbuf_getline(&sb, stdin, line_termination) != EOF) {
-               char *ptr, *ntr;
-               unsigned mode;
-               enum object_type type;
-               char *path;
-
-               ptr = sb.buf;
-               /* Input is non-recursive ls-tree output format
-                * mode SP type SP sha1 TAB name
-                */
-               mode = strtoul(ptr, &ntr, 8);
-               if (ptr == ntr || !ntr || *ntr != ' ')
-                       die("input format error: %s", sb.buf);
-               ptr = ntr + 1; /* type */
-               ntr = strchr(ptr, ' ');
-               if (!ntr || sb.buf + sb.len <= ntr + 40 ||
-                   ntr[41] != '\t' ||
-                   get_sha1_hex(ntr + 1, sha1))
-                       die("input format error: %s", sb.buf);
-               type = sha1_object_info(sha1, NULL);
-               if (type < 0)
-                       die("object %s unavailable", sha1_to_hex(sha1));
-               *ntr++ = 0; /* now at the beginning of SHA1 */
-               if (type != type_from_string(ptr))
-                       die("object type %s mismatch (%s)", ptr, typename(type));
-
-               path = ntr + 41;  /* at the beginning of name */
-               if (line_termination && path[0] == '"') {
-                       strbuf_reset(&p_uq);
-                       if (unquote_c_style(&p_uq, path, NULL)) {
-                               die("invalid quoting");
-                       }
-                       path = p_uq.buf;
-               }
-
-               append_to_tree(mode, sha1, path);
-       }
-       strbuf_release(&p_uq);
-       strbuf_release(&sb);
-
-       write_tree(sha1);
-       puts(sha1_to_hex(sha1));
-       exit(0);
-}
index c52b8ccf59a4848be6f3f810e01029f7c6625c78..79de18b37eb1aa96d2f25963b7f7cc2a08977846 100644 (file)
@@ -31,11 +31,20 @@ static int get_arg(struct parse_opt_ctx_t *p, const struct option *opt,
        return 0;
 }
 
+static void fix_filename(const char *prefix, const char **file)
+{
+       if (!file || !*file || !prefix || is_absolute_path(*file)
+           || !strcmp("-", *file))
+               return;
+       *file = xstrdup(prefix_filename(prefix, strlen(prefix), *file));
+}
+
 static int get_value(struct parse_opt_ctx_t *p,
                     const struct option *opt, int flags)
 {
        const char *s, *arg;
        const int unset = flags & OPT_UNSET;
+       int err;
 
        if (unset && p->opt)
                return opterror(opt, "takes no value", flags);
@@ -95,6 +104,19 @@ static int get_value(struct parse_opt_ctx_t *p,
                        return get_arg(p, opt, flags, (const char **)opt->value);
                return 0;
 
+       case OPTION_FILENAME:
+               err = 0;
+               if (unset)
+                       *(const char **)opt->value = NULL;
+               else if (opt->flags & PARSE_OPT_OPTARG && !p->opt)
+                       *(const char **)opt->value = (const char *)opt->defval;
+               else
+                       err = get_arg(p, opt, flags, (const char **)opt->value);
+
+               if (!err)
+                       fix_filename(p->prefix, (const char **)opt->value);
+               return err;
+
        case OPTION_CALLBACK:
                if (unset)
                        return (*opt->callback)(opt, NULL, 1) ? (-1) : 0;
@@ -284,13 +306,37 @@ static void check_typos(const char *arg, const struct option *options)
        }
 }
 
+static void parse_options_check(const struct option *opts)
+{
+       int err = 0;
+
+       for (; opts->type != OPTION_END; opts++) {
+               if ((opts->flags & PARSE_OPT_LASTARG_DEFAULT) &&
+                   (opts->flags & PARSE_OPT_OPTARG)) {
+                       if (opts->long_name) {
+                               error("`--%s` uses incompatible flags "
+                                     "LASTARG_DEFAULT and OPTARG", opts->long_name);
+                       } else {
+                               error("`-%c` uses incompatible flags "
+                                     "LASTARG_DEFAULT and OPTARG", opts->short_name);
+                       }
+                       err |= 1;
+               }
+       }
+
+       if (err)
+               exit(129);
+}
+
 void parse_options_start(struct parse_opt_ctx_t *ctx,
-                        int argc, const char **argv, int flags)
+                        int argc, const char **argv, const char *prefix,
+                        int flags)
 {
        memset(ctx, 0, sizeof(*ctx));
        ctx->argc = argc - 1;
        ctx->argv = argv + 1;
        ctx->out  = argv;
+       ctx->prefix = prefix;
        ctx->cpidx = ((flags & PARSE_OPT_KEEP_ARGV0) != 0);
        ctx->flags = flags;
        if ((flags & PARSE_OPT_KEEP_UNKNOWN) &&
@@ -307,6 +353,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
 {
        int internal_help = !(ctx->flags & PARSE_OPT_NO_INTERNAL_HELP);
 
+       parse_options_check(options);
+
        /* we must reset ->opt, unknown short option leave it dangling */
        ctx->opt = NULL;
 
@@ -389,12 +437,13 @@ int parse_options_end(struct parse_opt_ctx_t *ctx)
        return ctx->cpidx + ctx->argc;
 }
 
-int parse_options(int argc, const char **argv, const struct option *options,
-                 const char * const usagestr[], int flags)
+int parse_options(int argc, const char **argv, const char *prefix,
+                 const struct option *options, const char * const usagestr[],
+                 int flags)
 {
        struct parse_opt_ctx_t ctx;
 
-       parse_options_start(&ctx, argc, argv, flags);
+       parse_options_start(&ctx, argc, argv, prefix, flags);
        switch (parse_options_step(&ctx, options, usagestr)) {
        case PARSE_OPT_HELP:
                exit(129);
@@ -412,6 +461,20 @@ int parse_options(int argc, const char **argv, const struct option *options,
        return parse_options_end(&ctx);
 }
 
+static int usage_argh(const struct option *opts)
+{
+       const char *s;
+       int literal = opts->flags & PARSE_OPT_LITERAL_ARGHELP;
+       if (opts->flags & PARSE_OPT_OPTARG)
+               if (opts->long_name)
+                       s = literal ? "[=%s]" : "[=<%s>]";
+               else
+                       s = literal ? "[%s]" : "[<%s>]";
+       else
+               s = literal ? " %s" : " <%s>";
+       return fprintf(stderr, s, opts->argh);
+}
+
 #define USAGE_OPTS_WIDTH 24
 #define USAGE_GAP         2
 
@@ -477,16 +540,12 @@ int usage_with_options_internal(const char * const *usagestr,
                        if (opts->flags & PARSE_OPT_NOARG)
                                break;
                        /* FALLTHROUGH */
+               case OPTION_FILENAME:
+                       /* FALLTHROUGH */
                case OPTION_STRING:
-                       if (opts->argh) {
-                               if (opts->flags & PARSE_OPT_OPTARG)
-                                       if (opts->long_name)
-                                               pos += fprintf(stderr, "[=<%s>]", opts->argh);
-                                       else
-                                               pos += fprintf(stderr, "[<%s>]", opts->argh);
-                               else
-                                       pos += fprintf(stderr, " <%s>", opts->argh);
-                       } else {
+                       if (opts->argh)
+                               pos += usage_argh(opts);
+                       else {
                                if (opts->flags & PARSE_OPT_OPTARG)
                                        if (opts->long_name)
                                                pos += fprintf(stderr, "[=...]");
@@ -593,15 +652,3 @@ int parse_opt_with_commit(const struct option *opt, const char *arg, int unset)
        commit_list_insert(commit, opt->value);
        return 0;
 }
-
-/*
- * This should really be OPTION_FILENAME type as a part of
- * parse_options that take prefix to do this while parsing.
- */
-extern const char *parse_options_fix_filename(const char *prefix, const char *file)
-{
-       if (!file || !prefix || is_absolute_path(file) || !strcmp("-", file))
-               return file;
-       return prefix_filename(prefix, strlen(prefix), file);
-}
-
index 919b9b441f97511695308287a2fdc6f3a45e383d..5653dbab87a7d27b10e1513c14ec6d0ec3464325 100644 (file)
@@ -17,6 +17,7 @@ enum parse_opt_type {
        OPTION_STRING,
        OPTION_INTEGER,
        OPTION_CALLBACK,
+       OPTION_FILENAME
 };
 
 enum parse_opt_flags {
@@ -34,6 +35,7 @@ enum parse_opt_option_flags {
        PARSE_OPT_HIDDEN  = 8,
        PARSE_OPT_LASTARG_DEFAULT = 16,
        PARSE_OPT_NODASH = 32,
+       PARSE_OPT_LITERAL_ARGHELP = 64,
 };
 
 struct option;
@@ -69,9 +71,15 @@ typedef int parse_opt_cb(const struct option *, const char *arg, int unset);
  *   PARSE_OPT_NONEG: says that this option cannot be negated
  *   PARSE_OPT_HIDDEN: this option is skipped in the default usage, and
  *                     shown only in the full usage.
- *   PARSE_OPT_LASTARG_DEFAULT: if no argument is given, the default value
- *                              is used.
+ *   PARSE_OPT_LASTARG_DEFAULT: says that this option will take the default
+ *                             value if no argument is given when the option
+ *                             is last on the command line. If the option is
+ *                             not last it will require an argument.
+ *                             Should not be used with PARSE_OPT_OPTARG.
  *   PARSE_OPT_NODASH: this option doesn't start with a dash.
+ *   PARSE_OPT_LITERAL_ARGHELP: says that argh shouldn't be enclosed in brackets
+ *                             (i.e. '<argh>') in the help message.
+ *                             Useful for options with multiple parameters.
  *
  * `callback`::
  *   pointer to the callback to use for OPTION_CALLBACK.
@@ -113,12 +121,14 @@ struct option {
 #define OPT_NUMBER_CALLBACK(v, h, f) \
        { OPTION_NUMBER, 0, NULL, (v), NULL, (h), \
          PARSE_OPT_NOARG | PARSE_OPT_NONEG, (f) }
+#define OPT_FILENAME(s, l, v, h)    { OPTION_FILENAME, (s), (l), (v), \
+                                      "FILE", (h) }
 
 /* parse_options() will filter out the processed options and leave the
  * non-option arguments in argv[].
  * Returns the number of arguments left in argv[].
  */
-extern int parse_options(int argc, const char **argv,
+extern int parse_options(int argc, const char **argv, const char *prefix,
                          const struct option *options,
                          const char * const usagestr[], int flags);
 
@@ -144,13 +154,15 @@ struct parse_opt_ctx_t {
        int argc, cpidx;
        const char *opt;
        int flags;
+       const char *prefix;
 };
 
 extern int parse_options_usage(const char * const *usagestr,
                               const struct option *opts);
 
 extern void parse_options_start(struct parse_opt_ctx_t *ctx,
-                               int argc, const char **argv, int flags);
+                               int argc, const char **argv, const char *prefix,
+                               int flags);
 
 extern int parse_options_step(struct parse_opt_ctx_t *ctx,
                              const struct option *options,
@@ -178,6 +190,4 @@ extern int parse_opt_with_commit(const struct option *, const char *, int);
          "use <n> digits to display SHA-1s", \
          PARSE_OPT_OPTARG, &parse_opt_abbrev_cb, 0 }
 
-extern const char *parse_options_fix_filename(const char *prefix, const char *file);
-
 #endif
diff --git a/path.c b/path.c
index 8a0a6741fd664f98f2883348c0a755d60616035b..047fdb0a1fe8151f5f275ca5333365df786a8abd 100644 (file)
--- a/path.c
+++ b/path.c
@@ -139,6 +139,22 @@ int git_mkstemp(char *path, size_t len, const char *template)
        return mkstemp(path);
 }
 
+/* git_mkstemps() - create tmp file with suffix honoring TMPDIR variable. */
+int git_mkstemps(char *path, size_t len, const char *template, int suffix_len)
+{
+       const char *tmp;
+       size_t n;
+
+       tmp = getenv("TMPDIR");
+       if (!tmp)
+               tmp = "/tmp";
+       n = snprintf(path, len, "%s/%s", tmp, template);
+       if (len <= n) {
+               errno = ENAMETOOLONG;
+               return -1;
+       }
+       return mkstemps(path, suffix_len);
+}
 
 int validate_headref(const char *path)
 {
index a0ef356558f4cdb148010f1b47dbd3fcc363d8ba..e5328dab5b2978d90d20f47ed799782e7b2fb63b 100644 (file)
--- a/pretty.c
+++ b/pretty.c
@@ -284,7 +284,7 @@ static char *replace_encoding_header(char *buf, const char *encoding)
 static char *logmsg_reencode(const struct commit *commit,
                             const char *output_encoding)
 {
-       static const char *utf8 = "utf-8";
+       static const char *utf8 = "UTF-8";
        const char *use_encoding;
        char *encoding;
        char *out;
@@ -881,7 +881,7 @@ char *reencode_commit_message(const struct commit *commit, const char **encoding
                    ? git_log_output_encoding
                    : git_commit_encoding);
        if (!encoding)
-               encoding = "utf-8";
+               encoding = "UTF-8";
        if (encoding_p)
                *encoding_p = encoding;
        return logmsg_reencode(commit, encoding);
index 2c3e9053a492e0029eb1f98a8d2c649564888197..08a59644c03b9c61bfad8383e521ac813e0c4f05 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -1085,12 +1085,20 @@ static const struct refspec *check_pattern_match(const struct refspec *rs,
                return NULL;
 }
 
+static struct ref **tail_ref(struct ref **head)
+{
+       struct ref **tail = head;
+       while (*tail)
+               tail = &((*tail)->next);
+       return tail;
+}
+
 /*
  * Note. This is used only by "push"; refspec matching rules for
  * push and fetch are subtly different, so do not try to reuse it
  * without thinking.
  */
-int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
+int match_refs(struct ref *src, struct ref **dst,
               int nr_refspec, const char **refspec, int flags)
 {
        struct refspec *rs;
@@ -1098,13 +1106,14 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
        int send_mirror = flags & MATCH_REFS_MIRROR;
        int errs;
        static const char *default_refspec[] = { ":", 0 };
+       struct ref **dst_tail = tail_ref(dst);
 
        if (!nr_refspec) {
                nr_refspec = 1;
                refspec = default_refspec;
        }
        rs = parse_push_refspec(nr_refspec, (const char **) refspec);
-       errs = match_explicit_refs(src, dst, dst_tail, rs, nr_refspec);
+       errs = match_explicit_refs(src, *dst, &dst_tail, rs, nr_refspec);
 
        /* pick the remainder */
        for ( ; src; src = src->next) {
@@ -1134,7 +1143,7 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
                                                     dst_side, &dst_name))
                                die("Didn't think it matches any more");
                }
-               dst_peer = find_ref_by_name(dst, dst_name);
+               dst_peer = find_ref_by_name(*dst, dst_name);
                if (dst_peer) {
                        if (dst_peer->peer_ref)
                                /* We're already sending something to this ref. */
@@ -1150,7 +1159,7 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
                                goto free_name;
 
                        /* Create a new one and link it */
-                       dst_peer = make_linked_ref(dst_name, dst_tail);
+                       dst_peer = make_linked_ref(dst_name, &dst_tail);
                        hashcpy(dst_peer->new_sha1, src->new_sha1);
                }
                dst_peer->peer_ref = copy_ref(src);
index 99706a89bc6011c01fcd661d8bad4b26f59b0ca7..257a55538f3ff2d6330b84436a40d6ef972025a0 100644 (file)
--- a/remote.h
+++ b/remote.h
@@ -85,7 +85,7 @@ void ref_remove_duplicates(struct ref *ref_map);
 int valid_fetch_refspec(const char *refspec);
 struct refspec *parse_fetch_refspec(int nr_refspec, const char **refspec);
 
-int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
+int match_refs(struct ref *src, struct ref **dst,
               int nr_refspec, const char **refspec, int all);
 
 /*
index 18b7ebbbd599417462b5c4275c2581b91ebeca6a..bf584483675ef55b2ed9b8d8586b92d5432759a5 100644 (file)
@@ -256,10 +256,12 @@ static int everybody_uninteresting(struct commit_list *orig)
 
 /*
  * The goal is to get REV_TREE_NEW as the result only if the
- * diff consists of all '+' (and no other changes), and
- * REV_TREE_DIFFERENT otherwise (of course if the trees are
- * the same we want REV_TREE_SAME).  That means that once we
- * get to REV_TREE_DIFFERENT, we do not have to look any further.
+ * diff consists of all '+' (and no other changes), REV_TREE_OLD
+ * if the whole diff is removal of old data, and otherwise
+ * REV_TREE_DIFFERENT (of course if the trees are the same we
+ * want REV_TREE_SAME).
+ * That means that once we get to REV_TREE_DIFFERENT, we do not
+ * have to look any further.
  */
 static int tree_difference = REV_TREE_SAME;
 
@@ -268,22 +270,9 @@ static void file_add_remove(struct diff_options *options,
                    const unsigned char *sha1,
                    const char *fullpath)
 {
-       int diff = REV_TREE_DIFFERENT;
+       int diff = addremove == '+' ? REV_TREE_NEW : REV_TREE_OLD;
 
-       /*
-        * Is it an add of a new file? It means that the old tree
-        * didn't have it at all, so we will turn "REV_TREE_SAME" ->
-        * "REV_TREE_NEW", but leave any "REV_TREE_DIFFERENT" alone
-        * (and if it already was "REV_TREE_NEW", we'll keep it
-        * "REV_TREE_NEW" of course).
-        */
-       if (addremove == '+') {
-               diff = tree_difference;
-               if (diff != REV_TREE_SAME)
-                       return;
-               diff = REV_TREE_NEW;
-       }
-       tree_difference = diff;
+       tree_difference |= diff;
        if (tree_difference == REV_TREE_DIFFERENT)
                DIFF_OPT_SET(options, HAS_CHANGES);
 }
@@ -305,6 +294,8 @@ static int rev_compare_tree(struct rev_info *revs, struct commit *parent, struct
 
        if (!t1)
                return REV_TREE_NEW;
+       if (!t2)
+               return REV_TREE_OLD;
 
        if (revs->simplify_by_decoration) {
                /*
@@ -323,8 +314,7 @@ static int rev_compare_tree(struct rev_info *revs, struct commit *parent, struct
                if (!revs->prune_data)
                        return REV_TREE_SAME;
        }
-       if (!t2)
-               return REV_TREE_DIFFERENT;
+
        tree_difference = REV_TREE_SAME;
        DIFF_OPT_CLR(&revs->pruning, HAS_CHANGES);
        if (diff_tree_sha1(t1->object.sha1, t2->object.sha1, "",
@@ -429,6 +419,7 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
                                p->parents = NULL;
                        }
                /* fallthrough */
+               case REV_TREE_OLD:
                case REV_TREE_DIFFERENT:
                        tree_changed = 1;
                        pp = &parent->next;
index be39e7d38643817cced4e07a89b6db5201f2b747..227164cf7096d3b0642714b18ee345738684da79 100644 (file)
@@ -118,8 +118,9 @@ struct rev_info {
 };
 
 #define REV_TREE_SAME          0
-#define REV_TREE_NEW           1
-#define REV_TREE_DIFFERENT     2
+#define REV_TREE_NEW           1       /* Only new files */
+#define REV_TREE_OLD           2       /* Only files removed */
+#define REV_TREE_DIFFERENT     3       /* Mixed changes */
 
 /* revision.c */
 void read_revisions_from_stdin(struct rev_info *revs);
index 1d6b35b858020300f502e2a9341b82d4fa8a61fd..8dcd63261fff56e54c233224c6014b146d9bbeb3 100644 (file)
@@ -196,8 +196,9 @@ void invalidate_lstat_cache(const char *name, int len)
                        cache.path[previous_slash] = '\0';
                        cache.len = previous_slash;
                        cache.flags = FL_DIR;
-               } else
+               } else {
                        reset_lstat_cache();
+               }
        }
 }
 
@@ -263,7 +264,6 @@ static void do_remove_scheduled_dirs(int new_len)
                         removal.path[removal.len] != '/');
        }
        removal.len = new_len;
-       return;
 }
 
 void schedule_dir_for_removal(const char *name, int len)
@@ -296,11 +296,9 @@ void schedule_dir_for_removal(const char *name, int len)
                       last_slash - match_len);
                removal.len = last_slash;
        }
-       return;
 }
 
 void remove_scheduled_dirs(void)
 {
        do_remove_scheduled_dirs(0);
-       return;
 }
index cde659d14ac599e78bb4cd12a2ad88eab179549e..6765b08065e8959dcec38940188818b952d2fcd0 100644 (file)
@@ -93,14 +93,16 @@ prepare_httpd() {
 start_httpd() {
        prepare_httpd >&3 2>&4
 
-       trap 'stop_httpd; die' EXIT
+       trap 'code=$?; stop_httpd; (exit $code); die' EXIT
 
        "$LIB_HTTPD_PATH" -d "$HTTPD_ROOT_PATH" \
                -f "$TEST_PATH/apache.conf" $HTTPD_PARA \
                -c "Listen 127.0.0.1:$LIB_HTTPD_PORT" -k start \
                >&3 2>&4
-       if ! test $? = 0; then
+       if test $? -ne 0
+       then
                say "skipping test, web server setup failed"
+               trap 'die' EXIT
                test_done
        fi
 }
index a40c1236c0862da4d77231bf9255b499ccddd99f..bbc821ef97de76ef532ec1d1d704da15e8973500 100755 (executable)
@@ -19,6 +19,7 @@ usage: test-parse-options <options>
     --set23               set integer to 23
     -t <time>             get timestamp of <time>
     -L, --length <str>    get length of <str>
+    -F, --file <FILE>     set file to <FILE>
 
 String options
     -s, --string <string>
@@ -56,10 +57,12 @@ abbrev: 7
 verbose: 2
 quiet: no
 dry run: yes
+file: prefix/my.file
 EOF
 
 test_expect_success 'short options' '
-       test-parse-options -s123 -b -i 1729 -b -vv -n > output 2> output.err &&
+       test-parse-options -s123 -b -i 1729 -b -vv -n -F my.file \
+       > output 2> output.err &&
        test_cmp expect output &&
        test ! -s output.err
 '
@@ -73,11 +76,12 @@ abbrev: 10
 verbose: 2
 quiet: no
 dry run: no
+file: prefix/fi.le
 EOF
 
 test_expect_success 'long options' '
        test-parse-options --boolean --integer 1729 --boolean --string2=321 \
-               --verbose --verbose --no-dry-run --abbrev=10 \
+               --verbose --verbose --no-dry-run --abbrev=10 --file fi.le\
                > output 2> output.err &&
        test ! -s output.err &&
        test_cmp expect output
@@ -87,6 +91,8 @@ test_expect_success 'missing required value' '
        test-parse-options -s;
        test $? = 129 &&
        test-parse-options --string;
+       test $? = 129 &&
+       test-parse-options --file;
        test $? = 129
 '
 
@@ -99,6 +105,7 @@ abbrev: 7
 verbose: 0
 quiet: no
 dry run: no
+file: (not set)
 arg 00: a1
 arg 01: b1
 arg 02: --boolean
@@ -120,6 +127,7 @@ abbrev: 7
 verbose: 0
 quiet: no
 dry run: no
+file: (not set)
 EOF
 
 test_expect_success 'unambiguously abbreviated option' '
@@ -148,6 +156,7 @@ abbrev: 7
 verbose: 0
 quiet: no
 dry run: no
+file: (not set)
 EOF
 
 test_expect_success 'non ambiguous option (after two options it abbreviates)' '
@@ -175,6 +184,7 @@ abbrev: 7
 verbose: 0
 quiet: no
 dry run: no
+file: (not set)
 arg 00: --quux
 EOF
 
@@ -193,6 +203,7 @@ abbrev: 7
 verbose: 0
 quiet: yes
 dry run: no
+file: (not set)
 arg 00: foo
 EOF
 
@@ -213,6 +224,7 @@ abbrev: 7
 verbose: 0
 quiet: no
 dry run: no
+file: (not set)
 EOF
 
 test_expect_success 'OPT_CALLBACK() and OPT_BIT() work' '
@@ -240,6 +252,7 @@ abbrev: 7
 verbose: 0
 quiet: no
 dry run: no
+file: (not set)
 EOF
 
 test_expect_success 'OPT_BIT() and OPT_SET_INT() work' '
@@ -263,6 +276,7 @@ abbrev: 7
 verbose: 0
 quiet: no
 dry run: no
+file: (not set)
 EOF
 
 test_expect_success 'OPT_BIT() works' '
@@ -292,6 +306,7 @@ abbrev: 7
 verbose: 0
 quiet: no
 dry run: no
+file: (not set)
 EOF
 
 test_expect_success 'OPT_NUMBER_CALLBACK() works' '
diff --git a/t/t1010-mktree.sh b/t/t1010-mktree.sh
new file mode 100755 (executable)
index 0000000..9956e3a
--- /dev/null
@@ -0,0 +1,71 @@
+#!/bin/sh
+
+test_description='git mktree'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+       for d in a a. a0
+       do
+               mkdir "$d" && echo "$d/one" >"$d/one" &&
+               git add "$d"
+       done &&
+       echo zero >one &&
+       git update-index --add --info-only one &&
+       git write-tree --missing-ok >tree.missing &&
+       git ls-tree $(cat tree.missing) >top.missing &&
+       git ls-tree -r $(cat tree.missing) >all.missing &&
+       echo one >one &&
+       git add one &&
+       git write-tree >tree &&
+       git ls-tree $(cat tree) >top &&
+       git ls-tree -r $(cat tree) >all &&
+       test_tick &&
+       git commit -q -m one &&
+       H=$(git rev-parse HEAD) &&
+       git update-index --add --cacheinfo 160000 $H sub &&
+       test_tick &&
+       git commit -q -m two &&
+       git rev-parse HEAD^{tree} >tree.withsub &&
+       git ls-tree HEAD >top.withsub &&
+       git ls-tree -r HEAD >all.withsub
+'
+
+test_expect_success 'ls-tree piped to mktree (1)' '
+       git mktree <top >actual &&
+       test_cmp tree actual
+'
+
+test_expect_success 'ls-tree piped to mktree (2)' '
+       git mktree <top.withsub >actual &&
+       test_cmp tree.withsub actual
+'
+
+test_expect_success 'ls-tree output in wrong order given to mktree (1)' '
+       perl -e "print reverse <>" <top |
+       git mktree >actual &&
+       test_cmp tree actual
+'
+
+test_expect_success 'ls-tree output in wrong order given to mktree (2)' '
+       perl -e "print reverse <>" <top.withsub |
+       git mktree >actual &&
+       test_cmp tree.withsub actual
+'
+
+test_expect_success 'allow missing object with --missing' '
+       git mktree --missing <top.missing >actual &&
+       test_cmp tree.missing actual
+'
+
+test_expect_failure 'mktree reads ls-tree -r output (1)' '
+       git mktree <all >actual &&
+       test_cmp tree actual
+'
+
+test_expect_failure 'mktree reads ls-tree -r output (2)' '
+       git mktree <all.withsub >actual &&
+       test_cmp tree.withsub actual
+'
+
+test_done
index 050de42ef4148a730c30520ccaad5e9871e536bd..6ce8256a17bb7c775eed301b3af8a88497a12c09 100755 (executable)
@@ -230,4 +230,16 @@ test_expect_success BSLASHPSPEC "git add 'fo\\[ou\\]bar' ignores foobar" '
        ! ( git ls-files foobar | grep foobar )
 '
 
+test_expect_success 'git add to resolve conflicts on otherwise ignored path' '
+       git reset --hard &&
+       H=$(git rev-parse :1/2/a) &&
+       (
+               echo "100644 $H 1       track-this"
+               echo "100644 $H 3       track-this"
+       ) | git update-index --index-info &&
+       echo track-this >>.gitignore &&
+       echo resolved >track-this &&
+       git add track-this
+'
+
 test_done
index dfc65601aa2171bfc9321753a3d90db112d81f72..fd2a55a5c23247c010a02513af73a93641cfb067 100755 (executable)
@@ -165,4 +165,42 @@ test_expect_success FILEMODE 'stage mode but not hunk' '
 
 # end of tests disabled when filemode is not usable
 
+test_expect_success 'setup again' '
+       git reset --hard &&
+       test_chmod +x file &&
+       echo content >>file
+'
+
+# Write the patch file with a new line at the top and bottom
+cat >patch <<EOF
+index 180b47c..b6f2c08 100644
+--- a/file
++++ b/file
+@@ -1,2 +1,4 @@
++firstline
+ baseline
+ content
++lastline
+EOF
+# Expected output, similar to the patch but w/ diff at the top
+cat >expected <<EOF
+diff --git a/file b/file
+index b6f2c08..61b9053 100755
+--- a/file
++++ b/file
+@@ -1,2 +1,4 @@
++firstline
+ baseline
+ content
++lastline
+EOF
+# Test splitting the first patch, then adding both
+test_expect_success 'add first line works' '
+       git commit -am "clear local changes" &&
+       git apply patch &&
+       (echo s; echo y; echo y) | git add -p file &&
+       git diff --cached > diff &&
+       test_cmp expected diff
+'
+
 test_done
index b4ec2b53de2662a5ba40602d4b7a4fde984c4013..256c4c970145aa9f59e58ee1b0da4c6281b6d9e5 100755 (executable)
@@ -34,7 +34,7 @@ test_expect_success 'no encoding header for base case' '
        test z = "z$E"
 '
 
-for H in ISO-8859-1 EUCJP ISO-2022-JP
+for H in ISO8859-1 eucJP ISO-2022-JP
 do
        test_expect_success "$H setup" '
                git config i18n.commitencoding $H &&
@@ -44,7 +44,7 @@ do
        '
 done
 
-for H in ISO-8859-1 EUCJP ISO-2022-JP
+for H in ISO8859-1 eucJP ISO-2022-JP
 do
        test_expect_success "check encoding header for $H" '
                E=$(git cat-file commit '$H' | sed -ne "s/^encoding //p") &&
@@ -61,14 +61,14 @@ test_expect_success 'config to remove customization' '
        else
                test z = "z$Z"
        fi &&
-       git config i18n.commitencoding utf-8
+       git config i18n.commitencoding UTF-8
 '
 
-test_expect_success 'ISO-8859-1 should be shown in UTF-8 now' '
-       compare_with ISO-8859-1 "$TEST_DIRECTORY"/t3900/1-UTF-8.txt
+test_expect_success 'ISO8859-1 should be shown in UTF-8 now' '
+       compare_with ISO8859-1 "$TEST_DIRECTORY"/t3900/1-UTF-8.txt
 '
 
-for H in EUCJP ISO-2022-JP
+for H in eucJP ISO-2022-JP
 do
        test_expect_success "$H should be shown in UTF-8 now" '
                compare_with '$H' "$TEST_DIRECTORY"/t3900/2-UTF-8.txt
@@ -86,7 +86,7 @@ test_expect_success 'config to add customization' '
        fi
 '
 
-for H in ISO-8859-1 EUCJP ISO-2022-JP
+for H in ISO8859-1 eucJP ISO-2022-JP
 do
        test_expect_success "$H should be shown in itself now" '
                git config i18n.commitencoding '$H' &&
@@ -95,21 +95,21 @@ do
 done
 
 test_expect_success 'config to tweak customization' '
-       git config i18n.logoutputencoding utf-8
+       git config i18n.logoutputencoding UTF-8
 '
 
-test_expect_success 'ISO-8859-1 should be shown in UTF-8 now' '
-       compare_with ISO-8859-1 "$TEST_DIRECTORY"/t3900/1-UTF-8.txt
+test_expect_success 'ISO8859-1 should be shown in UTF-8 now' '
+       compare_with ISO8859-1 "$TEST_DIRECTORY"/t3900/1-UTF-8.txt
 '
 
-for H in EUCJP ISO-2022-JP
+for H in eucJP ISO-2022-JP
 do
        test_expect_success "$H should be shown in UTF-8 now" '
                compare_with '$H' "$TEST_DIRECTORY"/t3900/2-UTF-8.txt
        '
 done
 
-for J in EUCJP ISO-2022-JP
+for J in eucJP ISO-2022-JP
 do
        if test "$J" = ISO-2022-JP
        then
@@ -118,7 +118,7 @@ do
                ICONV=
        fi
        git config i18n.logoutputencoding $J
-       for H in EUCJP ISO-2022-JP
+       for H in eucJP ISO-2022-JP
        do
                test_expect_success "$H should be shown in $J now" '
                        compare_with '$H' "$TEST_DIRECTORY"/t3900/'$J'.txt $ICONV
@@ -126,7 +126,7 @@ do
        done
 done
 
-for H in ISO-8859-1 EUCJP ISO-2022-JP
+for H in ISO8859-1 eucJP ISO-2022-JP
 do
        test_expect_success "No conversion with $H" '
                compare_with "--encoding=none '$H'" "$TEST_DIRECTORY"/t3900/'$H'.txt
diff --git a/t/t3900/EUCJP.txt b/t/t3900/EUCJP.txt
deleted file mode 100644 (file)
index 546f2aa..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-¤Ï¤ì¤Ò¤Û¤Õ
-
-¤·¤Æ¤¤¤ë¤Î¤¬¡¢¤¤¤ë¤Î¤Ç¡£
-ßÀÉͤۤì¤×¤ê¤Ý¤ì¤Þ¤Ó¤°¤ê¤í¤Ø¡£
diff --git a/t/t3900/ISO-8859-1.txt b/t/t3900/ISO-8859-1.txt
deleted file mode 100644 (file)
index 7cbef0e..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-ÄËÑÏÖ
-
-Ábçdèfg
diff --git a/t/t3900/ISO8859-1.txt b/t/t3900/ISO8859-1.txt
new file mode 100644 (file)
index 0000000..7cbef0e
--- /dev/null
@@ -0,0 +1,3 @@
+ÄËÑÏÖ
+
+Ábçdèfg
diff --git a/t/t3900/eucJP.txt b/t/t3900/eucJP.txt
new file mode 100644 (file)
index 0000000..546f2aa
--- /dev/null
@@ -0,0 +1,4 @@
+¤Ï¤ì¤Ò¤Û¤Õ
+
+¤·¤Æ¤¤¤ë¤Î¤¬¡¢¤¤¤ë¤Î¤Ç¡£
+ßÀÉͤۤì¤×¤ê¤Ý¤ì¤Þ¤Ó¤°¤ê¤í¤Ø¡£
index 7655da3f8d5e68f293ae5afe2d58dd41b1396f37..31a5770b34466c9ed52a9f00bac27b71fd6e0deb 100755 (executable)
@@ -17,9 +17,9 @@ check_encoding () {
                git cat-file commit HEAD~$j |
                case "$header" in
                8859)
-                       grep "^encoding ISO-8859-1" ;;
+                       grep "^encoding ISO8859-1" ;;
                *)
-                       ! grep "^encoding ISO-8859-1" ;;
+                       grep "^encoding ISO8859-1"; test "$?" != 0 ;;
                esac || {
                        bad=1
                        break
@@ -55,7 +55,7 @@ test_expect_success setup '
        git commit -s -m "Second on side" &&
 
        # the second one on the side branch is ISO-8859-1
-       git config i18n.commitencoding ISO-8859-1 &&
+       git config i18n.commitencoding ISO8859-1 &&
        # use author and committer name in ISO-8859-1 to match it.
        . "$TEST_DIRECTORY"/t3901-8859-1.txt &&
        test_tick &&
@@ -68,14 +68,14 @@ test_expect_success setup '
 '
 
 test_expect_success 'format-patch output (ISO-8859-1)' '
-       git config i18n.logoutputencoding ISO-8859-1 &&
+       git config i18n.logoutputencoding ISO8859-1 &&
 
        git format-patch --stdout master..HEAD^ >out-l1 &&
        git format-patch --stdout HEAD^ >out-l2 &&
-       grep "^Content-Type: text/plain; charset=ISO-8859-1" out-l1 &&
-       grep "^From: =?ISO-8859-1?q?=C1=E9=ED=20=F3=FA?=" out-l1 &&
-       grep "^Content-Type: text/plain; charset=ISO-8859-1" out-l2 &&
-       grep "^From: =?ISO-8859-1?q?=C1=E9=ED=20=F3=FA?=" out-l2
+       grep "^Content-Type: text/plain; charset=ISO8859-1" out-l1 &&
+       grep "^From: =?ISO8859-1?q?=C1=E9=ED=20=F3=FA?=" out-l1 &&
+       grep "^Content-Type: text/plain; charset=ISO8859-1" out-l2 &&
+       grep "^From: =?ISO8859-1?q?=C1=E9=ED=20=F3=FA?=" out-l2
 '
 
 test_expect_success 'format-patch output (UTF-8)' '
@@ -110,7 +110,7 @@ test_expect_success 'rebase (U/U)' '
 
 test_expect_success 'rebase (U/L)' '
        git config i18n.commitencoding UTF-8 &&
-       git config i18n.logoutputencoding ISO-8859-1 &&
+       git config i18n.logoutputencoding ISO8859-1 &&
        . "$TEST_DIRECTORY"/t3901-utf8.txt &&
 
        git reset --hard side &&
@@ -121,8 +121,8 @@ test_expect_success 'rebase (U/L)' '
 
 test_expect_success 'rebase (L/L)' '
        # In this test we want ISO-8859-1 encoded commits as the result
-       git config i18n.commitencoding ISO-8859-1 &&
-       git config i18n.logoutputencoding ISO-8859-1 &&
+       git config i18n.commitencoding ISO8859-1 &&
+       git config i18n.logoutputencoding ISO8859-1 &&
        . "$TEST_DIRECTORY"/t3901-8859-1.txt &&
 
        git reset --hard side &&
@@ -134,7 +134,7 @@ test_expect_success 'rebase (L/L)' '
 test_expect_success 'rebase (L/U)' '
        # This is pathological -- use UTF-8 as intermediate form
        # to get ISO-8859-1 results.
-       git config i18n.commitencoding ISO-8859-1 &&
+       git config i18n.commitencoding ISO8859-1 &&
        git config i18n.logoutputencoding UTF-8 &&
        . "$TEST_DIRECTORY"/t3901-8859-1.txt &&
 
@@ -162,8 +162,8 @@ test_expect_success 'cherry-pick(U/U)' '
 test_expect_success 'cherry-pick(L/L)' '
        # Both the commitencoding and logoutputencoding is set to ISO-8859-1
 
-       git config i18n.commitencoding ISO-8859-1 &&
-       git config i18n.logoutputencoding ISO-8859-1 &&
+       git config i18n.commitencoding ISO8859-1 &&
+       git config i18n.logoutputencoding ISO8859-1 &&
        . "$TEST_DIRECTORY"/t3901-8859-1.txt &&
 
        git reset --hard master &&
@@ -178,7 +178,7 @@ test_expect_success 'cherry-pick(U/L)' '
        # Commitencoding is set to UTF-8 but logoutputencoding is ISO-8859-1
 
        git config i18n.commitencoding UTF-8 &&
-       git config i18n.logoutputencoding ISO-8859-1 &&
+       git config i18n.logoutputencoding ISO8859-1 &&
        . "$TEST_DIRECTORY"/t3901-utf8.txt &&
 
        git reset --hard master &&
@@ -193,7 +193,7 @@ test_expect_success 'cherry-pick(L/U)' '
        # Again, the commitencoding is set to ISO-8859-1 but
        # logoutputencoding is set to UTF-8.
 
-       git config i18n.commitencoding ISO-8859-1 &&
+       git config i18n.commitencoding ISO8859-1 &&
        git config i18n.logoutputencoding UTF-8 &&
        . "$TEST_DIRECTORY"/t3901-8859-1.txt &&
 
@@ -218,7 +218,7 @@ test_expect_success 'rebase --merge (U/U)' '
 
 test_expect_success 'rebase --merge (U/L)' '
        git config i18n.commitencoding UTF-8 &&
-       git config i18n.logoutputencoding ISO-8859-1 &&
+       git config i18n.logoutputencoding ISO8859-1 &&
        . "$TEST_DIRECTORY"/t3901-utf8.txt &&
 
        git reset --hard side &&
@@ -229,8 +229,8 @@ test_expect_success 'rebase --merge (U/L)' '
 
 test_expect_success 'rebase --merge (L/L)' '
        # In this test we want ISO-8859-1 encoded commits as the result
-       git config i18n.commitencoding ISO-8859-1 &&
-       git config i18n.logoutputencoding ISO-8859-1 &&
+       git config i18n.commitencoding ISO8859-1 &&
+       git config i18n.logoutputencoding ISO8859-1 &&
        . "$TEST_DIRECTORY"/t3901-8859-1.txt &&
 
        git reset --hard side &&
@@ -242,7 +242,7 @@ test_expect_success 'rebase --merge (L/L)' '
 test_expect_success 'rebase --merge (L/U)' '
        # This is pathological -- use UTF-8 as intermediate form
        # to get ISO-8859-1 results.
-       git config i18n.commitencoding ISO-8859-1 &&
+       git config i18n.commitencoding ISO8859-1 &&
        git config i18n.logoutputencoding UTF-8 &&
        . "$TEST_DIRECTORY"/t3901-8859-1.txt &&
 
index 0720001281db6aeb5a3b6bb46cd6914ad7d78d33..4ea42e00dad9bf15e221e6eac5d91748cb0a07e7 100755 (executable)
@@ -136,6 +136,15 @@ test_expect_success 'GIT_EXTERNAL_DIFF with more than one changed files' '
        GIT_EXTERNAL_DIFF=echo git diff
 '
 
+test_expect_success 'GIT_EXTERNAL_DIFF generates pretty paths' '
+       touch file.ext &&
+       git add file.ext &&
+       echo with extension > file.ext &&
+       GIT_EXTERNAL_DIFF=echo git diff file.ext | grep ......_file\.ext &&
+       git update-index --force-remove file.ext &&
+       rm file.ext
+'
+
 echo "#!$SHELL_PATH" >fake-diff.sh
 cat >> fake-diff.sh <<\EOF
 cat $2 >> crlfed.txt
diff --git a/t/t4131-apply-fake-ancestor.sh b/t/t4131-apply-fake-ancestor.sh
new file mode 100755 (executable)
index 0000000..94373ca
--- /dev/null
@@ -0,0 +1,42 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Stephen Boyd
+#
+
+test_description='git apply --build-fake-ancestor handling.'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+       test_commit 1 &&
+       test_commit 2 &&
+       mkdir sub &&
+       test_commit 3 sub/3 &&
+       test_commit 4
+'
+
+test_expect_success 'apply --build-fake-ancestor' '
+       git checkout 2 &&
+       echo "A" > 1.t &&
+       git diff > 1.patch &&
+       git reset --hard &&
+       git checkout 1 &&
+       git apply --build-fake-ancestor 1.ancestor 1.patch
+'
+
+test_expect_success 'apply --build-fake-ancestor in a subdirectory' '
+       git checkout 3 &&
+       echo "C" > sub/3.t &&
+       git diff > 3.patch &&
+       git reset --hard &&
+       git checkout 4 &&
+       (
+               cd sub &&
+               git apply --build-fake-ancestor 3.ancestor ../3.patch &&
+               test -f 3.ancestor
+       ) &&
+       git apply --build-fake-ancestor 3.ancestor 3.patch &&
+       test_cmp sub/3.ancestor 3.ancestor
+'
+
+test_done
index 3ca2470da2ef8e082bfbb210ee9acf651b6588d6..1fc224810da6f02fbb4407bd030ab5aee3f3ef50 100644 (file)
@@ -1,48 +1,48 @@
 From nobody Mon Sep 17 00:00:00 2001
 From: =?US-ASCII?Q?Keith_Moore?= <moore@cs.utk.edu>
-To: =?ISO-8859-1?Q?Keld_J=F8rn_Simonsen?= <keld@dkuug.dk>
-CC: =?ISO-8859-1?Q?Andr=E9?= Pirard <PIRARD@vm1.ulg.ac.be>
-Subject: =?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?=
- =?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=
+To: =?ISO8859-1?Q?Keld_J=F8rn_Simonsen?= <keld@dkuug.dk>
+CC: =?ISO8859-1?Q?Andr=E9?= Pirard <PIRARD@vm1.ulg.ac.be>
+Subject: =?ISO8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?=
+ =?ISO8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=
 
 From nobody Mon Sep 17 00:00:00 2001
-From: =?ISO-8859-1?Q?Olle_J=E4rnefors?= <ojarnef@admin.kth.se>
+From: =?ISO8859-1?Q?Olle_J=E4rnefors?= <ojarnef@admin.kth.se>
 To: ietf-822@dimacs.rutgers.edu, ojarnef@admin.kth.se
 Subject: Time for ISO 10646?
 
 From nobody Mon Sep 17 00:00:00 2001
 To: Dave Crocker <dcrocker@mordor.stanford.edu>
 Cc: ietf-822@dimacs.rutgers.edu, paf@comsol.se
-From: =?ISO-8859-1?Q?Patrik_F=E4ltstr=F6m?= <paf@nada.kth.se>
+From: =?ISO8859-1?Q?Patrik_F=E4ltstr=F6m?= <paf@nada.kth.se>
 Subject: Re: RFC-HDR care and feeding
 
 From nobody Mon Sep 17 00:00:00 2001
 From: Nathaniel Borenstein <nsb@thumper.bellcore.com>
-      (=?iso-8859-8?b?7eXs+SDv4SDp7Oj08A==?=)
+      (=?ISO8859-8?b?7eXs+SDv4SDp7Oj08A==?=)
 To: Greg Vaudreuil <gvaudre@NRI.Reston.VA.US>, Ned Freed
    <ned@innosoft.com>, Keith Moore <moore@cs.utk.edu>
 Subject: Test of new header generator
 MIME-Version: 1.0
-Content-type: text/plain; charset=ISO-8859-1
+Content-type: text/plain; charset=ISO8859-1
 
 From nobody Mon Sep 17 00:00:00 2001
-Subject: (=?ISO-8859-1?Q?a?=)
+Subject: (=?ISO8859-1?Q?a?=)
 
 From nobody Mon Sep 17 00:00:00 2001
-Subject: (=?ISO-8859-1?Q?a?= b)
+Subject: (=?ISO8859-1?Q?a?= b)
 
 From nobody Mon Sep 17 00:00:00 2001
-Subject: (=?ISO-8859-1?Q?a?= =?ISO-8859-1?Q?b?=)
+Subject: (=?ISO8859-1?Q?a?= =?ISO8859-1?Q?b?=)
 
 From nobody Mon Sep 17 00:00:00 2001
-Subject: (=?ISO-8859-1?Q?a?=  =?ISO-8859-1?Q?b?=)
+Subject: (=?ISO8859-1?Q?a?=  =?ISO8859-1?Q?b?=)
 
 From nobody Mon Sep 17 00:00:00 2001
-Subject: (=?ISO-8859-1?Q?a?=
-    =?ISO-8859-1?Q?b?=)
+Subject: (=?ISO8859-1?Q?a?=
+    =?ISO8859-1?Q?b?=)
 
 From nobody Mon Sep 17 00:00:00 2001
-Subject: (=?ISO-8859-1?Q?a_b?=)
+Subject: (=?ISO8859-1?Q?a_b?=)
 
 From nobody Mon Sep 17 00:00:00 2001
-Subject: (=?ISO-8859-1?Q?a?= =?ISO-8859-2?Q?_b?=)
+Subject: (=?ISO8859-1?Q?a?= =?ISO8859-2?Q?_b?=)
index c5ad206b40e1fcf79019cebdfd848d72c17cefcc..c3074ac5736fe266e901b4da3b060208cd71406e 100644 (file)
@@ -99,7 +99,7 @@ index 9123cdc..918dcf8 100644
 From nobody Sat Aug 27 23:07:49 2005
 Path: news.gmane.org!not-for-mail
 Message-ID: <20050721.091036.01119516.yoshfuji@linux-ipv6.org>
-From: YOSHIFUJI Hideaki / =?iso-2022-jp?B?GyRCNUhGIzFRTEAbKEI=?= 
+From: YOSHIFUJI Hideaki / =?ISO-2022-JP?B?GyRCNUhGIzFRTEAbKEI=?= 
        <yoshfuji@linux-ipv6.org>
 Newsgroups: gmane.comp.version-control.git
 Subject: [PATCH 1/2] GIT: Try all addresses for given remote name
@@ -218,7 +218,7 @@ GPG-FP  : 9022 65EB 1ECF 3AD1 0BDF  80D8 4807 F894 E062 0EEA
 From nobody Sat Aug 27 23:07:49 2005
 Path: news.gmane.org!not-for-mail
 Message-ID: <u5tacjjdpxq.fsf@lysator.liu.se>
-From: =?iso-8859-1?Q?David_K=E5gedal?= <davidk@lysator.liu.se>
+From: =?ISO8859-1?Q?David_K=E5gedal?= <davidk@lysator.liu.se>
 Newsgroups: gmane.comp.version-control.git
 Subject: [PATCH] Fixed two bugs in git-cvsimport-script.
 Date: Mon, 15 Aug 2005 20:18:25 +0200
@@ -226,7 +226,7 @@ Lines: 83
 Approved: news@gmane.org
 NNTP-Posting-Host: main.gmane.org
 Mime-Version: 1.0
-Content-Type: text/plain; charset=iso-8859-1
+Content-Type: text/plain; charset=ISO8859-1
 Content-Transfer-Encoding: QUOTED-PRINTABLE
 X-Trace: sea.gmane.org 1124130247 31839 80.91.229.2 (15 Aug 2005 18:24:07 GMT)
 X-Complaints-To: usenet@sea.gmane.org
@@ -476,7 +476,7 @@ MIME-Version: 1.0
 Content-Type: multipart/mixed; boundary="=-=-="
 
 --=-=-=
-Content-Type: text/plain; charset=iso-8859-15
+Content-Type: text/plain; charset=ISO8859-15
 Content-Transfer-Encoding: quoted-printable
 
 Here comes a commit log message, and
index c450f33f333e6f1c367f8f350dfd78f8f44a0fee..a8c2ca2a78dd54f69230cb443eff1d6e82336f0a 100755 (executable)
@@ -3,9 +3,8 @@
 # Copyright (c) 2005 Johannes Schindelin
 #
 
-test_description='Testing multi_ack pack fetching
+test_description='Testing multi_ack pack fetching'
 
-'
 . ./test-lib.sh
 
 # Test fetch-pack/upload-pack pair.
@@ -13,77 +12,60 @@ test_description='Testing multi_ack pack fetching
 # Some convenience functions
 
 add () {
-       name=$1
-       text="$@"
-       branch=`echo $name | sed -e 's/^\(.\).*$/\1/'`
-       parents=""
+       name=$1 &&
+       text="$@" &&
+       branch=`echo $name | sed -e 's/^\(.\).*$/\1/'` &&
+       parents="" &&
 
-       shift
+       shift &&
        while test $1; do
-               parents="$parents -p $1"
+               parents="$parents -p $1" &&
                shift
-       done
+       done &&
 
-       echo "$text" > test.txt
-       git update-index --add test.txt
-       tree=$(git write-tree)
+       echo "$text" > test.txt &&
+       git update-index --add test.txt &&
+       tree=$(git write-tree) &&
        # make sure timestamps are in correct order
-       sec=$(($sec+1))
-       commit=$(echo "$text" | GIT_AUTHOR_DATE=$sec \
-               git commit-tree $tree $parents 2>>log2.txt)
-       eval "$name=$commit; export $name"
-       echo $commit > .git/refs/heads/$branch
+       test_tick &&
+       commit=$(echo "$text" | git commit-tree $tree $parents) &&
+       eval "$name=$commit; export $name" &&
+       echo $commit > .git/refs/heads/$branch &&
        eval ${branch}TIP=$commit
 }
 
-count_objects () {
-       ls .git/objects/??/* 2>>log2.txt | wc -l | tr -d " "
-}
-
-test_expect_object_count () {
-       message=$1
-       count=$2
-
-       output="$(count_objects)"
-       test_expect_success \
-               "new object count $message" \
-               "test $count = $output"
-}
-
 pull_to_client () {
-       number=$1
-       heads=$2
-       count=$3
-       no_strict_count_check=$4
-
-       cd client
-       test_expect_success "$number pull" \
-               "git fetch-pack -k -v .. $heads"
-       case "$heads" in *A*) echo $ATIP > .git/refs/heads/A;; esac
-       case "$heads" in *B*) echo $BTIP > .git/refs/heads/B;; esac
-       git symbolic-ref HEAD refs/heads/`echo $heads | sed -e 's/^\(.\).*$/\1/'`
-
-       test_expect_success "fsck" 'git fsck --full > fsck.txt 2>&1'
-
-       test_expect_success 'check downloaded results' \
-       'mv .git/objects/pack/pack-* . &&
-        p=`ls -1 pack-*.pack` &&
-        git unpack-objects <$p &&
-        git fsck --full'
-
-       test_expect_success "new object count after $number pull" \
-       'idx=`echo pack-*.idx` &&
-        pack_count=`git show-index <$idx | wc -l` &&
-        test $pack_count = $count'
-       test -z "$pack_count" && pack_count=0
-       if [ -z "$no_strict_count_check" ]; then
-               test_expect_success "minimal count" "test $count = $pack_count"
-       else
-               test $count != $pack_count && \
-                       echo "WARNING: $pack_count objects transmitted, only $count of which were needed"
-       fi
-       rm -f pack-*
-       cd ..
+       number=$1 &&
+       heads=$2 &&
+       count=$3 &&
+       test_expect_success "$number pull" '
+               (
+                       cd client &&
+                       git fetch-pack -k -v .. $heads &&
+
+                       case "$heads" in
+                           *A*)
+                                   echo $ATIP > .git/refs/heads/A;;
+                       esac &&
+                       case "$heads" in *B*)
+                           echo $BTIP > .git/refs/heads/B;;
+                       esac &&
+                       git symbolic-ref HEAD refs/heads/`echo $heads \
+                               | sed -e "s/^\(.\).*$/\1/"` &&
+
+                       git fsck --full &&
+
+                       mv .git/objects/pack/pack-* . &&
+                       p=`ls -1 pack-*.pack` &&
+                       git unpack-objects <$p &&
+                       git fsck --full &&
+
+                       idx=`echo pack-*.idx` &&
+                       pack_count=`git show-index <$idx | wc -l` &&
+                       test $pack_count = $count &&
+                       rm -f pack-*
+               )
+       '
 }
 
 # Here begins the actual testing
@@ -94,89 +76,129 @@ pull_to_client () {
 
 # client pulls A20, B1. Then tracks only B. Then pulls A.
 
-(
+test_expect_success 'setup' '
        mkdir client &&
-       cd client &&
-       git init 2>> log2.txt &&
-       git config transfer.unpacklimit 0
-)
-
-add A1
-
-prev=1; cur=2; while [ $cur -le 10 ]; do
-       add A$cur $(eval echo \$A$prev)
-       prev=$cur
-       cur=$(($cur+1))
-done
-
-add B1 $A1
-
-echo $ATIP > .git/refs/heads/A
-echo $BTIP > .git/refs/heads/B
-git symbolic-ref HEAD refs/heads/B
+       (
+               cd client &&
+               git init &&
+               git config transfer.unpacklimit 0
+       ) &&
+       add A1 &&
+       prev=1 &&
+       cur=2 &&
+       while [ $cur -le 10 ]; do
+               add A$cur $(eval echo \$A$prev) &&
+               prev=$cur &&
+               cur=$(($cur+1))
+       done &&
+       add B1 $A1
+       echo $ATIP > .git/refs/heads/A &&
+       echo $BTIP > .git/refs/heads/B &&
+       git symbolic-ref HEAD refs/heads/B
+'
 
 pull_to_client 1st "B A" $((11*3))
 
-add A11 $A10
-
-prev=1; cur=2; while [ $cur -le 65 ]; do
-       add B$cur $(eval echo \$B$prev)
-       prev=$cur
-       cur=$(($cur+1))
-done
+test_expect_success 'post 1st pull setup' '
+       add A11 $A10 &&
+       prev=1 &&
+       cur=2 &&
+       while [ $cur -le 65 ]; do
+               add B$cur $(eval echo \$B$prev) &&
+               prev=$cur &&
+               cur=$(($cur+1))
+       done
+'
 
 pull_to_client 2nd "B" $((64*3))
 
-pull_to_client 3rd "A" $((1*3)) # old fails
-
-test_expect_success "clone shallow" 'git clone --depth 2 "file://$(pwd)/." shallow'
+pull_to_client 3rd "A" $((1*3))
 
-(cd shallow; git count-objects -v) > count.shallow
-
-test_expect_success "clone shallow object count" \
-       "test \"in-pack: 18\" = \"$(grep in-pack count.shallow)\""
-
-count_output () {
-       sed -e '/^in-pack:/d' -e '/^packs:/d' -e '/^size-pack:/d' -e '/: 0$/d' "$1"
-}
+test_expect_success 'clone shallow' '
+       git clone --depth 2 "file://$(pwd)/." shallow
+'
 
-test_expect_success "clone shallow object count (part 2)" '
-       test -z "$(count_output count.shallow)"
+test_expect_success 'clone shallow object count' '
+       (
+               cd shallow &&
+               git count-objects -v
+       ) > count.shallow &&
+       grep "^in-pack: 18" count.shallow
 '
 
-test_expect_success "fsck in shallow repo" \
-       "(cd shallow; git fsck --full)"
+test_expect_success 'clone shallow object count (part 2)' '
+       sed -e "/^in-pack:/d" -e "/^packs:/d" -e "/^size-pack:/d" \
+           -e "/: 0$/d" count.shallow > count_output &&
+       ! test -s count_output
+'
 
-#test_done; exit
+test_expect_success 'fsck in shallow repo' '
+       (
+               cd shallow &&
+               git fsck --full
+       )
+'
 
-add B66 $B65
-add B67 $B66
+test_expect_success 'add two more' '
+       add B66 $B65 &&
+       add B67 $B66
+'
 
-test_expect_success "pull in shallow repo" \
-       "(cd shallow; git pull .. B)"
+test_expect_success 'pull in shallow repo' '
+       (
+               cd shallow &&
+               git pull .. B
+       )
+'
 
-(cd shallow; git count-objects -v) > count.shallow
-test_expect_success "clone shallow object count" \
-       "test \"count: 6\" = \"$(grep count count.shallow)\""
+test_expect_success 'clone shallow object count' '
+       (
+               cd shallow &&
+               git count-objects -v
+       ) > count.shallow &&
+       grep "^count: 6" count.shallow
+'
 
-add B68 $B67
-add B69 $B68
+test_expect_success 'add two more (part 2)' '
+       add B68 $B67 &&
+       add B69 $B68
+'
 
-test_expect_success "deepening pull in shallow repo" \
-       "(cd shallow; git pull --depth 4 .. B)"
+test_expect_success 'deepening pull in shallow repo' '
+       (
+               cd shallow &&
+               git pull --depth 4 .. B
+       )
+'
 
-(cd shallow; git count-objects -v) > count.shallow
-test_expect_success "clone shallow object count" \
-       "test \"count: 12\" = \"$(grep count count.shallow)\""
+test_expect_success 'clone shallow object count' '
+       (
+               cd shallow &&
+               git count-objects -v
+       ) > count.shallow &&
+       grep "^count: 12" count.shallow
+'
 
-test_expect_success "deepening fetch in shallow repo" \
-       "(cd shallow; git fetch --depth 4 .. A:A)"
+test_expect_success 'deepening fetch in shallow repo' '
+       (
+               cd shallow &&
+               git fetch --depth 4 .. A:A
+       )
+'
 
-(cd shallow; git count-objects -v) > count.shallow
-test_expect_success "clone shallow object count" \
-       "test \"count: 18\" = \"$(grep count count.shallow)\""
+test_expect_success 'clone shallow object count' '
+       (
+               cd shallow &&
+               git count-objects -v
+       ) > count.shallow &&
+       grep "^count: 18" count.shallow
+'
 
-test_expect_success "pull in shallow repo with missing merge base" \
-       "(cd shallow && test_must_fail git pull --depth 4 .. A)"
+test_expect_success 'pull in shallow repo with missing merge base' '
+       (
+               cd shallow &&
+               test_must_fail git pull --depth 4 .. A
+       )
+'
 
 test_done
index 5ec668d6d8ac22f161549e5592a49bfdb0f11081..e70246b3fb5f0040a65db953b0adee7ada2d51ed 100755 (executable)
@@ -494,5 +494,15 @@ test_expect_success 'remote prune to cause a dangling symref' '
        grep "dangling symref" err
 '
 
+test_expect_success 'show empty remote' '
+
+       test_create_repo empty &&
+       git clone empty empty-clone &&
+       (
+               cd empty-clone &&
+               git remote show origin
+       )
+'
+
 test_done
 
index f8942bc8908fb92b1b11580e3554a81377dc3ba1..7dcf39191476f272431e19e10ebb299d6aa55bb1 100755 (executable)
@@ -54,6 +54,12 @@ deduxit me super semitas jusitiae,
 EOF
 printf "propter nomen suum." >> new4.txt
 
+test_expect_success 'merge with no changes' '
+       cp orig.txt test.txt &&
+       git merge-file test.txt orig.txt orig.txt &&
+       test_cmp test.txt orig.txt
+'
+
 cp new1.txt test.txt
 test_expect_success "merge without conflict" \
        "git merge-file test.txt orig.txt new2.txt"
index 54b7ea6505d8c189c6c557cffd3d6518df06fb73..5254b23512a411e911090cc0473bbbfd025df484 100755 (executable)
@@ -482,28 +482,17 @@ test_expect_success 'good merge bases when good and bad are siblings' '
        git bisect reset
 '
 
-check_trace() {
-       grep "$1" "$GIT_TRACE" | grep "\^$2" | grep "$3" >/dev/null
-}
-
 test_expect_success 'optimized merge base checks' '
-       GIT_TRACE="$(pwd)/trace.log" &&
-       export GIT_TRACE &&
        git bisect start "$HASH7" "$SIDE_HASH7" > my_bisect_log.txt &&
        grep "merge base must be tested" my_bisect_log.txt &&
        grep "$HASH4" my_bisect_log.txt &&
-       check_trace "rev-list" "$HASH7" "$SIDE_HASH7" &&
        git bisect good > my_bisect_log2.txt &&
        test -f ".git/BISECT_ANCESTORS_OK" &&
        test "$HASH6" = $(git rev-parse --verify HEAD) &&
-       : > "$GIT_TRACE" &&
        git bisect bad > my_bisect_log3.txt &&
-       test_must_fail check_trace "rev-list" "$HASH6" "$SIDE_HASH7" &&
        git bisect good "$A_HASH" > my_bisect_log4.txt &&
        grep "merge base must be tested" my_bisect_log4.txt &&
-       test_must_fail test -f ".git/BISECT_ANCESTORS_OK" &&
-       check_trace "rev-list" "$HASH6" "$A_HASH" &&
-       unset GIT_TRACE
+       test_must_fail test -f ".git/BISECT_ANCESTORS_OK"
 '
 
 # This creates another side branch called "parallel" with some files
index 2049ab6cf844da233837b58857cfde8a2d563252..42f6fff373ba9707216279011b112c6c59af8780 100755 (executable)
@@ -208,4 +208,36 @@ test_expect_success 'merge-msg test #5-2' '
        test_cmp expected actual
 '
 
+test_expect_success 'merge-msg -F' '
+
+       git config --unset-all merge.log
+       git config --unset-all merge.summary
+       git config merge.summary yes &&
+
+       git checkout master &&
+       setdate &&
+       git fetch . left right &&
+
+       git fmt-merge-msg -F .git/FETCH_HEAD >actual &&
+       test_cmp expected actual
+'
+
+test_expect_success 'merge-msg -F in subdirectory' '
+
+       git config --unset-all merge.log
+       git config --unset-all merge.summary
+       git config merge.summary yes &&
+
+       git checkout master &&
+       setdate &&
+       git fetch . left right &&
+       mkdir sub &&
+       cp .git/FETCH_HEAD sub/FETCH_HEAD &&
+       (
+               cd sub &&
+               git fmt-merge-msg -F FETCH_HEAD >../actual
+       ) &&
+       test_cmp expected actual
+'
+
 test_done
index b81593780a2a6adaf34bb10293b607e3a303cfcd..f275af82403dc0f1de4c584074c0eb63e61a6704 100755 (executable)
@@ -16,12 +16,13 @@ test_expect_success setup '
                echo foo mmap bar_mmap
                echo foo_mmap bar mmap baz
        } >file &&
+       echo ww w >w &&
        echo x x xx x >x &&
        echo y yy >y &&
        echo zzz > z &&
        mkdir t &&
        echo test >t/t &&
-       git add file x y z t/t &&
+       git add file x y z t/t &&
        test_tick &&
        git commit -m initial
 '
@@ -48,6 +49,12 @@ do
                diff expected actual
        '
 
+       test_expect_success "grep -w $L (w)" '
+               : >expected &&
+               ! git grep -n -w -e "^w" >actual &&
+               test_cmp expected actual
+       '
+
        test_expect_success "grep -w $L (x)" '
                {
                        echo ${HC}x:1:x x xx x
index 5998baf27b5ad0fb32bf0fd42023d029a65d0e6b..8eec0fa9bc7278981b9a16571c588ede0a94d341 100755 (executable)
@@ -183,4 +183,14 @@ test_expect_success 'commit message from stdin' '
        commit_msg_is "Log with foo word"
 '
 
+test_expect_success 'commit -F overrides -t' '
+       (
+               cd subdir &&
+               echo "-F log" > f.log &&
+               echo "-t template" > t.template &&
+               git commit --allow-empty -F f.log -t t.template
+       ) &&
+       commit_msg_is "-F log"
+'
+
 test_done
index 966bb0a61a89ed63dec085338d3c45f766a7f777..13c25f1d528ca1ec90575e42e0393accff5d8f35 100755 (executable)
@@ -129,4 +129,19 @@ test_expect_success 'blame wholesale copy and more' '
 
 '
 
+test_expect_success 'blame path that used to be a directory' '
+       mkdir path &&
+       echo A A A A A >path/file &&
+       echo B B B B B >path/elif &&
+       git add path &&
+       test_tick &&
+       git commit -m "path was a directory" &&
+       rm -fr path &&
+       echo A A A A A >path &&
+       git add path &&
+       test_tick &&
+       git commit -m "path is a regular file" &&
+       git blame HEAD^.. -- path
+'
+
 test_done
index fcd5c266754a2b5de3dbbf94c8ef25aebff061f2..9cca14d080e63d25f5d71179deaced8b226bba07 100755 (executable)
@@ -4,7 +4,7 @@ test_description='git blame encoding conversion'
 . ./test-lib.sh
 
 . "$TEST_DIRECTORY"/t8005/utf8.txt
-. "$TEST_DIRECTORY"/t8005/cp1251.txt
+. "$TEST_DIRECTORY"/t8005/iso8859-5.txt
 . "$TEST_DIRECTORY"/t8005/sjis.txt
 
 test_expect_success 'setup the repository' '
@@ -13,14 +13,14 @@ test_expect_success 'setup the repository' '
        git add file &&
        git commit --author "$UTF8_NAME <utf8@localhost>" -m "$UTF8_MSG" &&
 
-       echo "CP1251 LINE" >> file &&
+       echo "ISO-8859-5 LINE" >> file &&
        git add file &&
-       git config i18n.commitencoding cp1251 &&
-       git commit --author "$CP1251_NAME <cp1251@localhost>" -m "$CP1251_MSG" &&
+       git config i18n.commitencoding ISO8859-5 &&
+       git commit --author "$ISO8859_5_NAME <iso8859-5@localhost>" -m "$ISO8859_5_MSG" &&
 
        echo "SJIS LINE" >> file &&
        git add file &&
-       git config i18n.commitencoding shift-jis &&
+       git config i18n.commitencoding SJIS &&
        git commit --author "$SJIS_NAME <sjis@localhost>" -m "$SJIS_MSG"
 '
 
@@ -41,17 +41,17 @@ test_expect_success \
 '
 
 cat >expected <<EOF
-author $CP1251_NAME
-summary $CP1251_MSG
-author $CP1251_NAME
-summary $CP1251_MSG
-author $CP1251_NAME
-summary $CP1251_MSG
+author $ISO8859_5_NAME
+summary $ISO8859_5_MSG
+author $ISO8859_5_NAME
+summary $ISO8859_5_MSG
+author $ISO8859_5_NAME
+summary $ISO8859_5_MSG
 EOF
 
 test_expect_success \
        'blame respects i18n.logoutputencoding' '
-       git config i18n.logoutputencoding cp1251 &&
+       git config i18n.logoutputencoding ISO8859-5 &&
        git blame --incremental file | \
                egrep "^(author|summary) " > actual &&
        test_cmp actual expected
@@ -67,8 +67,8 @@ summary $UTF8_MSG
 EOF
 
 test_expect_success \
-       'blame respects --encoding=utf-8' '
-       git blame --incremental --encoding=utf-8 file | \
+       'blame respects --encoding=UTF-8' '
+       git blame --incremental --encoding=UTF-8 file | \
                egrep "^(author|summary) " > actual &&
        test_cmp actual expected
 '
@@ -76,8 +76,8 @@ test_expect_success \
 cat >expected <<EOF
 author $SJIS_NAME
 summary $SJIS_MSG
-author $CP1251_NAME
-summary $CP1251_MSG
+author $ISO8859_5_NAME
+summary $ISO8859_5_MSG
 author $UTF8_NAME
 summary $UTF8_MSG
 EOF
diff --git a/t/t8005/cp1251.txt b/t/t8005/cp1251.txt
deleted file mode 100644 (file)
index ce41e98..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-CP1251_NAME="Èâàí Ïåòðîâè÷ Ñèäîðîâ"
-CP1251_MSG="Òåñòîâîå ñîîáùåíèå"
diff --git a/t/t8005/iso8859-5.txt b/t/t8005/iso8859-5.txt
new file mode 100644 (file)
index 0000000..2e4b80c
--- /dev/null
@@ -0,0 +1,2 @@
+ISO8859_5_NAME="¸ÒÐÝ ¿ÕâàÞÒØç ÁØÔÞàÞÒ"
+ISO8859_5_MSG="ÂÕáâÞÒÞÕ áÞÞÑéÕÝØÕ"
index ce26ea4ac53a4608f6f8234b67868a9cc85be7f8..2ce24cd5a613a2f218f8a486a4ad4c15db29e695 100755 (executable)
@@ -533,7 +533,7 @@ test_expect_success 'utf8 Cc is rfc2047 encoded' '
        --smtp-server="$(pwd)/fake.sendmail" \
        outdir/*.patch &&
        grep "^Cc:" msgtxt1 |
-       grep "=?utf-8?q?=C3=A0=C3=A9=C3=AC=C3=B6=C3=BA?= <utf8@example.com>"
+       grep "=?UTF-8?q?=C3=A0=C3=A9=C3=AC=C3=B6=C3=BA?= <utf8@example.com>"
 '
 
 test_expect_success '--compose adds MIME for utf8 body' '
@@ -550,7 +550,7 @@ test_expect_success '--compose adds MIME for utf8 body' '
          --smtp-server="$(pwd)/fake.sendmail" \
          $patches &&
        grep "^utf8 body" msgtxt1 &&
-       grep "^Content-Type: text/plain; charset=utf-8" msgtxt1
+       grep "^Content-Type: text/plain; charset=UTF-8" msgtxt1
 '
 
 test_expect_success '--compose respects user mime type' '
@@ -573,7 +573,7 @@ test_expect_success '--compose respects user mime type' '
          $patches &&
        grep "^utf8 body" msgtxt1 &&
        grep "^Content-Type: text/plain; charset=iso-8859-1" msgtxt1 &&
-       ! grep "^Content-Type: text/plain; charset=utf-8" msgtxt1
+       ! grep "^Content-Type: text/plain; charset=UTF-8" msgtxt1
 '
 
 test_expect_success '--compose adds MIME for utf8 subject' '
@@ -586,7 +586,7 @@ test_expect_success '--compose adds MIME for utf8 subject' '
          --smtp-server="$(pwd)/fake.sendmail" \
          $patches &&
        grep "^fake edit" msgtxt1 &&
-       grep "^Subject: =?utf-8?q?utf8-s=C3=BCbj=C3=ABct?=" msgtxt1
+       grep "^Subject: =?UTF-8?q?utf8-s=C3=BCbj=C3=ABct?=" msgtxt1
 '
 
 test_expect_success 'detects ambiguous reference/file conflict' '
index 555a0189a7bd6412829da88a3e615208117eaa90..f159ab689bd5f7dfba1b27adb9dc68d8b65b67fe 100755 (executable)
@@ -14,17 +14,12 @@ test_expect_success 'setup svnrepo' '
        start_httpd
 '
 
-if test "$SVN_HTTPD_PORT" = ""
-then
-       test_expect_failure 'test clone with percent escapes - needs SVN_HTTPD_PORT set' 'false'
-else
-       test_expect_success 'test clone with percent escapes' '
-               git svn clone "$svnrepo/pr%20ject" clone &&
-               cd clone &&
-                       git rev-parse refs/${remotes_git_svn} &&
-               cd ..
-       '
-fi
+test_expect_success 'test clone with percent escapes' '
+       git svn clone "$svnrepo/pr%20ject" clone &&
+       cd clone &&
+               git rev-parse refs/${remotes_git_svn} &&
+       cd ..
+'
 
 stop_httpd
 
index d45fb73016362827e647118eec028c8b85e5aeff..b9224bdb20a397f40f1504684e1144428cf8a24e 100755 (executable)
@@ -29,7 +29,7 @@ compare_svn_head_with () {
        test_cmp current "$1"
 }
 
-for H in ISO-8859-1 EUCJP ISO-2022-JP
+for H in ISO8859-1 eucJP ISO-2022-JP
 do
        test_expect_success "$H setup" '
                mkdir $H &&
@@ -38,7 +38,7 @@ do
        '
 done
 
-for H in ISO-8859-1 EUCJP ISO-2022-JP
+for H in ISO8859-1 eucJP ISO-2022-JP
 do
        test_expect_success "$H commit on git side" '
        (
@@ -55,7 +55,7 @@ do
        '
 done
 
-for H in ISO-8859-1 EUCJP ISO-2022-JP
+for H in ISO8859-1 eucJP ISO-2022-JP
 do
        test_expect_success "$H dcommit to svn" '
        (
@@ -77,12 +77,12 @@ fi
 
 test_expect_success UTF8 'ISO-8859-1 should match UTF-8 in svn' '
        (
-               cd ISO-8859-1 &&
+               cd ISO8859-1 &&
                compare_svn_head_with "$TEST_DIRECTORY"/t3900/1-UTF-8.txt
        )
 '
 
-for H in EUCJP ISO-2022-JP
+for H in eucJP ISO-2022-JP
 do
        test_expect_success UTF8 "$H should match UTF-8 in svn" '
                (
diff --git a/t/t9139-git-svn-non-utf8-commitencoding.sh b/t/t9139-git-svn-non-utf8-commitencoding.sh
new file mode 100755 (executable)
index 0000000..f337959
--- /dev/null
@@ -0,0 +1,47 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Eric Wong
+
+test_description='git svn refuses to dcommit non-UTF8 messages'
+
+. ./lib-git-svn.sh
+
+# ISO-2022-JP can pass for valid UTF-8, so skipping that in this test
+
+for H in ISO8859-1 eucJP
+do
+       test_expect_success "$H setup" '
+               mkdir $H &&
+               svn_cmd import -m "$H test" $H "$svnrepo"/$H &&
+               git svn clone "$svnrepo"/$H $H
+       '
+done
+
+for H in ISO8859-1 eucJP
+do
+       test_expect_success "$H commit on git side" '
+       (
+               cd $H &&
+               git config i18n.commitencoding $H &&
+               git checkout -b t refs/remotes/git-svn &&
+               echo $H >F &&
+               git add F &&
+               git commit -a -F "$TEST_DIRECTORY"/t3900/$H.txt &&
+               E=$(git cat-file commit HEAD | sed -ne "s/^encoding //p") &&
+               test "z$E" = "z$H"
+       )
+       '
+done
+
+for H in ISO8859-1 eucJP
+do
+       test_expect_success "$H dcommit to svn" '
+       (
+               cd $H &&
+               git config --unset i18n.commitencoding &&
+               ! git svn dcommit
+       )
+       '
+done
+
+test_done
index 56b7c06921d9ef3b72ff3ee6f62f7a1c426b3028..ef1f8d22f67187089ff88811457d8e26cf354047 100755 (executable)
@@ -317,4 +317,22 @@ test_expect_success 'use the same checkout for Git and CVS' '
 
 '
 
+test_expect_success 're-commit a removed filename which remains in CVS attic' '
+
+    (cd "$CVSWORK" &&
+     echo >attic_gremlin &&
+     cvs -Q add attic_gremlin &&
+     cvs -Q ci -m "added attic_gremlin" &&
+     rm attic_gremlin &&
+     cvs -Q rm attic_gremlin &&
+     cvs -Q ci -m "removed attic_gremlin") &&
+
+    echo > attic_gremlin &&
+    git add attic_gremlin &&
+    git commit -m "Added attic_gremlin" &&
+       git cvsexportcommit -w "$CVSWORK" -c HEAD &&
+    (cd "$CVSWORK"; cvs -Q update -d) &&
+    test -f "$CVSWORK/attic_gremlin"
+'
+
 test_done
index 8da9ce54596416af6fc9779a5ac3f7131958aec8..8c8a9e63c26c594a837d266bff56f5f85cb376c8 100755 (executable)
@@ -68,7 +68,7 @@ test_expect_success 'fast-export master~2..master' '
 
 test_expect_success 'iso-8859-1' '
 
-       git config i18n.commitencoding ISO-8859-1 &&
+       git config i18n.commitencoding ISO8859-1 &&
        # use author and committer name in ISO-8859-1 to match it.
        . "$TEST_DIRECTORY"/t3901-8859-1.txt &&
        test_tick &&
index f4210fbb04065cfe32f26053eb5f5f054d52e3cf..d539619e89c5263e3b8339c408f1c0dcd867457b 100755 (executable)
@@ -590,7 +590,7 @@ test_expect_success \
         echo "ISO-8859-1" >> file &&
         git add file &&
         git config i18n.commitencoding ISO-8859-1 &&
-        git commit -F "$TEST_DIRECTORY"/t3900/ISO-8859-1.txt &&
+        git commit -F "$TEST_DIRECTORY"/t3900/ISO8859-1.txt &&
         git config --unset i18n.commitencoding &&
         gitweb_run "p=.git;a=commit"'
 test_debug 'cat gitweb.log'
index dad1437fa49596cf6f36b40b1ab18b008620a246..5fdc5d94a20cfcf231bf23590784c5146a3e44bc 100644 (file)
@@ -115,7 +115,7 @@ do
        --tee)
                shift ;; # was handled already
        *)
-               break ;;
+               echo "error: unknown test option '$1'" >&2; exit 1 ;;
        esac
 done
 
@@ -147,7 +147,7 @@ fi
 
 error () {
        say_color error "error: $*"
-       trap - EXIT
+       GIT_EXIT_OK=t
        exit 1
 }
 
@@ -179,10 +179,17 @@ test_broken=0
 test_success=0
 
 die () {
-       echo >&5 "FATAL: Unexpected exit with code $?"
-       exit 1
+       code=$?
+       if test -n "$GIT_EXIT_OK"
+       then
+               exit $code
+       else
+               echo >&5 "FATAL: Unexpected exit with code $code"
+               exit 1
+       fi
 }
 
+GIT_EXIT_OK=
 trap 'die' EXIT
 
 # The semantics of the editor variables are that of invoking
@@ -285,7 +292,7 @@ test_failure_ () {
        say_color error "FAIL $test_count: $1"
        shift
        echo "$@" | sed -e 's/^/        /'
-       test "$immediate" = "" || { trap - EXIT; exit 1; }
+       test "$immediate" = "" || { GIT_EXIT_OK=t; exit 1; }
 }
 
 test_known_broken_ok_ () {
@@ -347,7 +354,7 @@ test_expect_failure () {
                then
                        test_known_broken_ok_ "$1"
                else
-                   test_known_broken_failure_ "$1"
+                       test_known_broken_failure_ "$1"
                fi
        fi
        echo >&3 ""
@@ -498,7 +505,7 @@ test_create_repo () {
 }
 
 test_done () {
-       trap - EXIT
+       GIT_EXIT_OK=t
        test_results_dir="$TEST_DIRECTORY/test-results"
        mkdir -p "$test_results_dir"
        test_results_path="$test_results_dir/${0%.sh}-$$"
@@ -640,7 +647,7 @@ fi
 test="trash directory.$(basename "$0" .sh)"
 test ! -z "$debug" || remove_trash="$TEST_DIRECTORY/$test"
 rm -fr "$test" || {
-       trap - EXIT
+       GIT_EXIT_OK=t
        echo >&5 "FATAL: Cannot prepare test area"
        exit 1
 }
index e0669dcb41d1d779f274e1ff785352e284953b14..a90bc3003d97f86fcc2210e340666106647eb74c 100644 (file)
@@ -7,6 +7,7 @@ static unsigned long timestamp;
 static int abbrev = 7;
 static int verbose = 0, dry_run = 0, quiet = 0;
 static char *string = NULL;
+static char *file = NULL;
 
 int length_callback(const struct option *opt, const char *arg, int unset)
 {
@@ -27,6 +28,7 @@ int number_callback(const struct option *opt, const char *arg, int unset)
 
 int main(int argc, const char **argv)
 {
+       const char *prefix = "prefix/";
        const char *usage[] = {
                "test-parse-options <options>",
                NULL
@@ -43,6 +45,7 @@ int main(int argc, const char **argv)
                OPT_DATE('t', NULL, &timestamp, "get timestamp of <time>"),
                OPT_CALLBACK('L', "length", &integer, "str",
                        "get length of <str>", length_callback),
+               OPT_FILENAME('F', "file", &file, "set file to <FILE>"),
                OPT_GROUP("String options"),
                OPT_STRING('s', "string", &string, "string", "get a string"),
                OPT_STRING(0, "string2", &string, "str", "get another string"),
@@ -65,7 +68,7 @@ int main(int argc, const char **argv)
        };
        int i;
 
-       argc = parse_options(argc, argv, options, usage, 0);
+       argc = parse_options(argc, argv, prefix, options, usage, 0);
 
        printf("boolean: %d\n", boolean);
        printf("integer: %u\n", integer);
@@ -75,6 +78,7 @@ int main(int argc, const char **argv)
        printf("verbose: %d\n", verbose);
        printf("quiet: %s\n", quiet ? "yes" : "no");
        printf("dry run: %s\n", dry_run ? "yes" : "no");
+       printf("file: %s\n", file ? file : "(not set)");
 
        for (i = 0; i < argc; i++)
                printf("arg %02d: %s\n", i, argv[i]);
index 17891d5149aab99ce0ec5538a0e11b8e9c2398ec..d8a2392a655dc67948581b4bd94e14536972377b 100644 (file)
@@ -1003,7 +1003,6 @@ int transport_push(struct transport *transport,
        if (transport->push_refs) {
                struct ref *remote_refs =
                        transport->get_refs_list(transport, 1);
-               struct ref **remote_tail;
                struct ref *local_refs = get_local_heads();
                int match_flags = MATCH_REFS_NONE;
                int verbose = flags & TRANSPORT_PUSH_VERBOSE;
@@ -1014,10 +1013,7 @@ int transport_push(struct transport *transport,
                if (flags & TRANSPORT_PUSH_MIRROR)
                        match_flags |= MATCH_REFS_MIRROR;
 
-               remote_tail = &remote_refs;
-               while (*remote_tail)
-                       remote_tail = &((*remote_tail)->next);
-               if (match_refs(local_refs, remote_refs, &remote_tail,
+               if (match_refs(local_refs, &remote_refs,
                               refspec_nr, refspec, match_flags)) {
                        return -1;
                }
index d9737f04c220645aa762d79ff14a84855721ffda..1cb65a95166a8cb60af590118f59d78aa4d24b74 100644 (file)
@@ -563,23 +563,22 @@ int xdl_merge(mmfile_t *orig, mmfile_t *mf1, const char *name1,
                return -1;
        }
        status = 0;
-       if (xscr1 || xscr2) {
-               if (!xscr1) {
-                       result->ptr = xdl_malloc(mf2->size);
-                       memcpy(result->ptr, mf2->ptr, mf2->size);
-                       result->size = mf2->size;
-               } else if (!xscr2) {
-                       result->ptr = xdl_malloc(mf1->size);
-                       memcpy(result->ptr, mf1->ptr, mf1->size);
-                       result->size = mf1->size;
-               } else {
-                       status = xdl_do_merge(&xe1, xscr1, name1,
-                                             &xe2, xscr2, name2,
-                                             flags, xpp, result);
-               }
-               xdl_free_script(xscr1);
-               xdl_free_script(xscr2);
+       if (!xscr1) {
+               result->ptr = xdl_malloc(mf2->size);
+               memcpy(result->ptr, mf2->ptr, mf2->size);
+               result->size = mf2->size;
+       } else if (!xscr2) {
+               result->ptr = xdl_malloc(mf1->size);
+               memcpy(result->ptr, mf1->ptr, mf1->size);
+               result->size = mf1->size;
+       } else {
+               status = xdl_do_merge(&xe1, xscr1, name1,
+                                     &xe2, xscr2, name2,
+                                     flags, xpp, result);
        }
+       xdl_free_script(xscr1);
+       xdl_free_script(xscr2);
+
        xdl_free_env(&xe1);
        xdl_free_env(&xe2);