Imported Upstream version 2.9.4 upstream/2.9.4
authorDongHun Kwak <dh0128.kwak@samsung.com>
Wed, 3 Mar 2021 06:15:52 +0000 (15:15 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Wed, 3 Mar 2021 06:15:52 +0000 (15:15 +0900)
108 files changed:
Documentation/RelNotes/2.4.12.txt [new file with mode: 0644]
Documentation/RelNotes/2.5.6.txt [new file with mode: 0644]
Documentation/RelNotes/2.6.7.txt [new file with mode: 0644]
Documentation/RelNotes/2.7.5.txt [new file with mode: 0644]
Documentation/RelNotes/2.8.5.txt [new file with mode: 0644]
Documentation/RelNotes/2.9.4.txt [new file with mode: 0644]
Documentation/SubmittingPatches
Documentation/config.txt
Documentation/git-config.txt
Documentation/git-pack-objects.txt
Documentation/git-push.txt
Documentation/git-repack.txt
Documentation/git.txt
Documentation/gitattributes.txt
Documentation/pretty-formats.txt
Documentation/rev-list-options.txt
Documentation/technical/protocol-common.txt
GIT-VERSION-GEN
Makefile
RelNotes
builtin/blame.c
builtin/checkout.c
builtin/help.c
builtin/merge.c
builtin/mv.c
builtin/receive-pack.c
cache.h
commit.c
commit.h
common-main.c [new file with mode: 0644]
compat/mingw.c
compat/mingw.h
contrib/fast-import/import-tars.perl
convert.c
convert.h
credential-cache--daemon.c
credential-cache.c
credential-store.c
daemon.c
date.c
fast-import.c
git-compat-util.h
git-difftool--helper.sh
git.c
http-backend.c
http-fetch.c
http-push.c
imap-send.c
lockfile.h
mailinfo.c
merge-recursive.c
pretty.c
read-cache.c
remote-curl.c
remote-testsvn.c
remote.c
remote.h
sh-i18n--envsubst.c
shell.c
show-index.c
t/Makefile
t/helper/test-chmtime.c
t/helper/test-config.c
t/helper/test-ctype.c
t/helper/test-date.c
t/helper/test-delta.c
t/helper/test-dump-cache-tree.c
t/helper/test-dump-split-index.c
t/helper/test-dump-untracked-cache.c
t/helper/test-fake-ssh.c
t/helper/test-genrandom.c
t/helper/test-hashmap.c
t/helper/test-index-version.c
t/helper/test-line-buffer.c
t/helper/test-match-trees.c
t/helper/test-mergesort.c
t/helper/test-mktemp.c
t/helper/test-parse-options.c
t/helper/test-path-utils.c
t/helper/test-prio-queue.c
t/helper/test-read-cache.c
t/helper/test-regex.c
t/helper/test-revision-walking.c
t/helper/test-run-command.c
t/helper/test-scrap-cache-tree.c
t/helper/test-sha1-array.c
t/helper/test-sha1.c
t/helper/test-sigchain.c
t/helper/test-string-list.c
t/helper/test-submodule-config.c
t/helper/test-subprocess.c
t/helper/test-svn-fe.c
t/helper/test-urlmatch-normalization.c
t/helper/test-wildmatch.c
t/t0006-date.sh
t/t0025-crlf-auto.sh
t/t0027-auto-crlf.sh
t/t1410-reflog.sh
t/t2020-checkout-detach.sh
t/t3030-merge-recursive.sh
t/t5533-push-cas.sh
t/t6026-merge-attr.sh
t/t6038-merge-text-auto.sh
t/t7800-difftool.sh
tempfile.c
tempfile.h
transport.c
upload-pack.c

diff --git a/Documentation/RelNotes/2.4.12.txt b/Documentation/RelNotes/2.4.12.txt
new file mode 100644 (file)
index 0000000..7d15f94
--- /dev/null
@@ -0,0 +1,12 @@
+Git v2.4.12 Release Notes
+=========================
+
+Fixes since v2.4.11
+-------------------
+
+ * "git-shell" rejects a request to serve a repository whose name
+   begins with a dash, which makes it no longer possible to get it
+   confused into spawning service programs like "git-upload-pack" with
+   an option like "--help", which in turn would spawn an interactive
+   pager, instead of working with the repository user asked to access
+   (i.e. the one whose name is "--help").
diff --git a/Documentation/RelNotes/2.5.6.txt b/Documentation/RelNotes/2.5.6.txt
new file mode 100644 (file)
index 0000000..9cd025b
--- /dev/null
@@ -0,0 +1,12 @@
+Git v2.5.6 Release Notes
+========================
+
+Fixes since v2.5.5
+------------------
+
+ * "git-shell" rejects a request to serve a repository whose name
+   begins with a dash, which makes it no longer possible to get it
+   confused into spawning service programs like "git-upload-pack" with
+   an option like "--help", which in turn would spawn an interactive
+   pager, instead of working with the repository user asked to access
+   (i.e. the one whose name is "--help").
diff --git a/Documentation/RelNotes/2.6.7.txt b/Documentation/RelNotes/2.6.7.txt
new file mode 100644 (file)
index 0000000..1335de4
--- /dev/null
@@ -0,0 +1,12 @@
+Git v2.6.7 Release Notes
+========================
+
+Fixes since v2.6.6
+------------------
+
+ * "git-shell" rejects a request to serve a repository whose name
+   begins with a dash, which makes it no longer possible to get it
+   confused into spawning service programs like "git-upload-pack" with
+   an option like "--help", which in turn would spawn an interactive
+   pager, instead of working with the repository user asked to access
+   (i.e. the one whose name is "--help").
diff --git a/Documentation/RelNotes/2.7.5.txt b/Documentation/RelNotes/2.7.5.txt
new file mode 100644 (file)
index 0000000..83559ce
--- /dev/null
@@ -0,0 +1,14 @@
+Git v2.7.5 Release Notes
+========================
+
+Fixes since v2.7.4
+------------------
+
+ * "git-shell" rejects a request to serve a repository whose name
+   begins with a dash, which makes it no longer possible to get it
+   confused into spawning service programs like "git-upload-pack" with
+   an option like "--help", which in turn would spawn an interactive
+   pager, instead of working with the repository user asked to access
+   (i.e. the one whose name is "--help").
+
+Also contains a few fixes backported from later development tracks.
diff --git a/Documentation/RelNotes/2.8.5.txt b/Documentation/RelNotes/2.8.5.txt
new file mode 100644 (file)
index 0000000..7bd179f
--- /dev/null
@@ -0,0 +1,12 @@
+Git v2.8.5 Release Notes
+========================
+
+Fixes since v2.8.4
+------------------
+
+ * "git-shell" rejects a request to serve a repository whose name
+   begins with a dash, which makes it no longer possible to get it
+   confused into spawning service programs like "git-upload-pack" with
+   an option like "--help", which in turn would spawn an interactive
+   pager, instead of working with the repository user asked to access
+   (i.e. the one whose name is "--help").
diff --git a/Documentation/RelNotes/2.9.4.txt b/Documentation/RelNotes/2.9.4.txt
new file mode 100644 (file)
index 0000000..9768293
--- /dev/null
@@ -0,0 +1,90 @@
+Git v2.9.4 Release Notes
+========================
+
+Fixes since v2.9.3
+------------------
+
+ * There are certain house-keeping tasks that need to be performed at
+   the very beginning of any Git program, and programs that are not
+   built-in commands had to do them exactly the same way as "git"
+   potty does.  It was easy to make mistakes in one-off standalone
+   programs (like test helpers).  A common "main()" function that
+   calls cmd_main() of individual program has been introduced to
+   make it harder to make mistakes.
+
+ * "git merge" with renormalization did not work well with
+   merge-recursive, due to "safer crlf" conversion kicking in when it
+   shouldn't.
+
+ * The reflog output format is documented better, and a new format
+   --date=unix to report the seconds-since-epoch (without timezone)
+   has been added.
+
+ * "git push --force-with-lease" already had enough logic to allow
+   ensuring that such a push results in creation of a ref (i.e. the
+   receiving end did not have another push from sideways that would be
+   discarded by our force-pushing), but didn't expose this possibility
+   to the users.  It does so now.
+
+ * "import-tars" fast-import script (in contrib/) used to ignore a
+   hardlink target and replaced it with an empty file, which has been
+   corrected to record the same blob as the other file the hardlink is
+   shared with.
+
+ * "git mv dir non-existing-dir/" did not work in some environments
+   the same way as existing mainstream platforms.  The code now moves
+   "dir" to "non-existing-dir", without relying on rename("A", "B/")
+   that strips the trailing slash of '/'.
+
+ * The "t/" hierarchy is prone to get an unusual pathname; "make test"
+   has been taught to make sure they do not contain paths that cannot
+   be checked out on Windows (and the mechanism can be reusable to
+   catch pathnames that are not portable to other platforms as need
+   arises).
+
+ * When "git merge-recursive" works on history with many criss-cross
+   merges in "verbose" mode, the names the command assigns to the
+   virtual merge bases could have overwritten each other by unintended
+   reuse of the same piece of memory.
+
+ * "git checkout --detach <branch>" used to give the same advice
+   message as that is issued when "git checkout <tag>" (or anything
+   that is not a branch name) is given, but asking with "--detach" is
+   an explicit enough sign that the user knows what is going on.  The
+   advice message has been squelched in this case.
+
+ * "git difftool" by default ignores the error exit from the backend
+   commands it spawns, because often they signal that they found
+   differences by exiting with a non-zero status code just like "diff"
+   does; the exit status codes 126 and above however are special in
+   that they are used to signal that the command is not executable,
+   does not exist, or killed by a signal.  "git difftool" has been
+   taught to notice these exit status codes.
+
+ * On Windows, help.browser configuration variable used to be ignored,
+   which has been corrected.
+
+ * The "git -c var[=val] cmd" facility to append a configuration
+   variable definition at the end of the search order was described in
+   git(1) manual page, but not in git-config(1), which was more likely
+   place for people to look for when they ask "can I make a one-shot
+   override, and if so how?"
+
+ * The tempfile (hence its user lockfile) API lets the caller to open
+   a file descriptor to a temporary file, write into it and then
+   finalize it by first closing the filehandle and then either
+   removing or renaming the temporary file.  When the process spawns a
+   subprocess after obtaining the file descriptor, and if the
+   subprocess has not exited when the attempt to remove or rename is
+   made, the last step fails on Windows, because the subprocess has
+   the file descriptor still open.  Open tempfile with O_CLOEXEC flag
+   to avoid this (on Windows, this is mapped to O_NOINHERIT).
+
+ * "git-shell" rejects a request to serve a repository whose name
+   begins with a dash, which makes it no longer possible to get it
+   confused into spawning service programs like "git-upload-pack" with
+   an option like "--help", which in turn would spawn an interactive
+   pager, instead of working with the repository user asked to access
+   (i.e. the one whose name is "--help").
+
+Also contains minor documentation updates and code clean-ups.
index e8ad978..08352de 100644 (file)
@@ -121,6 +121,16 @@ its behaviour.  Try to make sure your explanation can be understood
 without external resources. Instead of giving a URL to a mailing list
 archive, summarize the relevant points of the discussion.
 
+If you want to reference a previous commit in the history of a stable
+branch, use the format "abbreviated sha1 (subject, date)",
+with the subject enclosed in a pair of double-quotes, like this:
+
+    Commit f86a374 ("pack-bitmap.c: fix a memleak", 2015-03-30)
+    noticed that ...
+
+The "Copy commit summary" command of gitk can be used to obtain this
+format.
+
 
 (3) Generate your patch using Git tools out of your commits.
 
index 6ad3eb6..f4721a0 100644 (file)
@@ -405,13 +405,11 @@ file with mixed line endings would be reported by the `core.safecrlf`
 mechanism.
 
 core.autocrlf::
-       Setting this variable to "true" is almost the same as setting
-       the `text` attribute to "auto" on all files except that text
-       files are not guaranteed to be normalized: files that contain
-       `CRLF` in the repository will not be touched.  Use this
-       setting if you want to have `CRLF` line endings in your
-       working directory even though the repository does not have
-       normalized line endings.  This variable can be set to 'input',
+       Setting this variable to "true" is the same as setting
+       the `text` attribute to "auto" on all files and core.eol to "crlf".
+       Set to true if you want to have `CRLF` line endings in your
+       working directory and the repository has LF line endings.
+       This variable can be set to 'input',
        in which case no output conversion is performed.
 
 core.symlinks::
index f163113..83f86b9 100644 (file)
@@ -263,6 +263,9 @@ The files are read in the order given above, with last value found taking
 precedence over values read earlier.  When multiple values are taken then all
 values of a key from all files will be used.
 
+You may override individual configuration parameters when running any git
+command by using the `-c` option. See linkgit:git[1] for details.
+
 All writing options will per default write to the repository specific
 configuration file. Note that this also affects options like `--replace-all`
 and `--unset`. *'git config' will only ever change one file at a time*.
index 19cdcd0..8973510 100644 (file)
@@ -104,8 +104,8 @@ base-name::
        out of memory with a large window, but still be able to take
        advantage of the large window for the smaller objects.  The
        size can be suffixed with "k", "m", or "g".
-       `--window-memory=0` makes memory usage unlimited, which is the
-       default.
+       `--window-memory=0` makes memory usage unlimited.  The default
+       is taken from the `pack.windowMemory` configuration variable.
 
 --max-pack-size=<n>::
        Maximum size of each output pack file. The size can be suffixed with
index 93c3527..927a034 100644 (file)
@@ -198,10 +198,11 @@ branch we have for it.
 +
 `--force-with-lease=<refname>:<expect>` will protect the named ref (alone),
 if it is going to be updated, by requiring its current value to be
-the same as the specified value <expect> (which is allowed to be
+the same as the specified value `<expect>` (which is allowed to be
 different from the remote-tracking branch we have for the refname,
 or we do not even have to have such a remote-tracking branch when
-this form is used).
+this form is used).  If `<expect>` is the empty string, then the named ref
+must not already exist.
 +
 Note that all forms other than `--force-with-lease=<refname>:<expect>`
 that specifies the expected current value of the ref explicitly are
index 0c03eec..9597777 100644 (file)
@@ -100,8 +100,10 @@ other objects in that pack they already have locally.
        out of memory with a large window, but still be able to take
        advantage of the large window for the smaller objects.  The
        size can be suffixed with "k", "m", or "g".
-       `--window-memory=0` makes memory usage unlimited, which is the
-       default.
+       `--window-memory=0` makes memory usage unlimited.  The default
+       is taken from the `pack.windowMemory` configuration variable.
+       Note that the actual memory usage will be the limit multiplied
+       by the number of threads used by linkgit:git-pack-objects[1].
 
 --max-pack-size=<n>::
        Maximum size of each output pack file. The size can be suffixed with
index 923aa49..80da7b7 100644 (file)
@@ -43,34 +43,40 @@ unreleased) version of Git, that is available from the 'master'
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
-* link:v2.9.3/git.html[documentation for release 2.9.3]
+
+* link:v2.9.4/git.html[documentation for release 2.9.4]
 
 * release notes for
