Merge branch 'maint' of git://github.com/git-l10n/git-po into maint
authorJunio C Hamano <gitster@pobox.com>
Mon, 19 Oct 2015 06:37:35 +0000 (23:37 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 19 Oct 2015 06:37:35 +0000 (23:37 -0700)
* 'maint' of git://github.com/git-l10n/git-po:
l10n: ru.po: update Russian translation

77 files changed:
Documentation/RelNotes/2.3.10.txt [new file with mode: 0644]
Documentation/RelNotes/2.4.10.txt [new file with mode: 0644]
Documentation/RelNotes/2.5.4.txt [new file with mode: 0644]
Documentation/RelNotes/2.6.1.txt [new file with mode: 0644]
Documentation/RelNotes/2.6.2.txt [new file with mode: 0644]
Documentation/config.txt
Documentation/git-am.txt
Documentation/git-bisect-lk2009.txt
Documentation/git-cherry-pick.txt
Documentation/git-commit-tree.txt
Documentation/git-commit.txt
Documentation/git-grep.txt
Documentation/git-interpret-trailers.txt
Documentation/git-log.txt
Documentation/git-ls-remote.txt
Documentation/git-merge.txt
Documentation/git-notes.txt
Documentation/git-rebase.txt
Documentation/git-revert.txt
Documentation/git-status.txt
Documentation/git-tag.txt
Documentation/git.txt
Documentation/pretty-options.txt
Documentation/user-manual.txt
GIT-VERSION-GEN
Makefile
RelNotes
advice.c
builtin/am.c
builtin/blame.c
builtin/fsck.c
builtin/ls-remote.c
builtin/merge-file.c
builtin/merge-tree.c
builtin/pull.c
builtin/rerere.c
combine-diff.c
connect.c
contrib/examples/git-pull.sh
diff.c
diffcore-pickaxe.c
dir.c
git-rebase--interactive.sh
git-submodule.sh
http.c
line-log.c
ll-merge.c
pager.c
quote.c
run-command.c
run-command.h
t/annotate-tests.sh
t/lib-httpd/apache.conf
t/lib-proto-disable.sh [new file with mode: 0644]
t/perf/aggregate.perl
t/t1450-fsck.sh
t/t2026-prune-linked-checkouts.sh [deleted file]
t/t2026-worktree-prune.sh [new file with mode: 0755]
t/t3203-branch-output.sh
t/t3301-notes.sh
t/t3404-rebase-interactive.sh
t/t5507-remote-environment.sh [new file with mode: 0755]
t/t5560-http-backend-noserver.sh
t/t5561-http-backend.sh
t/t556x_common
t/t5810-proto-disable-local.sh [new file with mode: 0755]
t/t5811-proto-disable-git.sh [new file with mode: 0755]
t/t5812-proto-disable-http.sh [new file with mode: 0755]
t/t5813-proto-disable-ssh.sh [new file with mode: 0755]
t/t5814-proto-disable-ext.sh [new file with mode: 0755]
t/t5815-submodule-protos.sh [new file with mode: 0755]
transport-helper.c
transport.c
transport.h
wt-status.c
xdiff-interface.c
xdiff-interface.h
diff --git a/Documentation/RelNotes/2.3.10.txt b/Documentation/RelNotes/2.3.10.txt
new file mode 100644 (file)
index 0000000..9d425d8
--- /dev/null
@@ -0,0 +1,18 @@
+Git v2.3.10 Release Notes
+=========================
+
+Fixes since v2.3.9
+------------------
+
+ * xdiff code we use to generate diffs is not prepared to handle
+   extremely large files.  It uses "int" in many places, which can
+   overflow if we have a very large number of lines or even bytes in
+   our input files, for example.  Cap the input size to soemwhere
+   around 1GB for now.
+
+ * Some protocols (like git-remote-ext) can execute arbitrary code
+   found in the URL.  The URLs that submodules use may come from
+   arbitrary sources (e.g., .gitmodules files in a remote
+   repository), and can hurt those who blindly enable recursive
+   fetch.  Restrict the allowed protocols to well known and safe
+   ones.
diff --git a/Documentation/RelNotes/2.4.10.txt b/Documentation/RelNotes/2.4.10.txt
new file mode 100644 (file)
index 0000000..8621199
--- /dev/null
@@ -0,0 +1,18 @@
+Git v2.4.10 Release Notes
+=========================
+
+Fixes since v2.4.9
+------------------
+
+ * xdiff code we use to generate diffs is not prepared to handle
+   extremely large files.  It uses "int" in many places, which can
+   overflow if we have a very large number of lines or even bytes in
+   our input files, for example.  Cap the input size to soemwhere
+   around 1GB for now.
+
+ * Some protocols (like git-remote-ext) can execute arbitrary code
+   found in the URL.  The URLs that submodules use may come from
+   arbitrary sources (e.g., .gitmodules files in a remote
+   repository), and can hurt those who blindly enable recursive
+   fetch.  Restrict the allowed protocols to well known and safe
+   ones.
diff --git a/Documentation/RelNotes/2.5.4.txt b/Documentation/RelNotes/2.5.4.txt
new file mode 100644 (file)
index 0000000..a5e8477
--- /dev/null
@@ -0,0 +1,18 @@
+Git v2.5.4 Release Notes
+========================
+
+Fixes since v2.5.4
+------------------
+
+ * xdiff code we use to generate diffs is not prepared to handle
+   extremely large files.  It uses "int" in many places, which can
+   overflow if we have a very large number of lines or even bytes in
+   our input files, for example.  Cap the input size to soemwhere
+   around 1GB for now.
+
+ * Some protocols (like git-remote-ext) can execute arbitrary code
+   found in the URL.  The URLs that submodules use may come from
+   arbitrary sources (e.g., .gitmodules files in a remote
+   repository), and can hurt those who blindly enable recursive
+   fetch.  Restrict the allowed protocols to well known and safe
+   ones.
diff --git a/Documentation/RelNotes/2.6.1.txt b/Documentation/RelNotes/2.6.1.txt
new file mode 100644 (file)
index 0000000..1e51363
--- /dev/null
@@ -0,0 +1,18 @@
+Git v2.6.1 Release Notes
+========================
+
+Fixes since v2.6
+----------------
+
+ * xdiff code we use to generate diffs is not prepared to handle
+   extremely large files.  It uses "int" in many places, which can
+   overflow if we have a very large number of lines or even bytes in
+   our input files, for example.  Cap the input size to soemwhere
+   around 1GB for now.
+
+ * Some protocols (like git-remote-ext) can execute arbitrary code
+   found in the URL.  The URLs that submodules use may come from
+   arbitrary sources (e.g., .gitmodules files in a remote
+   repository), and can hurt those who blindly enable recursive
+   fetch.  Restrict the allowed protocols to well known and safe
+   ones.
diff --git a/Documentation/RelNotes/2.6.2.txt b/Documentation/RelNotes/2.6.2.txt
new file mode 100644 (file)
index 0000000..5b65e35
--- /dev/null
@@ -0,0 +1,65 @@
+Git v2.6.2 Release Notes
+========================
+
+Fixes since v2.6.1
+------------------
+
+ * There were some classes of errors that "git fsck" diagnosed to its
+   standard error that did not cause it to exit with non-zero status.
+
+ * A test script for the HTTP service had a timing dependent bug,
+   which was fixed.
+
+ * Performance-measurement tests did not work without an installed Git.
+
+ * On a case insensitive filesystems, setting GIT_WORK_TREE variable
+   using a random cases that does not agree with what the filesystem
+   thinks confused Git that it wasn't inside the working tree.
+
+ * When "git am" was rewritten as a built-in, it stopped paying
+   attention to user.signingkey, which was fixed.
+
+ * After "git checkout --detach", "git status" reported a fairly
+   useless "HEAD detached at HEAD", instead of saying at which exact
+   commit.
+
+ * "git rebase -i" had a minor regression recently, which stopped
+   considering a line that begins with an indented '#' in its insn
+   sheet not a comment, which is now fixed.
+
+ * Description of the "log.follow" configuration variable in "git log"
+   documentation is now also copied to "git config" documentation.
+
+ * Allocation related functions and stdio are unsafe things to call
+   inside a signal handler, and indeed killing the pager can cause
+   glibc to deadlock waiting on allocation mutex as our signal handler
+   tries to free() some data structures in wait_for_pager().  Reduce
+   these unsafe calls.
+
+ * The way how --ref/--notes to specify the notes tree reference are
+   DWIMmed was not clearly documented.
+
+ * Customization to change the behaviour with "make -w" and "make -s"
+   in our Makefile was broken when they were used together.
+
+ * The Makefile always runs the library archiver with hardcoded "crs"
+   options, which was inconvenient for exotic platforms on which
+   people want to use programs with totally different set of command
+   line options.
+
+ * The ssh transport, just like any other transport over the network,
+   did not clear GIT_* environment variables, but it is possible to
+   use SendEnv and AcceptEnv to leak them to the remote invocation of
+   Git, which is not a good idea at all.  Explicitly clear them just
+   like we do for the local transport.
+
+ * "git blame --first-parent v1.0..v2.0" was not rejected but did not
+   limit the blame to commits on the first parent chain.
+
+ * Very small number of options take a parameter that is optional
+   (which is not a great UI element as they can only appear at the end
+   of the command line).  Add notice to documentation of each and
+   every one of them.
+
+Also contains typofixes, documentation updates and trivial code
+clean-ups.
index 0cc87a6f6565bbe794420bc47be8407e4ac47f22..fec0dea5d03343b40caf35ea6de6753049f08d35 100644 (file)
@@ -1840,6 +1840,12 @@ log.decorate::
        specified, the full ref name (including prefix) will be printed.
        This is the same as the log commands '--decorate' option.
 
+log.follow::
+       If `true`, `git log` will act as if the `--follow` option was used when
+       a single <path> is given.  This has the same limitations as `--follow`,
+       i.e. it cannot be used to follow multiple files and does not work well
+       on non-linear history.
+
 log.showRoot::
        If true, the initial commit will be shown as a big creation event.
        This is equivalent to a diff against an empty tree.
index dbea6e7ae9131a1e5c51dec460d58cc6deda701b..452c1feb2319a3ac47836b5039ebeba519be3c87 100644 (file)
@@ -141,7 +141,9 @@ default.   You can use `--no-utf8` to override this.
 
 -S[<keyid>]::
 --gpg-sign[=<keyid>]::
-       GPG-sign commits.
+       GPG-sign commits. The `keyid` argument is optional and
+       defaults to the committer identity; if specified, it must be
+       stuck to the option without a space.
 
 --continue::
 -r::
index 0f0c6ff0829dfab3bd45b34b76a5b489f648eba9..c06efbd42a6c1010f0a5ec17ba460e0ebcd91d9d 100644 (file)
@@ -1321,7 +1321,7 @@ So git bisect is unconditional goodness - and feel free to quote that
 _____________
 
 Acknowledgments
-----------------
+---------------
 
 Many thanks to Junio Hamano for his help in reviewing this paper, for
 reviewing the patches I sent to the Git mailing list, for discussing
index 1147c71da605c1f5779835137fb6bab5e2c349a6..77da29a474518c56c7dab23f5921aa50566506dd 100644 (file)
@@ -9,7 +9,7 @@ SYNOPSIS
 --------
 [verse]
 'git cherry-pick' [--edit] [-n] [-m parent-number] [-s] [-x] [--ff]
-                 [-S[<key-id>]] <commit>...
+                 [-S[<keyid>]] <commit>...
 'git cherry-pick' --continue
 'git cherry-pick' --quit
 'git cherry-pick' --abort
@@ -101,9 +101,11 @@ effect to your index in a row.
 --signoff::
        Add Signed-off-by line at the end of the commit message.
 
--S[<key-id>]::
---gpg-sign[=<key-id>]::
-       GPG-sign commits.
+-S[<keyid>]::
+--gpg-sign[=<keyid>]::
+       GPG-sign commits. The `keyid` argument is optional and
+       defaults to the committer identity; if specified, it must be
+       stuck to the option without a space.
 
 --ff::
        If the current HEAD is the same as the parent of the
index f5f2a8d326502714299cf85d9819bb065d5af390..a0b5457304008cec1cf728e5ac168c5f547173eb 100644 (file)
@@ -56,7 +56,9 @@ OPTIONS
 
 -S[<keyid>]::
 --gpg-sign[=<keyid>]::
-       GPG-sign commit.
+       GPG-sign commits. The `keyid` argument is optional and
+       defaults to the committer identity; if specified, it must be
+       stuck to the option without a space.
 
 --no-gpg-sign::
        Countermand `commit.gpgSign` configuration variable that is
index 904dafa0f7070fc438f138393a3b356542ae04d9..7f34a5b33103ed1c870f234687079badc393be77 100644 (file)
@@ -13,7 +13,7 @@ SYNOPSIS
           [-F <file> | -m <msg>] [--reset-author] [--allow-empty]
           [--allow-empty-message] [--no-verify] [-e] [--author=<author>]
           [--date=<date>] [--cleanup=<mode>] [--[no-]status]
-          [-i | -o] [-S[<key-id>]] [--] [<file>...]
+          [-i | -o] [-S[<keyid>]] [--] [<file>...]
 
 DESCRIPTION
 -----------
@@ -314,7 +314,9 @@ changes to tracked files.
 
 -S[<keyid>]::
 --gpg-sign[=<keyid>]::
-       GPG-sign commit.
+       GPG-sign commits. The `keyid` argument is optional and
+       defaults to the committer identity; if specified, it must be
+       stuck to the option without a space.
 
 --no-gpg-sign::
        Countermand `commit.gpgSign` configuration variable that is
index 31811f16bdaac49d01d38dcdea82bb191942b1cf..4a44d6da13cb749759f9d6164b88974ba55485ab 100644 (file)
@@ -160,12 +160,15 @@ OPTIONS
        For better compatibility with 'git diff', `--name-only` is a
        synonym for `--files-with-matches`.
 
--O [<pager>]::
---open-files-in-pager [<pager>]::
+-O[<pager>]::
+--open-files-in-pager[=<pager>]::
        Open the matching files in the pager (not the output of 'grep').
        If the pager happens to be "less" or "vi", and the user
        specified only one pattern, the first file is positioned at
-       the first match automatically.
+       the first match automatically. The `pager` argument is
+       optional; if specified, it must be stuck to the option
+       without a space. If `pager` is unspecified, the default pager
+       will be used (see `core.pager` in linkgit:git-config[1]).
 
 -z::
 --null::
index d6d9231b506b6a6918b4b7a342b33351eafd7e97..0ecd497c4de77ea2ed7afc5603b4bcbd8558d174 100644 (file)
@@ -67,7 +67,7 @@ OPTIONS
 --trim-empty::
        If the <value> part of any trailer contains only whitespace,
        the whole trailer will be removed from the resulting message.
-       This apply to existing trailers as well as new trailers.
+       This applies to existing trailers as well as new trailers.
 
 --trailer <token>[(=|:)<value>]::
        Specify a (<token>, <value>) pair that should be applied as a
index 97b9993ee8c2aeef504e96a041424e1d396a75d8..03f958029ad7a35ec29f111217cd76ba21de9b5e 100644 (file)
@@ -185,10 +185,10 @@ log.date::
        dates like `Sat May 8 19:35:34 2010 -0500`.
 
 log.follow::
-       If a single <path> is given to git log, it will act as
-       if the `--follow` option was also used.  This has the same
-       limitations as `--follow`, i.e. it cannot be used to follow
-       multiple files and does not work well on non-linear history.
+       If `true`, `git log` will act as if the `--follow` option was used when
+       a single <path> is given.  This has the same limitations as `--follow`,
+       i.e. it cannot be used to follow multiple files and does not work well
+       on non-linear history.
 
 log.showRoot::
        If `false`, `git log` and related commands will not treat the
index 2e22915eb857bd960f09afc725107198642bfd22..d510c05e11d3cbfb7fd1393331306e70bb7645db 100644 (file)
@@ -9,7 +9,7 @@ git-ls-remote - List references in a remote repository
 SYNOPSIS
 --------
 [verse]
-'git ls-remote' [--heads] [--tags]  [-u <exec> | --upload-pack <exec>]
+'git ls-remote' [--heads] [--tags]  [--upload-pack=<exec>]
              [--exit-code] <repository> [<refs>...]
 
 DESCRIPTION
@@ -29,7 +29,6 @@ OPTIONS
        both, references stored in refs/heads and refs/tags are
        displayed.
 
--u <exec>::
 --upload-pack=<exec>::
        Specify the full path of 'git-upload-pack' on the remote
        host. This allows listing references from repositories accessed via
index a62d6729b94963787ad435c486e1dc419c776012..07f7295ec8b603fcbd907e780d4ed1109ac5b358 100644 (file)
@@ -10,7 +10,7 @@ SYNOPSIS
 --------
 [verse]
 'git merge' [-n] [--stat] [--no-commit] [--squash] [--[no-]edit]
-       [-s <strategy>] [-X <strategy-option>] [-S[<key-id>]]
+       [-s <strategy>] [-X <strategy-option>] [-S[<keyid>]]
        [--[no-]rerere-autoupdate] [-m <msg>] [<commit>...]
 'git merge' <msg> HEAD <commit>...
 'git merge' --abort
@@ -67,7 +67,9 @@ include::merge-options.txt[]
 
 -S[<keyid>]::
 --gpg-sign[=<keyid>]::
-       GPG-sign the resulting merge commit.
+       GPG-sign the resulting merge commit. The `keyid` argument is
+       optional and defaults to the committer identity; if specified,
+       it must be stuck to the option without a space.
 
 -m <msg>::
        Set the commit message to be used for the merge commit (in
index a9a916f360ec9efb8a801acc982ba39a38f41cf5..8de349968a3be4ea7e65a4a254041b0f0fb63347 100644 (file)
@@ -162,7 +162,9 @@ OPTIONS
 --ref <ref>::
        Manipulate the notes tree in <ref>.  This overrides
        'GIT_NOTES_REF' and the "core.notesRef" configuration.  The ref
-       is taken to be in `refs/notes/` if it is not qualified.
+       specifies the full refname when it begins with `refs/notes/`; when it
+       begins with `notes/`, `refs/` and otherwise `refs/notes/` is prefixed
+       to form a full name of the ref.
 
 --ignore-missing::
        Do not consider it an error to request removing notes from an
index ca039546a463bee511ca3a1c7d301689fb56a412..bccfdf7fde9af8c80203f85d98030f8f38db4994 100644 (file)
@@ -294,7 +294,9 @@ which makes little sense.
 
 -S[<keyid>]::
 --gpg-sign[=<keyid>]::
-       GPG-sign commits.
+       GPG-sign commits. The `keyid` argument is optional and
+       defaults to the committer identity; if specified, it must be
+       stuck to the option without a space.
 
 -q::
 --quiet::
index cceb5f2f7fa0c41174215901a091158161d89bc3..b15139ffdcda488c9e2314540885965723292a48 100644 (file)
@@ -8,7 +8,7 @@ git-revert - Revert some existing commits
 SYNOPSIS
 --------
 [verse]
-'git revert' [--[no-]edit] [-n] [-m parent-number] [-s] [-S[<key-id>]] <commit>...
+'git revert' [--[no-]edit] [-n] [-m parent-number] [-s] [-S[<keyid>]] <commit>...
 'git revert' --continue
 'git revert' --quit
 'git revert' --abort
@@ -80,9 +80,11 @@ more details.
 This is useful when reverting more than one commits'
 effect to your index in a row.
 
--S[<key-id>]::
---gpg-sign[=<key-id>]::
-       GPG-sign commits.
+-S[<keyid>]::
+--gpg-sign[=<keyid>]::
+       GPG-sign commits. The `keyid` argument is optional and
+       defaults to the committer identity; if specified, it must be
+       stuck to the option without a space.
 
 -s::
 --signoff::
index 335f3123353482cfd708420dac3b766f181e89ff..e1e8f57cdd217b43b9b04bc54381e9b155d9cbde 100644 (file)
@@ -53,8 +53,9 @@ OPTIONS
 --untracked-files[=<mode>]::
        Show untracked files.
 +
-The mode parameter is optional (defaults to 'all'), and is used to
-specify the handling of untracked files.
+The mode parameter is used to specify the handling of untracked files.
+It is optional: it defaults to 'all', and if specified, it must be
+stuck to the option (e.g. `-uno`, but not `-u no`).
 +
 The possible options are:
 +
index 84f6496bf228454acaa04e570f7857ba1975cda4..08b4dfbf1b049a3fc3cd04edc573845e0c976a9c 100644 (file)
@@ -9,7 +9,7 @@ git-tag - Create, list, delete or verify a tag object signed with GPG
 SYNOPSIS
 --------
 [verse]
-'git tag' [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>]
+'git tag' [-a | -s | -u <keyid>] [-f] [-m <msg> | -F <file>]
        <tagname> [<commit> | <object>]
 'git tag' -d <tagname>...
 'git tag' [-n[<num>]] -l [--contains <commit>] [--points-at <object>]
@@ -24,19 +24,19 @@ to delete, list or verify tags.
 
 Unless `-f` is given, the named tag must not yet exist.
 
-If one of `-a`, `-s`, or `-u <key-id>` is passed, the command
+If one of `-a`, `-s`, or `-u <keyid>` is passed, the command
 creates a 'tag' object, and requires a tag message.  Unless
 `-m <msg>` or `-F <file>` is given, an editor is started for the user to type
 in the tag message.
 
-If `-m <msg>` or `-F <file>` is given and `-a`, `-s`, and `-u <key-id>`
+If `-m <msg>` or `-F <file>` is given and `-a`, `-s`, and `-u <keyid>`
 are absent, `-a` is implied.
 
 Otherwise just a tag reference for the SHA-1 object name of the commit object is
 created (i.e. a lightweight tag).
 
 A GnuPG signed tag object will be created when `-s` or `-u
-<key-id>` is used.  When `-u <key-id>` is not used, the
+<keyid>` is used.  When `-u <keyid>` is not used, the
 committer identity for the current user is used to find the
 GnuPG key for signing.         The configuration variable `gpg.program`
 is used to specify custom GnuPG binary.
@@ -63,8 +63,8 @@ OPTIONS
 --sign::
        Make a GPG-signed tag, using the default e-mail address's key.
 
--u <key-id>::
---local-user=<key-id>::
+-u <keyid>::
+--local-user=<keyid>::
        Make a GPG-signed tag, using the given key.
 
 -f::
@@ -125,14 +125,14 @@ This option is only applicable when listing tags without annotation lines.
        Use the given tag message (instead of prompting).
        If multiple `-m` options are given, their values are
        concatenated as separate paragraphs.
-       Implies `-a` if none of `-a`, `-s`, or `-u <key-id>`
+       Implies `-a` if none of `-a`, `-s`, or `-u <keyid>`
        is given.
 
 -F <file>::
 --file=<file>::
        Take the tag message from the given file.  Use '-' to
        read the message from the standard input.
-       Implies `-a` if none of `-a`, `-s`, or `-u <key-id>`
+       Implies `-a` if none of `-a`, `-s`, or `-u <keyid>`
        is given.
 
 --cleanup=<mode>::
@@ -166,7 +166,7 @@ it in the repository configuration as follows:
 
 -------------------------------------
 [user]
-    signingKey = <gpg-key-id>
+    signingKey = <gpg-keyid>
 -------------------------------------
 
 
index 8b2dede3e949b5178f9aa41c5aee4e27f228a077..4585103f996c0e68753520ad5064a1a9879054c8 100644 (file)
@@ -43,17 +43,26 @@ 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.5.3/git.html[documentation for release 2.5.3]
+* link:v2.6.2/git.html[documentation for release 2.6.2]
 
 * release notes for
+  link:RelNotes/2.6.2.txt[2.6.2],
+  link:RelNotes/2.6.1.txt[2.6.1],
+  link:RelNotes/2.6.0.txt[2.6].
+
+* link:v2.5.4/git.html[documentation for release 2.5.4]
+
+* release notes for
+  link:RelNotes/2.5.4.txt[2.5.4],
   link:RelNotes/2.5.3.txt[2.5.3],
   link:RelNotes/2.5.2.txt[2.5.2],
   link:RelNotes/2.5.1.txt[2.5.1],
   link:RelNotes/2.5.0.txt[2.5].
 
-* link:v2.4.9/git.html[documentation for release 2.4.9]
+* link:v2.4.10/git.html[documentation for release 2.4.10]
 
 * release notes for
+  link:RelNotes/2.4.10.txt[2.4.10],
   link:RelNotes/2.4.9.txt[2.4.9],
   link:RelNotes/2.4.8.txt[2.4.8],
   link:RelNotes/2.4.7.txt[2.4.7],
@@ -65,9 +74,10 @@ Documentation for older releases are available here:
   link:RelNotes/2.4.1.txt[2.4.1],
   link:RelNotes/2.4.0.txt[2.4].
 
-* link:v2.3.9/git.html[documentation for release 2.3.9]
+* link:v2.3.10/git.html[documentation for release 2.3.10]
 
 * release notes for
+  link:RelNotes/2.3.10.txt[2.3.10],
   link:RelNotes/2.3.9.txt[2.3.9],
   link:RelNotes/2.3.8.txt[2.3.8],
   link:RelNotes/2.3.7.txt[2.3.7],
@@ -1087,6 +1097,33 @@ GIT_ICASE_PATHSPECS::
        an operation has touched every ref (e.g., because you are
        cloning a repository to make a backup).
 
+`GIT_ALLOW_PROTOCOL`::
+       If set, provide a colon-separated list of protocols which are
+       allowed to be used with fetch/push/clone. This is useful to
+       restrict recursive submodule initialization from an untrusted
+       repository. Any protocol not mentioned will be disallowed (i.e.,
+       this is a whitelist, not a blacklist). If the variable is not
+       set at all, all protocols are enabled.  The protocol names
+       currently used by git are:
+
+         - `file`: any local file-based path (including `file://` URLs,
+           or local paths)
+
+         - `git`: the anonymous git protocol over a direct TCP
+           connection (or proxy, if configured)
+
+         - `ssh`: git over ssh (including `host:path` syntax,
+           `git+ssh://`, etc).
+
+         - `rsync`: git over rsync
+
+         - `http`: git over http, both "smart http" and "dumb http".
+           Note that this does _not_ include `https`; if you want both,
+           you should specify both as `http:https`.
+
+         - any external helpers are named by their protocol (e.g., use
+           `hg` to allow the `git-remote-hg` helper)
+
 
 Discussion[[Discussion]]
 ------------------------
index 8d6c5cec4c5edc904a5f2d7595fd8943457f550d..4b659ac1a6a6c1b57d0cadc5cd69ce6b69525cc1 100644 (file)
@@ -55,8 +55,9 @@ By default, the notes shown are from the notes refs listed in the
 environment overrides). See linkgit:git-config[1] for more details.
 +
 With an optional '<ref>' argument, show this notes ref instead of the
