Merge branch 'maint'
authorJeff King <peff@peff.net>
Tue, 1 Dec 2015 22:32:38 +0000 (17:32 -0500)
committerJeff King <peff@peff.net>
Tue, 1 Dec 2015 22:32:38 +0000 (17:32 -0500)
* maint:
http: treat config options sslCAPath and sslCAInfo as paths
Documentation/diff: give --word-diff-regex=. example
filter-branch: deal with object name vs. pathname ambiguity in tree-filter
check-ignore: correct documentation about output
git-p4: clean up after p4 submit failure
git-p4: work with a detached head
git-p4: add option to system() to return subshell status
git-p4: add failing test for submit from detached head
remote-http(s): support SOCKS proxies
t5813: avoid creating urls that break on cygwin
Escape Git's exec path in contrib/rerere-train.sh script
allow hooks to ignore their standard input stream
rebase-i-exec: Allow space in SHELL_PATH
Documentation: make environment variable formatting more consistent

15 files changed:
Documentation/diff-options.txt
Documentation/git-check-ignore.txt
Documentation/git.txt
builtin/commit.c
contrib/rerere-train.sh
git-filter-branch.sh
git-p4.py
git-rebase--interactive.sh
http.c
t/t5571-pre-push-hook.sh
t/t5813-proto-disable-ssh.sh
t/t7003-filter-branch.sh
t/t9800-git-p4-basic.sh
t/t9807-git-p4-submit.sh
transport.c
index d56ca90998a740dbe4cc5c242326023b4cc769b3..306b7e360409255a7aafaa3860d6d6c0412fb870 100644 (file)
@@ -267,6 +267,9 @@ expression to make sure that it matches all non-whitespace characters.
 A match that contains a newline is silently truncated(!) at the
 newline.
 +
+For example, `--word-diff-regex=.` will treat each character as a word
+and, correspondingly, show differences character by character.
++
 The regex can also be set via a diff driver or configuration option, see
 linkgit:gitattributes[1] or linkgit:git-config[1].  Giving it explicitly
 overrides any diff driver or configuration setting.  Diff drivers
index 59531abba481c4788357fc07342fcc7672727fbf..e94367a5ed8e8b94bca7036ff7616bc3cfa9ca97 100644 (file)
@@ -16,10 +16,9 @@ DESCRIPTION
 -----------
 
 For each pathname given via the command-line or from a file via