+  link:RelNotes/2.9.4.txt[2.9.4],
   link:RelNotes/2.9.3.txt[2.9.3],
   link:RelNotes/2.9.2.txt[2.9.2],
   link:RelNotes/2.9.1.txt[2.9.1],
   link:RelNotes/2.9.0.txt[2.9].
 
-* link:v2.8.4/git.html[documentation for release 2.8.4]
+* link:v2.8.5/git.html[documentation for release 2.8.5]
 
 * release notes for
+  link:RelNotes/2.8.5.txt[2.8.5],
   link:RelNotes/2.8.4.txt[2.8.4],
   link:RelNotes/2.8.3.txt[2.8.3],
   link:RelNotes/2.8.2.txt[2.8.2],
   link:RelNotes/2.8.1.txt[2.8.1],
   link:RelNotes/2.8.0.txt[2.8].
 
-* link:v2.7.3/git.html[documentation for release 2.7.3]
+* link:v2.7.5/git.html[documentation for release 2.7.5]
 
 * release notes for
+  link:RelNotes/2.7.5.txt[2.7.5],
+  link:RelNotes/2.7.4.txt[2.7.4],
   link:RelNotes/2.7.3.txt[2.7.3],
   link:RelNotes/2.7.2.txt[2.7.2],
   link:RelNotes/2.7.1.txt[2.7.1],
   link:RelNotes/2.7.0.txt[2.7].
 
-* link:v2.6.6/git.html[documentation for release 2.6.6]
+* link:v2.6.7/git.html[documentation for release 2.6.7]
 
 * release notes for
+  link:RelNotes/2.6.7.txt[2.6.7],
   link:RelNotes/2.6.6.txt[2.6.6],
   link:RelNotes/2.6.5.txt[2.6.5],
   link:RelNotes/2.6.4.txt[2.6.4],
@@ -79,9 +85,10 @@ Documentation for older releases are available here:
   link:RelNotes/2.6.1.txt[2.6.1],
   link:RelNotes/2.6.0.txt[2.6].
 
-* link:v2.5.5/git.html[documentation for release 2.5.5]
+* link:v2.5.6/git.html[documentation for release 2.5.6]
 
 * release notes for
+  link:RelNotes/2.5.6.txt[2.5.6],
   link:RelNotes/2.5.5.txt[2.5.5],
   link:RelNotes/2.5.4.txt[2.5.4],
   link:RelNotes/2.5.3.txt[2.5.3],
@@ -89,9 +96,10 @@ Documentation for older releases are available here:
   link:RelNotes/2.5.1.txt[2.5.1],
   link:RelNotes/2.5.0.txt[2.5].
 
-* link:v2.4.11/git.html[documentation for release 2.4.11]
+* link:v2.4.12/git.html[documentation for release 2.4.12]
 
 * release notes for
+  link:RelNotes/2.4.12.txt[2.4.12],
   link:RelNotes/2.4.11.txt[2.4.11],
   link:RelNotes/2.4.10.txt[2.4.10],
   link:RelNotes/2.4.9.txt[2.4.9],
index 145dd10..6d20400 100644 (file)
@@ -115,6 +115,7 @@ text file is normalized, its line endings are converted to LF in the
 repository.  To control what line ending style is used in the working
 directory, use the `eol` attribute for a single file and the
 `core.eol` configuration variable for all text files.
+Note that `core.autocrlf` overrides `core.eol`
 
 Set::
 
@@ -130,8 +131,9 @@ Unset::
 Set to string value "auto"::
 
        When `text` is set to "auto", the path is marked for automatic
-       end-of-line normalization.  If Git decides that the content is
-       text, its line endings are normalized to LF on checkin.
+       end-of-line conversion.  If Git decides that the content is
+       text, its line endings are converted to LF on checkin.
+       When the file has been commited with CRLF, no conversion is done.
 
 Unspecified::
 
@@ -146,7 +148,7 @@ unspecified.
 ^^^^^
 
 This attribute sets a specific line-ending style to be used in the
-working directory.  It enables end-of-line normalization without any
+working directory.  It enables end-of-line conversion without any
 content checks, effectively setting the `text` attribute.
 
 Set to string value "crlf"::
@@ -186,9 +188,10 @@ the working directory, and prevent .jpg files from being normalized
 regardless of their content.
 
 ------------------------
+*               text=auto
 *.txt          text
-*.vcproj       eol=crlf
-*.sh           eol=lf
+*.vcproj       text eol=crlf
+*.sh           text eol=lf
 *.jpg          -text
 ------------------------
 
@@ -198,7 +201,7 @@ normalization in Git.
 
 If you simply want to have CRLF line endings in your working directory
 regardless of the repository you are working with, you can set the
-config variable "core.autocrlf" without changing any attributes.
+config variable "core.autocrlf" without using any attributes.
 
 ------------------------
 [core]
index 29b19b9..b95d67e 100644 (file)
@@ -147,8 +147,14 @@ endif::git-rev-list[]
   "U" for a good signature with unknown validity and "N" for no signature
 - '%GS': show the name of the signer for a signed commit
 - '%GK': show the key used to sign a signed commit
-- '%gD': reflog selector, e.g., `refs/stash@{1}`
-- '%gd': shortened reflog selector, e.g., `stash@{1}`
+- '%gD': reflog selector, e.g., `refs/stash@{1}` or
+  `refs/stash@{2 minutes ago`}; the format follows the rules described
+  for the `-g` option. The portion before the `@` is the refname as
+  given on the command line (so `git log -g refs/heads/master` would
+  yield `refs/heads/master@{0}`).
+- '%gd': shortened reflog selector; same as `%gD`, but the refname
+  portion is shortened for human readability (so `refs/heads/master`
+  becomes just `master`).
 - '%gn': reflog identity name
 - '%gN': reflog identity name (respecting .mailmap, see
   linkgit:git-shortlog[1] or linkgit:git-blame[1])
index c5bd218..eac982c 100644 (file)
@@ -252,10 +252,25 @@ list.
 +
 With `--pretty` format other than `oneline` (for obvious reasons),
 this causes the output to have two extra lines of information
-taken from the reflog.  By default, 'commit@\{Nth}' notation is
-used in the output.  When the starting commit is specified as
-'commit@\{now}', output also uses 'commit@\{timestamp}' notation
-instead.  Under `--pretty=oneline`, the commit message is
+taken from the reflog.  The reflog designator in the output may be shown
+as `ref@{Nth}` (where `Nth` is the reverse-chronological index in the
+reflog) or as `ref@{timestamp}` (with the timestamp for that entry),
+depending on a few rules:
++
+--
+1. If the starting point is specified as `ref@{Nth}`, show the index
+format.
++
+2. If the starting point was specified as `ref@{now}`, show the
+timestamp format.
++
+3. If neither was used, but `--date` was given on the command line, show
+the timestamp in the format requested by `--date`.
++
+4. Otherwise, show the index format.
+--
++
+Under `--pretty=oneline`, the commit message is
 prefixed with this information on the same line.
 This option cannot be combined with `--reverse`.
 See also linkgit:git-reflog[1].
@@ -710,8 +725,8 @@ include::pretty-options.txt[]
        `iso-local`), the user's local time zone is used instead.
 +
 `--date=relative` shows dates relative to the current time,
-e.g. ``2 hours ago''. The `-local` option cannot be used with
-`--raw` or `--relative`.
+e.g. ``2 hours ago''. The `-local` option has no effect for
+`--date=relative`.
 +
 `--date=local` is an alias for `--date=default-local`.
 +
@@ -731,7 +746,18 @@ format, often found in email messages.
 +
 `--date=short` shows only the date, but not the time, in `YYYY-MM-DD` format.
 +
-`--date=raw` shows the date in the internal raw Git format `%s %z` format.
+`--date=raw` shows the date as seconds since the epoch (1970-01-01
+00:00:00 UTC), followed by a space, and then the timezone as an offset
+from UTC (a `+` or `-` with four digits; the first two are hours, and
+the second two are minutes). I.e., as if the timestamp were formatted
+with `strftime("%s %z")`).
+Note that the `-local` option does not affect the seconds-since-epoch
+value (which is always measured in UTC), but does switch the accompanying
+timezone value.
++
+`--date=unix` shows the date as a Unix epoch timestamp (seconds since
+1970).  As with `--raw`, this is always in UTC and therefore `-local`
+has no effect.
 +
 `--date=format:...` feeds the format `...` to your system `strftime`.
 Use `--date=format:%c` to show the date in your system locale's
index bf30167..ecedb34 100644 (file)
@@ -67,9 +67,9 @@ with non-binary data the same whether or not they contain the trailing
 LF (stripping the LF if present, and not complaining when it is
 missing).
 
-The maximum length of a pkt-line's data component is 65520 bytes.
-Implementations MUST NOT send pkt-line whose length exceeds 65524
-(65520 bytes of payload + 4 bytes of length data).
+The maximum length of a pkt-line's data component is 65516 bytes.
+Implementations MUST NOT send pkt-line whose length exceeds 65520
+(65516 bytes of payload + 4 bytes of length data).
 
 Implementations SHOULD NOT send an empty pkt-line ("0004").
 
index 0011c3f..f0c6bb0 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.9.3
+DEF_VER=v2.9.4
 
 LF='
 '
index 4579eab..13ed57f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -939,7 +939,7 @@ BUILTIN_OBJS += builtin/verify-tag.o
 BUILTIN_OBJS += builtin/worktree.o
 BUILTIN_OBJS += builtin/write-tree.o
 
-GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
+GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB)
 EXTLIBS =
 
 GIT_USER_AGENT = git/$(GIT_VERSION)
@@ -1572,7 +1572,15 @@ TCLTK_PATH_SQ = $(subst ','\'',$(TCLTK_PATH))
 DIFF_SQ = $(subst ','\'',$(DIFF))
 PERLLIB_EXTRA_SQ = $(subst ','\'',$(PERLLIB_EXTRA))
 
-LIBS = $(GITLIBS) $(EXTLIBS)
+# We must filter out any object files from $(GITLIBS),
+# as it is typically used like:
+#
+#   foo: foo.o $(GITLIBS)
+#      $(CC) $(filter %.o,$^) $(LIBS)
+#
+# where we use it as a dependency. Since we also pull object files
+# from the dependency list, that would make each entry appear twice.
+LIBS = $(filter-out %.o, $(GITLIBS)) $(EXTLIBS)
 
 BASIC_CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER_SQ)' \
        $(COMPAT_CFLAGS)
@@ -1708,8 +1716,8 @@ git.sp git.s git.o: EXTRA_CPPFLAGS = \
        '-DGIT_INFO_PATH="$(infodir_relative_SQ)"'
 
 git$X: git.o GIT-LDFLAGS $(BUILTIN_OBJS) $(GITLIBS)
-       $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) git.o \
-               $(BUILTIN_OBJS) $(LIBS)
+       $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \
+               $(filter %.o,$^) $(LIBS)
 
 help.sp help.s help.o: common-cmds.h
 
