summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/RelNotes-1.6.3.2.txt48
-rw-r--r--Documentation/git-difftool.txt2
-rw-r--r--Documentation/git-mergetool.txt2
-rw-r--r--Documentation/git-repack.txt7
-rw-r--r--Documentation/git-send-email.txt4
-rw-r--r--Documentation/git-show-branch.txt12
-rw-r--r--Documentation/git-stash.txt16
-rw-r--r--Documentation/git-submodule.txt14
-rw-r--r--Documentation/git.txt12
-rw-r--r--Documentation/gitmodules.txt9
-rw-r--r--Documentation/gittutorial.txt4
-rw-r--r--Documentation/merge-config.txt2
-rw-r--r--Makefile70
-rw-r--r--builtin-blame.c26
-rw-r--r--builtin-fetch-pack.c4
-rw-r--r--builtin-help.c16
-rw-r--r--builtin-merge.c5
-rw-r--r--builtin-receive-pack.c10
-rw-r--r--builtin-remote.c16
-rw-r--r--builtin-send-pack.c9
-rw-r--r--builtin-show-branch.c3
-rw-r--r--cache.h2
-rw-r--r--compat/basename.c15
-rw-r--r--compat/mkstemps.c70
-rw-r--r--config.mak.in3
-rw-r--r--configure.ac22
-rw-r--r--connect.c5
-rwxr-xr-xcontrib/completion/git-completion.bash18
-rw-r--r--daemon.c10
-rw-r--r--diff.c13
-rwxr-xr-xgit-add--interactive.perl1
-rw-r--r--git-compat-util.h29
-rwxr-xr-xgit-cvsexportcommit.perl49
-rw-r--r--git-mergetool--lib.sh25
-rwxr-xr-xgit-rebase--interactive.sh2
-rwxr-xr-xgit-send-email.perl14
-rwxr-xr-xgit-sh-setup.sh28
-rwxr-xr-xgit-stash.sh4
-rwxr-xr-xgit-submodule.sh35
-rw-r--r--grep.c8
-rw-r--r--http-push.c11
-rw-r--r--ll-merge.c11
-rw-r--r--merge-index.c42
-rw-r--r--parse-options.c24
-rw-r--r--parse-options.h7
-rw-r--r--path.c16
-rw-r--r--remote.c17
-rw-r--r--remote.h2
-rw-r--r--revision.c33
-rw-r--r--revision.h5
-rw-r--r--symlinks.c6
-rw-r--r--t/lib-httpd.sh6
-rwxr-xr-xt/t3030-merge-recursive.sh3
-rwxr-xr-xt/t4020-diff-external.sh9
-rwxr-xr-xt/t6023-merge-file.sh6
-rwxr-xr-xt/t7406-submodule-update.sh140
-rwxr-xr-xt/t8003-blame.sh15
-rwxr-xr-xt/t9001-send-email.sh8
-rwxr-xr-xt/t9200-git-cvsexportcommit.sh18
-rw-r--r--t/test-lib.sh23
-rw-r--r--transport.c6
-rw-r--r--utf8.c2
-rw-r--r--xdiff/xmerge.c31
63 files changed, 841 insertions, 244 deletions
diff --git a/Documentation/RelNotes-1.6.3.2.txt b/Documentation/RelNotes-1.6.3.2.txt
index a3fceeb..b2f3f02 100644
--- a/Documentation/RelNotes-1.6.3.2.txt
+++ b/Documentation/RelNotes-1.6.3.2.txt
@@ -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
-
diff --git a/Documentation/git-difftool.txt b/Documentation/git-difftool.txt
index 15b247b..96a6c51 100644
--- a/Documentation/git-difftool.txt
+++ b/Documentation/git-difftool.txt
@@ -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
diff --git a/Documentation/git-mergetool.txt b/Documentation/git-mergetool.txt
index ff9700d..68ed6c0 100644
--- a/Documentation/git-mergetool.txt
+++ b/Documentation/git-mergetool.txt
@@ -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
diff --git a/Documentation/git-repack.txt b/Documentation/git-repack.txt
index aaa8852..c9257a1 100644
--- a/Documentation/git-repack.txt
+++ b/Documentation/git-repack.txt
@@ -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
diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt
index 7c5ce41..e7cb0e6 100644
--- a/Documentation/git-send-email.txt
+++ b/Documentation/git-send-email.txt
@@ -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
diff --git a/Documentation/git-show-branch.txt b/Documentation/git-show-branch.txt
index edd8f64..89ec536 100644
--- a/Documentation/git-show-branch.txt
+++ b/Documentation/git-show-branch.txt
@@ -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
diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.txt
index 1cc24cc..a42d4c8 100644
--- a/Documentation/git-stash.txt
+++ b/Documentation/git-stash.txt
@@ -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
@@ -86,16 +86,16 @@ 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.
+
-When no `<stash>` is given, `stash@\{0}` is assumed. See also `apply`.
-
-apply [--index] [<stash>]::
-
- Like `pop`, but do not remove the state from the stash list.
-+
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>]::
diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index 14256c6..cd8e861 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -13,7 +13,7 @@ SYNOPSIS
[--reference <repository>] [--] <repository> <path>
'git submodule' [--quiet] status [--cached] [--] [<path>...]
'git submodule' [--quiet] init [--] [<path>...]
-'git submodule' [--quiet] update [--init] [-N|--no-fetch]
+'git submodule' [--quiet] update [--init] [-N|--no-fetch] [--rebase]
[--reference <repository>] [--] [<path>...]
'git submodule' [--quiet] summary [--summary-limit <n>] [commit] [--] [<path>...]
'git submodule' [--quiet] foreach <command>
@@ -115,7 +115,8 @@ init::
update::
Update the registered submodules, i.e. clone missing submodules and
checkout the commit specified in the index of the containing repository.
- This will make the submodules HEAD be detached.
+ This will make the submodules HEAD be detached unless '--rebase' is
+ specified or the key `submodule.$name.update` is set to `rebase`.
+
If the submodule is not yet initialized, and you just want to use the
setting as stored in .gitmodules, you can automatically initialize the
@@ -179,6 +180,15 @@ OPTIONS
This option is only valid for the update command.
Don't fetch new objects from the remote site.
+--rebase::
+ This option is only valid for the update command.
+ Rebase the current branch onto the commit recorded in the
+ superproject. If this option is given, the submodule's HEAD will not
+ be detached. If a a merge failure prevents this process, you will have
+ to resolve these failures with linkgit:git-rebase[1].
+ If the key `submodule.$name.update` is set to `rebase`, this option is
+ implicit.
+
--reference <repository>::
This option is only valid for add and update commands. These
commands sometimes need to clone a remote repository. In this case,
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 9d8f236..56d4770 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -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
---
diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.txt
index d1a17e2..1b67f0a 100644
--- a/Documentation/gitmodules.txt
+++ b/Documentation/gitmodules.txt
@@ -30,6 +30,15 @@ submodule.<name>.path::
submodule.<name>.url::
Defines an url from where the submodule repository can be cloned.
+submodule.<name>.update::
+ Defines what to do when the submodule is updated by the superproject.
+ If 'checkout' (the default), the new commit specified in the
+ superproject will be checked out in the submodule on a detached HEAD.
+ If 'rebase', the current branch of the submodule will be rebased onto
+ the commit specified in the superproject.
+ This config option is overridden if 'git submodule update' is given
+ the '--rebase' option.
+
EXAMPLES
--------
diff --git a/Documentation/gittutorial.txt b/Documentation/gittutorial.txt
index c5d5596..c7fa949 100644
--- a/Documentation/gittutorial.txt
+++ b/Documentation/gittutorial.txt
@@ -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]
diff --git a/Documentation/merge-config.txt b/Documentation/merge-config.txt
index 4832bc7..c0f96e7 100644
--- a/Documentation/merge-config.txt
+++ b/Documentation/merge-config.txt
@@ -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.
diff --git a/Makefile b/Makefile
index 867438d..41ab8e9 100644
--- a/Makefile
+++ b/Makefile
@@ -3,6 +3,11 @@ all::
# Define V=1 to have a more verbose compile.
#
+# Define SHELL_PATH to a POSIX shell if your /bin/sh is broken.
+#
+# Define SANE_TOOL_PATH to a colon-separated list of paths to prepend
+# to PATH if your tools in /usr/bin are broken.
+#
# Define SNPRINTF_RETURNS_BOGUS if your are on a system which snprintf()
# or vsnprintf() return -1 instead of number of characters which would
# have been written to the final string if enough space had been available.
@@ -52,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.
@@ -91,6 +100,10 @@ all::
# Define NEEDS_SOCKET if linking with libc is not enough (SunOS,
# Patrick Mauritz).
#
+# Define NEEDS_RESOLV if linking with -lnsl and/or -lsocket is not enough.
+# Notably on Solaris hstrerror resides in libresolv and on Solaris 7
+# inet_ntop and inet_pton additionally reside there.
+#
# Define NO_MMAP if you want to avoid mmap.
#
# Define NO_PTHREADS if you do not have or do not want to use Pthreads.
@@ -639,10 +652,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)
@@ -654,6 +669,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
@@ -677,6 +693,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
@@ -701,12 +718,20 @@ ifeq ($(uname_S),SunOS)
NEEDS_SOCKET = YesPlease
NEEDS_NSL = YesPlease
SHELL_PATH = /bin/bash
+ SANE_TOOL_PATH = /usr/xpg6/bin:/usr/xpg4/bin
NO_STRCASESTR = YesPlease
NO_MEMMEM = YesPlease
- NO_HSTRERROR = YesPlease
NO_MKDTEMP = YesPlease
- ifneq ($(uname_R),5.11)
- OLD_ICONV = UnfortunatelyYes
+ NO_MKSTEMPS = YesPlease
+ ifeq ($(uname_R),5.7)
+ NEEDS_RESOLV = YesPlease
+ NO_IPV6 = YesPlease
+ NO_SOCKADDR_STORAGE = YesPlease
+ NO_UNSETENV = YesPlease
+ NO_SETENV = YesPlease
+ NO_STRLCPY = YesPlease
+ NO_C99_FORMAT = YesPlease
+ NO_STRTOUMAX = YesPlease
endif
ifeq ($(uname_R),5.8)
NO_UNSETENV = YesPlease
@@ -720,15 +745,19 @@ ifeq ($(uname_S),SunOS)
NO_C99_FORMAT = YesPlease
NO_STRTOUMAX = YesPlease
endif
- INSTALL = ginstall
+ ifdef NO_IPV6
+ NEEDS_RESOLV = YesPlease
+ endif
+ INSTALL = /usr/ucb/install
TAR = gtar
- BASIC_CFLAGS += -D__EXTENSIONS__
+ BASIC_CFLAGS += -D__EXTENSIONS__ -D__sun__
endif
ifeq ($(uname_O),Cygwin)
NO_D_TYPE_IN_DIRENT = YesPlease
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
@@ -772,11 +801,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
@@ -792,12 +823,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
@@ -810,6 +843,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
@@ -825,6 +859,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
pathsep = ;
NO_PREAD = YesPlease
NO_OPENSSL = YesPlease
+ NO_LIBGEN_H = YesPlease
NO_SYMLINK_HEAD = YesPlease
NO_IPV6 = YesPlease
NO_SETENV = YesPlease
@@ -837,6 +872,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
@@ -868,11 +904,20 @@ endif
endif
ifneq (,$(findstring arm,$(uname_M)))
ARM_SHA1 = YesPlease
+ NO_MKSTEMPS = YesPlease
endif
-include config.mak.autogen
-include config.mak
+ifdef SANE_TOOL_PATH
+SANE_TOOL_PATH_SQ = $(subst ','\'',$(SANE_TOOL_PATH))
+BROKEN_PATH_FIX = 's|^\# @@BROKEN_PATH_FIX@@$$|git_broken_path_fix $(SANE_TOOL_PATH_SQ)|'
+PATH := $(SANE_TOOL_PATH):${PATH}
+else
+BROKEN_PATH_FIX = '/^\# @@BROKEN_PATH_FIX@@$$/d'
+endif
+
ifeq ($(uname_S),Darwin)
ifndef NO_FINK
ifeq ($(shell test -d /sw/lib && echo y),y)
@@ -899,6 +944,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
@@ -971,6 +1021,9 @@ endif
ifdef NEEDS_NSL
EXTLIBS += -lnsl
endif
+ifdef NEEDS_RESOLV
+ EXTLIBS += -lresolv
+endif
ifdef NO_D_TYPE_IN_DIRENT
BASIC_CFLAGS += -DNO_D_TYPE_IN_DIRENT
endif
@@ -1026,6 +1079,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
@@ -1276,6 +1333,7 @@ $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
-e 's|@SHELL_PATH@|$(SHELL_PATH_SQ)|' \
-e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
-e 's/@@NO_CURL@@/$(NO_CURL)/g' \
+ -e $(BROKEN_PATH_FIX) \
$@.sh >$@+ && \
chmod +x $@+ && \
mv $@+ $@
@@ -1515,6 +1573,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)
diff --git a/builtin-blame.c b/builtin-blame.c
index 9dc3335..0c2d29a 100644
--- a/builtin-blame.c
+++ b/builtin-blame.c
@@ -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)",
diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c
index 6202462..629735f 100644
--- a/builtin-fetch-pack.c
+++ b/builtin-fetch-pack.c
@@ -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)
diff --git a/builtin-help.c b/builtin-help.c
index af565fb..6e53b23 100644
--- a/builtin-help.c
+++ b/builtin-help.c
@@ -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);
diff --git a/builtin-merge.c b/builtin-merge.c
index 8d101ef..793f2f4 100644
--- a/builtin-merge.c
+++ b/builtin-merge.c
@@ -836,8 +836,11 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
struct commit_list **remotes = &remoteheads;
setup_work_tree();
+ if (file_exists(git_path("MERGE_HEAD")))
+ die("You have not concluded your merge. (MERGE_HEAD exists)");
if (read_cache_unmerged())
- die("You are in the middle of a conflicted merge.");
+ die("You are in the middle of a conflicted merge."
+ " (index unmerged)");
/*
* Check if we are _not_ on a detached HEAD, i.e. if there is a
diff --git a/builtin-receive-pack.c b/builtin-receive-pack.c
index 0b08da9..33d345d 100644
--- a/builtin-receive-pack.c
+++ b/builtin-receive-pack.c
@@ -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)
diff --git a/builtin-remote.c b/builtin-remote.c
index f7d6618..dfc0b9e 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -295,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();
push_map = copy_ref_list(remote_refs);
- push_tail = &push_map;
- while (*push_tail)
- push_tail = &((*push_tail)->next);
- 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;
@@ -1005,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)
diff --git a/builtin-send-pack.c b/builtin-send-pack.c
index be3b092..c375a3d 100644
--- a/builtin-send-pack.c
+++ b/builtin-send-pack.c
@@ -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);
diff --git a/builtin-show-branch.c b/builtin-show-branch.c
index 9433811..01bea3b 100644
--- a/builtin-show-branch.c
+++ b/builtin-show-branch.c
@@ -657,8 +657,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
"color '*!+-' corresponding to the branch"),
{ OPTION_INTEGER, 0, "more", &extra, "n",
"show <n> more commits after the common ancestor",
- PARSE_OPT_OPTARG | PARSE_OPT_LASTARG_DEFAULT,
- NULL, (intptr_t)1 },
+ 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,
diff --git a/cache.h b/cache.h
index b8503ad..871c984 100644
--- 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!!
*
diff --git a/compat/basename.c b/compat/basename.c
new file mode 100644
index 0000000..d8f8a3c
--- /dev/null
+++ b/compat/basename.c
@@ -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
index 0000000..14179c8
--- /dev/null
+++ b/compat/mkstemps.c
@@ -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;
+}
diff --git a/config.mak.in b/config.mak.in
index 7cce0c1..dd60451 100644
--- a/config.mak.in
+++ b/config.mak.in
@@ -30,8 +30,10 @@ 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@
NO_SYS_SELECT_H=@NO_SYS_SELECT_H@
NO_D_INO_IN_DIRENT=@NO_D_INO_IN_DIRENT@
NO_D_TYPE_IN_DIRENT=@NO_D_TYPE_IN_DIRENT@
@@ -46,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@
diff --git a/configure.ac b/configure.ac
index 4e728bc..7937e60 100644
--- a/configure.ac
+++ b/configure.ac
@@ -467,6 +467,15 @@ AC_CHECK_LIB([c], [socket],
AC_SUBST(NEEDS_SOCKET)
test -n "$NEEDS_SOCKET" && LIBS="$LIBS -lsocket"
+#
+# Define NEEDS_RESOLV if linking with -lnsl and/or -lsocket is not enough.
+# Notably on Solaris hstrerror resides in libresolv and on Solaris 7
+# inet_ntop and inet_pton additionally reside there.
+AC_CHECK_LIB([resolv], [hstrerror],
+[NEEDS_RESOLV=],
+[NEEDS_RESOLV=YesPlease])
+AC_SUBST(NEEDS_RESOLV)
+test -n "$NEEDS_RESOLV" && LIBS="$LIBS -lresolv"
## Checks for header files.
AC_MSG_NOTICE([CHECKS for header files])
@@ -627,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=],
@@ -677,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.
diff --git a/connect.c b/connect.c
index 692d476..0ce941e 100644
--- 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",
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 98b9cbe..80ab4e4 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -40,6 +40,10 @@
# 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
@@ -127,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
@@ -148,12 +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 "${1-}" ]; then
- printf "$1" "$c${b##refs/heads/}$w$i$r"
+ printf "$1" "$c${b##refs/heads/}$w$i$s$r"
else
- printf " (%s)" "$c${b##refs/heads/}$w$i$r"
+ printf " (%s)" "$c${b##refs/heads/}$w$i$s$r"
fi
fi
}
@@ -919,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 ()
@@ -1873,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,*)
diff --git a/daemon.c b/daemon.c
index daa4c8e..b2babcc 100644
--- 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 dcfbcb0..43835d7 100644
--- 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/git-add--interactive.perl b/git-add--interactive.perl
index a06172c..df9f231 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -1317,7 +1317,6 @@ sub patch_update_file {
open $fh, '| git apply --cached --recount';
for (@{$head->{TEXT}}, @result) {
print $fh $_;
- print STDERR $_;
}
if (!close $fh) {
for (@{$head->{TEXT}}, @result) {
diff --git a/git-compat-util.h b/git-compat-util.h
index 4236647..919b7f1 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -7,7 +7,7 @@
/*
* See if our compiler is known to support flexible array members.
*/
-#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && (!defined(__SUNPRO_C) || (__SUNPRO_C > 0x580))
# define FLEX_ARRAY /* empty */
#elif defined(__GNUC__)
# if (__GNUC__ >= 3)
@@ -39,7 +39,20 @@
/* Approximation of the length of the decimal representation of this type. */
#define decimal_length(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1)
-#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__USLC__) && !defined(_M_UNIX)
+#if defined(__sun__)
+ /*
+ * On Solaris, when _XOPEN_EXTENDED is set, its header file
+ * forces the programs to be XPG4v2, defeating any _XOPEN_SOURCE
+ * setting to say we are XPG5 or XPG6. Also on Solaris,
+ * XPG6 programs must be compiled with a c99 compiler, while
+ * non XPG6 programs must be compiled with a pre-c99 compiler.
+ */
+# if __STDC_VERSION__ - 0 >= 199901L
+# define _XOPEN_SOURCE 600
+# else
+# define _XOPEN_SOURCE 500
+# 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 */
@@ -99,6 +112,13 @@
#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
@@ -234,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 *);
diff --git a/git-cvsexportcommit.perl b/git-cvsexportcommit.perl
index 6d9f0ef..9ec1df9 100755
--- a/git-cvsexportcommit.perl
+++ b/git-cvsexportcommit.perl
@@ -225,7 +225,14 @@ if (@canstatusfiles) {
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+$//;
@@ -233,31 +240,45 @@ if (@canstatusfiles) {
$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;
diff --git a/git-mergetool--lib.sh b/git-mergetool--lib.sh
index 8b5e6a8..bfb01f7 100644
--- a/git-mergetool--lib.sh
+++ b/git-mergetool--lib.sh
@@ -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
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 314cd36..f96d887 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -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
;;
diff --git a/git-send-email.perl b/git-send-email.perl
index 3d6a982..4c795a4 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -577,7 +577,7 @@ EOT
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) {
@@ -766,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
{
@@ -783,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;
}
diff --git a/git-sh-setup.sh b/git-sh-setup.sh
index 8382339..80acb7d 100755
--- a/git-sh-setup.sh
+++ b/git-sh-setup.sh
@@ -11,6 +11,34 @@
# exporting it.
unset CDPATH
+git_broken_path_fix () {
+ case ":$PATH:" in
+ *:$1:*) : ok ;;
+ *)
+ PATH=$(
+ SANE_TOOL_PATH="$1"
+ IFS=: path= sep=
+ set x $PATH
+ shift
+ for elem
+ do
+ case "$SANE_TOOL_PATH:$elem" in
+ (?*:/bin | ?*:/usr/bin)
+ path="$path$sep$SANE_TOOL_PATH"
+ sep=:
+ SANE_TOOL_PATH=
+ esac
+ path="$path$sep$elem"
+ sep=:
+ done
+ echo "$path"
+ )
+ ;;
+ esac
+}
+
+# @@BROKEN_PATH_FIX@@
+
die() {
echo >&2 "$@"
exit 1
diff --git a/git-stash.sh b/git-stash.sh
index b9ace99..e6a5867 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -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"
diff --git a/git-submodule.sh b/git-submodule.sh
index ab1ed02..19a3a84 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -18,6 +18,7 @@ quiet=
reference=
cached=
nofetch=
+update=
#
# print stuff on stdout unless -q was specified
@@ -310,6 +311,11 @@ cmd_init()
git config submodule."$name".url "$url" ||
die "Failed to register url for submodule path '$path'"
+ upd="$(git config -f .gitmodules submodule."$name".update)"
+ test -z "$upd" ||
+ git config submodule."$name".update "$upd" ||
+ die "Failed to register update mode for submodule path '$path'"
+
say "Submodule '$name' ($url) registered for path '$path'"
done
}
@@ -337,6 +343,10 @@ cmd_update()
shift
nofetch=1
;;
+ -r|--rebase)
+ shift
+ update="rebase"
+ ;;
--reference)
case "$2" in '') usage ;; esac
reference="--reference=$2"
@@ -369,6 +379,7 @@ cmd_update()
do
name=$(module_name "$path") || exit
url=$(git config submodule."$name".url)
+ update_module=$(git config submodule."$name".update)
if test -z "$url"
then
# Only mention uninitialized submodules when its
@@ -389,6 +400,11 @@ cmd_update()
die "Unable to find current revision in submodule path '$path'"
fi
+ if ! test -z "$update"
+ then
+ update_module=$update
+ fi
+
if test "$subsha1" != "$sha1"
then
force=
@@ -404,11 +420,22 @@ cmd_update()
die "Unable to fetch in submodule path '$path'"
fi
- (unset GIT_DIR; cd "$path" &&
- git-checkout $force -q "$sha1") ||
- die "Unable to checkout '$sha1' in submodule path '$path'"
+ case "$update_module" in
+ rebase)
+ command="git rebase"
+ action="rebase"
+ msg="rebased onto"
+ ;;
+ *)
+ command="git checkout $force -q"
+ action="checkout"
+ msg="checked out"
+ ;;
+ esac
- say "Submodule path '$path': checked out '$sha1'"
+ (unset GIT_DIR; cd "$path" && $command "$sha1") ||
+ die "Unable to $action '$sha1' in submodule path '$path'"
+ say "Submodule path '$path': $msg '$sha1'"
fi
done
}
diff --git a/grep.c b/grep.c
index cc6d5b0..92a47c7 100644
--- 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
@@ -500,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,
diff --git a/http-push.c b/http-push.c
index 43e2dda..a7e28e3 100644
--- a/http-push.c
+++ b/http-push.c
@@ -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,13 +1874,12 @@ 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);
}
@@ -2300,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;
diff --git a/ll-merge.c b/ll-merge.c
index 81c02ad..31d6f0a 100644
--- a/ll-merge.c
+++ b/ll-merge.c
@@ -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
diff --git a/merge-index.c b/merge-index.c
index aa9cf23..19ddd03 100644
--- a/merge-index.c
+++ b/merge-index.c
@@ -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/parse-options.c b/parse-options.c
index b85cab2..79de18b 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -306,6 +306,28 @@ 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, const char *prefix,
int flags)
@@ -331,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;
diff --git a/parse-options.h b/parse-options.h
index b374ade..5653dba 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -71,8 +71,11 @@ 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.
diff --git a/path.c b/path.c
index 8a0a674..047fdb0 100644
--- 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)
{
diff --git a/remote.c b/remote.c
index 2c3e905..08a5964 100644
--- 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);
diff --git a/remote.h b/remote.h
index 99706a8..257a555 100644
--- 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);
/*
diff --git a/revision.c b/revision.c
index 18b7ebb..bf58448 100644
--- a/revision.c
+++ b/revision.c
@@ -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;
diff --git a/revision.h b/revision.h
index be39e7d..227164c 100644
--- a/revision.h
+++ b/revision.h
@@ -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);
diff --git a/symlinks.c b/symlinks.c
index 1d6b35b..8dcd632 100644
--- a/symlinks.c
+++ b/symlinks.c
@@ -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;
}
diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh
index cde659d..6765b08 100644
--- a/t/lib-httpd.sh
+++ b/t/lib-httpd.sh
@@ -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
}
diff --git a/t/t3030-merge-recursive.sh b/t/t3030-merge-recursive.sh
index 0de613d..9b3fa2b 100755
--- a/t/t3030-merge-recursive.sh
+++ b/t/t3030-merge-recursive.sh
@@ -276,6 +276,9 @@ test_expect_success 'fail if the index has unresolved entries' '
test_must_fail git merge "$c5" &&
test_must_fail git merge "$c5" 2> out &&
+ grep "You have not concluded your merge" out &&
+ rm -f .git/MERGE_HEAD &&
+ test_must_fail git merge "$c5" 2> out &&
grep "You are in the middle of a conflicted merge" out
'
diff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh
index 0720001..4ea42e0 100755
--- a/t/t4020-diff-external.sh
+++ b/t/t4020-diff-external.sh
@@ -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/t6023-merge-file.sh b/t/t6023-merge-file.sh
index f8942bc..7dcf391 100755
--- a/t/t6023-merge-file.sh
+++ b/t/t6023-merge-file.sh
@@ -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"
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
new file mode 100755
index 0000000..0773fe4
--- /dev/null
+++ b/t/t7406-submodule-update.sh
@@ -0,0 +1,140 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Red Hat, Inc.
+#
+
+test_description='Test updating submodules
+
+This test verifies that "git submodule update" detaches the HEAD of the
+submodule and "git submodule update --rebase" does not detach the HEAD.
+'
+
+. ./test-lib.sh
+
+
+compare_head()
+{
+ sha_master=`git-rev-list --max-count=1 master`
+ sha_head=`git-rev-list --max-count=1 HEAD`
+
+ test "$sha_master" = "$sha_head"
+}
+
+
+test_expect_success 'setup a submodule tree' '
+ echo file > file &&
+ git add file &&
+ test_tick &&
+ git commit -m upstream
+ git clone . super &&
+ git clone super submodule &&
+ (cd super &&
+ git submodule add ../submodule submodule &&
+ test_tick &&
+ git commit -m "submodule" &&
+ git submodule init submodule
+ ) &&
+ (cd submodule &&
+ echo "line2" > file &&
+ git add file &&
+ git commit -m "Commit 2"
+ ) &&
+ (cd super &&
+ (cd submodule &&
+ git pull --rebase origin
+ ) &&
+ git add submodule &&
+ git commit -m "submodule update"
+ )
+'
+
+test_expect_success 'submodule update detaching the HEAD ' '
+ (cd super/submodule &&
+ git reset --hard HEAD~1
+ ) &&
+ (cd super &&
+ (cd submodule &&
+ compare_head
+ ) &&
+ git submodule update submodule &&
+ cd submodule &&
+ ! compare_head
+ )
+'
+
+test_expect_success 'submodule update --rebase staying on master' '
+ (cd super/submodule &&
+ git checkout master
+ ) &&
+ (cd super &&
+ (cd submodule &&
+ compare_head
+ ) &&
+ git submodule update --rebase submodule &&
+ cd submodule &&
+ compare_head
+ )
+'
+
+test_expect_success 'submodule update - rebase in .git/config' '
+ (cd super &&
+ git config submodule.submodule.update rebase
+ ) &&
+ (cd super/submodule &&
+ git reset --hard HEAD~1
+ ) &&
+ (cd super &&
+ (cd submodule &&
+ compare_head
+ ) &&
+ git submodule update submodule &&
+ cd submodule &&
+ compare_head
+ )
+'
+
+test_expect_success 'submodule update - checkout in .git/config but --rebase given' '
+ (cd super &&
+ git config submodule.submodule.update checkout
+ ) &&
+ (cd super/submodule &&
+ git reset --hard HEAD~1
+ ) &&
+ (cd super &&
+ (cd submodule &&
+ compare_head
+ ) &&
+ git submodule update --rebase submodule &&
+ cd submodule &&
+ compare_head
+ )
+'
+
+test_expect_success 'submodule update - checkout in .git/config' '
+ (cd super &&
+ git config submodule.submodule.update checkout
+ ) &&
+ (cd super/submodule &&
+ git reset --hard HEAD^
+ ) &&
+ (cd super &&
+ (cd submodule &&
+ compare_head
+ ) &&
+ git submodule update submodule &&
+ cd submodule &&
+ ! compare_head
+ )
+'
+
+test_expect_success 'submodule init picks up rebase' '
+ (cd super &&
+ git config submodule.rebasing.url git://non-existing/git &&
+ git config submodule.rebasing.path does-not-matter &&
+ git config submodule.rebasing.update rebase &&
+ git submodule init rebasing &&
+ test "rebase" = $(git config submodule.rebasing.update)
+ )
+'
+
+test_done
diff --git a/t/t8003-blame.sh b/t/t8003-blame.sh
index 966bb0a..13c25f1 100755
--- a/t/t8003-blame.sh
+++ b/t/t8003-blame.sh
@@ -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
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index ce26ea4..2ce24cd 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -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' '
diff --git a/t/t9200-git-cvsexportcommit.sh b/t/t9200-git-cvsexportcommit.sh
index 56b7c06..ef1f8d2 100755
--- a/t/t9200-git-cvsexportcommit.sh
+++ b/t/t9200-git-cvsexportcommit.sh
@@ -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
diff --git a/t/test-lib.sh b/t/test-lib.sh
index dad1437..5fdc5d9 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -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
}
diff --git a/transport.c b/transport.c
index 17891d5..d8a2392 100644
--- a/transport.c
+++ b/transport.c
@@ -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;
}
diff --git a/utf8.c b/utf8.c
index ddfdc5e..db706ac 100644
--- a/utf8.c
+++ b/utf8.c
@@ -354,7 +354,7 @@ int is_encoding_utf8(const char *name)
* with iconv. If the conversion fails, returns NULL.
*/
#ifndef NO_ICONV
-#ifdef OLD_ICONV
+#if defined(OLD_ICONV) || (defined(__sun__) && !defined(_XPG6))
typedef const char * iconv_ibp;
#else
typedef char * iconv_ibp;
diff --git a/xdiff/xmerge.c b/xdiff/xmerge.c
index d9737f0..1cb65a9 100644
--- a/xdiff/xmerge.c
+++ b/xdiff/xmerge.c
@@ -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);