-`--stdin`, show the pattern from .gitignore (or other input files to
-the exclude mechanism) that decides if the pathname is excluded or
-included.  Later patterns within a file take precedence over earlier
-ones.
+`--stdin`, check whether the file is excluded by .gitignore (or other
+input files to the exclude mechanism) and output the path if it is
+excluded.
 
 By default, tracked files are not shown at all since they are not
 subject to exclude rules; but see `--no-index'.
@@ -32,7 +31,8 @@ OPTIONS
 
 -v, --verbose::
        Also output details about the matching pattern (if any)
-       for each given pathname.
+       for each given pathname. For precedence rules within and
+       between exclude sources, see linkgit:gitignore[5].
 
 --stdin::
        Read pathnames from the standard input, one per line,
index c2e2a94e754fb0f831f1604634901d4c155784af..900272b1c35ad304e86eefc848fae879799be511 100644 (file)
@@ -1056,7 +1056,7 @@ of clones and fetches.
        cloning of shallow repositories.
        See 'GIT_TRACE' for available trace output options.
 
-GIT_LITERAL_PATHSPECS::
+'GIT_LITERAL_PATHSPECS'::
        Setting this variable to `1` will cause Git to treat all
        pathspecs literally, rather than as glob patterns. For example,
        running `GIT_LITERAL_PATHSPECS=1 git log -- '*.c'` will search
@@ -1065,15 +1065,15 @@ GIT_LITERAL_PATHSPECS::
        literal paths to Git (e.g., paths previously given to you by
        `git ls-tree`, `--raw` diff output, etc).
 
-GIT_GLOB_PATHSPECS::
+'GIT_GLOB_PATHSPECS'::
        Setting this variable to `1` will cause Git to treat all
        pathspecs as glob patterns (aka "glob" magic).
 
-GIT_NOGLOB_PATHSPECS::
+'GIT_NOGLOB_PATHSPECS'::
        Setting this variable to `1` will cause Git to treat all
        pathspecs as literal (aka "literal" magic).
 
-GIT_ICASE_PATHSPECS::
+'GIT_ICASE_PATHSPECS'::
        Setting this variable to `1` will cause Git to treat all
        pathspecs as case-insensitive.
 
@@ -1087,7 +1087,7 @@ GIT_ICASE_PATHSPECS::
        variable when it is invoked as the top level command by the
        end user, to be recorded in the body of the reflog.
 
-`GIT_REF_PARANOIA`::
+'GIT_REF_PARANOIA'::
        If set to `1`, include broken or badly named refs when iterating
        over lists of refs. In a normal, non-corrupted repository, this
        does nothing. However, enabling it may help git to detect and
@@ -1098,7 +1098,7 @@ GIT_ICASE_PATHSPECS::
        an operation has touched every ref (e.g., because you are
        cloning a repository to make a backup).
 
-`GIT_ALLOW_PROTOCOL`::
+'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
index dca09e2c3bd8a839b27e279c427ebba71e88966e..f2a8b78c7a7c5f52c46e03e644cf50413b643d3e 100644 (file)
@@ -32,6 +32,7 @@
 #include "sequencer.h"
 #include "notes-utils.h"
 #include "mailmap.h"
+#include "sigchain.h"
 
 static const char * const builtin_commit_usage[] = {
        N_("git commit [<options>] [--] <pathspec>..."),
@@ -1537,8 +1538,10 @@ static int run_rewrite_hook(const unsigned char *oldsha1,
                return code;
        n = snprintf(buf, sizeof(buf), "%s %s\n",
                     sha1_to_hex(oldsha1), sha1_to_hex(newsha1));
+       sigchain_push(SIGPIPE, SIG_IGN);
        write_in_full(proc.in, buf, n);
        close(proc.in);
+       sigchain_pop(SIGPIPE);
        return finish_command(&proc);
 }
 
index 36b6feebe00060e4d522c506f12d2848673dbee6..52ad9e41fb7aba37abf71dad2bf5a0015b01dca7 100755 (executable)
@@ -7,7 +7,7 @@ USAGE="$me rev-list-args"
 
 SUBDIRECTORY_OK=Yes
 OPTIONS_SPEC=
-. $(git --exec-path)/git-sh-setup
+. "$(git --exec-path)/git-sh-setup"
 require_work_tree
 cd_to_toplevel
 
index 27c9c54fbd24ef3a2995fd90b04911e5a1d8aed9..cefd1452c66663fee9b00d1406b1d4f14e7964ac 100755 (executable)
@@ -349,7 +349,7 @@ while read commit parents; do
                        die "tree filter failed: $filter_tree"
 
                (
-                       git diff-index -r --name-only --ignore-submodules $commit &&
+                       git diff-index -r --name-only --ignore-submodules $commit -- &&
                        git ls-files --others
                ) > "$tempdir"/tree-state || exit
                git update-index --add --replace --remove --stdin \
index 212ef2be9670bc2fe5573eee856471113eb96889..13f124061f43a4bc212066f865aaaac39feb5385 100755 (executable)
--- a/git-p4.py
+++ b/git-p4.py
@@ -203,14 +203,16 @@ def p4_has_move_command():
     # assume it failed because @... was invalid changelist
     return True
 
-def system(cmd):
+def system(cmd, ignore_error=False):
     expand = isinstance(cmd,basestring)
     if verbose:
         sys.stderr.write("executing %s\n" % str(cmd))
     retcode = subprocess.call(cmd, shell=expand)
-    if retcode:
+    if retcode and not ignore_error:
         raise CalledProcessError(retcode, cmd)
 
+    return retcode
+
 def p4_system(cmd):
     """Specifically invoke p4 as the system command. """
     real_cmd = p4_build_cmd(cmd)
@@ -553,7 +555,12 @@ def p4Where(depotPath):
     return clientPath
 
 def currentGitBranch():
-    return read_pipe("git name-rev HEAD").split(" ")[1].strip()
+    retcode = system(["git", "symbolic-ref", "-q", "HEAD"], ignore_error=True)
+    if retcode != 0:
+        # on a detached head
+        return None
+    else:
+        return read_pipe(["git", "name-rev", "HEAD"]).split(" ")[1].strip()
 
 def isValidGitDir(path):
     if (os.path.exists(path + "/HEAD")
@@ -1741,44 +1748,47 @@ def applyCommit(self, id):
         #
         # Let the user edit the change description, then submit it.
         #
-        if self.edit_template(fileName):
-            # read the edited message and submit
-            ret = True
-            tmpFile = open(fileName, "rb")
-            message = tmpFile.read()
-            tmpFile.close()
-            if self.isWindows:
-                message = message.replace("\r\n", "\n")
-            submitTemplate = message[:message.index(separatorLine)]
-            p4_write_pipe(['submit', '-i'], submitTemplate)
-
-            if self.preserveUser:
-                if p4User:
-                    # Get last changelist number. Cannot easily get it from
-                    # the submit command output as the output is
-                    # unmarshalled.
-                    changelist = self.lastP4Changelist()
-                    self.modifyChangelistUser(changelist, p4User)
-
-            # The rename/copy happened by applying a patch that created a
-            # new file.  This leaves it writable, which confuses p4.
-            for f in pureRenameCopy:
-                p4_sync(f, "-f")
+        submitted = False
 
-        else:
+        try:
+            if self.edit_template(fileName):
+                # read the edited message and submit
+                tmpFile = open(fileName, "rb")
+                message = tmpFile.read()
+                tmpFile.close()
+                if self.isWindows:
+                    message = message.replace("\r\n", "\n")
+                submitTemplate = message[:message.index(separatorLine)]
+                p4_write_pipe(['submit', '-i'], submitTemplate)
+
+                if self.preserveUser:
+                    if p4User:
+                        # Get last changelist number. Cannot easily get it from
+                        # the submit command output as the output is
+                        # unmarshalled.
+                        changelist = self.lastP4Changelist()
+                        self.modifyChangelistUser(changelist, p4User)
+
+                # The rename/copy happened by applying a patch that created a
+                # new file.  This leaves it writable, which confuses p4.
+                for f in pureRenameCopy:
+                    p4_sync(f, "-f")
+                submitted = True
+
+        finally:
             # skip this patch
-            ret = False
-            print "Submission cancelled, undoing p4 changes."
-            for f in editedFiles:
-                p4_revert(f)
-            for f in filesToAdd:
-                p4_revert(f)
-                os.remove(f)
-            for f in filesToDelete:
-                p4_revert(f)
+            if not submitted:
+                print "Submission cancelled, undoing p4 changes."
+                for f in editedFiles:
+                    p4_revert(f)
+                for f in filesToAdd:
+                    p4_revert(f)
+                    os.remove(f)
+                for f in filesToDelete:
+                    p4_revert(f)
 
         os.remove(fileName)
-        return ret
+        return submitted
 
     # Export git tags as p4 labels. Create a p4 label and then tag
     # with that.
@@ -1854,8 +1864,6 @@ def exportGitTags(self, gitTags):
     def run(self, args):
         if len(args) == 0:
             self.master = currentGitBranch()
-            if len(self.master) == 0 or not gitBranchExists("refs/heads/%s" % self.master):
-                die("Detecting current git branch failed!")
         elif len(args) == 1:
             self.master = args[0]
             if not branchExists(self.master):
@@ -1863,9 +1871,10 @@ def run(self, args):
         else:
             return False
 
-        allowSubmit = gitConfig("git-p4.allowSubmit")
-        if len(allowSubmit) > 0 and not self.master in allowSubmit.split(","):
-            die("%s is not in git-p4.allowSubmit" % self.master)
+        if self.master:
+            allowSubmit = gitConfig("git-p4.allowSubmit")
+            if len(allowSubmit) > 0 and not self.master in allowSubmit.split(","):
+                die("%s is not in git-p4.allowSubmit" % self.master)
 
         [upstream, settings] = findUpstreamBranchPoint()
         self.depotPath = settings['depot-paths'][0]
@@ -1933,7 +1942,12 @@ def run(self, args):
         self.check()
 
         commits = []
-        for line in read_pipe_lines(["git", "rev-list", "--no-merges", "%s..%s" % (self.origin, self.master)]):
+        if self.master:
+            commitish = self.master
+        else:
+            commitish = 'HEAD'
+
+        for line in read_pipe_lines(["git", "rev-list", "--no-merges", "%s..%s" % (self.origin, commitish)]):
             commits.append(line.strip())
         commits.reverse()
 
index 30edb179259d634f20649fe7f74df3f0c58f10ec..b938a6d4aa86b5f1e75312188c71cc4b0cdaab23 100644 (file)
@@ -610,7 +610,7 @@ do_next () {
                read -r command rest < "$todo"
                mark_action_done
                printf 'Executing: %s\n' "$rest"
-               ${SHELL:-@SHELL_PATH@} -c "$rest" # Actual execution
+               "${SHELL:-@SHELL_PATH@}" -c "$rest" # Actual execution
                status=$?
                # Run in subshell because require_clean_work_tree can die.
                dirty=f
diff --git a/http.c b/http.c
index 42f29ce0aaf7aac1e81849cf733e8ea92738f5b0..553d85674acac02856eac0fa19cf880993405e1b 100644 (file)
--- a/http.c
+++ b/http.c
@@ -214,10 +214,10 @@ static int http_options(const char *var, const char *value, void *cb)
 #endif
 #if LIBCURL_VERSION_NUM >= 0x070908
        if (!strcmp("http.sslcapath", var))
-               return git_config_string(&ssl_capath, var, value);
+               return git_config_pathname(&ssl_capath, var, value);
 #endif
        if (!strcmp("http.sslcainfo", var))
-               return git_config_string(&ssl_cainfo, var, value);
+               return git_config_pathname(&ssl_cainfo, var, value);
        if (!strcmp("http.sslcertpasswordprotected", var)) {
                ssl_cert_password_required = git_config_bool(var, value);
                return 0;
@@ -464,6 +464,17 @@ static CURL *get_curl_handle(void)
 
        if (curl_http_proxy) {
                curl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy);
+#if LIBCURL_VERSION_NUM >= 0x071800
+               if (starts_with(curl_http_proxy, "socks5"))
+                       curl_easy_setopt(result,
+                               CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
+               else if (starts_with(curl_http_proxy, "socks4a"))
+                       curl_easy_setopt(result,
+                               CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4A);
+               else if (starts_with(curl_http_proxy, "socks"))
+                       curl_easy_setopt(result,
+                               CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
+#endif
        }
 #if LIBCURL_VERSION_NUM >= 0x070a07
        curl_easy_setopt(result, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
index 6f9916a3901caa71b6a1994b6091b629a4397473..ba975bb3557b5e243deb2c40217dbe04ff4953ae 100755 (executable)
@@ -109,23 +109,20 @@ test_expect_success 'push to URL' '
        diff expected actual
 '
 
-# Test that filling pipe buffers doesn't cause failure
-# Too slow to leave enabled for general use
-if false
-then
-       printf 'parent1\nrepo1\n' >expected
-       nr=1000
-       while test $nr -lt 2000
-       do
-               nr=$(( $nr + 1 ))
-               git branch b/$nr $COMMIT3
-               echo "refs/heads/b/$nr $COMMIT3 refs/heads/b/$nr $_z40" >>expected
-       done
-
-       test_expect_success 'push many refs' '
-               git push parent1 "refs/heads/b/*:refs/heads/b/*" &&
-               diff expected actual
-       '
-fi
+test_expect_success 'set up many-ref tests' '
+       {
+               nr=1000
+               while test $nr -lt 2000
+               do
+                       nr=$(( $nr + 1 ))
+                       echo "create refs/heads/b/$nr $COMMIT3"
+               done
+       } | git update-ref --stdin
+'
+
+test_expect_success 'sigpipe does not cause pre-push hook failure' '
+       echo "exit 0" | write_script "$HOOK" &&
+       git push parent1 "refs/heads/b/*:refs/heads/b/*"
+'
 
 test_done
index ad877d774aad308bc81ecfae6eead262719694b9..a954ead8af882002d3e8bbb6dad8c52190f794c7 100755 (executable)
@@ -14,7 +14,7 @@ test_expect_success 'setup repository to clone' '
 '
 
 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_proto "ssh://" ssh "ssh://remote$PWD/remote/repo.git"
+test_proto "git+ssh://" ssh "git+ssh://remote$PWD/remote/repo.git"
 
 test_done
index 377c648e04f55359eefa87cdf2ad0c06be0df171..869e0bf0735033f66c5cba44d107f799fc07b112 100755 (executable)
@@ -418,4 +418,11 @@ test_expect_success 'filter commit message without trailing newline' '
        test_cmp expect actual
 '
 
+test_expect_success 'tree-filter deals with object name vs pathname ambiguity' '
+       test_when_finished "git reset --hard original" &&
+       ambiguous=$(git rev-list -1 HEAD) &&
+       git filter-branch --tree-filter "mv file.t $ambiguous" HEAD^.. &&
+       git show HEAD:$ambiguous
+'
+
 test_done
index 90d41ed954c829bfb3735f3cea9db336f74adb81..0730f18d0f83f4145c5a0dbfde784d71bdc57a1d 100755 (executable)
@@ -241,6 +241,22 @@ test_expect_success 'unresolvable host in P4PORT should display error' '
        )
 '
 
+test_expect_success 'submit from detached head' '
+       test_when_finished cleanup_git &&
+       git p4 clone --dest="$git" //depot &&
+       (
+               cd "$git" &&
+               git checkout p4/master &&
+               >detached_head_test &&
+               git add detached_head_test &&
+               git commit -m "add detached_head" &&
+               git config git-p4.skipSubmitEdit true &&
+               git p4 submit &&
+               git p4 rebase &&
+               git log p4/master | grep detached_head
+       )
+'
+
 test_expect_success 'kill p4d' '
        kill_p4d
 '
index 1f74a88385e827f7162256fafc22db5de3d41bf8..593152817dadaf1804f4a851c51b8bf1cbf52db9 100755 (executable)
@@ -389,7 +389,7 @@ test_expect_success 'description with Jobs section and bogus following text' '
        (
                cd "$cli" &&
                p4 revert desc6 &&
-               rm desc6
+               rm -f desc6
        )
 '
 
index 23b2ed6f0cf6f521c4d5afa6c1cffe0786d29a5f..e34ab929729ad1b69cde22544e44b48b715cb984 100644 (file)
@@ -15,6 +15,7 @@
 #include "submodule.h"
 #include "string-list.h"
 #include "sha1-array.h"
+#include "sigchain.h"
 
 /* rsync support */
 
@@ -1127,6 +1128,8 @@ static int run_pre_push_hook(struct transport *transport,
                return -1;
        }
 
+       sigchain_push(SIGPIPE, SIG_IGN);
+
        strbuf_init(&buf, 256);
 
        for (r = remote_refs; r; r = r->next) {
@@ -1140,8 +1143,10 @@ static int run_pre_push_hook(struct transport *transport,
                         r->peer_ref->name, sha1_to_hex(r->new_sha1),
                         r->name, sha1_to_hex(r->old_sha1));
 
-               if (write_in_full(proc.in, buf.buf, buf.len) != buf.len) {
-                       ret = -1;
+               if (write_in_full(proc.in, buf.buf, buf.len) < 0) {
+                       /* We do not mind if a hook does not read all refs. */
+                       if (errno != EPIPE)
+                               ret = -1;
                        break;
                }
        }
@@ -1152,6 +1157,8 @@ static int run_pre_push_hook(struct transport *transport,
        if (!ret)
                ret = x;
 
+       sigchain_pop(SIGPIPE);
+
        x = finish_command(&proc);
        if (!ret)
                ret = x;