@@ -1902,6 +1910,7 @@ TEST_OBJS := $(patsubst %$X,%.o,$(TEST_PROGRAMS))
 OBJECTS := $(LIB_OBJS) $(BUILTIN_OBJS) $(PROGRAM_OBJS) $(TEST_OBJS) \
        $(XDIFF_OBJS) \
        $(VCSSVN_OBJS) \
+       common-main.o \
        git.o
 ifndef NO_CURL
        OBJECTS += http.o http-walker.o remote-curl.o
index 779efe8..a5f3cbf 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.9.3.txt
\ No newline at end of file
+Documentation/RelNotes/2.9.4.txt
\ No newline at end of file
index d123e2e..5e5d30e 100644 (file)
@@ -2633,6 +2633,9 @@ parse_done:
        case DATE_RAW:
                blame_date_width = sizeof("1161298804 -0700");
                break;
+       case DATE_UNIX:
+               blame_date_width = sizeof("1161298804");
+               break;
        case DATE_SHORT:
                blame_date_width = sizeof("2006-10-19");
                break;
index c3486bd..d3b2968 100644 (file)
@@ -655,7 +655,8 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
                update_ref(msg.buf, "HEAD", new->commit->object.oid.hash, NULL,
                           REF_NODEREF, UPDATE_REFS_DIE_ON_ERR);
                if (!opts->quiet) {
-                       if (old->path && advice_detached_head)
+                       if (old->path &&
+                           advice_detached_head && !opts->force_detach)
                                detach_advice(new->name);
                        describe_detached_head(_("HEAD is now at"), new->commit);
                }
@@ -703,8 +704,7 @@ static int add_pending_uninteresting_ref(const char *refname,
 static void describe_one_orphan(struct strbuf *sb, struct commit *commit)
 {
        strbuf_addstr(sb, "  ");
-       strbuf_addstr(sb,
-               find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));
+       strbuf_add_unique_abbrev(sb, commit->object.oid.hash, DEFAULT_ABBREV);
        strbuf_addch(sb, ' ');
        if (!parse_commit(commit))
                pp_commit_easy(CMIT_FMT_ONELINE, commit, sb);
index 8848013..e8f79d7 100644 (file)
@@ -379,17 +379,10 @@ static void get_html_page_path(struct strbuf *page_path, const char *page)
        free(to_free);
 }
 
-/*
- * If open_html is not defined in a platform-specific way (see for
- * example compat/mingw.h), we use the script web--browse to display
- * HTML.
- */
-#ifndef open_html
 static void open_html(const char *path)
 {
        execl_git_cmd("web--browse", "-c", "help.browser", path, (char *)NULL);
 }
-#endif
 
 static void show_html_page(const char *git_cmd)
 {
index b555a1b..6ec3126 100644 (file)
@@ -30,6 +30,7 @@
 #include "fmt-merge-msg.h"
 #include "gpg-interface.h"
 #include "sequencer.h"
+#include "string-list.h"
 
 #define DEFAULT_TWOHEAD (1<<0)
 #define DEFAULT_OCTOPUS (1<<1)
@@ -712,42 +713,17 @@ static int count_unmerged_entries(void)
        return ret;
 }
 