-default notes ref(s). The ref is taken to be in `refs/notes/` if it
-is not qualified.
+default notes ref(s). The ref specifies the full refname when it begins
+with `refs/notes/`; when it begins with `notes/`, `refs/` and otherwise
+`refs/notes/` is prefixed to form a full name of the ref.
 +
 Multiple --notes options can be combined to control which notes are
 being displayed. Examples: "--notes=foo" will show only notes from
index 68978f53381baf1b179b70f22e97084893d5c227..1b7987e73767f1c71d777909f3b275b5976419aa 100644 (file)
@@ -3424,7 +3424,7 @@ just missing one particular blob version.
 
 [[the-index]]
 The index
------------
+---------
 
 The index is a binary file (generally kept in `.git/index`) containing a
 sorted list of path names, each with permissions and the SHA-1 of a blob
index 49d60c06718b1458268218d4cebb1b4cdfe06fca..787670926a1283864ccd4a04379a939ff36e51aa 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.6.0-rc3
+DEF_VER=v2.6.2
 
 LF='
 '
index 8d5df7ea1ee672753e2f29302ef9a1a7db77638e..04c223102346c209bad78550723027543cffe7d1 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -375,6 +375,9 @@ ALL_CFLAGS = $(CPPFLAGS) $(CFLAGS)
 ALL_LDFLAGS = $(LDFLAGS)
 STRIP ?= strip
 
+# Create as necessary, replace existing, make ranlib unneeded.
+ARFLAGS = rcs
+
 # Among the variables below, these:
 #   gitexecdir
 #   template_dir
@@ -1465,13 +1468,13 @@ endif
 QUIET_SUBDIR0  = +$(MAKE) -C # space to separate -C and subdir
 QUIET_SUBDIR1  =
 
-ifneq ($(findstring $(MAKEFLAGS),w),w)
+ifneq ($(findstring w,$(MAKEFLAGS)),w)
 PRINT_DIR = --no-print-directory
 else # "make -w"
 NO_SUBDIR = :
 endif
 
-ifneq ($(findstring $(MAKEFLAGS),s),s)
+ifneq ($(findstring s,$(MAKEFLAGS)),s)
 ifndef V
        QUIET_CC       = @echo '   ' CC $@;
        QUIET_AR       = @echo '   ' AR $@;
@@ -1995,13 +1998,13 @@ $(REMOTE_CURL_PRIMARY): remote-curl.o http.o http-walker.o GIT-LDFLAGS $(GITLIBS
                $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
 
 $(LIB_FILE): $(LIB_OBJS)
-       $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $^
+       $(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^
 
 $(XDIFF_LIB): $(XDIFF_OBJS)
-       $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $^
+       $(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^
 
 $(VCSSVN_LIB): $(VCSSVN_OBJS)
-       $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $^
+       $(QUIET_AR)$(RM) $@ && $(AR) $(ARFLAGS) $@ $^
 
 export DEFAULT_EDITOR DEFAULT_PAGER
 
index 84a20c84c648cacea6b2cbdab43d36e92aaaa5c8..022358074dff1b5fee7d1d9c354b64a048041226 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.6.0.txt
\ No newline at end of file
+Documentation/RelNotes/2.6.2.txt
\ No newline at end of file
index 4965686e19cbb44b86d48363f8f3e289bebef94d..4dc5cf10a8533b1bfc3bd1483e91df115aa8f868 100644 (file)
--- a/advice.c
+++ b/advice.c
@@ -100,7 +100,7 @@ void NORETURN die_conclude_merge(void)
 {
        error(_("You have not concluded your merge (MERGE_HEAD exists)."));
        if (advice_resolve_conflict)
-               advise(_("Please, commit your changes before you can merge."));
+               advise(_("Please, commit your changes before merging."));
        die(_("Exiting because of unfinished merge."));
 }
 
index 4f77e07b9549f8ff144d770fb0b66e9124ae4dc6..3bd4fd701bdccab91f1343b371cf19e822c14db5 100644 (file)
@@ -2208,6 +2208,17 @@ enum resume_mode {
        RESUME_ABORT
 };
 
+static int git_am_config(const char *k, const char *v, void *cb)
+{
+       int status;
+
+       status = git_gpg_config(k, v, NULL);
+       if (status)
+               return status;
+
+       return git_default_config(k, v, NULL);
+}
+
 int cmd_am(int argc, const char **argv, const char *prefix)
 {
        struct am_state state;
@@ -2308,7 +2319,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
                OPT_END()
        };
 
-       git_config(git_default_config, NULL);
+       git_config(git_am_config, NULL);
 
        am_state_init(&state, git_path("rebase-apply"));
 
index 4db01c195cd27719023eeb599e76428ad752c9c9..295ce92da5df25a9082b868e848ee9634145e636 100644 (file)
@@ -974,7 +974,10 @@ static void pass_blame_to_parent(struct scoreboard *sb,
        fill_origin_blob(&sb->revs->diffopt, target, &file_o);
        num_get_patch++;
 
-       diff_hunks(&file_p, &file_o, 0, blame_chunk_cb, &d);
+       if (diff_hunks(&file_p, &file_o, 0, blame_chunk_cb, &d))
+               die("unable to generate diff (%s -> %s)",
+                   sha1_to_hex(parent->commit->object.sha1),
+                   sha1_to_hex(target->commit->object.sha1));
        /* The rest are the same as the parent */
        blame_chunk(&d.dstq, &d.srcq, INT_MAX, d.offset, INT_MAX, parent);
        *d.dstq = NULL;
@@ -1120,7 +1123,9 @@ static void find_copy_in_blob(struct scoreboard *sb,
         * file_p partially may match that image.
         */
        memset(split, 0, sizeof(struct blame_entry [3]));
-       diff_hunks(file_p, &file_o, 1, handle_split_cb, &d);
+       if (diff_hunks(file_p, &file_o, 1, handle_split_cb, &d))
+               die("unable to generate diff (%s)",
+                   sha1_to_hex(parent->commit->object.sha1));
        /* remainder, if any, all match the preimage */
        handle_split(sb, ent, d.tlno, d.plno, ent->num_lines, parent, split);
 }
@@ -1366,8 +1371,15 @@ static void pass_whole_blame(struct scoreboard *sb,
  */
 static struct commit_list *first_scapegoat(struct rev_info *revs, struct commit *commit)
 {
-       if (!reverse)
+       if (!reverse) {
+               if (revs->first_parent_only &&
+                   commit->parents &&
+                   commit->parents->next) {
+                       free_commit_list(commit->parents->next);
+                       commit->parents->next = NULL;
+               }
                return commit->parents;
+       }
        return lookup_decoration(&revs->children, &commit->object);
 }
 
@@ -2680,6 +2692,8 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
        }
        else if (contents_from)
                die("--contents and --children do not blend well.");
+       else if (revs.first_parent_only)
+               die("combining --first-parent and --reverse is not supported");
        else {
                final_commit_name = prepare_initial(&sb);
                sb.commits.compare = compare_commits_by_reverse_commit_date;
index 079470342fc926b97ae1c065d37926cf5a449101..b9a74f0cf6e169073994e466110fd1bde9febba7 100644 (file)
@@ -38,6 +38,7 @@ static int show_dangling = 1;
 #define ERROR_OBJECT 01
 #define ERROR_REACHABLE 02
 #define ERROR_PACK 04
+#define ERROR_REFS 010
 
 #ifdef NO_D_INO_IN_DIRENT
 #define SORT_DIRENT 0
@@ -521,8 +522,10 @@ static int fsck_handle_ref(const char *refname, const struct object_id *oid,
                /* We'll continue with the rest despite the error.. */
                return 0;
        }
-       if (obj->type != OBJ_COMMIT && is_branch(refname))
+       if (obj->type != OBJ_COMMIT && is_branch(refname)) {
                error("%s: not a commit", refname);
+               errors_found |= ERROR_REFS;
+       }
        default_refs++;
        obj->used = 1;
        mark_object_reachable(obj);
@@ -585,17 +588,23 @@ static int fsck_head_link(void)
                fprintf(stderr, "Checking HEAD link\n");
 
        head_points_at = resolve_ref_unsafe("HEAD", 0, head_oid.hash, &flag);
-       if (!head_points_at)
+       if (!head_points_at) {
+               errors_found |= ERROR_REFS;
                return error("Invalid HEAD");
+       }
        if (!strcmp(head_points_at, "HEAD"))
                /* detached HEAD */
                null_is_error = 1;
-       else if (!starts_with(head_points_at, "refs/heads/"))
+       else if (!starts_with(head_points_at, "refs/heads/")) {
+               errors_found |= ERROR_REFS;
                return error("HEAD points to something strange (%s)",
                             head_points_at);
+       }
        if (is_null_oid(&head_oid)) {
-               if (null_is_error)
+               if (null_is_error) {
+                       errors_found |= ERROR_REFS;
                        return error("HEAD: detached HEAD points at nothing");
+               }
                fprintf(stderr, "notice: HEAD points to an unborn branch (%s)\n",
                        head_points_at + 11);
        }
@@ -615,6 +624,7 @@ static int fsck_cache_tree(struct cache_tree *it)
                if (!obj) {
                        error("%s: invalid sha1 pointer in cache-tree",
                              sha1_to_hex(it->sha1));
+                       errors_found |= ERROR_REFS;
                        return 1;
                }
                obj->used = 1;
index 4554dbc8a98c0daaa67c8ea65f5ddf5c48f19383..5e9d5450b79713524eeeb981e4685725951cd9d2 100644 (file)
@@ -4,7 +4,7 @@
 #include "remote.h"
 
 static const char ls_remote_usage[] =
-"git ls-remote [--heads] [--tags]  [-u <exec> | --upload-pack <exec>]\n"
+"git ls-remote [--heads] [--tags]  [--upload-pack=<exec>]\n"
 "                     [-q | --quiet] [--exit-code] [--get-url] [<repository> [<refs>...]]";
 
 /*
index ea8093f6769e278c4f7871faf405fe1e3f0a7544..50d0bc873bee47ea6d1ab3b8e303e0a779465825 100644 (file)
@@ -75,7 +75,8 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix)
                        names[i] = argv[i];
                if (read_mmfile(mmfs + i, fname))
                        return -1;
-               if (buffer_is_binary(mmfs[i].ptr, mmfs[i].size))
+               if (mmfs[i].size > MAX_XDIFF_SIZE ||
+                   buffer_is_binary(mmfs[i].ptr, mmfs[i].size))
                        return error("Cannot merge binary files: %s",
                                        argv[i]);
        }
index f9ab48597e58ed97fc208b58c17b8becb105e095..2a4aafec6a906e22713b88d90f350071bfdb1d59 100644 (file)
@@ -118,7 +118,8 @@ static void show_diff(struct merge_list *entry)
        if (!dst.ptr)
                size = 0;
        dst.size = size;
-       xdi_diff(&src, &dst, &xpp, &xecfg, &ecb);
+       if (xdi_diff(&src, &dst, &xpp, &xecfg, &ecb))
+               die("unable to generate diff");
        free(src.ptr);
        free(dst.ptr);
 }
index a39bb0a11f72982f51222cdcf19d1010367c908f..bf3fd3f9c8d80ff84ace4150214118355585e917 100644 (file)
@@ -66,7 +66,7 @@ static int parse_opt_rebase(const struct option *opt, const char *arg, int unset
 }
 
 static const char * const pull_usage[] = {
-       N_("git pull [options] [<repository> [<refspec>...]]"),
+       N_("git pull [<options>] [<repository> [<refspec>...]]"),
        NULL
 };
 
index 12535c9b4f48cd196943c1914fefee7c47cecec2..88e1359ebcaad338d96dd942a5f88f54d6cce271 100644 (file)
@@ -29,9 +29,10 @@ static int diff_two(const char *file1, const char *label1,
        xdemitconf_t xecfg;
        xdemitcb_t ecb;
        mmfile_t minus, plus;
+       int ret;
 
        if (read_mmfile(&minus, file1) || read_mmfile(&plus, file2))
-               return 1;
+               return -1;
 
        printf("--- a/%s\n+++ b/%s\n", label1, label2);
        fflush(stdout);
@@ -40,11 +41,11 @@ static int diff_two(const char *file1, const char *label1,
        memset(&xecfg, 0, sizeof(xecfg));
        xecfg.ctxlen = 3;
        ecb.outf = outf;
-       xdi_diff(&minus, &plus, &xpp, &xecfg, &ecb);
+       ret = xdi_diff(&minus, &plus, &xpp, &xecfg, &ecb);
 
        free(minus.ptr);
        free(plus.ptr);
-       return 0;
+       return ret;
 }
 
 int cmd_rerere(int argc, const char **argv, const char *prefix)
@@ -104,7 +105,8 @@ int cmd_rerere(int argc, const char **argv, const char *prefix)
                for (i = 0; i < merge_rr.nr; i++) {
                        const char *path = merge_rr.items[i].string;
                        const char *name = (const char *)merge_rr.items[i].util;
-                       diff_two(rerere_path(name, "preimage"), path, path, path);
+                       if (diff_two(rerere_path(name, "preimage"), path, path, path))
+                               die("unable to generate diff for %s", name);
                }
        } else
                usage_with_options(rerere_usage, options);
index 30c7eb6d3cddbdf17d6ca8ff3bc85267041d1669..0f62f54b5ef4bb4ec81cff5aead2d6cd66da194e 100644 (file)
@@ -419,8 +419,10 @@ static void combine_diff(const struct object_id *parent, unsigned int mode,
        state.num_parent = num_parent;
        state.n = n;
 
-       xdi_diff_outf(&parent_file, result_file, consume_line, &state,
-                     &xpp, &xecfg);
+       if (xdi_diff_outf(&parent_file, result_file, consume_line, &state,
+                         &xpp, &xecfg))
+               die("unable to generate combined diff for %s",
+                   oid_to_hex(parent));
        free(parent_file.ptr);
 
        /* Assign line numbers for this parent.
index c0144d859ae4275860df464f73a688c649d092fe..d3283b8a4f3e8ed8451e723ce8b39d468aaa3dd3 100644 (file)
--- a/connect.c
+++ b/connect.c
@@ -9,6 +9,7 @@
 #include "url.h"
 #include "string-list.h"
 #include "sha1-array.h"
+#include "transport.h"
 
 static char *server_capabilities;
 static const char *parse_feature_value(const char *, const char *, int *);
@@ -254,7 +255,7 @@ static const char *prot_name(enum protocol protocol)
                case PROTO_GIT:
                        return "git";
                default:
-                       return "unkown protocol";
+                       return "unknown protocol";
        }
 }
 
@@ -694,6 +695,8 @@ struct child_process *git_connect(int fd[2], const char *url,
                else
                        target_host = xstrdup(hostandport);
 
+               transport_check_allowed("git");
+
                /* These underlying connection commands die() if they
                 * cannot connect.
                 */
@@ -721,12 +724,16 @@ struct child_process *git_connect(int fd[2], const char *url,
                strbuf_addch(&cmd, ' ');
                sq_quote_buf(&cmd, path);
 
+               /* remove repo-local variables from the environment */
+               conn->env = local_repo_env;
+               conn->use_shell = 1;
                conn->in = conn->out = -1;
                if (protocol == PROTO_SSH) {
                        const char *ssh;
-                       int putty, tortoiseplink = 0;
+                       int putty = 0, tortoiseplink = 0;
                        char *ssh_host = hostandport;
                        const char *port = NULL;
+                       transport_check_allowed("ssh");
                        get_host_and_port(&ssh_host, &port);
 
                        if (!port)
@@ -746,13 +753,17 @@ struct child_process *git_connect(int fd[2], const char *url,
                        }
 
                        ssh = getenv("GIT_SSH_COMMAND");
-                       if (ssh) {
-                               conn->use_shell = 1;
-                               putty = 0;
-                       } else {
+                       if (!ssh) {
                                const char *base;
                                char *ssh_dup;
 
+                               /*
+                                * GIT_SSH is the no-shell version of
+                                * GIT_SSH_COMMAND (and must remain so for
+                                * historical compatibility).
+                                */
+                               conn->use_shell = 0;
+
                                ssh = getenv("GIT_SSH");
                                if (!ssh)
                                        ssh = "ssh";
@@ -762,8 +773,9 @@ struct child_process *git_connect(int fd[2], const char *url,
 
                                tortoiseplink = !strcasecmp(base, "tortoiseplink") ||
                                        !strcasecmp(base, "tortoiseplink.exe");
-                               putty = !strcasecmp(base, "plink") ||
-                                       !strcasecmp(base, "plink.exe") || tortoiseplink;
+                               putty = tortoiseplink ||
+                                       !strcasecmp(base, "plink") ||
+                                       !strcasecmp(base, "plink.exe");
 
                                free(ssh_dup);
                        }
@@ -778,9 +790,7 @@ struct child_process *git_connect(int fd[2], const char *url,
                        }
                        argv_array_push(&conn->args, ssh_host);
                } else {
-                       /* remove repo-local variables from the environment */
-                       conn->env = local_repo_env;
-                       conn->use_shell = 1;
+                       transport_check_allowed("file");
                }
                argv_array_push(&conn->args, cmd.buf);
 
index e8dc2e0e7d5d8fb37f818a05c3ef4c58f28850da..6b3a03f9b070e6451572db9b160b293044279fa3 100755 (executable)
@@ -69,7 +69,7 @@ as appropriate to mark resolution and make a commit.")"
 die_merge () {
     if [ $(git config --bool --get advice.resolveConflict || echo true) = "true" ]; then
        die "$(gettext "You have not concluded your merge (MERGE_HEAD exists).
-Please, commit your changes before you can merge.")"
+Please, commit your changes before merging.")"
     else
        die "$(gettext "You have not concluded your merge (MERGE_HEAD exists).")"
     fi
diff --git a/diff.c b/diff.c
index 08508f6a2017eb35a350268ea78a44cfc1d867e4..46260ed7a1d521cf95342caff83a825b34959bdc 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -1041,8 +1041,9 @@ static void diff_words_show(struct diff_words_data *diff_words)
        xpp.flags = 0;
        /* as only the hunk header will be parsed, we need a 0-context */
        xecfg.ctxlen = 0;
-       xdi_diff_outf(&minus, &plus, fn_out_diff_words_aux, diff_words,
-                     &xpp, &xecfg);
+       if (xdi_diff_outf(&minus, &plus, fn_out_diff_words_aux, diff_words,
+                         &xpp, &xecfg))
+               die("unable to generate word diff");
        free(minus.ptr);
        free(plus.ptr);
        if (diff_words->current_plus != diff_words->plus.text.ptr +
@@ -2449,8 +2450,9 @@ static void builtin_diff(const char *name_a,
                        xecfg.ctxlen = strtoul(v, NULL, 10);
                if (o->word_diff)
                        init_diff_words_data(&ecbdata, o, one, two);
-               xdi_diff_outf(&mf1, &mf2, fn_out_consume, &ecbdata,
-                             &xpp, &xecfg);
+               if (xdi_diff_outf(&mf1, &mf2, fn_out_consume, &ecbdata,
+                                 &xpp, &xecfg))
+                       die("unable to generate diff for %s", one->path);
                if (o->word_diff)
                        free_diff_words_data(&ecbdata);
                if (textconv_one)
@@ -2527,8 +2529,9 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
                xpp.flags = o->xdl_opts;
                xecfg.ctxlen = o->context;
                xecfg.interhunkctxlen = o->interhunkcontext;
-               xdi_diff_outf(&mf1, &mf2, diffstat_consume, diffstat,
-                             &xpp, &xecfg);
+               if (xdi_diff_outf(&mf1, &mf2, diffstat_consume, diffstat,
+                                 &xpp, &xecfg))
+                       die("unable to generate diffstat for %s", one->path);
        }
 
        diff_free_filespec_data(one);
@@ -2574,8 +2577,9 @@ static void builtin_checkdiff(const char *name_a, const char *name_b,
                memset(&xecfg, 0, sizeof(xecfg));
                xecfg.ctxlen = 1; /* at least one context line */
                xpp.flags = 0;
-               xdi_diff_outf(&mf1, &mf2, checkdiff_consume, &data,
-                             &xpp, &xecfg);
+               if (xdi_diff_outf(&mf1, &mf2, checkdiff_consume, &data,
+                                 &xpp, &xecfg))
+                       die("unable to generate checkdiff for %s", one->path);
 
                if (data.ws_rule & WS_BLANK_AT_EOF) {
                        struct emit_callback ecbdata;
@@ -4510,8 +4514,10 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1)
                xpp.flags = 0;
                xecfg.ctxlen = 3;
                xecfg.flags = 0;
-               xdi_diff_outf(&mf1, &mf2, patch_id_consume, &data,
-                             &xpp, &xecfg);
+               if (xdi_diff_outf(&mf1, &mf2, patch_id_consume, &data,
+                                 &xpp, &xecfg))
+                       return error("unable to generate patch-id diff for %s",
+                                    p->one->path);
        }
 
        git_SHA1_Final(sha1, &ctx);
index 185f86b2840d3337eac9fb2b17b260ca0c53fbab..7715c13ec4780a755ec2a6552c0aec9994691087 100644 (file)
@@ -62,8 +62,8 @@ static int diff_grep(mmfile_t *one, mmfile_t *two,
        ecbdata.hit = 0;
        xecfg.ctxlen = o->context;
        xecfg.interhunkctxlen = o->interhunkcontext;
-       xdi_diff_outf(one, two, diffgrep_consume, &ecbdata,
-                     &xpp, &xecfg);
+       if (xdi_diff_outf(one, two, diffgrep_consume, &ecbdata, &xpp, &xecfg))
+               return 0;
        return ecbdata.hit;
 }
 
diff --git a/dir.c b/dir.c
index 7b25634832716ade46686d118184c4d43d8c11e7..118ba59a27f51d1966c03faa8c36627a0a8d6246 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -2030,6 +2030,15 @@ int file_exists(const char *f)
        return lstat(f, &sb) == 0;
 }
 
+static int cmp_icase(char a, char b)
+{
+       if (a == b)
+               return 0;
+       if (ignore_case)
+               return toupper(a) - toupper(b);
+       return a - b;
+}
+
 /*
  * Given two normalized paths (a trailing slash is ok), if subdir is
  * outside dir, return -1.  Otherwise return the offset in subdir that
@@ -2041,7 +2050,7 @@ int dir_inside_of(const char *subdir, const char *dir)
 
        assert(dir && subdir && *dir && *subdir);
 
-       while (*dir && *subdir && *dir == *subdir) {
+       while (*dir && *subdir && !cmp_icase(*dir, *subdir)) {
                dir++;
                subdir++;
                offset++;
index f01637b1fdeb7f021b74171135ac0e7dba566542..d65c06eff36f09c982d66b11684d8f3ab3784393 100644 (file)
@@ -729,8 +729,8 @@ transform_todo_ids () {
                        # that do not have a SHA-1 at the beginning of $rest.
                        ;;
                *)
-                       sha1=$(git rev-parse --verify --quiet "$@" ${rest%% *}) &&
-                       rest="$sha1 ${rest#* }"
+                       sha1=$(git rev-parse --verify --quiet "$@" ${rest%%[     ]*}) &&
+                       rest="$sha1 ${rest#*[    ]}"
                        ;;
                esac
                printf '%s\n' "$command${rest:+ }$rest"
@@ -857,7 +857,8 @@ add_exec_commands () {
 # Check if the SHA-1 passed as an argument is a
 # correct one, if not then print $2 in "$todo".badsha
 # $1: the SHA-1 to test
-# $2: the line to display if incorrect SHA-1
+# $2: the line number of the input
+# $3: the input filename
 check_commit_sha () {
        badsha=0
        if test -z $1
@@ -873,9 +874,10 @@ check_commit_sha () {
 
        if test $badsha -ne 0
        then
+               line="$(sed -n -e "${2}p" "$3")"
                warn "Warning: the SHA-1 is missing or isn't" \
                        "a commit in the following line:"
-               warn " - $2"
+               warn " - $line"
                warn
        fi
 
@@ -886,37 +888,31 @@ check_commit_sha () {
 # from the todolist in stdin
 check_bad_cmd_and_sha () {
        retval=0
-       git stripspace --strip-comments |
-       (
-               while read -r line
-               do
-                       IFS=' '
-                       set -- $line
-                       command=$1
-                       sha1=$2
-
-                       case $command in
-                       ''|noop|x|"exec")
-                               # Doesn't expect a SHA-1
-                               ;;
-                       pick|p|drop|d|reword|r|edit|e|squash|s|fixup|f)
-                               if ! check_commit_sha $sha1 "$line"
-                               then
-                                       retval=1
-                               fi
-                               ;;
-                       *)
-                               warn "Warning: the command isn't recognized" \
-                                       "in the following line:"
-                               warn " - $line"
-                               warn
+       lineno=0
+       while read -r command rest
+       do
+               lineno=$(( $lineno + 1 ))
+               case $command in
+               "$comment_char"*|''|noop|x|exec)
+                       # Doesn't expect a SHA-1
+                       ;;
+               pick|p|drop|d|reword|r|edit|e|squash|s|fixup|f)
+                       if ! check_commit_sha "${rest%%[        ]*}" "$lineno" "$1"
+                       then
                                retval=1
-                               ;;
-                       esac
-               done
-
-               return $retval
-       )
+                       fi
+                       ;;
+               *)
+                       line="$(sed -n -e "${lineno}p" "$1")"
+                       warn "Warning: the command isn't recognized" \
+                               "in the following line:"
+                       warn " - $line"
+                       warn
+                       retval=1
+                       ;;
+               esac
+       done <"$1"
+       return $retval
 }
 
 # Print the list of the SHA-1 of the commits
@@ -1010,7 +1006,7 @@ check_todo_list () {
                ;;
        esac
 
-       if ! check_bad_cmd_and_sha <"$todo"
+       if ! check_bad_cmd_and_sha "$todo"
        then
                raise_error=t
        fi
index 25b1ddf2520800af4f78f1b7b72be2e271dfd8e2..82e35582cd8e741280229f377b4f61d7d985bc6a 100755 (executable)
@@ -22,6 +22,15 @@ require_work_tree
 wt_prefix=$(git rev-parse --show-prefix)
 cd_to_toplevel
 
+# Restrict ourselves to a vanilla subset of protocols; the URLs
+# we get are under control of a remote repository, and we do not
+# want them kicking off arbitrary git-remote-* programs.
+#
+# If the user has already specified a set of allowed protocols,
+# we assume they know what they're doing and use that instead.
+: ${GIT_ALLOW_PROTOCOL=file:git:http:https:ssh}
+export GIT_ALLOW_PROTOCOL
+
 command=
 branch=
 force=
diff --git a/http.c b/http.c
index 9dce38025c7b35f7f5ad19121c0529b442aec92d..0f924a8b48f3e30fd4a646ef48acb8d066988a53 100644 (file)
--- a/http.c
+++ b/http.c
@@ -9,6 +9,7 @@
 #include "version.h"
 #include "pkt-line.h"
 #include "gettext.h"
+#include "transport.h"
 
 int active_requests;
 int http_is_verbose;
@@ -356,6 +357,7 @@ static void set_curl_keepalive(CURL *c)
 static CURL *get_curl_handle(void)
 {
        CURL *result = curl_easy_init();
+       long allowed_protocols = 0;
 
        if (!result)
                die("curl_easy_init failed");
@@ -425,11 +427,27 @@ static CURL *get_curl_handle(void)
        }
 
        curl_easy_setopt(result, CURLOPT_FOLLOWLOCATION, 1);
+       curl_easy_setopt(result, CURLOPT_MAXREDIRS, 20);
 #if LIBCURL_VERSION_NUM >= 0x071301
        curl_easy_setopt(result, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL);
 #elif LIBCURL_VERSION_NUM >= 0x071101
        curl_easy_setopt(result, CURLOPT_POST301, 1);
 #endif
+#if LIBCURL_VERSION_NUM >= 0x071304
+       if (is_transport_allowed("http"))
+               allowed_protocols |= CURLPROTO_HTTP;
+       if (is_transport_allowed("https"))
+               allowed_protocols |= CURLPROTO_HTTPS;
+       if (is_transport_allowed("ftp"))
+               allowed_protocols |= CURLPROTO_FTP;
+       if (is_transport_allowed("ftps"))
+               allowed_protocols |= CURLPROTO_FTPS;
+       curl_easy_setopt(result, CURLOPT_REDIR_PROTOCOLS, allowed_protocols);
+#else
+       if (transport_restrict_protocols())
+               warning("protocol restrictions not applied to curl redirects because\n"
+                       "your curl version is too old (>= 7.19.4)");
+#endif
 
        if (getenv("GIT_CURL_VERBOSE"))
                curl_easy_setopt(result, CURLOPT_VERBOSE, 1);
index c12c69f05ab478cd35208eed4fdc6697977b86de..626b22cc31726c146347f44d73daa80b776ab74f 100644 (file)
@@ -325,7 +325,7 @@ static int collect_diff_cb(long start_a, long count_a,
        return 0;
 }
 
-static void collect_diff(mmfile_t *parent, mmfile_t *target, struct diff_ranges *out)
+static int collect_diff(mmfile_t *parent, mmfile_t *target, struct diff_ranges *out)
 {
        struct collect_diff_cbdata cbdata = {NULL};
        xpparam_t xpp;
@@ -340,7 +340,7 @@ static void collect_diff(mmfile_t *parent, mmfile_t *target, struct diff_ranges
        xecfg.hunk_func = collect_diff_cb;
        memset(&ecb, 0, sizeof(ecb));
        ecb.priv = &cbdata;
-       xdi_diff(parent, target, &xpp, &xecfg, &ecb);
+       return xdi_diff(parent, target, &xpp, &xecfg, &ecb);
 }
 
 /*
@@ -1030,7 +1030,8 @@ static int process_diff_filepair(struct rev_info *rev,
        }
 
        diff_ranges_init(&diff);
-       collect_diff(&file_parent, &file_target, &diff);
+       if (collect_diff(&file_parent, &file_target, &diff))
+               die("unable to generate diff for %s", pair->one->path);
 
        /* NEEDSWORK should apply some heuristics to prevent mismatches */
        free(rg->path);
index fc3c0495942e2a8d7c31a087429f894633c603d8..bf83290793059dc42d89db07a12e3bc3c14a48dc 100644 (file)
@@ -89,7 +89,10 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused,
        xmparam_t xmp;
        assert(opts);
 
-       if (buffer_is_binary(orig->ptr, orig->size) ||
+       if (orig->size > MAX_XDIFF_SIZE ||
+           src1->size > MAX_XDIFF_SIZE ||
+           src2->size > MAX_XDIFF_SIZE ||
+           buffer_is_binary(orig->ptr, orig->size) ||
            buffer_is_binary(src1->ptr, src1->size) ||
            buffer_is_binary(src2->ptr, src2->size)) {
                return ll_binary_merge(drv_unused, result,
diff --git a/pager.c b/pager.c
index 27d4c8a17aa17bb2cf31484227073e1a3204c17f..e425070528f4f9fbf0953c9056d1ea43686e176f 100644 (file)
--- a/pager.c
+++ b/pager.c
 static const char *pager_argv[] = { NULL, NULL };
 static struct child_process pager_process = CHILD_PROCESS_INIT;
 
-static void wait_for_pager(void)
+static void wait_for_pager(int in_signal)
 {
-       fflush(stdout);
-       fflush(stderr);
+       if (!in_signal) {
+               fflush(stdout);
+               fflush(stderr);
+       }
        /* signal EOF to pager */
        close(1);
        close(2);
-       finish_command(&pager_process);
+       if (in_signal)
+               finish_command_in_signal(&pager_process);
+       else
+               finish_command(&pager_process);
+}
+
+static void wait_for_pager_atexit(void)
+{
+       wait_for_pager(0);
 }
 
 static void wait_for_pager_signal(int signo)
 {
-       wait_for_pager();
+       wait_for_pager(1);
        sigchain_pop(signo);
        raise(signo);
 }
@@ -90,7 +100,7 @@ void setup_pager(void)
 
        /* this makes sure that the parent terminates after the pager */
        sigchain_push_common(wait_for_pager_signal);
-       atexit(wait_for_pager);
+       atexit(wait_for_pager_atexit);
 }
 
 int pager_in_use(void)
diff --git a/quote.c b/quote.c
index 7920e18e44834f1f86c218c172ae10227858ed66..fe884d24521f91a0f1f30b3cf5f08734bab7bd31 100644 (file)
--- a/quote.c
+++ b/quote.c
@@ -4,9 +4,15 @@
 
 int quote_path_fully = 1;
 
+static inline int need_bs_quote(char c)
+{
+       return (c == '\'' || c == '!');
+}
+
 /* Help to copy the thing properly quoted for the shell safety.
  * any single quote is replaced with '\'', any exclamation point
  * is replaced with '\!', and the whole thing is enclosed in a
+ * single quote pair.
  *
  * E.g.
  *  original     sq_quote     result
@@ -15,11 +21,6 @@ int quote_path_fully = 1;
  *  a'b      ==> a'\''b    ==> 'a'\''b'
  *  a!b      ==> a'\!'b    ==> 'a'\!'b'
  */
-static inline int need_bs_quote(char c)
-{
-       return (c == '\'' || c == '!');
-}
-
 void sq_quote_buf(struct strbuf *dst, const char *src)
 {
        char *to_free = NULL;
index 3277cf797ed41e5834b3b94fa8d2e9e9d5b4a317..e09275bd9e360ee7683ef5d3753ccfe753ee8dcc 100644 (file)
@@ -18,26 +18,27 @@ struct child_to_clean {
 static struct child_to_clean *children_to_clean;
 static int installed_child_cleanup_handler;
 
-static void cleanup_children(int sig)
+static void cleanup_children(int sig, int in_signal)
 {
        while (children_to_clean) {
                struct child_to_clean *p = children_to_clean;
                children_to_clean = p->next;
                kill(p->pid, sig);
-               free(p);
+               if (!in_signal)
+                       free(p);
        }
 }
 
 static void cleanup_children_on_signal(int sig)
 {
-       cleanup_children(sig);
+       cleanup_children(sig, 1);
        sigchain_pop(sig);
        raise(sig);
 }
 
 static void cleanup_children_on_exit(void)
 {
-       cleanup_children(SIGTERM);
+       cleanup_children(SIGTERM, 0);
 }
 
 static void mark_child_for_cleanup(pid_t pid)
@@ -220,7 +221,7 @@ static inline void set_cloexec(int fd)
                fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
 }
 
-static int wait_or_whine(pid_t pid, const char *argv0)
+static int wait_or_whine(pid_t pid, const char *argv0, int in_signal)
 {
        int status, code = -1;
        pid_t waiting;
@@ -228,6 +229,8 @@ static int wait_or_whine(pid_t pid, const char *argv0)
 
        while ((waiting = waitpid(pid, &status, 0)) < 0 && errno == EINTR)
                ;       /* nothing */
+       if (in_signal)
+               return 0;
 
        if (waiting < 0) {
                failed_errno = errno;
@@ -437,7 +440,7 @@ int start_command(struct child_process *cmd)
                 * At this point we know that fork() succeeded, but execvp()
                 * failed. Errors have been reported to our stderr.
                 */
-               wait_or_whine(cmd->pid, cmd->argv[0]);
+               wait_or_whine(cmd->pid, cmd->argv[0], 0);
                failed_errno = errno;
                cmd->pid = -1;
        }
@@ -536,12 +539,18 @@ int start_command(struct child_process *cmd)
 
 int finish_command(struct child_process *cmd)
 {
-       int ret = wait_or_whine(cmd->pid, cmd->argv[0]);
+       int ret = wait_or_whine(cmd->pid, cmd->argv[0], 0);
        argv_array_clear(&cmd->args);
        argv_array_clear(&cmd->env_array);
        return ret;
 }
 
+int finish_command_in_signal(struct child_process *cmd)
+{
+       return wait_or_whine(cmd->pid, cmd->argv[0], 1);
+}
+
+
 int run_command(struct child_process *cmd)
 {
        int code;
@@ -772,7 +781,7 @@ int start_async(struct async *async)
 int finish_async(struct async *async)
 {
 #ifdef NO_PTHREADS
-       return wait_or_whine(async->pid, "child process");
+       return wait_or_whine(async->pid, "child process", 0);
 #else
        void *ret = (void *)(intptr_t)(-1);
 
index 5b4425a3cbe1aea2bae40c4e060e45ee2d7a29a5..275d35c442ac575f8f3f40aeb915cd0d341c776f 100644 (file)
@@ -50,6 +50,7 @@ void child_process_init(struct child_process *);
 
 int start_command(struct child_process *);
 int finish_command(struct child_process *);
+int finish_command_in_signal(struct child_process *);
 int run_command(struct child_process *);
 
 /*
index f5c01758ca38b58fc10e30cfac81be5becb0316b..b1673b3e8f38d9961b8b2783e1f5c47a865638fb 100644 (file)
@@ -111,6 +111,10 @@ test_expect_success 'blame 2 authors + 2 merged-in authors' '
        check_count A 2 B 1 B1 2 B2 1
 '
 
+test_expect_success 'blame --first-parent blames merge for branch1' '
+       check_count --first-parent A 2 B 1 "A U Thor" 2 B2 1
+'
+
 test_expect_success 'blame ancestor' '
        check_count -h master A 2 B 2
 '
index 0b81a0047b8d9cd60266500907e95ddc5b87742c..7d15e6d44c83f6b37297ae01a2998825e313b9b2 100644 (file)
@@ -119,6 +119,10 @@ RewriteRule ^/smart-redir-perm/(.*)$ /smart/$1 [R=301]
 RewriteRule ^/smart-redir-temp/(.*)$ /smart/$1 [R=302]
 RewriteRule ^/smart-redir-auth/(.*)$ /auth/smart/$1 [R=301]
 RewriteRule ^/smart-redir-limited/(.*)/info/refs$ /smart/$1/info/refs [R=301]
+RewriteRule ^/ftp-redir/(.*)$ ftp://localhost:1000/$1 [R=302]
+
+RewriteRule ^/loop-redir/x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-(.*) /$1 [R=302]
+RewriteRule ^/loop-redir/(.*)$ /loop-redir/x-$1 [R=302]
 
 <IfDefine SSL>
 LoadModule ssl_module modules/mod_ssl.so
diff --git a/t/lib-proto-disable.sh b/t/lib-proto-disable.sh
new file mode 100644 (file)
index 0000000..b0917d9
--- /dev/null
@@ -0,0 +1,96 @@
+# Test routines for checking protocol disabling.
+
+# test cloning a particular protocol
+#   $1 - description of the protocol
+#   $2 - machine-readable name of the protocol
+#   $3 - the URL to try cloning
+test_proto () {
+       desc=$1
+       proto=$2
+       url=$3
+
+       test_expect_success "clone $1 (enabled)" '
+               rm -rf tmp.git &&
+               (
+                       GIT_ALLOW_PROTOCOL=$proto &&
+                       export GIT_ALLOW_PROTOCOL &&
+                       git clone --bare "$url" tmp.git
+               )
+       '
+
+       test_expect_success "fetch $1 (enabled)" '
+               (
+                       cd tmp.git &&
+                       GIT_ALLOW_PROTOCOL=$proto &&
+                       export GIT_ALLOW_PROTOCOL &&
+                       git fetch
+               )
+       '
+
+       test_expect_success "push $1 (enabled)" '
+               (
+                       cd tmp.git &&
+                       GIT_ALLOW_PROTOCOL=$proto &&
+                       export GIT_ALLOW_PROTOCOL &&
+                       git push origin HEAD:pushed
+               )
+       '
+
+       test_expect_success "push $1 (disabled)" '
+               (
+                       cd tmp.git &&
+                       GIT_ALLOW_PROTOCOL=none &&
+                       export GIT_ALLOW_PROTOCOL &&
+                       test_must_fail git push origin HEAD:pushed
+               )
+       '
+
+       test_expect_success "fetch $1 (disabled)" '
+               (
+                       cd tmp.git &&
+                       GIT_ALLOW_PROTOCOL=none &&
+                       export GIT_ALLOW_PROTOCOL &&
+                       test_must_fail git fetch
+               )
+       '
+
+       test_expect_success "clone $1 (disabled)" '
+               rm -rf tmp.git &&
+               (
+                       GIT_ALLOW_PROTOCOL=none &&
+                       export GIT_ALLOW_PROTOCOL &&
+                       test_must_fail git clone --bare "$url" tmp.git
+               )
+       '
+}
+
+# set up an ssh wrapper that will access $host/$repo in the
+# trash directory, and enable it for subsequent tests.
+setup_ssh_wrapper () {
+       test_expect_success 'setup ssh wrapper' '
+               write_script ssh-wrapper <<-\EOF &&
+               echo >&2 "ssh: $*"
+               host=$1; shift
+               cd "$TRASH_DIRECTORY/$host" &&
+               eval "$*"
+               EOF
+               GIT_SSH="$PWD/ssh-wrapper" &&
+               export GIT_SSH &&
+               export TRASH_DIRECTORY
+       '
+}
+
+# set up a wrapper that can be used with remote-ext to
+# access repositories in the "remote" directory of trash-dir,
+# like "ext::fake-remote %S repo.git"
+setup_ext_wrapper () {
+       test_expect_success 'setup ext wrapper' '
+               write_script fake-remote <<-\EOF &&
+               echo >&2 "fake-remote: $*"
+               cd "$TRASH_DIRECTORY/remote" &&
+               eval "$*"
+               EOF
+               PATH=$TRASH_DIRECTORY:$PATH &&
+               export TRASH_DIRECTORY
+       '
+}
index 15f7fc1b8015114883bc36d1e35dffd730721e52..924b19dab4122a36112bd908a6252e754ecc531a 100755 (executable)
@@ -1,5 +1,6 @@
 #!/usr/bin/perl
 
+use lib '../../perl/blib/lib';
 use strict;
 use warnings;
 use Git;
index 956673b8a14d39ef6bece7629b2407b0c10a071a..dc09797021a6a5fc8eed6da4412164673ab484a1 100755 (executable)
@@ -77,11 +77,31 @@ test_expect_success 'object with bad sha1' '
 test_expect_success 'branch pointing to non-commit' '
        git rev-parse HEAD^{tree} >.git/refs/heads/invalid &&
        test_when_finished "git update-ref -d refs/heads/invalid" &&
-       git fsck 2>out &&
+       test_must_fail git fsck 2>out &&
        cat out &&
        grep "not a commit" out
 '
 
+test_expect_success 'HEAD link pointing at a funny object' '
+       test_when_finished "mv .git/SAVED_HEAD .git/HEAD" &&
+       mv .git/HEAD .git/SAVED_HEAD &&
+       echo 0000000000000000000000000000000000000000 >.git/HEAD &&
+       # avoid corrupt/broken HEAD from interfering with repo discovery
+       test_must_fail env GIT_DIR=.git git fsck 2>out &&
+       cat out &&
+       grep "detached HEAD points" out
+'
+
+test_expect_success 'HEAD link pointing at a funny place' '
+       test_when_finished "mv .git/SAVED_HEAD .git/HEAD" &&
+       mv .git/HEAD .git/SAVED_HEAD &&
+       echo "ref: refs/funny/place" >.git/HEAD &&
+       # avoid corrupt/broken HEAD from interfering with repo discovery
+       test_must_fail env GIT_DIR=.git git fsck 2>out &&
+       cat out &&
+       grep "HEAD points to something strange" out
+'
+
 test_expect_success 'email without @ is okay' '
        git cat-file commit HEAD >basis &&
        sed "s/@/AT/" basis >okay &&
diff --git a/t/t2026-prune-linked-checkouts.sh b/t/t2026-prune-linked-checkouts.sh
deleted file mode 100755 (executable)
index a0f1e3b..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-#!/bin/sh
-
-test_description='prune $GIT_DIR/worktrees'
-
-. ./test-lib.sh
-
-test_expect_success initialize '
-       git commit --allow-empty -m init
-'
-
-test_expect_success 'worktree prune on normal repo' '
-       git worktree prune &&
-       test_must_fail git worktree prune abc
-'
-
-test_expect_success 'prune files inside $GIT_DIR/worktrees' '
-       mkdir .git/worktrees &&
-       : >.git/worktrees/abc &&
-       git worktree prune --verbose >actual &&
-       cat >expect <<EOF &&
-Removing worktrees/abc: not a valid directory
-EOF
-       test_i18ncmp expect actual &&
-       ! test -f .git/worktrees/abc &&
-       ! test -d .git/worktrees
-'
-
-test_expect_success 'prune directories without gitdir' '
-       mkdir -p .git/worktrees/def/abc &&
-       : >.git/worktrees/def/def &&
-       cat >expect <<EOF &&
-Removing worktrees/def: gitdir file does not exist
-EOF
-       git worktree prune --verbose >actual &&
-       test_i18ncmp expect actual &&
-       ! test -d .git/worktrees/def &&
-       ! test -d .git/worktrees
-'
-
-test_expect_success SANITY 'prune directories with unreadable gitdir' '
-       mkdir -p .git/worktrees/def/abc &&
-       : >.git/worktrees/def/def &&
-       : >.git/worktrees/def/gitdir &&
-       chmod u-r .git/worktrees/def/gitdir &&
-       git worktree prune --verbose >actual &&
-       test_i18ngrep "Removing worktrees/def: unable to read gitdir file" actual &&
-       ! test -d .git/worktrees/def &&
-       ! test -d .git/worktrees
-'
-
-test_expect_success 'prune directories with invalid gitdir' '
-       mkdir -p .git/worktrees/def/abc &&
-       : >.git/worktrees/def/def &&
-       : >.git/worktrees/def/gitdir &&
-       git worktree prune --verbose >actual &&
-       test_i18ngrep "Removing worktrees/def: invalid gitdir file" actual &&
-       ! test -d .git/worktrees/def &&
-       ! test -d .git/worktrees
-'
-
-test_expect_success 'prune directories with gitdir pointing to nowhere' '
-       mkdir -p .git/worktrees/def/abc &&
-       : >.git/worktrees/def/def &&
-       echo "$(pwd)"/nowhere >.git/worktrees/def/gitdir &&
-       git worktree prune --verbose >actual &&
-       test_i18ngrep "Removing worktrees/def: gitdir file points to non-existent location" actual &&
-       ! test -d .git/worktrees/def &&
-       ! test -d .git/worktrees
-'
-
-test_expect_success 'not prune locked checkout' '
-       test_when_finished rm -r .git/worktrees &&
-       mkdir -p .git/worktrees/ghi &&
-       : >.git/worktrees/ghi/locked &&
-       git worktree prune &&
-       test -d .git/worktrees/ghi
-'
-
-test_expect_success 'not prune recent checkouts' '
-       test_when_finished rm -r .git/worktrees &&
-       mkdir zz &&
-       mkdir -p .git/worktrees/jlm &&
-       echo "$(pwd)"/zz >.git/worktrees/jlm/gitdir &&
-       rmdir zz &&
-       git worktree prune --verbose --expire=2.days.ago &&
-       test -d .git/worktrees/jlm
-'
-
-test_expect_success 'not prune proper checkouts' '
-       test_when_finished rm -r .git/worktrees &&
-       git worktree add --detach "$PWD/nop" master &&
-       git worktree prune &&
-       test -d .git/worktrees/nop
-'
-
-test_done
diff --git a/t/t2026-worktree-prune.sh b/t/t2026-worktree-prune.sh
new file mode 100755 (executable)
index 0000000..a0f1e3b
--- /dev/null
@@ -0,0 +1,96 @@
+#!/bin/sh
+
+test_description='prune $GIT_DIR/worktrees'
+
+. ./test-lib.sh
+
+test_expect_success initialize '
+       git commit --allow-empty -m init
+'
+
+test_expect_success 'worktree prune on normal repo' '
+       git worktree prune &&
+       test_must_fail git worktree prune abc
+'
+
+test_expect_success 'prune files inside $GIT_DIR/worktrees' '
+       mkdir .git/worktrees &&
+       : >.git/worktrees/abc &&
+       git worktree prune --verbose >actual &&
+       cat >expect <<EOF &&
+Removing worktrees/abc: not a valid directory
+EOF
+       test_i18ncmp expect actual &&
+       ! test -f .git/worktrees/abc &&
+       ! test -d .git/worktrees
+'
+
+test_expect_success 'prune directories without gitdir' '
+       mkdir -p .git/worktrees/def/abc &&
+       : >.git/worktrees/def/def &&
+       cat >expect <<EOF &&
+Removing worktrees/def: gitdir file does not exist
+EOF
+       git worktree prune --verbose >actual &&
+       test_i18ncmp expect actual &&
+       ! test -d .git/worktrees/def &&
+       ! test -d .git/worktrees
+'
+
+test_expect_success SANITY 'prune directories with unreadable gitdir' '
+       mkdir -p .git/worktrees/def/abc &&
+       : >.git/worktrees/def/def &&
+       : >.git/worktrees/def/gitdir &&
+       chmod u-r .git/worktrees/def/gitdir &&
+       git worktree prune --verbose >actual &&
+       test_i18ngrep "Removing worktrees/def: unable to read gitdir file" actual &&
+       ! test -d .git/worktrees/def &&
+       ! test -d .git/worktrees
+'
+
+test_expect_success 'prune directories with invalid gitdir' '
+       mkdir -p .git/worktrees/def/abc &&
+       : >.git/worktrees/def/def &&
+       : >.git/worktrees/def/gitdir &&
+       git worktree prune --verbose >actual &&
+       test_i18ngrep "Removing worktrees/def: invalid gitdir file" actual &&
+       ! test -d .git/worktrees/def &&
+       ! test -d .git/worktrees
+'
+
+test_expect_success 'prune directories with gitdir pointing to nowhere' '
+       mkdir -p .git/worktrees/def/abc &&
+       : >.git/worktrees/def/def &&
+       echo "$(pwd)"/nowhere >.git/worktrees/def/gitdir &&
+       git worktree prune --verbose >actual &&
+       test_i18ngrep "Removing worktrees/def: gitdir file points to non-existent location" actual &&
+       ! test -d .git/worktrees/def &&
+       ! test -d .git/worktrees
+'
+
+test_expect_success 'not prune locked checkout' '
+       test_when_finished rm -r .git/worktrees &&
+       mkdir -p .git/worktrees/ghi &&
+       : >.git/worktrees/ghi/locked &&
+       git worktree prune &&
+       test -d .git/worktrees/ghi
+'
+
+test_expect_success 'not prune recent checkouts' '
+       test_when_finished rm -r .git/worktrees &&
+       mkdir zz &&
+       mkdir -p .git/worktrees/jlm &&
+       echo "$(pwd)"/zz >.git/worktrees/jlm/gitdir &&
+       rmdir zz &&
+       git worktree prune --verbose --expire=2.days.ago &&
+       test -d .git/worktrees/jlm
+'
+
+test_expect_success 'not prune proper checkouts' '
+       test_when_finished rm -r .git/worktrees &&
+       git worktree add --detach "$PWD/nop" master &&
+       git worktree prune &&
+       test -d .git/worktrees/nop
+'
+
+test_done
index f51d0f3cadcb4f97f4cf9f2d79aad9ed401781d8..16efe7af03d210cb349337e978c6105cb22d80e8 100755 (executable)
@@ -106,6 +106,19 @@ EOF
        test_i18ncmp expect actual
 '
 
+test_expect_success 'git branch shows detached HEAD properly after checkout --detach' '
+       git checkout master &&
+       cat >expect <<EOF &&
+* (HEAD detached at $(git rev-parse --short HEAD^0))
+  branch-one
+  branch-two
+  master
+EOF
+       git checkout --detach &&
+       git branch >actual &&
+       test_i18ncmp expect actual
+'
+
 test_expect_success 'git branch shows detached HEAD properly after moving' '
        cat >expect <<EOF &&
 * (HEAD detached from $(git rev-parse --short HEAD))
index 8cffd35fb03d7ca5abbd1a229c6c8533f8c5e917..cd70274ea51ac5c5ba6669495b944da5b7b97431 100755 (executable)
@@ -1122,6 +1122,12 @@ test_expect_success 'git notes copy diagnoses too many or too few parameters' '
        test_must_fail git notes copy one two three
 '
 
+test_expect_success 'git notes get-ref expands refs/heads/master to refs/notes/refs/heads/master' '
+       test_unconfig core.notesRef &&
+       sane_unset GIT_NOTES_REF &&
+       test "$(git notes --ref=refs/heads/master get-ref)" = "refs/notes/refs/heads/master"
+'
+
 test_expect_success 'git notes get-ref (no overrides)' '
        test_unconfig core.notesRef &&
        sane_unset GIT_NOTES_REF &&
index d26e3f57dcbc18585c360ee78a725708f5a69207..3de0b1dcfdc9c5948c10e5e8c107a3820df9f357 100755 (executable)
@@ -1227,6 +1227,21 @@ test_expect_success 'static check of bad command' '
        test C = $(git cat-file commit HEAD^ | sed -ne \$p)
 '
 
+test_expect_success 'tabs and spaces are accepted in the todolist' '
+       rebase_setup_and_clean indented-comment &&
+       write_script add-indent.sh <<-\EOF &&
+       (
+               # Turn single spaces into space/tab mix
+               sed "1s/ /      /g; 2s/ /  /g; 3s/ /    /g" "$1"
+               printf "\n\t# comment\n #more\n\t # comment\n"
+       ) >$1.new
+       mv "$1.new" "$1"
+       EOF
+       test_set_editor "$(pwd)/add-indent.sh" &&
+       git rebase -i HEAD^^^ &&
+       test E = $(git cat-file commit HEAD | sed -ne \$p)
+'
+
 cat >expect <<EOF
 Warning: the SHA-1 is missing or isn't a commit in the following line:
  - edit XXXXXXX False commit
diff --git a/t/t5507-remote-environment.sh b/t/t5507-remote-environment.sh
new file mode 100755 (executable)
index 0000000..e614929
--- /dev/null
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+test_description='check environment showed to remote side of transports'
+. ./test-lib.sh
+
+test_expect_success 'set up "remote" push situation' '
+       test_commit one &&
+       git config push.default current &&
+       git init remote
+'
+
+test_expect_success 'set up fake ssh' '
+       GIT_SSH_COMMAND="f() {
+               cd \"\$TRASH_DIRECTORY\" &&
+               eval \"\$2\"
+       }; f" &&
+       export GIT_SSH_COMMAND &&
+       export TRASH_DIRECTORY
+'
+
+# due to receive.denyCurrentBranch=true
+test_expect_success 'confirm default push fails' '
+       test_must_fail git push remote
+'
+
+test_expect_success 'config does not travel over same-machine push' '
+       test_must_fail git -c receive.denyCurrentBranch=false push remote
+'
+
+test_expect_success 'config does not travel over ssh push' '
+       test_must_fail git -c receive.denyCurrentBranch=false push host:remote
+'
+
+test_done
index aa73eeaef82adff56083fdc2d5d35d599b73edee..9fafcf194589218e28b894a7bd9e83c9a1893fbf 100755 (executable)
@@ -44,10 +44,6 @@ POST() {
        test_cmp exp act
 }
 
-log_div() {
-       return 0
-}
-
 . "$TEST_DIRECTORY"/t556x_common
 
 expect_aliased() {
index 19afe966986cdc72cf8fc23f113bd77a8128f382..90e0d6f0fe935970c0941bfef2af39bb15d2f959 100755 (executable)
@@ -29,15 +29,9 @@ POST() {
        test_cmp exp act
 }
 
-log_div() {
-       echo >>"$HTTPD_ROOT_PATH"/access.log
-       echo "###  $1" >>"$HTTPD_ROOT_PATH"/access.log
-       echo "###" >>"$HTTPD_ROOT_PATH"/access.log
-}
-
 . "$TEST_DIRECTORY"/t556x_common
 
-cat >exp <<EOF
+grep '^[^#]' >exp <<EOF
 
 ###  refs/heads/master
 ###
index 82926cfdb7b7c6a86ab7d73efdfa327a6be28c83..359fcfe32b66a2cd597778b58a45a937fa7656fa 100755 (executable)
@@ -52,21 +52,17 @@ get_static_files() {
 SMART=smart
 GIT_HTTP_EXPORT_ALL=1 && export GIT_HTTP_EXPORT_ALL
 test_expect_success 'direct refs/heads/master not found' '
-       log_div "refs/heads/master" &&
        GET refs/heads/master "404 Not Found"
 '
 test_expect_success 'static file is ok' '
-       log_div "getanyfile default" &&
        get_static_files "200 OK"
 '
 SMART=smart_noexport
 unset GIT_HTTP_EXPORT_ALL
 test_expect_success 'no export by default' '
-       log_div "no git-daemon-export-ok" &&
        get_static_files "404 Not Found"
 '
 test_expect_success 'export if git-daemon-export-ok' '
-       log_div "git-daemon-export-ok" &&
         (cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
         touch git-daemon-export-ok
        ) &&
@@ -75,47 +71,39 @@ test_expect_success 'export if git-daemon-export-ok' '
 SMART=smart
 GIT_HTTP_EXPORT_ALL=1 && export GIT_HTTP_EXPORT_ALL
 test_expect_success 'static file if http.getanyfile true is ok' '
-       log_div "getanyfile true" &&
        config http.getanyfile true &&
        get_static_files "200 OK"
 '
 test_expect_success 'static file if http.getanyfile false fails' '
-       log_div "getanyfile false" &&
        config http.getanyfile false &&
        get_static_files "403 Forbidden"
 '
 
 test_expect_success 'http.uploadpack default enabled' '
-       log_div "uploadpack default" &&
        GET info/refs?service=git-upload-pack "200 OK"  &&
        POST git-upload-pack 0000 "200 OK"
 '
 test_expect_success 'http.uploadpack true' '
-       log_div "uploadpack true" &&
        config http.uploadpack true &&
        GET info/refs?service=git-upload-pack "200 OK" &&
        POST git-upload-pack 0000 "200 OK"
 '
 test_expect_success 'http.uploadpack false' '
-       log_div "uploadpack false" &&
        config http.uploadpack false &&
        GET info/refs?service=git-upload-pack "403 Forbidden" &&
        POST git-upload-pack 0000 "403 Forbidden"
 '
 
 test_expect_success 'http.receivepack default disabled' '
-       log_div "receivepack default" &&
        GET info/refs?service=git-receive-pack "403 Forbidden"  &&
        POST git-receive-pack 0000 "403 Forbidden"
 '
 test_expect_success 'http.receivepack true' '
-       log_div "receivepack true" &&
        config http.receivepack true &&
        GET info/refs?service=git-receive-pack "200 OK" &&
        POST git-receive-pack 0000 "200 OK"
 '
 test_expect_success 'http.receivepack false' '
-       log_div "receivepack false" &&
        config http.receivepack false &&
        GET info/refs?service=git-receive-pack "403 Forbidden" &&
        POST git-receive-pack 0000 "403 Forbidden"
diff --git a/t/t5810-proto-disable-local.sh b/t/t5810-proto-disable-local.sh
new file mode 100755 (executable)
index 0000000..563592d
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+test_description='test disabling of local paths in clone/fetch'
+. ./test-lib.sh
+. "$TEST_DIRECTORY/lib-proto-disable.sh"
+
+test_expect_success 'setup repository to clone' '
+       test_commit one
+'
+
+test_proto "file://" file "file://$PWD"
+test_proto "path" file .
+
+test_done
diff --git a/t/t5811-proto-disable-git.sh b/t/t5811-proto-disable-git.sh
new file mode 100755 (executable)
index 0000000..8ac6b2a
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+test_description='test disabling of git-over-tcp in clone/fetch'
+. ./test-lib.sh
+. "$TEST_DIRECTORY/lib-proto-disable.sh"
+. "$TEST_DIRECTORY/lib-git-daemon.sh"
+start_git_daemon
+
+test_expect_success 'create git-accessible repo' '
+       bare="$GIT_DAEMON_DOCUMENT_ROOT_PATH/repo.git" &&
+       test_commit one &&
+       git --bare init "$bare" &&
+       git push "$bare" HEAD &&
+       >"$bare/git-daemon-export-ok" &&
+       git -C "$bare" config daemon.receivepack true
+'
+
+test_proto "git://" git "$GIT_DAEMON_URL/repo.git"
+
+test_done
diff --git a/t/t5812-proto-disable-http.sh b/t/t5812-proto-disable-http.sh
new file mode 100755 (executable)
index 0000000..0d105d5
--- /dev/null
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+test_description='test disabling of git-over-http in clone/fetch'
+. ./test-lib.sh
+. "$TEST_DIRECTORY/lib-proto-disable.sh"
+. "$TEST_DIRECTORY/lib-httpd.sh"
+start_httpd
+
+test_expect_success 'create git-accessible repo' '
+       bare="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+       test_commit one &&
+       git --bare init "$bare" &&
+       git push "$bare" HEAD &&
+       git -C "$bare" config http.receivepack true
+'
+
+test_proto "smart http" http "$HTTPD_URL/smart/repo.git"
+
+test_expect_success 'curl redirects respect whitelist' '
+       test_must_fail env GIT_ALLOW_PROTOCOL=http:https \
+               git clone "$HTTPD_URL/ftp-redir/repo.git" 2>stderr &&
+       {
+               test_i18ngrep "ftp.*disabled" stderr ||
+               test_i18ngrep "your curl version is too old"
+       }
+'
+
+test_expect_success 'curl limits redirects' '
+       test_must_fail git clone "$HTTPD_URL/loop-redir/smart/repo.git"
+'
+
+stop_httpd
+test_done
diff --git a/t/t5813-proto-disable-ssh.sh b/t/t5813-proto-disable-ssh.sh
new file mode 100755 (executable)
index 0000000..ad877d7
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+test_description='test disabling of git-over-ssh in clone/fetch'
+. ./test-lib.sh
+. "$TEST_DIRECTORY/lib-proto-disable.sh"
+
+setup_ssh_wrapper
+
+test_expect_success 'setup repository to clone' '
+       test_commit one &&
+       mkdir remote &&
+       git init --bare remote/repo.git &&
+       git push remote/repo.git HEAD
+'
+
+test_proto "host:path" ssh "remote:repo.git"
+test_proto "ssh://" ssh "ssh://remote/$PWD/remote/repo.git"
+test_proto "git+ssh://" ssh "git+ssh://remote/$PWD/remote/repo.git"
+
+test_done
diff --git a/t/t5814-proto-disable-ext.sh b/t/t5814-proto-disable-ext.sh
new file mode 100755 (executable)
index 0000000..9d6f7df
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+test_description='test disabling of remote-helper paths in clone/fetch'
+. ./test-lib.sh
+. "$TEST_DIRECTORY/lib-proto-disable.sh"
+
+setup_ext_wrapper
+
+test_expect_success 'setup repository to clone' '
+       test_commit one &&
+       mkdir remote &&
+       git init --bare remote/repo.git &&
+       git push remote/repo.git HEAD
+'
+
+test_proto "remote-helper" ext "ext::fake-remote %S repo.git"
+
+test_done
diff --git a/t/t5815-submodule-protos.sh b/t/t5815-submodule-protos.sh
new file mode 100755 (executable)
index 0000000..06f55a1
--- /dev/null
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+test_description='test protocol whitelisting with submodules'
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-proto-disable.sh
+
+setup_ext_wrapper
+setup_ssh_wrapper
+
+test_expect_success 'setup repository with submodules' '
+       mkdir remote &&
+       git init remote/repo.git &&
+       (cd remote/repo.git && test_commit one) &&
+       # submodule-add should probably trust what we feed it on the cmdline,
+       # but its implementation is overly conservative.
+       GIT_ALLOW_PROTOCOL=ssh git submodule add remote:repo.git ssh-module &&
+       GIT_ALLOW_PROTOCOL=ext git submodule add "ext::fake-remote %S repo.git" ext-module &&
+       git commit -m "add submodules"
+'
+
+test_expect_success 'clone with recurse-submodules fails' '
+       test_must_fail git clone --recurse-submodules . dst
+'
+
+test_expect_success 'setup individual updates' '
+       rm -rf dst &&
+       git clone . dst &&
+       git -C dst submodule init
+'
+
+test_expect_success 'update of ssh allowed' '
+       git -C dst submodule update ssh-module
+'
+
+test_expect_success 'update of ext not allowed' '
+       test_must_fail git -C dst submodule update ext-module
+'
+
+test_expect_success 'user can override whitelist' '
+       GIT_ALLOW_PROTOCOL=ext git -C dst submodule update ext-module
+'
+
+test_done
index 99f1ace1f2b56c359eba6736d1f0ab0fb49ba980..63d54271b09d34dc21076205e6cecf88a56ab422 100644 (file)
@@ -1043,6 +1043,8 @@ int transport_helper_init(struct transport *transport, const char *name)
        struct helper_data *data = xcalloc(1, sizeof(*data));
        data->name = name;
 
+       transport_check_allowed(name);
+
        if (getenv("GIT_TRANSPORT_HELPER_DEBUG"))
                debug = 1;
 
index 2d51348f3f3a5be03b2d00ec6530ac4cabfbf7c6..863eb524f9087302be6b99c89f071195dd1258b8 100644 (file)
@@ -915,6 +915,42 @@ static int external_specification_len(const char *url)
        return strchr(url, ':') - url;
 }
 
+static const struct string_list *protocol_whitelist(void)
+{
+       static int enabled = -1;
+       static struct string_list allowed = STRING_LIST_INIT_DUP;
+
+       if (enabled < 0) {
+               const char *v = getenv("GIT_ALLOW_PROTOCOL");
+               if (v) {
+                       string_list_split(&allowed, v, ':', -1);
+                       string_list_sort(&allowed);
+                       enabled = 1;
+               } else {
+                       enabled = 0;
+               }
+       }
+
+       return enabled ? &allowed : NULL;
+}
+
+int is_transport_allowed(const char *type)
+{
+       const struct string_list *allowed = protocol_whitelist();
+       return !allowed || string_list_has_string(allowed, type);
+}
+
+void transport_check_allowed(const char *type)
+{
+       if (!is_transport_allowed(type))
+               die("transport '%s' not allowed", type);
+}
+
+int transport_restrict_protocols(void)
+{
+       return !!protocol_whitelist();
+}
+
 struct transport *transport_get(struct remote *remote, const char *url)
 {
        const char *helper;
@@ -946,12 +982,14 @@ struct transport *transport_get(struct remote *remote, const char *url)
        if (helper) {
                transport_helper_init(ret, helper);
        } else if (starts_with(url, "rsync:")) {
+               transport_check_allowed("rsync");
                ret->get_refs_list = get_refs_via_rsync;
                ret->fetch = fetch_objs_via_rsync;
                ret->push = rsync_transport_push;
                ret->smart_options = NULL;
        } else if (url_is_local_not_ssh(url) && is_file(url) && is_bundle(url, 1)) {
                struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
+               transport_check_allowed("file");
                ret->data = data;
                ret->get_refs_list = get_refs_from_bundle;
                ret->fetch = fetch_refs_from_bundle;
@@ -963,7 +1001,10 @@ struct transport *transport_get(struct remote *remote, const char *url)
                || starts_with(url, "ssh://")
                || starts_with(url, "git+ssh://")
                || starts_with(url, "ssh+git://")) {
-               /* These are builtin smart transports. */
+               /*
+                * These are builtin smart transports; "allowed" transports
+                * will be checked individually in git_connect.
+                */
                struct git_transport_data *data = xcalloc(1, sizeof(*data));
                ret->data = data;
                ret->set_option = NULL;
index d682b77b9e3be70954f3552813f66718d7262151..4336dd33eb301306ff2a57c4c2c4f8c45d61fc50 100644 (file)
@@ -133,6 +133,24 @@ struct transport {
 /* Returns a transport suitable for the url */
 struct transport *transport_get(struct remote *, const char *);
 
+/*
+ * Check whether a transport is allowed by the environment. Type should
+ * generally be the URL scheme, as described in Documentation/git.txt
+ */
+int is_transport_allowed(const char *type);
+
+/*
+ * Check whether a transport is allowed by the environment,
+ * and die otherwise.
+ */
+void transport_check_allowed(const char *type);
+
+/*
+ * Returns true if the user has attempted to turn on protocol
+ * restrictions at all.
+ */
+int transport_restrict_protocols(void);
+
 /* Transport options which apply to git:// and scp-style URLs */
 
 /* The program to use on the remote side to send a pack */
index c327fe8128fdb2e380db15f526056a22862ac33f..3e3b8c098924d655bccb395e95cee832abb1d39f 100644 (file)
@@ -1319,6 +1319,12 @@ static int grab_1st_switch(unsigned char *osha1, unsigned char *nsha1,
        hashcpy(cb->nsha1, nsha1);
        for (end = target; *end && *end != '\n'; end++)
                ;
+       if (!memcmp(target, "HEAD", end - target)) {
+               /* HEAD is relative. Resolve it to the right reflog entry. */
+               strbuf_addstr(&cb->buf,
+                             find_unique_abbrev(nsha1, DEFAULT_ABBREV));
+               return 1;
+       }
        strbuf_add(&cb->buf, target, end - target);
        return 1;
 }
index ecfa05f616f4b72d65bcb129c1ee2141cf3d1c47..cb67c1c42b35e412dccf9a13ad18dde727ab8ce6 100644 (file)
@@ -131,6 +131,9 @@ int xdi_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, xdemitconf_t co
        mmfile_t a = *mf1;
        mmfile_t b = *mf2;
 
+       if (mf1->size > MAX_XDIFF_SIZE || mf2->size > MAX_XDIFF_SIZE)
+               return -1;
+
        trim_common_tail(&a, &b, xecfg->ctxlen);
 
        return xdl_diff(&a, &b, xpp, xecfg, xecb);
index eff7762ee1a1bb0ea648c60a07389e22e9a1ac07..fbb5a1c3949b6ef6ba0dfb758723a48f3b402190 100644 (file)
@@ -3,6 +3,13 @@
 
 #include "xdiff/xdiff.h"
 
+/*
+ * xdiff isn't equipped to handle content over a gigabyte;
+ * we make the cutoff 1GB - 1MB to give some breathing
+ * room for constant-sized additions (e.g., merge markers)
+ */
+#define MAX_XDIFF_SIZE (1024UL * 1024 * 1023)
+
 typedef void (*xdiff_emit_consume_fn)(void *, char *, unsigned long);
 
 int xdi_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, xdemitconf_t const *xecfg, xdemitcb_t *ecb);