-static void split_merge_strategies(const char *string, struct strategy **list,
-                                  int *nr, int *alloc)
-{
-       char *p, *q, *buf;
-
-       if (!string)
-               return;
-
-       buf = xstrdup(string);
-       q = buf;
-       for (;;) {
-               p = strchr(q, ' ');
-               if (!p) {
-                       ALLOC_GROW(*list, *nr + 1, *alloc);
-                       (*list)[(*nr)++].name = xstrdup(q);
-                       free(buf);
-                       return;
-               } else {
-                       *p = '\0';
-                       ALLOC_GROW(*list, *nr + 1, *alloc);
-                       (*list)[(*nr)++].name = xstrdup(q);
-                       q = ++p;
-               }
-       }
-}
-
 static void add_strategies(const char *string, unsigned attr)
 {
-       struct strategy *list = NULL;
-       int list_alloc = 0, list_nr = 0, i;
-
-       memset(&list, 0, sizeof(list));
-       split_merge_strategies(string, &list, &list_nr, &list_alloc);
-       if (list) {
-               for (i = 0; i < list_nr; i++)
-                       append_strategy(get_strategy(list[i].name));
+       int i;
+
+       if (string) {
+               struct string_list list = STRING_LIST_INIT_DUP;
+               struct string_list_item *item;
+               string_list_split(&list, string, ' ', -1);
+               for_each_string_list_item(item, &list)
+                       append_strategy(get_strategy(item->string));
+               string_list_clear(&list, 0);
                return;
        }
        for (i = 0; i < ARRAY_SIZE(all_strategy); i++)
index a201426..446a316 100644 (file)
@@ -104,7 +104,7 @@ static int index_range_of_same_dir(const char *src, int length,
 
 int cmd_mv(int argc, const char **argv, const char *prefix)
 {
-       int i, gitmodules_modified = 0;
+       int i, flags, gitmodules_modified = 0;
        int verbose = 0, show_only = 0, force = 0, ignore_errors = 0;
        struct option builtin_mv_options[] = {
                OPT__VERBOSE(&verbose, N_("be verbose")),
@@ -134,10 +134,13 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
        modes = xcalloc(argc, sizeof(enum update_mode));
        /*
         * Keep trailing slash, needed to let
-        * "git mv file no-such-dir/" error out.
+        * "git mv file no-such-dir/" error out, except in the case
+        * "git mv directory no-such-dir/".
         */
-       dest_path = internal_copy_pathspec(prefix, argv + argc, 1,
-                                          KEEP_TRAILING_SLASH);
+       flags = KEEP_TRAILING_SLASH;
+       if (argc == 1 && is_directory(argv[0]) && !is_directory(argv[1]))
+               flags = 0;
+       dest_path = internal_copy_pathspec(prefix, argv + argc, 1, flags);
        submodule_gitfile = xcalloc(argc, sizeof(char *));
 
        if (dest_path[0][0] == '\0')
index a744437..05d0440 100644 (file)
@@ -1375,11 +1375,9 @@ static struct command **queue_command(struct command **tail,
 
        refname = line + 82;
        reflen = linelen - 82;
-       cmd = xcalloc(1, st_add3(sizeof(struct command), reflen, 1));
+       FLEX_ALLOC_MEM(cmd, ref_name, refname, reflen);
        hashcpy(cmd->old_sha1, old_sha1);
        hashcpy(cmd->new_sha1, new_sha1);
-       memcpy(cmd->ref_name, refname, reflen);
-       cmd->ref_name[reflen] = '\0';
        *tail = cmd;
        return &cmd->next;
 }
diff --git a/cache.h b/cache.h
index c141b3c..1fd2d5d 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -632,6 +632,7 @@ extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);
 #define REFRESH_IGNORE_SUBMODULES      0x0010  /* ignore submodules */
 #define REFRESH_IN_PORCELAIN   0x0020  /* user friendly output, not "needs update" */
 extern int refresh_index(struct index_state *, unsigned int flags, const struct pathspec *pathspec, char *seen, const char *header_msg);
+extern struct cache_entry *refresh_cache_entry(struct cache_entry *, unsigned int);
 
 extern void update_index_if_able(struct index_state *, struct lock_file *);
 
@@ -1223,7 +1224,8 @@ struct date_mode {
                DATE_ISO8601_STRICT,
                DATE_RFC2822,
                DATE_STRFTIME,
-               DATE_RAW
+               DATE_RAW,
+               DATE_UNIX
        } type;
        const char *strftime_fmt;
        int local;
index 2a90e37..5f616b7 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -1576,6 +1576,15 @@ int commit_tree_extended(const char *msg, size_t msg_len,
        return result;
 }
 
+void set_merge_remote_desc(struct commit *commit,
+                          const char *name, struct object *obj)
+{
+       struct merge_remote_desc *desc;
+       FLEX_ALLOC_STR(desc, name, name);
+       desc->obj = obj;
+       commit->util = desc;
+}
+
 struct commit *get_merge_parent(const char *name)
 {
        struct object *obj;
@@ -1585,13 +1594,8 @@ struct commit *get_merge_parent(const char *name)
                return NULL;
        obj = parse_object(oid.hash);
        commit = (struct commit *)peel_to_type(name, 0, obj, OBJ_COMMIT);
-       if (commit && !commit->util) {
-               struct merge_remote_desc *desc;
-               desc = xmalloc(sizeof(*desc));
-               desc->obj = obj;
-               desc->name = strdup(name);
-               commit->util = desc;
-       }
+       if (commit && !commit->util)
+               set_merge_remote_desc(commit, name, obj);
        return commit;
 }
 
index adf57d6..15ee924 100644 (file)
--- a/commit.h
+++ b/commit.h
@@ -356,9 +356,11 @@ extern void for_each_mergetag(each_mergetag_fn fn, struct commit *commit, void *
 
 struct merge_remote_desc {
        struct object *obj; /* the named object, could be a tag */
-       const char *name;
+       char name[FLEX_ARRAY];
 };
 #define merge_remote_util(commit) ((struct merge_remote_desc *)((commit)->util))
+extern void set_merge_remote_desc(struct commit *commit,
+                                 const char *name, struct object *obj);
 
 /*
  * Given "name" from the command line to merge, find the commit object
diff --git a/common-main.c b/common-main.c
new file mode 100644 (file)
index 0000000..44a29e8
--- /dev/null
@@ -0,0 +1,41 @@
+#include "cache.h"
+#include "exec_cmd.h"
+
+/*
+ * Many parts of Git have subprograms communicate via pipe, expect the
+ * upstream of a pipe to die with SIGPIPE when the downstream of a
+ * pipe does not need to read all that is written.  Some third-party
+ * programs that ignore or block SIGPIPE for their own reason forget
+ * to restore SIGPIPE handling to the default before spawning Git and
+ * break this carefully orchestrated machinery.
+ *
+ * Restore the way SIGPIPE is handled to default, which is what we
+ * expect.
+ */
+static void restore_sigpipe_to_default(void)
+{
+       sigset_t unblock;
+
+       sigemptyset(&unblock);
+       sigaddset(&unblock, SIGPIPE);
+       sigprocmask(SIG_UNBLOCK, &unblock, NULL);
+       signal(SIGPIPE, SIG_DFL);
+}
+
+int main(int argc, const char **argv)
+{
+       /*
+        * Always open file descriptors 0/1/2 to avoid clobbering files
+        * in die().  It also avoids messing up when the pipes are dup'ed
+        * onto stdin/stdout/stderr in the child processes we spawn.
+        */
+       sanitize_stdfds();
+
+       git_setup_gettext();
+
+       argv[0] = git_extract_argv0_path(argv[0]);
+
+       restore_sigpipe_to_default();
+
+       return cmd_main(argc, argv);
+}
index 2b5467d..3fbfda5 100644 (file)
@@ -1930,48 +1930,6 @@ int mingw_raise(int sig)
        }
 }
 
-
-static const char *make_backslash_path(const char *path)
-{
-       static char buf[PATH_MAX + 1];
-       char *c;
-
-       if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
-               die("Too long path: %.*s", 60, path);
-
-       for (c = buf; *c; c++) {
-               if (*c == '/')
-                       *c = '\\';
-       }
-       return buf;
-}
-
-void mingw_open_html(const char *unixpath)
-{
-       const char *htmlpath = make_backslash_path(unixpath);
-       typedef HINSTANCE (WINAPI *T)(HWND, const char *,
-                       const char *, const char *, const char *, INT);
-       T ShellExecute;
-       HMODULE shell32;
-       int r;
-
-       shell32 = LoadLibrary("shell32.dll");
-       if (!shell32)
-               die("cannot load shell32.dll");
-       ShellExecute = (T)GetProcAddress(shell32, "ShellExecuteA");
-       if (!ShellExecute)
-               die("cannot run browser");
-
-       printf("Launching default browser to display HTML ...\n");
-       r = HCAST(int, ShellExecute(NULL, "open", htmlpath,
-                               NULL, "\\", SW_SHOWNORMAL));
-       FreeLibrary(shell32);
-       /* see the MSDN documentation referring to the result codes here */
-       if (r <= 32) {
-               die("failed to launch browser for %.*s", MAX_PATH, unixpath);
-       }
-}
-
 int link(const char *oldpath, const char *newpath)
 {
        typedef BOOL (WINAPI *T)(LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES);
index ef22cbb..034fff9 100644 (file)
@@ -67,6 +67,10 @@ typedef int pid_t;
 #define F_SETFD 2
 #define FD_CLOEXEC 0x1
 
+#if !defined O_CLOEXEC && defined O_NOINHERIT
+#define O_CLOEXEC      O_NOINHERIT
+#endif
+
 #ifndef EAFNOSUPPORT
 #define EAFNOSUPPORT WSAEAFNOSUPPORT
 #endif
@@ -417,9 +421,6 @@ int mingw_offset_1st_component(const char *path);
 #include <inttypes.h>
 #endif
 
-void mingw_open_html(const char *path);
-#define open_html mingw_open_html
-
 /**
  * Converts UTF-8 encoded string to UTF-16LE.
  *
@@ -538,7 +539,7 @@ extern CRITICAL_SECTION pinfo_cs;
 void mingw_startup(void);
 #define main(c,v) dummy_decl_mingw_main(void); \
 static int mingw_main(c,v); \
-int main(int argc, char **argv) \
+int main(int argc, const char **argv) \
 { \
        mingw_startup(); \
        return mingw_main(__argc, (void *)__argv); \
index 95438e1..d60b431 100755 (executable)
@@ -96,18 +96,21 @@ foreach my $tar_file (@ARGV)
                $mtime = oct $mtime;
                next if $typeflag == 5; # directory
 
-               print FI "blob\n", "mark :$next_mark\n";
-               if ($typeflag == 2) { # symbolic link
-                       print FI "data ", length($linkname), "\n", $linkname;
-                       $mode = 0120000;
-               } else {
-                       print FI "data $size\n";
-                       while ($size > 0 && read(I, $_, 512) == 512) {
-                               print FI substr($_, 0, $size);
-                               $size -= 512;
+               if ($typeflag != 1) { # handle hard links later
+                       print FI "blob\n", "mark :$next_mark\n";
+                       if ($typeflag == 2) { # symbolic link
+                               print FI "data ", length($linkname), "\n",
+                                       $linkname;
+                               $mode = 0120000;
+                       } else {
+                               print FI "data $size\n";
+                               while ($size > 0 && read(I, $_, 512) == 512) {
+                                       print FI substr($_, 0, $size);
+                                       $size -= 512;
+                               }
                        }
+                       print FI "\n";
                }
-               print FI "\n";
 
                my $path;
                if ($prefix) {
@@ -115,7 +118,13 @@ foreach my $tar_file (@ARGV)
                } else {
                        $path = "$name";
                }
-               $files{$path} = [$next_mark++, $mode];
+
+               if ($typeflag == 1) { # hard link
+                       $linkname = "$prefix/$linkname" if $prefix;
+                       $files{$path} = [ $files{$linkname}->[0], $mode ];
+               } else {
+                       $files{$path} = [$next_mark++, $mode];
+               }
 
                $author_time = $mtime if $mtime > $author_time;
                $path =~ m,^([^/]+)/,;
index b1614bf..67d69b5 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -176,7 +176,9 @@ static enum eol output_eol(enum crlf_action crlf_action)
                return EOL_LF;
        case CRLF_UNDEFINED:
        case CRLF_AUTO_CRLF:
+               return EOL_CRLF;
        case CRLF_AUTO_INPUT:
+               return EOL_LF;
        case CRLF_TEXT:
        case CRLF_AUTO:
                /* fall through */
@@ -254,17 +256,15 @@ static int crlf_to_git(const char *path, const char *src, size_t len,
        if (crlf_action == CRLF_AUTO || crlf_action == CRLF_AUTO_INPUT || crlf_action == CRLF_AUTO_CRLF) {
                if (convert_is_binary(len, &stats))
                        return 0;
-
-               if (crlf_action == CRLF_AUTO_INPUT || crlf_action == CRLF_AUTO_CRLF) {
-                       /*
-                        * If the file in the index has any CR in it, do not convert.
-                        * This is the new safer autocrlf handling.
-                        */
-                       if (has_cr_in_index(path))
-                               return 0;
-               }
+               /*
+                * If the file in the index has any CR in it, do not convert.
+                * This is the new safer autocrlf handling.
+                */
+               if (checksafe == SAFE_CRLF_RENORMALIZE)
+                       checksafe = SAFE_CRLF_FALSE;
+               else if (has_cr_in_index(path))
+                       return 0;
        }
-
        check_safe_crlf(path, crlf_action, &stats, checksafe);
 
        /* Optimization: No CRLF? Nothing to convert, regardless. */
@@ -320,12 +320,10 @@ static int crlf_to_worktree(const char *path, const char *src, size_t len,
                return 0;
 
        if (crlf_action == CRLF_AUTO || crlf_action == CRLF_AUTO_INPUT || crlf_action == CRLF_AUTO_CRLF) {
-               if (crlf_action == CRLF_AUTO_INPUT || crlf_action == CRLF_AUTO_CRLF) {
-                       /* If we have any CR or CRLF line endings, we do not touch it */
-                       /* This is the new safer autocrlf-handling */
-                       if (stats.lonecr || stats.crlf )
-                               return 0;
-               }
+               /* If we have any CR or CRLF line endings, we do not touch it */
+               /* This is the new safer autocrlf-handling */
+               if (stats.lonecr || stats.crlf )
+                       return 0;
 
                if (convert_is_binary(len, &stats))
                        return 0;
@@ -786,7 +784,11 @@ static void convert_attrs(struct conv_attrs *ca, const char *path)
                ca->drv = git_path_check_convert(ccheck + 2);
                if (ca->crlf_action != CRLF_BINARY) {
                        enum eol eol_attr = git_path_check_eol(ccheck + 3);
-                       if (eol_attr == EOL_LF)
+                       if (ca->crlf_action == CRLF_AUTO && eol_attr == EOL_LF)
+                               ca->crlf_action = CRLF_AUTO_INPUT;
+                       else if (ca->crlf_action == CRLF_AUTO && eol_attr == EOL_CRLF)
+                               ca->crlf_action = CRLF_AUTO_CRLF;
+                       else if (eol_attr == EOL_LF)
                                ca->crlf_action = CRLF_TEXT_INPUT;
                        else if (eol_attr == EOL_CRLF)
                                ca->crlf_action = CRLF_TEXT_CRLF;
@@ -845,9 +847,9 @@ const char *get_convert_attr_ascii(const char *path)
        case CRLF_AUTO:
                return "text=auto";
        case CRLF_AUTO_CRLF:
-               return "text=auto eol=crlf"; /* This is not supported yet */
+               return "text=auto eol=crlf";
        case CRLF_AUTO_INPUT:
-               return "text=auto eol=lf"; /* This is not supported yet */
+               return "text=auto eol=lf";
        }
        return "";
 }
@@ -949,7 +951,7 @@ int renormalize_buffer(const char *path, const char *src, size_t len, struct str
                src = dst->buf;
                len = dst->len;
        }
-       return ret | convert_to_git(path, src, len, dst, SAFE_CRLF_FALSE);
+       return ret | convert_to_git(path, src, len, dst, SAFE_CRLF_RENORMALIZE);
 }
 
 /*****************************************************************
index ccf436b..82871a1 100644 (file)
--- a/convert.h
+++ b/convert.h
@@ -7,7 +7,8 @@
 enum safe_crlf {
        SAFE_CRLF_FALSE = 0,
        SAFE_CRLF_FAIL = 1,
-       SAFE_CRLF_WARN = 2
+       SAFE_CRLF_WARN = 2,
+       SAFE_CRLF_RENORMALIZE = 3
 };
 
 extern enum safe_crlf safe_crlf;
index 1f14d56..1e5f16a 100644 (file)
@@ -257,7 +257,7 @@ static void init_socket_directory(const char *path)
        free(path_copy);
 }
 
-int main(int argc, const char **argv)
+int cmd_main(int argc, const char **argv)
 {
        const char *socket_path;
        int ignore_sighup = 0;
index 86e21de..cc8a6ee 100644 (file)
@@ -83,7 +83,7 @@ static void do_cache(const char *socket, const char *action, int timeout,
        strbuf_release(&buf);
 }
 
-int main(int argc, const char **argv)
+int cmd_main(int argc, const char **argv)
 {
        char *socket_path = NULL;
        int timeout = 900;
index 5714167..55ca1b1 100644 (file)
@@ -142,7 +142,7 @@ static void lookup_credential(const struct string_list *fns, struct credential *
                        return; /* Found credential */
 }
 
-int main(int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
        const char * const usage[] = {
                "git credential-store [<options>] <action>",
index a844951..425aad0 100644 (file)
--- a/daemon.c
+++ b/daemon.c
@@ -1,6 +1,5 @@
 #include "cache.h"
 #include "pkt-line.h"
-#include "exec_cmd.h"
 #include "run-command.h"
 #include "strbuf.h"
 #include "string-list.h"
@@ -32,7 +31,7 @@ static const char daemon_usage[] =
 "           [<directory>...]";
 
 /* List of acceptable pathname prefixes */
-static char **ok_paths;
+static const char **ok_paths;
 static int strict_paths;
 
 /* If this is set, git-daemon-export-ok is not required */
@@ -240,7 +239,7 @@ static const char *path_ok(const char *directory, struct hostinfo *hi)
        }
 
        if ( ok_paths && *ok_paths ) {
-               char **pp;
+               const char **pp;
                int pathlen = strlen(path);
 
                /* The validation is done on the paths after enter_repo
@@ -1194,7 +1193,7 @@ static int serve(struct string_list *listen_addr, int listen_port,
        return service_loop(&socklist);
 }
 
-int main(int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
        int listen_port = 0;
        struct string_list listen_addr = STRING_LIST_INIT_NODUP;
@@ -1204,12 +1203,8 @@ int main(int argc, char **argv)
        struct credentials *cred = NULL;
        int i;
 
-       git_setup_gettext();
-
-       git_extract_argv0_path(argv[0]);
-
        for (i = 1; i < argc; i++) {
-               char *arg = argv[i];
+               const char *arg = argv[i];
                const char *v;
 
                if (skip_prefix(arg, "--listen=", &v)) {
@@ -1383,8 +1378,7 @@ int main(int argc, char **argv)
        if (detach) {
                if (daemonize())
                        die("--detach not supported on this platform");
-       } else
-               sanitize_stdfds();
+       }
 
        if (pid_file)
                write_file(pid_file, "%"PRIuMAX, (uintmax_t) getpid());
diff --git a/date.c b/date.c
index 4c7aa9b..a996331 100644 (file)
--- a/date.c
+++ b/date.c
@@ -177,6 +177,12 @@ const char *show_date(unsigned long time, int tz, const struct date_mode *mode)
        struct tm *tm;
        static struct strbuf timebuf = STRBUF_INIT;
 
+       if (mode->type == DATE_UNIX) {
+               strbuf_reset(&timebuf);
+               strbuf_addf(&timebuf, "%lu", time);
+               return timebuf.buf;
+       }
+
        if (mode->local)
                tz = local_tzoffset(time);
 
@@ -792,6 +798,8 @@ static enum date_mode_type parse_date_type(const char *format, const char **end)
                return DATE_NORMAL;
        if (skip_prefix(format, "raw", end))
                return DATE_RAW;
+       if (skip_prefix(format, "unix", end))
+               return DATE_UNIX;
        if (skip_prefix(format, "format", end))
                return DATE_STRFTIME;
 
index c504ef7..84a1375 100644 (file)
@@ -164,7 +164,6 @@ Format of STDIN stream:
 #include "refs.h"
 #include "csum-file.h"
 #include "quote.h"
-#include "exec_cmd.h"
 #include "dir.h"
 
 #define PACK_ID_BITS 16
@@ -300,7 +299,7 @@ static int failure;
 static FILE *pack_edges;
 static unsigned int show_stats = 1;
 static int global_argc;
-static char **global_argv;
+static const char **global_argv;
 
 /* Memory pools */
 static size_t mem_pool_alloc = 2*1024*1024 - sizeof(struct mem_pool);
@@ -3384,14 +3383,10 @@ static void parse_argv(void)
                read_marks();
 }
 
-int main(int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
        unsigned int i;
 
-       git_extract_argv0_path(argv[0]);
-
-       git_setup_gettext();
-
        if (argc == 2 && !strcmp(argv[1], "-h"))
                usage(fast_import_usage);
 
index 49d4029..b4b7f44 100644 (file)
@@ -650,6 +650,10 @@ void *gitmemmem(const void *haystack, size_t haystacklen,
 #define getpagesize() sysconf(_SC_PAGESIZE)
 #endif
 
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+
 #ifdef FREAD_READS_DIRECTORIES
 #ifdef fopen
 #undef fopen
@@ -798,7 +802,7 @@ extern FILE *fopen_for_writing(const char *path);
  * you can do:
  *
  *   struct foo *f;
- *   FLEX_ALLOC_STR(f, name, src);
+ *   FLEXPTR_ALLOC_STR(f, name, src);
  *
  * and "name" will point to a block of memory after the struct, which will be
  * freed along with the struct (but the pointer can be repointed anywhere).
@@ -1045,3 +1049,5 @@ struct tm *git_gmtime_r(const time_t *, struct tm *);
 #endif
 
 #endif
+
+extern int cmd_main(int, const char **);
index 84d6cc0..7bfb673 100755 (executable)
@@ -86,6 +86,13 @@ else
        do
                launch_merge_tool "$1" "$2" "$5"
                status=$?
+               if test $status -ge 126
+               then
+                       # Command not found (127), not executable (126) or
+                       # exited via a signal (>= 128).
+                       exit $status
+               fi
+
                if test "$status" != 0 &&
                        test "$GIT_DIFFTOOL_TRUST_EXIT_CODE" = true
                then
diff --git a/git.c b/git.c
index 968a8a4..0f1937f 100644 (file)
--- a/git.c
+++ b/git.c
@@ -609,48 +609,15 @@ static int run_argv(int *argcp, const char ***argv)
        return done_alias;
 }
 
-/*
- * Many parts of Git have subprograms communicate via pipe, expect the
- * upstream of a pipe to die with SIGPIPE when the downstream of a
- * pipe does not need to read all that is written.  Some third-party
- * programs that ignore or block SIGPIPE for their own reason forget
- * to restore SIGPIPE handling to the default before spawning Git and
- * break this carefully orchestrated machinery.
- *
- * Restore the way SIGPIPE is handled to default, which is what we
- * expect.
- */
-static void restore_sigpipe_to_default(void)
-{
-       sigset_t unblock;
-
-       sigemptyset(&unblock);
-       sigaddset(&unblock, SIGPIPE);
-       sigprocmask(SIG_UNBLOCK, &unblock, NULL);
-       signal(SIGPIPE, SIG_DFL);
-}
-
-int main(int argc, char **av)
+int cmd_main(int argc, const char **argv)
 {
-       const char **argv = (const char **) av;
        const char *cmd;
        int done_help = 0;
 
-       cmd = git_extract_argv0_path(argv[0]);
+       cmd = argv[0];
        if (!cmd)
                cmd = "git-help";
 
-       /*
-        * Always open file descriptors 0/1/2 to avoid clobbering files
-        * in die().  It also avoids messing up when the pipes are dup'ed
-        * onto stdin/stdout/stderr in the child processes we spawn.
-        */
-       sanitize_stdfds();
-
-       restore_sigpipe_to_default();
-
-       git_setup_gettext();
-
        trace_command_performance(argv);
 
        /*
index 2148814..0d59499 100644 (file)
@@ -632,7 +632,7 @@ static struct service_cmd {
        {"POST", "/git-receive-pack$", service_rpc}
 };
 
-int main(int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
        char *method = getenv("REQUEST_METHOD");
        char *dir;
@@ -640,9 +640,6 @@ int main(int argc, char **argv)
        char *cmd_arg = NULL;
        int i;
 
-       git_setup_gettext();
-
-       git_extract_argv0_path(argv[0]);
        set_die_routine(die_webcgi);
        set_die_is_recursing_routine(die_webcgi_recursing);
 
index ba3ea10..3b556d6 100644 (file)
@@ -6,7 +6,7 @@
 static const char http_fetch_usage[] = "git http-fetch "
 "[-c] [-t] [-a] [-v] [--recover] [-w ref] [--stdin] commit-id url";
 
-int main(int argc, const char **argv)
+int cmd_main(int argc, const char **argv)
 {
        struct walker *walker;
        int commits_on_stdin = 0;
@@ -22,10 +22,6 @@ int main(int argc, const char **argv)
        int get_verbosely = 0;
        int get_recover = 0;
 
-       git_setup_gettext();
-
-       git_extract_argv0_path(argv[0]);
-
        while (arg < argc && argv[arg][0] == '-') {
                if (argv[arg][1] == 't') {
                        get_tree = 1;
index d0b29ac..704b1c8 100644 (file)
@@ -1692,12 +1692,12 @@ static void run_request_queue(void)
 #endif
 }
 
-int main(int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
        struct transfer_request *request;
        struct transfer_request *next_request;
        int nr_refspec = 0;
-       char **refspec = NULL;
+       const char **refspec = NULL;
        struct remote_lock *ref_lock = NULL;
        struct remote_lock *info_ref_lock = NULL;
        struct rev_info revs;
@@ -1709,15 +1709,11 @@ int main(int argc, char **argv)
        int new_refs;
        struct ref *ref, *local_refs;
 
-       git_setup_gettext();
-
-       git_extract_argv0_path(argv[0]);
-
        repo = xcalloc(1, sizeof(*repo));
 
        argv++;
        for (i = 1; i < argc; i++, argv++) {
-               char *arg = *argv;
+               const char *arg = *argv;
 
                if (*arg == '-') {
                        if (!strcmp(arg, "--all")) {
index 938c691..9cbe27f 100644 (file)
@@ -1494,16 +1494,12 @@ static int curl_append_msgs_to_imap(struct imap_server_conf *server,
 }
 #endif
 
-int main(int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
        struct strbuf all_msgs = STRBUF_INIT;
        int total;
        int nongit_ok;
 
-       git_extract_argv0_path(argv[0]);
-
-       git_setup_gettext();
-
        setup_git_directory_gently(&nongit_ok);
        git_imap_config();
 
index 3d30193..d26ad27 100644 (file)
  *   * calling `fdopen_lock_file()` to get a `FILE` pointer for the
  *     open file and writing to the file using stdio.
  *
+ *   Note that the file descriptor returned by hold_lock_file_for_update()
+ *   is marked O_CLOEXEC, so the new contents must be written by the
+ *   current process, not a spawned one.
+ *
  * When finished writing, the caller can:
  *
  * * Close the file descriptor and rename the lockfile to its final
index 9f19ca1..e19abe3 100644 (file)
@@ -179,12 +179,6 @@ static void handle_content_type(struct mailinfo *mi, struct strbuf *line)
        }
 }
 
-static void handle_message_id(struct mailinfo *mi, const struct strbuf *line)
-{
-       if (mi->add_message_id)
-               mi->message_id = strdup(line->buf);
-}
-
 static void handle_content_transfer_encoding(struct mailinfo *mi,
                                             const struct strbuf *line)
 {
@@ -495,7 +489,8 @@ static int check_header(struct mailinfo *mi,
                len = strlen("Message-Id: ");
                strbuf_add(&sb, line->buf + len, line->len - len);
                decode_header(mi, &sb);
-               handle_message_id(mi, &sb);
+               if (mi->add_message_id)
+                       mi->message_id = strbuf_detach(&sb, NULL);
                ret = 1;
                goto check_header_out;
        }
index 65cb5d6..a52139e 100644 (file)
@@ -42,12 +42,9 @@ static struct tree *shift_tree_object(struct tree *one, struct tree *two,
 static struct commit *make_virtual_commit(struct tree *tree, const char *comment)
 {
        struct commit *commit = alloc_commit_node();
-       struct merge_remote_desc *desc = xmalloc(sizeof(*desc));
 
-       desc->name = comment;
-       desc->obj = (struct object *)commit;
+       set_merge_remote_desc(commit, comment, (struct object *)commit);
        commit->tree = tree;
-       commit->util = desc;
        commit->object.parsed = 1;
        return commit;
 }
@@ -202,12 +199,21 @@ static int add_cacheinfo(unsigned int mode, const unsigned char *sha1,
                const char *path, int stage, int refresh, int options)
 {
        struct cache_entry *ce;
-       ce = make_cache_entry(mode, sha1 ? sha1 : null_sha1, path, stage,
-                             (refresh ? (CE_MATCH_REFRESH |
-                                         CE_MATCH_IGNORE_MISSING) : 0 ));
+       int ret;
+
+       ce = make_cache_entry(mode, sha1 ? sha1 : null_sha1, path, stage, 0);
        if (!ce)
                return error(_("addinfo_cache failed for path '%s'"), path);
-       return add_cache_entry(ce, options);
+
+       ret = add_cache_entry(ce, options);
+       if (refresh) {
+               struct cache_entry *nce;
+
+               nce = refresh_cache_entry(ce, CE_MATCH_REFRESH | CE_MATCH_IGNORE_MISSING);
+               if (nce != ce)
+                       ret = add_cache_entry(nce, options);
+       }
+       return ret;
 }
 
 static void init_tree_desc_from_tree(struct tree_desc *desc, struct tree *tree)
@@ -400,7 +406,7 @@ static void record_df_conflict_files(struct merge_options *o,
         * and the file need to be present, then the D/F file will be
         * reinstated with a new unique name at the time it is processed.
         */
-       struct string_list df_sorted_entries;
+       struct string_list df_sorted_entries = STRING_LIST_INIT_NODUP;
        const char *last_file = NULL;
        int last_len = 0;
        int i;
@@ -413,7 +419,6 @@ static void record_df_conflict_files(struct merge_options *o,
                return;
 
        /* Ensure D/F conflicts are adjacent in the entries list. */
-       memset(&df_sorted_entries, 0, sizeof(struct string_list));
        for (i = 0; i < entries->nr; i++) {
                struct string_list_item *next = &entries->items[i];
                string_list_append(&df_sorted_entries, next->string)->util =
index b271656..dede7de 100644 (file)
--- a/pretty.c
+++ b/pretty.c
@@ -1141,8 +1141,8 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
                        strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
                        return 1;
                }
-               strbuf_addstr(sb, find_unique_abbrev(commit->object.oid.hash,
-                                                    c->pretty_ctx->abbrev));
+               strbuf_add_unique_abbrev(sb, commit->object.oid.hash,
+                                        c->pretty_ctx->abbrev);
                strbuf_addstr(sb, diff_get_color(c->auto_color, DIFF_RESET));
                c->abbrev_commit_hash.len = sb->len - c->abbrev_commit_hash.off;
                return 1;
@@ -1152,8 +1152,8 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
        case 't':               /* abbreviated tree hash */
                if (add_again(sb, &c->abbrev_tree_hash))
                        return 1;
-               strbuf_addstr(sb, find_unique_abbrev(commit->tree->object.oid.hash,
-                                                    c->pretty_ctx->abbrev));
+               strbuf_add_unique_abbrev(sb, commit->tree->object.oid.hash,
+                                        c->pretty_ctx->abbrev);
                c->abbrev_tree_hash.len = sb->len - c->abbrev_tree_hash.off;
                return 1;
        case 'P':               /* parent hashes */
@@ -1169,9 +1169,8 @@ static size_t format_commit_one(struct strbuf *sb, /* in UTF-8 */
                for (p = commit->parents; p; p = p->next) {
                        if (p != commit->parents)
                                strbuf_addch(sb, ' ');
-                       strbuf_addstr(sb, find_unique_abbrev(
-                                       p->item->object.oid.hash,
-                                       c->pretty_ctx->abbrev));
+                       strbuf_add_unique_abbrev(sb, p->item->object.oid.hash,
+                                                c->pretty_ctx->abbrev);
                }
                c->abbrev_parent_hashes.len = sb->len -
                                              c->abbrev_parent_hashes.off;
index db27766..491e52d 100644 (file)
@@ -19,9 +19,6 @@
 #include "split-index.h"
 #include "utf8.h"
 
-static struct cache_entry *refresh_cache_entry(struct cache_entry *ce,
-                                              unsigned int options);
-
 /* Mask for the name length in ce_flags in the on-disk index */
 
 #define CE_NAMEMASK  (0x0fff)
@@ -1257,7 +1254,7 @@ int refresh_index(struct index_state *istate, unsigned int flags,
        return has_errors;
 }
 
-static struct cache_entry *refresh_cache_entry(struct cache_entry *ce,
+struct cache_entry *refresh_cache_entry(struct cache_entry *ce,
                                               unsigned int options)
 {
        return refresh_cache_ent(&the_index, ce, options, NULL, NULL);
index 672b382..6b83b77 100644 (file)
@@ -984,14 +984,11 @@ static void parse_push(struct strbuf *buf)
        free(specs);
 }
 
-int main(int argc, const char **argv)
+int cmd_main(int argc, const char **argv)
 {
        struct strbuf buf = STRBUF_INIT;
        int nongit;
 
-       git_setup_gettext();
-
-       git_extract_argv0_path(argv[0]);
        setup_git_directory_gently(&nongit);
        if (argc < 2) {
                error("remote-curl: usage: git remote-curl <remote> [<url>]");
index f05ff45..f87bf85 100644 (file)
@@ -284,7 +284,7 @@ static int do_command(struct strbuf *line)
        return 0;
 }
 
-int main(int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
        struct strbuf buf = STRBUF_INIT, url_sb = STRBUF_INIT,
                        private_ref_sb = STRBUF_INIT, marksfilename_sb = STRBUF_INIT,
@@ -292,7 +292,6 @@ int main(int argc, char **argv)
        static struct remote *remote;
        const char *url_in;
 
-       git_extract_argv0_path(argv[0]);
        setup_git_directory();
        if (argc < 2 || argc > 3) {
                usage("git-remote-svn <remote-name> [<url>]");
index a326e4e..d29850a 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -1544,8 +1544,7 @@ void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,
                 * branch.
                 */
                if (ref->expect_old_sha1) {
-                       if (ref->expect_old_no_trackback ||
-                           oidcmp(&ref->old_oid, &ref->old_oid_expect))
+                       if (oidcmp(&ref->old_oid, &ref->old_oid_expect))
                                reject_reason = REF_STATUS_REJECT_STALE;
                        else
                                /* If the ref isn't stale then force the update. */
@@ -2294,6 +2293,8 @@ int parse_push_cas_option(struct push_cas_option *cas, const char *arg, int unse
        entry = add_cas_entry(cas, arg, colon - arg);
        if (!*colon)
                entry->use_tracking = 1;
+       else if (!colon[1])
+               hashclr(entry->expect);
        else if (get_sha1(colon + 1, entry->expect))
                return error("cannot parse expected object name '%s'", colon + 1);
        return 0;
@@ -2343,7 +2344,7 @@ static void apply_cas(struct push_cas_option *cas,
                if (!entry->use_tracking)
                        hashcpy(ref->old_oid_expect.hash, cas->entry[i].expect);
                else if (remote_tracking(remote, ref->name, &ref->old_oid_expect))
-                       ref->expect_old_no_trackback = 1;
+                       oidclr(&ref->old_oid_expect);
                return;
        }
 
@@ -2353,7 +2354,7 @@ static void apply_cas(struct push_cas_option *cas,
 
        ref->expect_old_sha1 = 1;
        if (remote_tracking(remote, ref->name, &ref->old_oid_expect))
-               ref->expect_old_no_trackback = 1;
+               oidclr(&ref->old_oid_expect);
 }
 
 void apply_push_cas(struct push_cas_option *cas,
index c21fd37..9248811 100644 (file)
--- a/remote.h
+++ b/remote.h
@@ -89,7 +89,6 @@ struct ref {
                force:1,
                forced_update:1,
                expect_old_sha1:1,
-               expect_old_no_trackback:1,
                deletion:1,
                matched:1;
 
index 2842a22..e06b2c1 100644 (file)
@@ -64,7 +64,7 @@ static void note_variables (const char *string);
 static void subst_from_stdin (void);
 
 int
-main (int argc, char *argv[])
+cmd_main (int argc, const char *argv[])
 {
   /* Default values for command line options.  */
   /* unsigned short int show_variables = 0; */
diff --git a/shell.c b/shell.c
index c5439a6..fe2d314 100644 (file)
--- a/shell.c
+++ b/shell.c
@@ -13,7 +13,7 @@ static int do_generic_cmd(const char *me, char *arg)
        const char *my_argv[4];
 
        setup_path();
-       if (!arg || !(arg = sq_dequote(arg)))
+       if (!arg || !(arg = sq_dequote(arg)) || *arg == '-')
                die("bad argument");
        if (!starts_with(me, "git-"))
                die("bad command");
@@ -138,24 +138,13 @@ static struct commands {
        { NULL },
 };
 
-int main(int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
        char *prog;
        const char **user_argv;
        struct commands *cmd;
        int count;
 
-       git_setup_gettext();
-
-       git_extract_argv0_path(argv[0]);
-
-       /*
-        * Always open file descriptors 0/1/2 to avoid clobbering files
-        * in die().  It also avoids messing up when the pipes are dup'ed
-        * onto stdin/stdout/stderr in the child processes we spawn.
-        */
-       sanitize_stdfds();
-
        /*
         * Special hack to pretend to be a CVS server
         */
index acf8d54..1ead41e 100644 (file)
@@ -4,15 +4,13 @@
 static const char show_index_usage[] =
 "git show-index";
 
-int main(int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
        int i;
        unsigned nr;
        unsigned int version;
        static unsigned int top_index[256];
 
-       git_setup_gettext();
-
        if (argc != 1)
                usage(show_index_usage);
        if (fread(top_index, 2 * 4, 1, stdin) != 1)
index 18e2b28..d613935 100644 (file)
@@ -52,7 +52,8 @@ clean-except-prove-cache:
 clean: clean-except-prove-cache
        $(RM) .prove
 
-test-lint: test-lint-duplicates test-lint-executable test-lint-shell-syntax
+test-lint: test-lint-duplicates test-lint-executable test-lint-shell-syntax \
+       test-lint-filenames
 
 test-lint-duplicates:
        @dups=`echo $(T) | tr ' ' '\n' | sed 's/-.*//' | sort | uniq -d` && \
@@ -67,6 +68,14 @@ test-lint-executable:
 test-lint-shell-syntax:
        @'$(PERL_PATH_SQ)' check-non-portable-shell.pl $(T) $(THELPERS)
 
+test-lint-filenames:
+       @# We do *not* pass a glob to ls-files but use grep instead, to catch
+       @# non-ASCII characters (which are quoted within double-quotes)
+       @bad="$$(git -c core.quotepath=true ls-files 2>/dev/null | \
+                       grep '["*:<>?\\|]')"; \
+               test -z "$$bad" || { \
+               echo >&2 "non-portable file name(s): $$bad"; exit 1; }
+
 aggregate-results-and-cleanup: $(T)
        $(MAKE) aggregate-results
        $(MAKE) clean
index dfe8a83..e760256 100644 (file)
@@ -56,7 +56,7 @@ static int timespec_arg(const char *arg, long int *set_time, int *set_eq)
        return 1;
 }
 
-int main(int argc, char *argv[])
+int cmd_main(int argc, const char **argv)
 {
        static int verbose;
 
index 6a77552..d143cd7 100644 (file)
@@ -33,7 +33,7 @@
  */
 
 
-int main(int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
        int i, val;
        const char *v;
index 707a821..bb72c47 100644 (file)
@@ -28,7 +28,7 @@ static int is_in(const char *s, int ch)
 #define LOWER "abcdefghijklmnopqrstuvwxyz"
 #define UPPER "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 
-int main(int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
        TEST_CLASS(isdigit, DIGIT);
        TEST_CLASS(isspace, " \n\r\t");
index d9ab360..506054b 100644 (file)
@@ -6,7 +6,7 @@ static const char *usage_msg = "\n"
 "  test-date parse [date]...\n"
 "  test-date approxidate [date]...\n";
 
-static void show_relative_dates(char **argv, struct timeval *now)
+static void show_relative_dates(const char **argv, struct timeval *now)
 {
        struct strbuf buf = STRBUF_INIT;
 
@@ -18,13 +18,13 @@ static void show_relative_dates(char **argv, struct timeval *now)
        strbuf_release(&buf);
 }
 
-static void show_dates(char **argv, const char *format)
+static void show_dates(const char **argv, const char *format)
 {
        struct date_mode mode;
 
        parse_date_format(format, &mode);
        for (; *argv; argv++) {
-               char *arg = *argv;
+               char *arg;
                time_t t;
                int tz;
 
@@ -32,7 +32,7 @@ static void show_dates(char **argv, const char *format)
                 * Do not use our normal timestamp parsing here, as the point
                 * is to test the formatting code in isolation.
                 */
-               t = strtol(arg, &arg, 10);
+               t = strtol(*argv, &arg, 10);
                while (*arg == ' ')
                        arg++;
                tz = atoi(arg);
@@ -41,7 +41,7 @@ static void show_dates(char **argv, const char *format)
        }
 }
 
-static void parse_dates(char **argv, struct timeval *now)
+static void parse_dates(const char **argv, struct timeval *now)
 {
        struct strbuf result = STRBUF_INIT;
 
@@ -60,7 +60,7 @@ static void parse_dates(char **argv, struct timeval *now)
        strbuf_release(&result);
 }
 
-static void parse_approxidate(char **argv, struct timeval *now)
+static void parse_approxidate(const char **argv, struct timeval *now)
 {
        for (; *argv; argv++) {
                time_t t;
@@ -69,7 +69,7 @@ static void parse_approxidate(char **argv, struct timeval *now)
        }
 }
 
-int main(int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
        struct timeval now;
        const char *x;
index 4595cd6..59937dc 100644 (file)
@@ -15,7 +15,7 @@
 static const char usage_str[] =
        "test-delta (-d|-p) <from_file> <data_file> <out_file>";
 
-int main(int argc, char *argv[])
+int cmd_main(int argc, const char **argv)
 {
        int fd;
        struct stat st;
index bb53c0a..44f3290 100644 (file)
@@ -54,7 +54,7 @@ static int dump_cache_tree(struct cache_tree *it,
        return errs;
 }
 
-int main(int ac, char **av)
+int cmd_main(int ac, const char **av)
 {
        struct index_state istate;
        struct cache_tree *another = cache_tree();
index 861d28c..d168924 100644 (file)
@@ -7,7 +7,7 @@ static void show_bit(size_t pos, void *data)
        printf(" %d", (int)pos);
 }
 
-int main(int ac, char **av)
+int cmd_main(int ac, const char **av)
 {
        struct split_index *si;
        int i;
index 0a1c285..50112cc 100644 (file)
@@ -40,7 +40,7 @@ static void dump(struct untracked_cache_dir *ucd, struct strbuf *base)
        strbuf_setlen(base, len);
 }
 
-int main(int ac, char **av)
+int cmd_main(int ac, const char **av)
 {
        struct untracked_cache *uc;
        struct strbuf base = STRBUF_INIT;
index 980de21..12beee9 100644 (file)
@@ -2,7 +2,7 @@
 #include "run-command.h"
 #include "strbuf.h"
 
-int main(int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
        const char *trash_directory = getenv("TRASH_DIRECTORY");
        struct strbuf buf = STRBUF_INIT;
index 54824d0..8d11d22 100644 (file)
@@ -6,7 +6,7 @@
 
 #include "git-compat-util.h"
 
-int main(int argc, char *argv[])
+int cmd_main(int argc, const char **argv)
 {
        unsigned long count, next = 0;
        unsigned char *c;
index cc2891d..7aa9440 100644 (file)
@@ -138,7 +138,7 @@ static void perf_hashmap(unsigned int method, unsigned int rounds)
  *
  * perfhashmap method rounds -> test hashmap.[ch] performance
  */
-int main(int argc, char *argv[])
+int cmd_main(int argc, const char **argv)
 {
        char line[1024];
        struct hashmap map;
index 05d4699..f569f6b 100644 (file)
@@ -1,6 +1,6 @@
 #include "cache.h"
 
-int main(int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
        struct cache_header hdr;
        int version;
index 1e58f04..81575fe 100644 (file)
@@ -50,7 +50,7 @@ static void handle_line(const char *line, struct line_buffer *stdin_buf)
        handle_command(line, arg + 1, stdin_buf);
 }
 
-int main(int argc, char *argv[])
+int cmd_main(int argc, const char **argv)
 {
        struct line_buffer stdin_buf = LINE_BUFFER_INIT;
        struct line_buffer file_buf = LINE_BUFFER_INIT;
index d446b8e..e939502 100644 (file)
@@ -1,7 +1,7 @@
 #include "cache.h"
 #include "tree.h"
 
-int main(int ac, char **av)
+int cmd_main(int ac, const char **av)
 {
        struct object_id hash1, hash2, shifted;
        struct tree *one, *two;
index ea3b959..335cf6b 100644 (file)
@@ -22,7 +22,7 @@ static int compare_strings(const void *a, const void *b)
        return strcmp(x->text, y->text);
 }
 
-int main(int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
        struct line *line, *p = NULL, *lines = NULL;
        struct strbuf sb = STRBUF_INIT;
index c8c5421..89d9b2f 100644 (file)
@@ -3,7 +3,7 @@
  */
 #include "git-compat-util.h"
 
-int main(int argc, char *argv[])
+int cmd_main(int argc, const char **argv)
 {
        if (argc != 2)
                usage("Expected 1 parameter defining the temporary file template");
index 8a1235d..d51d292 100644 (file)
@@ -94,7 +94,7 @@ static void show(struct string_list *expect, int *status, const char *fmt, ...)
        strbuf_release(&buf);
 }
 
-int main(int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
        const char *prefix = "prefix/";
        const char *usage[] = {
index ba805b3..1ebe0f7 100644 (file)
@@ -156,7 +156,7 @@ static struct test_data dirname_data[] = {
        { NULL,              NULL     }
 };
 
-int main(int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
        if (argc == 3 && !strcmp(argv[1], "normalize_path_copy")) {
                char *buf = xmallocz(strlen(argv[2]));
@@ -213,7 +213,7 @@ int main(int argc, char **argv)
        }
 
        if (argc >= 4 && !strcmp(argv[1], "prefix_path")) {
-               char *prefix = argv[2];
+               const char *prefix = argv[2];
                int prefix_len = strlen(prefix);
                int nongit_ok;
                setup_git_directory_gently(&nongit_ok);
index 7be72f0..ae58fff 100644 (file)
@@ -16,7 +16,7 @@ static void show(int *v)
        free(v);
 }
 
-int main(int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
        struct prio_queue pq = { intcmp };
 
index b25bcf1..2a7990e 100644 (file)
@@ -1,6 +1,6 @@
 #include "cache.h"
 
-int main (int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
        int i, cnt = 1;
        if (argc == 2)
index eff26f5..b5ea8a9 100644 (file)
@@ -36,7 +36,7 @@ static int test_regex_bug(void)
        return 0;
 }
 
-int main(int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
        const char *pat;
        const char *str;
index 3d03133..b8e6fe1 100644 (file)
@@ -45,7 +45,7 @@ static int run_revision_walk(void)
        return got_revision;
 }
 
-int main(int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
        if (argc < 2)
                return 1;
index 6bb53da..d24d157 100644 (file)
@@ -49,7 +49,7 @@ static int task_finished(int result,
        return 1;
 }
 
-int main(int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
        struct child_process proc = CHILD_PROCESS_INIT;
        int jobs;
index 6efee31..5b2fd09 100644 (file)
@@ -5,7 +5,7 @@
 
 static struct lock_file index_lock;
 
-int main(int ac, char **av)
+int cmd_main(int ac, const char **av)
 {
        hold_locked_index(&index_lock, 1);
        if (read_cache() < 0)
index 60ea1d5..09f7790 100644 (file)
@@ -6,7 +6,7 @@ static void print_sha1(const unsigned char sha1[20], void *data)
        puts(sha1_to_hex(sha1));
 }
 
-int main(int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
        struct sha1_array array = SHA1_ARRAY_INIT;
        struct strbuf line = STRBUF_INIT;
index e57eae1..a1c13f5 100644 (file)
@@ -1,6 +1,6 @@
 #include "cache.h"
 
-int main(int ac, char **av)
+int cmd_main(int ac, const char **av)
 {
        git_SHA_CTX ctx;
        unsigned char sha1[20];
index e499fce..b71edbd 100644 (file)
@@ -13,7 +13,7 @@ X(two)
 X(three)
 #undef X
 
-int main(int argc, char **argv) {
+int cmd_main(int argc, const char **argv) {
        sigchain_push(SIGTERM, one);
        sigchain_push(SIGTERM, two);
        sigchain_push(SIGTERM, three);
index 14bdf9d..4a68967 100644 (file)
@@ -41,7 +41,7 @@ static int prefix_cb(struct string_list_item *item, void *cb_data)
        return starts_with(item->string, prefix);
 }
 
-int main(int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
        if (argc == 5 && !strcmp(argv[1], "split")) {
                struct string_list list = STRING_LIST_INIT_DUP;
index a4e4098..2a50217 100644 (file)
@@ -2,7 +2,7 @@
 #include "submodule-config.h"
 #include "submodule.h"
 
-static void die_usage(int argc, char **argv, const char *msg)
+static void die_usage(int argc, const char **argv, const char *msg)
 {
        fprintf(stderr, "%s\n", msg);
        fprintf(stderr, "Usage: %s [<commit> <submodulepath>] ...\n", argv[0]);
@@ -14,9 +14,9 @@ static int git_test_config(const char *var, const char *value, void *cb)
        return parse_submodule_config_option(var, value);
 }
 
-int main(int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
-       char **arg = argv;
+       const char **arg = argv;
        int my_argc = argc;
        int output_url = 0;
        int lookup_name = 0;
index 56881a0..30c5765 100644 (file)
@@ -1,7 +1,7 @@
 #include "cache.h"
 #include "run-command.h"
 
-int main(int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
        struct child_process cp = CHILD_PROCESS_INIT;
        int nogit = 0;
index 120ec96..7667c08 100644 (file)
@@ -11,7 +11,7 @@
 static const char test_svnfe_usage[] =
        "test-svn-fe (<dumpfile> | [-d] <preimage> <delta> <len>)";
 
-static int apply_delta(int argc, char *argv[])
+static int apply_delta(int argc, const char **argv)
 {
        struct line_buffer preimage = LINE_BUFFER_INIT;
        struct line_buffer delta = LINE_BUFFER_INIT;
@@ -35,7 +35,7 @@ static int apply_delta(int argc, char *argv[])
        return 0;
 }
 
-int main(int argc, char *argv[])
+int cmd_main(int argc, const char **argv)
 {
        if (argc == 2) {
                if (svndump_init(argv[1]))
index 090bf21..49b6e83 100644 (file)
@@ -1,7 +1,7 @@
 #include "git-compat-util.h"
 #include "urlmatch.h"
 
-int main(int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
        const char usage[] = "test-urlmatch-normalization [-p | -l] <url1> | <url1> <url2>";
        char *url1, *url2;
index 578b164..52be876 100644 (file)
@@ -1,6 +1,6 @@
 #include "cache.h"
 
-int main(int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
        int i;
        for (i = 2; i < argc; i++) {
index 4c8cf58..c0c9108 100755 (executable)
@@ -46,7 +46,10 @@ check_show rfc2822 "$TIME" 'Wed, 15 Jun 2016 16:13:20 +0200'
 check_show short "$TIME" '2016-06-15'
 check_show default "$TIME" 'Wed Jun 15 16:13:20 2016 +0200'
 check_show raw "$TIME" '1466000000 +0200'
+check_show unix "$TIME" '1466000000'
 check_show iso-local "$TIME" '2016-06-15 14:13:20 +0000'
+check_show raw-local "$TIME" '1466000000 +0000'
+check_show unix-local "$TIME" '1466000000'
 
 # arbitrary time absurdly far in the future
 FUTURE="5758122296 -0400"
index c164b46..d0bee08 100755 (executable)
@@ -114,7 +114,7 @@ test_expect_success 'autocrlf=true does not normalize CRLF files' '
        test -z "$LFonlydiff" -a -z "$CRLFonlydiff" -a -z "$LFwithNULdiff"
 '
 
-test_expect_success 'text=auto, autocrlf=true _does_ normalize CRLF files' '
+test_expect_success 'text=auto, autocrlf=true does not normalize CRLF files' '
 
        rm -f .gitattributes tmp LFonly CRLFonly LFwithNUL &&
        git config core.autocrlf true &&
@@ -126,7 +126,7 @@ test_expect_success 'text=auto, autocrlf=true _does_ normalize CRLF files' '
        LFonlydiff=$(git diff LFonly) &&
        CRLFonlydiff=$(git diff CRLFonly) &&
        LFwithNULdiff=$(git diff LFwithNUL) &&
-       test -z "$LFonlydiff" -a -n "$CRLFonlydiff" -a -z "$LFwithNULdiff"
+       test -z "$LFonlydiff" -a -z "$CRLFonlydiff" -a -z "$LFwithNULdiff"
 '
 
 test_expect_success 'text=auto, autocrlf=true does not normalize binary files' '
index 9372589..2860d2d 100755 (executable)
@@ -175,8 +175,8 @@ attr_ascii () {
        text,lf)   echo "text eol=lf" ;;
        text,crlf) echo "text eol=crlf" ;;
        auto,)     echo "text=auto" ;;
-       auto,lf)   echo "text eol=lf" ;;
-       auto,crlf) echo "text eol=crlf" ;;
+       auto,lf)   echo "text=auto eol=lf" ;;
+       auto,crlf) echo "text=auto eol=crlf" ;;
        lf,)       echo "text eol=lf" ;;
        crlf,)     echo "text eol=crlf" ;;
        ,) echo "" ;;
@@ -397,10 +397,9 @@ commit_chk_wrnNNO ""      ""      false   ""        ""        ""          ""
 commit_chk_wrnNNO ""      ""      true    LF_CRLF   ""        ""          ""          ""
 commit_chk_wrnNNO ""      ""      input   ""        ""        ""          ""          ""
 
-commit_chk_wrnNNO "auto"  ""      false   "$WILC"   "$WICL"   "$WAMIX"    ""          ""
-commit_chk_wrnNNO "auto"  ""      true    LF_CRLF   ""        LF_CRLF     ""          ""
-commit_chk_wrnNNO "auto"  ""      input   ""        CRLF_LF   CRLF_LF     ""          ""
-
+commit_chk_wrnNNO "auto"  ""      false   "$WILC"   ""        ""          ""          ""
+commit_chk_wrnNNO "auto"  ""      true    LF_CRLF   ""        ""          ""          ""
+commit_chk_wrnNNO "auto"  ""      input   ""        ""        ""          ""          ""
 for crlf in true false input
 do
        commit_chk_wrnNNO -text ""      $crlf   ""        ""        ""          ""          ""
@@ -408,8 +407,8 @@ do
        commit_chk_wrnNNO -text crlf    $crlf   ""        ""        ""          ""          ""
        commit_chk_wrnNNO ""    lf      $crlf   ""       CRLF_LF    CRLF_LF      ""         CRLF_LF
        commit_chk_wrnNNO ""    crlf    $crlf   LF_CRLF   ""        LF_CRLF     LF_CRLF     ""
-       commit_chk_wrnNNO auto  lf      $crlf   ""       CRLF_LF    CRLF_LF     ""          CRLF_LF
-       commit_chk_wrnNNO auto  crlf    $crlf   LF_CRLF   ""        LF_CRLF     LF_CRLF     ""
+       commit_chk_wrnNNO auto  lf      $crlf   ""        ""        ""          ""          ""
+       commit_chk_wrnNNO auto  crlf    $crlf   LF_CRLF   ""        ""          ""          ""
        commit_chk_wrnNNO text  lf      $crlf   ""       CRLF_LF    CRLF_LF     ""          CRLF_LF
        commit_chk_wrnNNO text  crlf    $crlf   LF_CRLF   ""        LF_CRLF     LF_CRLF     ""
 done
@@ -454,9 +453,9 @@ do
        check_in_repo_NNO -text ""     $crlf   LF  CRLF  CRLF_mix_LF  LF_mix_CR  CRLF_nul
        check_in_repo_NNO -text lf     $crlf   LF  CRLF  CRLF_mix_LF  LF_mix_CR  CRLF_nul
        check_in_repo_NNO -text crlf   $crlf   LF  CRLF  CRLF_mix_LF  LF_mix_CR  CRLF_nul
-       check_in_repo_NNO auto  ""     $crlf   LF  LF    LF           LF_mix_CR  CRLF_nul
-       check_in_repo_NNO auto  lf     $crlf   LF  LF    LF           LF_mix_CR  LF_nul
-       check_in_repo_NNO auto  crlf   $crlf   LF  LF    LF           LF_mix_CR  LF_nul
+       check_in_repo_NNO auto  ""     $crlf   LF  CRLF  CRLF_mix_LF  LF_mix_CR  CRLF_nul
+       check_in_repo_NNO auto  lf     $crlf   LF  CRLF  CRLF_mix_LF  LF_mix_CR  CRLF_nul
+       check_in_repo_NNO auto  crlf   $crlf   LF  CRLF  CRLF_mix_LF  LF_mix_CR  CRLF_nul
        check_in_repo_NNO text  ""     $crlf   LF  LF    LF           LF_mix_CR  LF_nul
        check_in_repo_NNO text  lf     $crlf   LF  LF    LF           LF_mix_CR  LF_nul
        check_in_repo_NNO text  crlf   $crlf   LF  LF    LF           LF_mix_CR  LF_nul
@@ -509,7 +508,7 @@ do
                        checkout_files text  "$id" "crlf" "$crlf" "$ceol"  CRLF  CRLF  CRLF         CRLF_mix_CR  CRLF_nul
                        # currently the same as text, eol=XXX
                        checkout_files auto  "$id" "lf"   "$crlf" "$ceol"  LF    CRLF  CRLF_mix_LF  LF_mix_CR    LF_nul
-                       checkout_files auto  "$id" "crlf" "$crlf" "$ceol"  CRLF  CRLF  CRLF         CRLF_mix_CR  CRLF_nul
+                       checkout_files auto  "$id" "crlf" "$crlf" "$ceol"  CRLF  CRLF  CRLF_mix_LF  LF_mix_CR    LF_nul
                done
 
                # core.autocrlf false, different core.eol
@@ -517,7 +516,7 @@ do
                # core.autocrlf true
                checkout_files   ""    "$id" ""     true    "$ceol"  CRLF  CRLF  CRLF_mix_LF  LF_mix_CR    LF_nul
                # text: core.autocrlf = true overrides core.eol
-               checkout_files   auto  "$id" ""     true    "$ceol"  CRLF  CRLF  CRLF         LF_mix_CR    LF_nul
+               checkout_files   auto  "$id" ""     true    "$ceol"  CRLF  CRLF  CRLF_mix_LF  LF_mix_CR    LF_nul
                checkout_files   text  "$id" ""     true    "$ceol"  CRLF  CRLF  CRLF         CRLF_mix_CR  CRLF_nul
                # text: core.autocrlf = input overrides core.eol
                checkout_files   text  "$id" ""     input   "$ceol"  LF    CRLF  CRLF_mix_LF  LF_mix_CR    LF_nul
@@ -531,8 +530,8 @@ do
        checkout_files     text  "$id" ""     false   ""       $NL   CRLF  $MIX_CRLF_LF $MIX_LF_CR   $LFNUL
        checkout_files     text  "$id" ""     false   native   $NL   CRLF  $MIX_CRLF_LF $MIX_LF_CR   $LFNUL
        # auto: core.autocrlf=false and core.eol unset(or native) uses native eol
-       checkout_files     auto  "$id" ""     false   ""       $NL   CRLF  $MIX_CRLF_LF LF_mix_CR    LF_nul
-       checkout_files     auto  "$id" ""     false   native   $NL   CRLF  $MIX_CRLF_LF LF_mix_CR    LF_nul
+       checkout_files     auto  "$id" ""     false   ""       $NL   CRLF  CRLF_mix_LF  LF_mix_CR    LF_nul
+       checkout_files     auto  "$id" ""     false   native   $NL   CRLF  CRLF_mix_LF  LF_mix_CR    LF_nul
 done
 
 # Should be the last test case: remove some files from the worktree
index dd2be04..553e26d 100755 (executable)
@@ -359,7 +359,6 @@ test_expect_success 'continue walking past root commits' '
                HEAD@{3} commit (initial): initial
                EOF
                test_commit initial &&
-               git reflog &&
                git checkout --orphan orphan1 &&
                test_commit orphan1-1 &&
                test_commit orphan1-2 &&
index 5d68729..fbb4ee9 100755 (executable)
@@ -163,4 +163,27 @@ test_expect_success 'tracking count is accurate after orphan check' '
        test_i18ncmp expect stdout
 '
 
+test_expect_success 'no advice given for explicit detached head state' '
+       # baseline
+       test_config advice.detachedHead true &&
+       git checkout child && git checkout HEAD^0 >expect.advice 2>&1 &&
+       test_config advice.detachedHead false &&
+       git checkout child && git checkout HEAD^0 >expect.no-advice 2>&1 &&
+       test_unconfig advice.detachedHead &&
+       # without configuration, the advice.* variables default to true
+       git checkout child && git checkout HEAD^0 >actual 2>&1 &&
+       test_cmp expect.advice actual &&
+
+       # with explicit --detach
+       # no configuration
+       test_unconfig advice.detachedHead &&
+       git checkout child && git checkout --detach HEAD^0 >actual 2>&1 &&
+       test_cmp expect.no-advice actual &&
+
+       # explicitly decline advice
+       test_config advice.detachedHead false &&
+       git checkout child && git checkout --detach HEAD^0 >actual 2>&1 &&
+       test_cmp expect.no-advice actual
+'
+
 test_done
index f7b0e59..470f334 100755 (executable)
@@ -660,4 +660,22 @@ test_expect_success 'merging with triple rename across D/F conflict' '
        git merge other
 '
 
+test_expect_success 'merge-recursive remembers the names of all base trees' '
+       git reset --hard HEAD &&
+
+       # more trees than static slots used by oid_to_hex()
+       for commit in $c0 $c2 $c4 $c5 $c6 $c7
+       do
+               git rev-parse "$commit^{tree}"
+       done >trees &&
+
+       # ignore the return code -- it only fails because the input is weird
+       test_must_fail git -c merge.verbosity=5 merge-recursive $(cat trees) -- $c1 $c3 >out &&
+
+       # merge-recursive prints in reverse order, but we do not care
+       sort <trees >expect &&
+       sed -n "s/^virtual //p" out | sort >actual &&
+       test_cmp expect actual
+'
+
 test_done
index c732012..a2c9e74 100755 (executable)
@@ -191,4 +191,42 @@ test_expect_success 'cover everything with default force-with-lease (allowed)' '
        test_cmp expect actual
 '
 
+test_expect_success 'new branch covered by force-with-lease' '
+       setup_srcdst_basic &&
+       (
+               cd dst &&
+               git branch branch master &&
+               git push --force-with-lease=branch origin branch
+       ) &&
+       git ls-remote dst refs/heads/branch >expect &&
+       git ls-remote src refs/heads/branch >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'new branch covered by force-with-lease (explicit)' '
+       setup_srcdst_basic &&
+       (
+               cd dst &&
+               git branch branch master &&
+               git push --force-with-lease=branch: origin branch
+       ) &&
+       git ls-remote dst refs/heads/branch >expect &&
+       git ls-remote src refs/heads/branch >actual &&
+       test_cmp expect actual
+'
+
+test_expect_success 'new branch already exists' '
+       setup_srcdst_basic &&
+       (
+               cd src &&
+               git checkout -b branch master &&
+               test_commit F
+       ) &&
+       (
+               cd dst &&
+               git branch branch master &&
+               test_must_fail git push --force-with-lease=branch: origin branch
+       )
+'
+
 test_done
index ef0cbce..dd8f88d 100755 (executable)
@@ -181,4 +181,17 @@ test_expect_success 'up-to-date merge without common ancestor' '
        )
 '
 
+test_expect_success 'custom merge does not lock index' '
+       git reset --hard anchor &&
+       write_script sleep-one-second.sh <<-\EOF &&
+               sleep 1 &
+       EOF
+
+       test_write_lines >.gitattributes \
+               "* merge=ours" "text merge=sleep-one-second" &&
+       test_config merge.ours.driver true &&
+       test_config merge.sleep-one-second.driver ./sleep-one-second.sh &&
+       git merge master
+'
+
 test_done
index 85c10b0..5e8d5fa 100755 (executable)
@@ -16,6 +16,13 @@ test_description='CRLF merge conflict across text=auto change
 
 test_have_prereq SED_STRIPS_CR && SED_OPTIONS=-b
 
+compare_files () {
+       tr '\015\000' QN <"$1" >"$1".expect &&
+       tr '\015\000' QN <"$2" >"$2".actual &&
+       test_cmp "$1".expect "$2".actual &&
+       rm "$1".expect "$2".actual
+}
+
 test_expect_success setup '
        git config core.autocrlf false &&
 
@@ -30,7 +37,7 @@ test_expect_success setup '
        git branch side &&
 
        echo "* text=auto" >.gitattributes &&
-       touch file &&
+       echo first line >file &&
        git add .gitattributes file &&
        test_tick &&
        git commit -m "normalize file" &&
@@ -81,38 +88,49 @@ test_expect_success 'Merge after setting text=auto' '
        rm -f .gitattributes &&
        git reset --hard a &&
        git merge b &&
-       test_cmp expected file
+       compare_files expected file
 '
 
-test_expect_success 'Merge addition of text=auto' '
+test_expect_success 'Merge addition of text=auto eol=LF' '
+       git config core.eol lf &&
        cat <<-\EOF >expected &&
        first line
        same line
        EOF
 
-       if test_have_prereq NATIVE_CRLF; then
-               append_cr <expected >expected.temp &&
-               mv expected.temp expected
-       fi &&
        git config merge.renormalize true &&
        git rm -fr . &&
        rm -f .gitattributes &&
        git reset --hard b &&
        git merge a &&
-       test_cmp expected file
+       compare_files  expected file
+'
+
+test_expect_success 'Merge addition of text=auto eol=CRLF' '
+       git config core.eol crlf &&
+       cat <<-\EOF >expected &&
+       first line
+       same line
+       EOF
+
+       append_cr <expected >expected.temp &&
+       mv expected.temp expected &&
+       git config merge.renormalize true &&
+       git rm -fr . &&
+       rm -f .gitattributes &&
+       git reset --hard b &&
+       echo >&2 "After git reset --hard b" &&
+       git ls-files -s --eol >&2 &&
+       git merge a &&
+       compare_files  expected file
 '
 
 test_expect_success 'Detect CRLF/LF conflict after setting text=auto' '
+       git config core.eol native &&
        echo "<<<<<<<" >expected &&
-       if test_have_prereq NATIVE_CRLF; then
-               echo first line | append_cr >>expected &&
-               echo same line | append_cr >>expected &&
-               echo ======= | append_cr >>expected
-       else
-               echo first line >>expected &&
-               echo same line >>expected &&
-               echo ======= >>expected
-       fi &&
+       echo first line >>expected &&
+       echo same line >>expected &&
+       echo ======= >>expected &&
        echo first line | append_cr >>expected &&
        echo same line | append_cr >>expected &&
        echo ">>>>>>>" >>expected &&
@@ -121,29 +139,23 @@ test_expect_success 'Detect CRLF/LF conflict after setting text=auto' '
        git reset --hard a &&
        test_must_fail git merge b &&
        fuzz_conflict file >file.fuzzy &&
-       test_cmp expected file.fuzzy
+       compare_files expected file.fuzzy
 '
 
 test_expect_success 'Detect LF/CRLF conflict from addition of text=auto' '
        echo "<<<<<<<" >expected &&
        echo first line | append_cr >>expected &&
        echo same line | append_cr >>expected &&
-       if test_have_prereq NATIVE_CRLF; then
-               echo ======= | append_cr >>expected &&
-               echo first line | append_cr >>expected &&
-               echo same line | append_cr >>expected
-       else
-               echo ======= >>expected &&
-               echo first line >>expected &&
-               echo same line >>expected
-       fi &&
+       echo ======= >>expected &&
+       echo first line >>expected &&
+       echo same line >>expected &&
        echo ">>>>>>>" >>expected &&
        git config merge.renormalize false &&
        rm -f .gitattributes &&
        git reset --hard b &&
        test_must_fail git merge a &&
        fuzz_conflict file >file.fuzzy &&
-       test_cmp expected file.fuzzy
+       compare_files expected file.fuzzy
 '
 
 test_expect_failure 'checkout -m after setting text=auto' '
@@ -158,7 +170,7 @@ test_expect_failure 'checkout -m after setting text=auto' '
        git reset --hard initial &&
        git checkout a -- . &&
        git checkout -m b &&
-       test_cmp expected file
+       compare_files expected file
 '
 
 test_expect_failure 'checkout -m addition of text=auto' '
@@ -173,7 +185,7 @@ test_expect_failure 'checkout -m addition of text=auto' '
        git reset --hard initial &&
        git checkout b -- . &&
        git checkout -m a &&
-       test_cmp expected file
+       compare_files expected file
 '
 
 test_expect_failure 'cherry-pick patch from after text=auto was added' '
@@ -187,7 +199,7 @@ test_expect_failure 'cherry-pick patch from after text=auto was added' '
        git reset --hard b &&
        test_must_fail git cherry-pick a >err 2>&1 &&
        grep "[Nn]othing added" err &&
-       test_cmp expected file
+       compare_files expected file
 '
 
 test_expect_success 'Test delete/normalize conflict' '
index 2974900..70a2de4 100755 (executable)
@@ -124,6 +124,12 @@ test_expect_success PERL 'difftool stops on error with --trust-exit-code' '
        test_cmp expect actual
 '
 
+test_expect_success PERL 'difftool honors exit status if command not found' '
+       test_config difftool.nonexistent.cmd i-dont-exist &&
+       test_config difftool.trustExitCode false &&
+       test_must_fail git difftool -y -t nonexistent branch
+'
+
 test_expect_success PERL 'difftool honors --gui' '
        difftool_test_setup &&
        test_config merge.tool bogus-tool &&
index 0af7ebf..2990c92 100644 (file)
@@ -120,7 +120,12 @@ int create_tempfile(struct tempfile *tempfile, const char *path)
        prepare_tempfile_object(tempfile);
 
        strbuf_add_absolute_path(&tempfile->filename, path);
-       tempfile->fd = open(tempfile->filename.buf, O_RDWR | O_CREAT | O_EXCL, 0666);
+       tempfile->fd = open(tempfile->filename.buf,
+                           O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC, 0666);
+       if (O_CLOEXEC && tempfile->fd < 0 && errno == EINVAL)
+               /* Try again w/o O_CLOEXEC: the kernel might not support it */
+               tempfile->fd = open(tempfile->filename.buf,
+                                   O_RDWR | O_CREAT | O_EXCL, 0666);
        if (tempfile->fd < 0) {
                strbuf_reset(&tempfile->filename);
                return -1;
index 4219fe4..2f0038d 100644 (file)
  *   * calling `fdopen_tempfile()` to get a `FILE` pointer for the
  *     open file and writing to the file using stdio.
  *
+ *   Note that the file descriptor returned by create_tempfile()
+ *   is marked O_CLOEXEC, so the new contents must be written by
+ *   the current process, not any spawned one.
+ *
  * When finished writing, the caller can:
  *
  * * Close the file descriptor and remove the temporary file by
index be4a63e..41eb82c 100644 (file)
@@ -321,11 +321,6 @@ static void print_ref_status(char flag, const char *summary, struct ref *to, str
        }
 }
 
-static const char *status_abbrev(unsigned char sha1[20])
-{
-       return find_unique_abbrev(sha1, DEFAULT_ABBREV);
-}
-
 static void print_ok_ref_status(struct ref *ref, int porcelain)
 {
        if (ref->deletion)
@@ -340,7 +335,8 @@ static void print_ok_ref_status(struct ref *ref, int porcelain)
                char type;
                const char *msg;
 
-               strbuf_addstr(&quickref, status_abbrev(ref->old_oid.hash));
+               strbuf_add_unique_abbrev(&quickref, ref->old_oid.hash,
+                                        DEFAULT_ABBREV);
                if (ref->forced_update) {
                        strbuf_addstr(&quickref, "...");
                        type = '+';
@@ -350,7 +346,8 @@ static void print_ok_ref_status(struct ref *ref, int porcelain)
                        type = ' ';
                        msg = NULL;
                }
-               strbuf_addstr(&quickref, status_abbrev(ref->new_oid.hash));
+               strbuf_add_unique_abbrev(&quickref, ref->new_oid.hash,
+                                        DEFAULT_ABBREV);
 
                print_ref_status(type, quickref.buf, ref, ref->peer_ref, msg, porcelain);
                strbuf_release(&quickref);
index 44d63fb..26746f6 100644 (file)
@@ -813,20 +813,17 @@ static int upload_pack_config(const char *var, const char *value, void *unused)
        return parse_hide_refs_config(var, value, "uploadpack");
 }
 
-int main(int argc, char **argv)
+int cmd_main(int argc, const char **argv)
 {
-       char *dir;
+       const char *dir;
        int i;
        int strict = 0;
 
-       git_setup_gettext();
-
        packet_trace_identity("upload-pack");
-       git_extract_argv0_path(argv[0]);
        check_replace_refs = 0;
 
        for (i = 1; i < argc; i++) {
-               char *arg = argv[i];
+               const char *arg = argv[i];
 
                if (arg[0] != '-')
                        break;