Imported Upstream version 2.10.3 upstream/2.10.3
authorDongHun Kwak <dh0128.kwak@samsung.com>
Wed, 3 Mar 2021 06:15:57 +0000 (15:15 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Wed, 3 Mar 2021 06:15:57 +0000 (15:15 +0900)
46 files changed:
.travis.yml
Documentation/RelNotes/2.10.3.txt [new file with mode: 0644]
Documentation/RelNotes/2.4.12.txt [new file with mode: 0644]
Documentation/RelNotes/2.5.6.txt [new file with mode: 0644]
Documentation/RelNotes/2.6.7.txt [new file with mode: 0644]
Documentation/RelNotes/2.7.5.txt [new file with mode: 0644]
Documentation/RelNotes/2.8.5.txt [new file with mode: 0644]
Documentation/RelNotes/2.9.4.txt
Documentation/config.txt
Documentation/git-fmt-merge-msg.txt
Documentation/git-worktree.txt
Documentation/git.txt
Documentation/gitrepository-layout.txt
GIT-VERSION-GEN
Makefile
RelNotes
branch.c
branch.h
builtin/am.c
builtin/branch.c
builtin/checkout.c
builtin/commit.c
common-main.c
contrib/coccinelle/object_id.cocci
contrib/completion/git-completion.bash
daemon.c
diff.c
diffcore-break.c
diffcore-delta.c
diffcore-rename.c
diffcore.h
exec_cmd.c
exec_cmd.h
git-compat-util.h
git-sh-setup.sh
git.c
hex.c
path.c
perl/Git.pm
shell.c
t/t6026-merge-attr.sh
t/t9000/test.pl
t/t9001-send-email.sh
t/test-lib.sh
t/valgrind/valgrind.sh
templates/hooks--pre-receive.sample [changed mode: 0644->0755]

index 9a65514..0b2ea5c 100644 (file)
@@ -32,7 +32,6 @@ env:
     - DEFAULT_TEST_TARGET=prove
     - GIT_PROVE_OPTS="--timer --jobs 3 --state=failed,slow,save"
     - GIT_TEST_OPTS="--verbose-log"
-    - GIT_TEST_HTTPD=true
     - GIT_TEST_CLONE_2GB=YesPlease
     # t9810 occasionally fails on Travis CI OS X
     # t9816 occasionally fails with "TAP out of sequence errors" on Travis CI OS X
@@ -57,6 +56,8 @@ before_install:
   - >
     case "${TRAVIS_OS_NAME:-linux}" in
     linux)
+      export GIT_TEST_HTTPD=YesPlease
+
       mkdir --parents custom/p4
       pushd custom/p4
         wget --quiet http://filehost.perforce.com/perforce/r$LINUX_P4_VERSION/bin.linux26x86_64/p4d
diff --git a/Documentation/RelNotes/2.10.3.txt b/Documentation/RelNotes/2.10.3.txt
new file mode 100644 (file)
index 0000000..ad6a01b
--- /dev/null
@@ -0,0 +1,55 @@
+Git v2.10.3 Release Notes
+=========================
+
+Fixes since v2.10.2
+-------------------
+
+ * Extract a small helper out of the function that reads the authors
+   script file "git am" internally uses.
+   This by itself is not useful until a second caller appears in the
+   future for "rebase -i" helper.
+
+ * The command-line completion script (in contrib/) learned to
+   complete "git cmd ^mas<HT>" to complete the negative end of
+   reference to "git cmd ^master".
+
+ * "git send-email" attempts to pick up valid e-mails from the
+   trailers, but people in real world write non-addresses there, like
+   "Cc: Stable <add@re.ss> # 4.8+", which broke the output depending
+   on the availability and vintage of Mail::Address perl module.
+
+ * The code that we have used for the past 10+ years to cycle
+   4-element ring buffers turns out to be not quite portable in
+   theoretical world.
+
+ * "git daemon" used fixed-length buffers to turn URL to the
+   repository the client asked for into the server side directory
+   path, using snprintf() to avoid overflowing these buffers, but
+   allowed possibly truncated paths to the directory.  This has been
+   tightened to reject such a request that causes overlong path to be
+   required to serve.
+
+ * Recent update to git-sh-setup (a library of shell functions that
+   are used by our in-tree scripted Porcelain commands) included
+   another shell library git-sh-i18n without specifying where it is,
+   relying on the $PATH.  This has been fixed to be more explicit by
+   prefixing $(git --exec-path) output in front.
+
+ * Fix for a racy false-positive test failure.
+
+ * Portability update and workaround for builds on recent Mac OS X.
+
+ * Update to the test framework made in 2.9 timeframe broke running
+   the tests under valgrind, which has been fixed.
+
+ * Improve the rule to convert "unsigned char [20]" into "struct
+   object_id *" in contrib/coccinelle/
+
+ * "git-shell" rejects a request to serve a repository whose name
+   begins with a dash, which makes it no longer possible to get it
+   confused into spawning service programs like "git-upload-pack" with
+   an option like "--help", which in turn would spawn an interactive
+   pager, instead of working with the repository user asked to access
+   (i.e. the one whose name is "--help").
+
+Also contains minor documentation updates and code clean-ups.
diff --git a/Documentation/RelNotes/2.4.12.txt b/Documentation/RelNotes/2.4.12.txt
new file mode 100644 (file)
index 0000000..7d15f94
--- /dev/null
@@ -0,0 +1,12 @@
+Git v2.4.12 Release Notes
+=========================
+
+Fixes since v2.4.11
+-------------------
+
+ * "git-shell" rejects a request to serve a repository whose name
+   begins with a dash, which makes it no longer possible to get it
+   confused into spawning service programs like "git-upload-pack" with
+   an option like "--help", which in turn would spawn an interactive
+   pager, instead of working with the repository user asked to access
+   (i.e. the one whose name is "--help").
diff --git a/Documentation/RelNotes/2.5.6.txt b/Documentation/RelNotes/2.5.6.txt
new file mode 100644 (file)
index 0000000..9cd025b
--- /dev/null
@@ -0,0 +1,12 @@
+Git v2.5.6 Release Notes
+========================
+
+Fixes since v2.5.5
+------------------
+
+ * "git-shell" rejects a request to serve a repository whose name
+   begins with a dash, which makes it no longer possible to get it
+   confused into spawning service programs like "git-upload-pack" with
+   an option like "--help", which in turn would spawn an interactive
+   pager, instead of working with the repository user asked to access
+   (i.e. the one whose name is "--help").
diff --git a/Documentation/RelNotes/2.6.7.txt b/Documentation/RelNotes/2.6.7.txt
new file mode 100644 (file)
index 0000000..1335de4
--- /dev/null
@@ -0,0 +1,12 @@
+Git v2.6.7 Release Notes
+========================
+
+Fixes since v2.6.6
+------------------
+
+ * "git-shell" rejects a request to serve a repository whose name
+   begins with a dash, which makes it no longer possible to get it
+   confused into spawning service programs like "git-upload-pack" with
+   an option like "--help", which in turn would spawn an interactive
+   pager, instead of working with the repository user asked to access
+   (i.e. the one whose name is "--help").
diff --git a/Documentation/RelNotes/2.7.5.txt b/Documentation/RelNotes/2.7.5.txt
new file mode 100644 (file)
index 0000000..83559ce
--- /dev/null
@@ -0,0 +1,14 @@
+Git v2.7.5 Release Notes
+========================
+
+Fixes since v2.7.4
+------------------
+
+ * "git-shell" rejects a request to serve a repository whose name
+   begins with a dash, which makes it no longer possible to get it
+   confused into spawning service programs like "git-upload-pack" with
+   an option like "--help", which in turn would spawn an interactive
+   pager, instead of working with the repository user asked to access
+   (i.e. the one whose name is "--help").
+
+Also contains a few fixes backported from later development tracks.
diff --git a/Documentation/RelNotes/2.8.5.txt b/Documentation/RelNotes/2.8.5.txt
new file mode 100644 (file)
index 0000000..7bd179f
--- /dev/null
@@ -0,0 +1,12 @@
+Git v2.8.5 Release Notes
+========================
+
+Fixes since v2.8.4
+------------------
+
+ * "git-shell" rejects a request to serve a repository whose name
+   begins with a dash, which makes it no longer possible to get it
+   confused into spawning service programs like "git-upload-pack" with
+   an option like "--help", which in turn would spawn an interactive
+   pager, instead of working with the repository user asked to access
+   (i.e. the one whose name is "--help").
index 01e8642..9768293 100644 (file)
@@ -80,4 +80,11 @@ Fixes since v2.9.3
    the file descriptor still open.  Open tempfile with O_CLOEXEC flag
    to avoid this (on Windows, this is mapped to O_NOINHERIT).
 
+ * "git-shell" rejects a request to serve a repository whose name
+   begins with a dash, which makes it no longer possible to get it
+   confused into spawning service programs like "git-upload-pack" with
+   an option like "--help", which in turn would spawn an interactive
+   pager, instead of working with the repository user asked to access
+   (i.e. the one whose name is "--help").
+
 Also contains minor documentation updates and code clean-ups.
index 21fdddf..cbae7a6 100644 (file)
@@ -2436,7 +2436,7 @@ rebase.missingCommitsCheck::
        command in the todo-list.
        Defaults to "ignore".
 
-rebase.instructionFormat
+rebase.instructionFormat::
        A format string, as specified in linkgit:git-log[1], to be used for
        the instruction list during an interactive rebase.  The format will automatically
        have the long commit hash prepended to the format.
index 6526b17..44892c4 100644 (file)
@@ -60,10 +60,10 @@ merge.summary::
 EXAMPLE
 -------
 
---
+---------
 $ git fetch origin master
 $ git fmt-merge-msg --log <$GIT_DIR/FETCH_HEAD
---
+---------
 
 Print a log message describing a merge of the "master" branch from
 the "origin" remote.
index 0aeb020..e257c19 100644 (file)
@@ -133,7 +133,7 @@ OPTIONS
 +
 If the last path components in the working tree's path is unique among
 working trees, it can be used to identify worktrees. For example if
-you only have to working trees at "/abc/def/ghi" and "/abc/def/ggg",
+you only have two working trees, at "/abc/def/ghi" and "/abc/def/ggg",
 then "ghi" or "def/ghi" is enough to point to the former working tree.
 
 DETAILS
index ed717e4..89157e2 100644 (file)
@@ -43,41 +43,47 @@ 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.10.2/git.html[documentation for release 2.10.2]
+* link:v2.10.3/git.html[documentation for release 2.10.3]
 
 * release notes for
+  link:RelNotes/2.10.3.txt[2.10.3],
   link:RelNotes/2.10.2.txt[2.10.2],
   link:RelNotes/2.10.1.txt[2.10.1],
   link:RelNotes/2.10.0.txt[2.10].
 
-* link:v2.9.3/git.html[documentation for release 2.9.3]
+* link:v2.9.4/git.html[documentation for release 2.9.4]
 
 * release notes for
+  link:RelNotes/2.9.4.txt[2.9.4],
   link:RelNotes/2.9.3.txt[2.9.3],
   link:RelNotes/2.9.2.txt[2.9.2],
   link:RelNotes/2.9.1.txt[2.9.1],
   link:RelNotes/2.9.0.txt[2.9].
 
-* link:v2.8.4/git.html[documentation for release 2.8.4]
+* link:v2.8.5/git.html[documentation for release 2.8.5]
 
 * release notes for
+  link:RelNotes/2.8.5.txt[2.8.5],
   link:RelNotes/2.8.4.txt[2.8.4],
   link:RelNotes/2.8.3.txt[2.8.3],
   link:RelNotes/2.8.2.txt[2.8.2],
   link:RelNotes/2.8.1.txt[2.8.1],
   link:RelNotes/2.8.0.txt[2.8].
 
-* link:v2.7.3/git.html[documentation for release 2.7.3]
+* link:v2.7.5/git.html[documentation for release 2.7.5]
 
 * release notes for
+  link:RelNotes/2.7.5.txt[2.7.5],
+  link:RelNotes/2.7.4.txt[2.7.4],
   link:RelNotes/2.7.3.txt[2.7.3],
   link:RelNotes/2.7.2.txt[2.7.2],
   link:RelNotes/2.7.1.txt[2.7.1],
   link:RelNotes/2.7.0.txt[2.7].
 
-* link:v2.6.6/git.html[documentation for release 2.6.6]
+* link:v2.6.7/git.html[documentation for release 2.6.7]
 
 * release notes for
+  link:RelNotes/2.6.7.txt[2.6.7],
   link:RelNotes/2.6.6.txt[2.6.6],
   link:RelNotes/2.6.5.txt[2.6.5],
   link:RelNotes/2.6.4.txt[2.6.4],
@@ -86,9 +92,10 @@ Documentation for older releases are available here:
   link:RelNotes/2.6.1.txt[2.6.1],
   link:RelNotes/2.6.0.txt[2.6].
 
-* link:v2.5.5/git.html[documentation for release 2.5.5]
+* link:v2.5.6/git.html[documentation for release 2.5.6]
 
 * release notes for
+  link:RelNotes/2.5.6.txt[2.5.6],
   link:RelNotes/2.5.5.txt[2.5.5],
   link:RelNotes/2.5.4.txt[2.5.4],
   link:RelNotes/2.5.3.txt[2.5.3],
@@ -96,9 +103,10 @@ Documentation for older releases are available here:
   link:RelNotes/2.5.1.txt[2.5.1],
   link:RelNotes/2.5.0.txt[2.5].
 
-* link:v2.4.11/git.html[documentation for release 2.4.11]
+* link:v2.4.12/git.html[documentation for release 2.4.12]
 
 * release notes for
+  link:RelNotes/2.4.12.txt[2.4.12],
   link:RelNotes/2.4.11.txt[2.4.11],
   link:RelNotes/2.4.10.txt[2.4.10],
   link:RelNotes/2.4.9.txt[2.4.9],
index 577ee84..a5f99cb 100644 (file)
@@ -177,7 +177,7 @@ sharedindex.<SHA-1>::
 info::
        Additional information about the repository is recorded
        in this directory. This directory is ignored if $GIT_COMMON_DIR
-       is set and "$GIT_COMMON_DIR/index" will be used instead.
+       is set and "$GIT_COMMON_DIR/info" will be used instead.
 
 info/refs::
        This file helps dumb transports discover what refs are
index 153c17c..40700d5 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.10.2
+DEF_VER=v2.10.3
 
 LF='
 '
index ddd1bdf..46ad908 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1044,6 +1044,7 @@ ifeq ($(uname_S),Darwin)
                endif
        endif
        ifndef NO_APPLE_COMMON_CRYPTO
+               NO_OPENSSL = YesPlease
                APPLE_COMMON_CRYPTO = YesPlease
                COMPAT_CFLAGS += -DAPPLE_COMMON_CRYPTO
        endif
index c02235f..75030cb 120000 (symlink)
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.10.2.txt
\ No newline at end of file
+Documentation/RelNotes/2.10.3.txt
\ No newline at end of file
index a5a8dcb..0d459b3 100644 (file)
--- a/branch.c
+++ b/branch.c
@@ -228,8 +228,7 @@ N_("\n"
 "will track its remote counterpart, you may want to use\n"
 "\"git push -u\" to set the upstream config as you push.");
 
-void create_branch(const char *head,
-                  const char *name, const char *start_name,
+void create_branch(const char *name, const char *start_name,
                   int force, int reflog, int clobber_head,
                   int quiet, enum branch_track track)
 {
index b2f9649..3103eb9 100644 (file)
--- a/branch.h
+++ b/branch.h
@@ -4,15 +4,21 @@
 /* Functions for acting on the information about branches. */
 
 /*
- * Creates a new branch, where head is the branch currently checked
- * out, name is the new branch name, start_name is the name of the
- * existing branch that the new branch should start from, force
- * enables overwriting an existing (non-head) branch, reflog creates a
- * reflog for the branch, and track causes the new branch to be
- * configured to merge the remote branch that start_name is a tracking
- * branch for (if any).
+ * Creates a new branch, where:
+ *
+ *   - name is the new branch name
+ *
+ *   - start_name is the name of the existing branch that the new branch should
+ *     start from
+ *
+ *   - force enables overwriting an existing (non-head) branch
+ *
+ *   - reflog creates a reflog for the branch
+ *
+ *   - track causes the new branch to be configured to merge the remote branch
+ *     that start_name is a tracking branch for (if any).
  */
-void create_branch(const char *head, const char *name, const char *start_name,
+void create_branch(const char *name, const char *start_name,
                   int force, int reflog,
                   int clobber_head, int quiet, enum branch_track track);
 
index 9e2ae5c..9daeb27 100644 (file)
@@ -28,6 +28,7 @@
 #include "rerere.h"
 #include "prompt.h"
 #include "mailinfo.h"
+#include "string-list.h"
 
 /**
  * Returns 1 if the file is empty or does not exist, 0 otherwise.
@@ -258,38 +259,29 @@ static int read_state_file(struct strbuf *sb, const struct am_state *state,
 }
 
 /**
- * Reads a KEY=VALUE shell variable assignment from `fp`, returning the VALUE
- * as a newly-allocated string. VALUE must be a quoted string, and the KEY must
- * match `key`. Returns NULL on failure.
- *
- * This is used by read_author_script() to read the GIT_AUTHOR_* variables from
- * the author-script.
+ * Take a series of KEY='VALUE' lines where VALUE part is
+ * sq-quoted, and append <KEY, VALUE> at the end of the string list
  */
-static char *read_shell_var(FILE *fp, const char *key)
+static int parse_key_value_squoted(char *buf, struct string_list *list)
 {
-       struct strbuf sb = STRBUF_INIT;
-       const char *str;
-
-       if (strbuf_getline_lf(&sb, fp))
-               goto fail;
-
-       if (!skip_prefix(sb.buf, key, &str))
-               goto fail;
-
-       if (!skip_prefix(str, "=", &str))
-               goto fail;
-
-       strbuf_remove(&sb, 0, str - sb.buf);
-
-       str = sq_dequote(sb.buf);
-       if (!str)
-               goto fail;
-
-       return strbuf_detach(&sb, NULL);
-
-fail:
-       strbuf_release(&sb);
-       return NULL;
+       while (*buf) {
+               struct string_list_item *item;
+               char *np;
+               char *cp = strchr(buf, '=');
+               if (!cp)
+                       return -1;
+               np = strchrnul(cp, '\n');
+               *cp++ = '\0';
+               item = string_list_append(list, buf);
+
+               buf = np + (*np == '\n');
+               *np = '\0';
+               cp = sq_dequote(cp);
+               if (!cp)
+                       return -1;
+               item->util = xstrdup(cp);
+       }
+       return 0;
 }
 
 /**
@@ -311,44 +303,39 @@ fail:
 static int read_author_script(struct am_state *state)
 {
        const char *filename = am_path(state, "author-script");
-       FILE *fp;
+       struct strbuf buf = STRBUF_INIT;
+       struct string_list kv = STRING_LIST_INIT_DUP;
+       int retval = -1; /* assume failure */
+       int fd;
 
        assert(!state->author_name);
        assert(!state->author_email);
        assert(!state->author_date);
 
-       fp = fopen(filename, "r");
-       if (!fp) {
+       fd = open(filename, O_RDONLY);
+       if (fd < 0) {
                if (errno == ENOENT)
                        return 0;
                die_errno(_("could not open '%s' for reading"), filename);
        }
+       strbuf_read(&buf, fd, 0);
+       close(fd);
+       if (parse_key_value_squoted(buf.buf, &kv))
+               goto finish;
 
-       state->author_name = read_shell_var(fp, "GIT_AUTHOR_NAME");
-       if (!state->author_name) {
-               fclose(fp);
-               return -1;
-       }
-
-       state->author_email = read_shell_var(fp, "GIT_AUTHOR_EMAIL");
-       if (!state->author_email) {
-               fclose(fp);
-               return -1;
-       }
-
-       state->author_date = read_shell_var(fp, "GIT_AUTHOR_DATE");
-       if (!state->author_date) {
-               fclose(fp);
-               return -1;
-       }
-
-       if (fgetc(fp) != EOF) {
-               fclose(fp);
-               return -1;
-       }
-
-       fclose(fp);
-       return 0;
+       if (kv.nr != 3 ||
+           strcmp(kv.items[0].string, "GIT_AUTHOR_NAME") ||
+           strcmp(kv.items[1].string, "GIT_AUTHOR_EMAIL") ||
+           strcmp(kv.items[2].string, "GIT_AUTHOR_DATE"))
+               goto finish;
+       state->author_name = kv.items[0].util;
+       state->author_email = kv.items[1].util;
+       state->author_date = kv.items[2].util;
+       retval = 0;
+finish:
+       string_list_clear(&kv, !!retval);
+       strbuf_release(&buf);
+       return retval;
 }
 
 /**
index 7df0543..6810c3a 100644 (file)
@@ -807,7 +807,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
                 * create_branch takes care of setting up the tracking
                 * info and making sure new_upstream is correct
                 */
-               create_branch(head, branch->name, new_upstream, 0, 0, 0, quiet, BRANCH_TRACK_OVERRIDE);
+               create_branch(branch->name, new_upstream, 0, 0, 0, quiet, BRANCH_TRACK_OVERRIDE);
        } else if (unset_upstream) {
                struct branch *branch = branch_get(argv[0]);
                struct strbuf buf = STRBUF_INIT;
@@ -853,7 +853,7 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
                strbuf_release(&buf);
 
                branch_existed = ref_exists(branch->refname);
-               create_branch(head, argv[0], (argc == 2) ? argv[1] : head,
+               create_branch(argv[0], (argc == 2) ? argv[1] : head,
                              force, reflog, 0, quiet, track);
 
                /*
index 32cf317..899bd8d 100644 (file)
@@ -631,7 +631,7 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
                        }
                }
                else
-                       create_branch(old->name, opts->new_branch, new->name,
+                       create_branch(opts->new_branch, new->name,
                                      opts->new_branch_force ? 1 : 0,
                                      opts->new_branch_log,
                                      opts->new_branch_force ? 1 : 0,
index 7a1ade0..63a8424 100644 (file)
@@ -1647,7 +1647,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
        const char *index_file, *reflog_msg;
        char *nl;
        unsigned char sha1[20];
-       struct commit_list *parents = NULL, **pptr = &parents;
+       struct commit_list *parents = NULL;
        struct stat statbuf;
        struct commit *current_head = NULL;
        struct commit_extra_header *extra = NULL;
@@ -1693,20 +1693,18 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
                if (!reflog_msg)
                        reflog_msg = "commit (initial)";
        } else if (amend) {
-               struct commit_list *c;
-
                if (!reflog_msg)
                        reflog_msg = "commit (amend)";
-               for (c = current_head->parents; c; c = c->next)
-                       pptr = &commit_list_insert(c->item, pptr)->next;
+               parents = copy_commit_list(current_head->parents);
        } else if (whence == FROM_MERGE) {
                struct strbuf m = STRBUF_INIT;
                FILE *fp;
                int allow_fast_forward = 1;
+               struct commit_list **pptr = &parents;
 
                if (!reflog_msg)
                        reflog_msg = "commit (merge)";
-               pptr = &commit_list_insert(current_head, pptr)->next;
+               pptr = commit_list_append(current_head, pptr);
                fp = fopen(git_path_merge_head(), "r");
                if (fp == NULL)
                        die_errno(_("could not open '%s' for reading"),
@@ -1717,7 +1715,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
                        parent = get_merge_parent(m.buf);
                        if (!parent)
                                die(_("Corrupt MERGE_HEAD file (%s)"), m.buf);
-                       pptr = &commit_list_insert(parent, pptr)->next;
+                       pptr = commit_list_append(parent, pptr);
                }
                fclose(fp);
                strbuf_release(&m);
@@ -1734,7 +1732,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
                        reflog_msg = (whence == FROM_CHERRY_PICK)
                                        ? "commit (cherry-pick)"
                                        : "commit";
-               pptr = &commit_list_insert(current_head, pptr)->next;
+               commit_list_insert(current_head, &parents);
        }
 
        /* Finally, get the commit message */
index 44a29e8..c654f95 100644 (file)
@@ -33,7 +33,7 @@ int main(int argc, const char **argv)
 
        git_setup_gettext();
 
-       argv[0] = git_extract_argv0_path(argv[0]);
+       git_extract_argv0_path(argv[0]);
 
        restore_sigpipe_to_default();
 
index 0307624..09afdbf 100644 (file)
@@ -17,10 +17,13 @@ expression E1;
 + oid_to_hex(&E1)
 
 @@
+identifier f != oid_to_hex;
 expression E1;
 @@
+  f(...) {...
 - sha1_to_hex(E1->hash)
 + oid_to_hex(E1)
+  ...}
 
 @@
 expression E1, E2;
@@ -29,10 +32,13 @@ expression E1, E2;
 + oid_to_hex_r(E1, &E2)
 
 @@
+identifier f != oid_to_hex_r;
 expression E1, E2;
 @@
+   f(...) {...
 - sha1_to_hex_r(E1, E2->hash)
 + oid_to_hex_r(E1, E2)
+  ...}
 
 @@
 expression E1;
@@ -41,10 +47,13 @@ expression E1;
 + oidclr(&E1)
 
 @@
+identifier f != oidclr;
 expression E1;
 @@
+  f(...) {...
 - hashclr(E1->hash)
 + oidclr(E1)
+  ...}
 
 @@
 expression E1, E2;
@@ -53,10 +62,13 @@ expression E1, E2;
 + oidcmp(&E1, &E2)
 
 @@
+identifier f != oidcmp;
 expression E1, E2;
 @@
+  f(...) {...
 - hashcmp(E1->hash, E2->hash)
 + oidcmp(E1, E2)
+  ...}
 
 @@
 expression E1, E2;
@@ -77,10 +89,13 @@ expression E1, E2;
 + oidcpy(&E1, &E2)
 
 @@
+identifier f != oidcpy;
 expression E1, E2;
 @@
+  f(...) {...
 - hashcpy(E1->hash, E2->hash)
 + oidcpy(E1, E2)
+  ...}
 
 @@
 expression E1, E2;
index 9c8f738..21016bf 100644 (file)
@@ -338,7 +338,7 @@ __git_tags ()
 __git_refs ()
 {
        local i hash dir="$(__gitdir "${1-}")" track="${2-}"
-       local format refs
+       local format refs pfx
        if [ -d "$dir" ]; then
                case "$cur" in
                refs|refs/*)
@@ -347,14 +347,15 @@ __git_refs ()
                        track=""
                        ;;
                *)
+                       [[ "$cur" == ^* ]] && pfx="^"
                        for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD; do
-                               if [ -e "$dir/$i" ]; then echo $i; fi
+                               if [ -e "$dir/$i" ]; then echo $pfx$i; fi
                        done
                        format="refname:short"
                        refs="refs/tags refs/heads refs/remotes"
                        ;;
                esac
-               git --git-dir="$dir" for-each-ref --format="%($format)" \
+               git --git-dir="$dir" for-each-ref --format="$pfx%($format)" \
                        $refs
                if [ -n "$track" ]; then
                        # employ the heuristic used by git checkout
index 425aad0..ff0fa58 100644 (file)
--- a/daemon.c
+++ b/daemon.c
@@ -160,6 +160,7 @@ static const char *path_ok(const char *directory, struct hostinfo *hi)
 {
        static char rpath[PATH_MAX];
        static char interp_path[PATH_MAX];
+       size_t rlen;
        const char *path;
        const char *dir;
 
@@ -187,8 +188,12 @@ static const char *path_ok(const char *directory, struct hostinfo *hi)
                        namlen = slash - dir;
                        restlen -= namlen;
                        loginfo("userpath <%s>, request <%s>, namlen %d, restlen %d, slash <%s>", user_path, dir, namlen, restlen, slash);
-                       snprintf(rpath, PATH_MAX, "%.*s/%s%.*s",
-                                namlen, dir, user_path, restlen, slash);
+                       rlen = snprintf(rpath, sizeof(rpath), "%.*s/%s%.*s",
+                                       namlen, dir, user_path, restlen, slash);
+                       if (rlen >= sizeof(rpath)) {
+                               logerror("user-path too large: %s", rpath);
+                               return NULL;
+                       }
                        dir = rpath;
                }
        }
@@ -207,7 +212,15 @@ static const char *path_ok(const char *directory, struct hostinfo *hi)
 
                strbuf_expand(&expanded_path, interpolated_path,
                              expand_path, &context);
-               strlcpy(interp_path, expanded_path.buf, PATH_MAX);
+
+               rlen = strlcpy(interp_path, expanded_path.buf,
+                              sizeof(interp_path));
+               if (rlen >= sizeof(interp_path)) {
+                       logerror("interpolated path too large: %s",
+                                interp_path);
+                       return NULL;
+               }
+
                strbuf_release(&expanded_path);
                loginfo("Interpolated dir '%s'", interp_path);
 
@@ -219,7 +232,11 @@ static const char *path_ok(const char *directory, struct hostinfo *hi)
                        logerror("'%s': Non-absolute path denied (base-path active)", dir);
                        return NULL;
                }
-               snprintf(rpath, PATH_MAX, "%s%s", base_path, dir);
+               rlen = snprintf(rpath, sizeof(rpath), "%s%s", base_path, dir);
+               if (rlen >= sizeof(rpath)) {
+                       logerror("base-path too large: %s", rpath);
+                       return NULL;
+               }
                dir = rpath;
        }
 
diff --git a/diff.c b/diff.c
index fe6f591..8c78fce 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -1954,7 +1954,7 @@ static void show_dirstat(struct diff_options *options)
                if (DIFF_FILE_VALID(p->one) && DIFF_FILE_VALID(p->two)) {
                        diff_populate_filespec(p->one, 0);
                        diff_populate_filespec(p->two, 0);
-                       diffcore_count_changes(p->one, p->two, NULL, NULL, 0,
+                       diffcore_count_changes(p->one, p->two, NULL, NULL,
                                               &copied, &added);
                        diff_free_filespec_data(p->one);
                        diff_free_filespec_data(p->two);
index 881a74f..c64359f 100644 (file)
@@ -73,7 +73,6 @@ static int should_break(struct diff_filespec *src,
 
        if (diffcore_count_changes(src, dst,
                                   &src->cnt_data, &dst->cnt_data,
-                                  0,
                                   &src_copied, &literal_added))
                return 0;
 
index 4159748..e2db85a 100644 (file)
@@ -169,7 +169,6 @@ int diffcore_count_changes(struct diff_filespec *src,
                           struct diff_filespec *dst,
                           void **src_count_p,
                           void **dst_count_p,
-                          unsigned long delta_limit,
                           unsigned long *src_copied,
                           unsigned long *literal_added)
 {
index 73d003a..15c014d 100644 (file)
@@ -145,7 +145,6 @@ static int estimate_similarity(struct diff_filespec *src,
         * call into this function in that case.
         */
        unsigned long max_size, delta_size, base_size, src_copied, literal_added;
-       unsigned long delta_limit;
        int score;
 
        /* We deal only with regular files.  Symlink renames are handled
@@ -191,11 +190,8 @@ static int estimate_similarity(struct diff_filespec *src,
        if (!dst->cnt_data && diff_populate_filespec(dst, 0))
                return 0;
 
-       delta_limit = (unsigned long)
-               (base_size * (MAX_SCORE-minimum_score) / MAX_SCORE);
        if (diffcore_count_changes(src, dst,
                                   &src->cnt_data, &dst->cnt_data,
-                                  delta_limit,
                                   &src_copied, &literal_added))
                return 0;
 
index c11b846..6230241 100644 (file)
@@ -142,7 +142,6 @@ extern int diffcore_count_changes(struct diff_filespec *src,
                                  struct diff_filespec *dst,
                                  void **src_count_p,
                                  void **dst_count_p,
-                                 unsigned long delta_limit,
                                  unsigned long *src_copied,
                                  unsigned long *literal_added);
 
index 9d5703a..19ac214 100644 (file)
@@ -38,21 +38,17 @@ char *system_path(const char *path)
        return strbuf_detach(&d, NULL);
 }
 
-const char *git_extract_argv0_path(const char *argv0)
+void git_extract_argv0_path(const char *argv0)
 {
        const char *slash;
 
        if (!argv0 || !*argv0)
-               return NULL;
+               return;
 
        slash = find_last_dir_sep(argv0);
 
-       if (slash) {
+       if (slash)
                argv0_path = xstrndup(argv0, slash - argv0);
-               return slash + 1;
-       }
-
-       return argv0;
 }
 
 void git_set_argv_exec_path(const char *exec_path)
index 1f6b433..ff0b480 100644 (file)
@@ -4,7 +4,7 @@
 struct argv_array;
 
 extern void git_set_argv_exec_path(const char *exec_path);
-extern const char *git_extract_argv0_path(const char *path);
+extern void git_extract_argv0_path(const char *path);
 extern const char *git_exec_path(void);
 extern void setup_path(void);
 extern const char **prepare_git_cmd(struct argv_array *out, const char **argv);
index b4d9c2a..d89a786 100644 (file)
@@ -1090,6 +1090,6 @@ struct tm *git_gmtime_r(const time_t *, struct tm *);
 #define getc_unlocked(fh) getc(fh)
 #endif
 
-#endif
-
 extern int cmd_main(int, const char **);
+
+#endif
index a8a4576..240c7eb 100644 (file)
@@ -2,9 +2,6 @@
 # to set up some variables pointing at the normal git directories and
 # a few helper shell functions.
 
-# Source git-sh-i18n for gettext support.
-. git-sh-i18n
-
 # Having this variable in your environment would break scripts because
 # you would cause "cd" to be taken to unexpected places.  If you
 # like CDPATH, define it for your interactive shell sessions without
@@ -46,6 +43,9 @@ git_broken_path_fix () {
 
 # @@BROKEN_PATH_FIX@@
 
+# Source git-sh-i18n for gettext support.
+. "$(git --exec-path)/git-sh-i18n"
+
 die () {
        die_with_status 1 "$@"
 }
diff --git a/git.c b/git.c
index f914490..7acf290 100644 (file)
--- a/git.c
+++ b/git.c
@@ -616,6 +616,11 @@ int cmd_main(int argc, const char **argv)
        cmd = argv[0];
        if (!cmd)
                cmd = "git-help";
+       else {
+               const char *slash = find_last_dir_sep(cmd);
+               if (slash)
+                       cmd = slash + 1;
+       }
 
        trace_command_performance(argv);
 
diff --git a/hex.c b/hex.c
index ab2610e..845b01a 100644 (file)
--- a/hex.c
+++ b/hex.c
@@ -78,7 +78,8 @@ char *sha1_to_hex(const unsigned char *sha1)
 {
        static int bufno;
        static char hexbuffer[4][GIT_SHA1_HEXSZ + 1];
-       return sha1_to_hex_r(hexbuffer[3 & ++bufno], sha1);
+       bufno = (bufno + 1) % ARRAY_SIZE(hexbuffer);
+       return sha1_to_hex_r(hexbuffer[bufno], sha1);
 }
 
 char *oid_to_hex(const struct object_id *oid)
diff --git a/path.c b/path.c
index fe3c4d9..9bfaeda 100644 (file)
--- a/path.c
+++ b/path.c
@@ -24,7 +24,8 @@ static struct strbuf *get_pathname(void)
                STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT
        };
        static int index;
-       struct strbuf *sb = &pathname_array[3 & ++index];
+       struct strbuf *sb = &pathname_array[index];
+       index = (index + 1) % ARRAY_SIZE(pathname_array);
        strbuf_reset(sb);
        return sb;
 }
index ce7e4e8..864123f 100644 (file)
@@ -871,6 +871,8 @@ Return an array of mailboxes extracted from a string.
 
 =cut
 
+# Very close to Mail::Address's parser, but we still have minor
+# differences in some cases (see t9000 for examples).
 sub parse_mailboxes {
        my $re_comment = qr/\((?:[^)]*)\)/;
        my $re_quote = qr/"(?:[^\"\\]|\\.)*"/;
@@ -879,6 +881,7 @@ sub parse_mailboxes {
        # divide the string in tokens of the above form
        my $re_token = qr/(?:$re_quote|$re_word|$re_comment|\S)/;
        my @tokens = map { $_ =~ /\s*($re_token)\s*/g } @_;
+       my $end_of_addr_seen = 0;
 
        # add a delimiter to simplify treatment for the last mailbox
        push @tokens, ",";
@@ -888,10 +891,10 @@ sub parse_mailboxes {
                if ($token =~ /^[,;]$/) {
                        # if buffer still contains undeterminated strings
                        # append it at the end of @address or @phrase
-                       if (@address) {
-                               push @address, @buffer;
-                       } else {
+                       if ($end_of_addr_seen) {
                                push @phrase, @buffer;
+                       } else {
+                               push @address, @buffer;
                        }
 
                        my $str_phrase = join ' ', @phrase;
@@ -915,16 +918,16 @@ sub parse_mailboxes {
                        push @addr_list, $str_mailbox if ($str_mailbox);
 
                        @phrase = @address = @comment = @buffer = ();
+                       $end_of_addr_seen = 0;
                } elsif ($token =~ /^\(/) {
                        push @comment, $token;
                } elsif ($token eq "<") {
                        push @phrase, (splice @address), (splice @buffer);
                } elsif ($token eq ">") {
+                       $end_of_addr_seen = 1;
                        push @address, (splice @buffer);
-               } elsif ($token eq "@") {
+               } elsif ($token eq "@" && !$end_of_addr_seen) {
                        push @address, (splice @buffer), "@";
-               } elsif ($token eq ".") {
-                       push @address, (splice @buffer), ".";
                } else {
                        push @buffer, $token;
                }
diff --git a/shell.c b/shell.c
index 464ee1a..fe2d314 100644 (file)
--- a/shell.c
+++ b/shell.c
@@ -13,7 +13,7 @@ static int do_generic_cmd(const char *me, char *arg)
        const char *my_argv[4];
 
        setup_path();
-       if (!arg || !(arg = sq_dequote(arg)))
+       if (!arg || !(arg = sq_dequote(arg)) || *arg == '-')
                die("bad argument");
        if (!starts_with(me, "git-"))
                die("bad command");
index 7a6e33e..8f9b48a 100755 (executable)
@@ -183,16 +183,24 @@ test_expect_success 'up-to-date merge without common ancestor' '
 
 test_expect_success 'custom merge does not lock index' '
        git reset --hard anchor &&
-       write_script sleep-one-second.sh <<-\EOF &&
-               sleep 1 &
+       write_script sleep-an-hour.sh <<-\EOF &&
+               sleep 3600 &
                echo $! >sleep.pid
        EOF
-       test_when_finished "kill \$(cat sleep.pid)" &&
 
        test_write_lines >.gitattributes \
-               "* merge=ours" "text merge=sleep-one-second" &&
+               "* merge=ours" "text merge=sleep-an-hour" &&
        test_config merge.ours.driver true &&
-       test_config merge.sleep-one-second.driver ./sleep-one-second.sh &&
+       test_config merge.sleep-an-hour.driver ./sleep-an-hour.sh &&
+
+       # We are testing that the custom merge driver does not block
+       # index.lock on Windows due to an inherited file handle.
+       # To ensure that the backgrounded process ran sufficiently
+       # long (and has been started in the first place), we do not
+       # ignore the result of the kill command.
+       # By packaging the command in test_when_finished, we get both
+       # the correctness check and the clean-up.
+       test_when_finished "kill \$(cat sleep.pid)" &&
        git merge master
 '
 
index 2d05d3e..dfeaa9c 100755 (executable)
@@ -32,15 +32,15 @@ my @success_list = (q[Jane],
        q["Jane\" Doe" <jdoe@example.com>],
        q[Doe, jane <jdoe@example.com>],
        q["Jane Doe <jdoe@example.com>],
-       q['Jane 'Doe' <jdoe@example.com>]);
+       q['Jane 'Doe' <jdoe@example.com>],
+       q[Jane@:;\.,()<>Doe <jdoe@example.com>],
+       q[Jane <jdoe@example.com> Doe],
+       q[<jdoe@example.com> Jane Doe]);
 
 my @known_failure_list = (q[Jane\ Doe <jdoe@example.com>],
        q["Doe, Ja"ne <jdoe@example.com>],
        q["Doe, Katarina" Jane <jdoe@example.com>],
-       q[Jane@:;\.,()<>Doe <jdoe@example.com>],
        q[Jane jdoe@example.com],
-       q[<jdoe@example.com> Jane Doe],
-       q[Jane <jdoe@example.com> Doe],
        q["Jane "Kat"a" ri"na" ",Doe" <jdoe@example.com>],
        q[Jane Doe],
        q[Jane "Doe <jdoe@example.com>"],
index b3355d2..3dc4a34 100755 (executable)
@@ -140,6 +140,35 @@ test_expect_success $PREREQ 'Verify commandline' '
        test_cmp expected commandline1
 '
 
+test_expect_success $PREREQ 'setup expect for cc trailer' "
+cat >expected-cc <<\EOF
+!recipient@example.com!
+!author@example.com!
+!one@example.com!
+!two@example.com!
+!three@example.com!
+!four@example.com!
+!five@example.com!
+EOF
+"
+
+test_expect_success $PREREQ 'cc trailer with various syntax' '
+       test_commit cc-trailer &&
+       test_when_finished "git reset --hard HEAD^" &&
+       git commit --amend -F - <<-EOF &&
+       Test Cc: trailers.
+
+       Cc: one@example.com
+       Cc: <two@example.com> # this is part of the name
+       Cc: <three@example.com>, <four@example.com> # not.five@example.com
+       Cc: "Some # Body" <five@example.com> [part.of.name.too]
+       EOF
+       clean_fake_sendmail &&
+       git send-email -1 --to=recipient@example.com \
+               --smtp-server="$(pwd)/fake.sendmail" &&
+       test_cmp expected-cc commandline1
+'
+
 test_expect_success $PREREQ 'setup expect' "
 cat >expected-show-all-headers <<\EOF
 0001-Second.patch
index 21e4aa2..b021329 100644 (file)
@@ -809,7 +809,14 @@ then
                return;
 
                base=$(basename "$1")
-               symlink_target=$GIT_BUILD_DIR/$base
+               case "$base" in
+               test-*)
+                       symlink_target="$GIT_BUILD_DIR/t/helper/$base"
+                       ;;
+               *)
+                       symlink_target="$GIT_BUILD_DIR/$base"
+                       ;;
+               esac
                # do not override scripts
                if test -x "$symlink_target" &&
                    test ! -d "$symlink_target" &&
index 4215303..669ebaf 100755 (executable)
@@ -1,11 +1,19 @@
 #!/bin/sh
 
 base=$(basename "$0")
+case "$base" in
+test-*)
+       program="$GIT_VALGRIND/../../t/helper/$base"
+       ;;
+*)
+       program="$GIT_VALGRIND/../../$base"
+       ;;
+esac
 
 TOOL_OPTIONS='--leak-check=no'
 
 test -z "$GIT_VALGRIND_ENABLED" &&
-exec "$GIT_VALGRIND"/../../"$base" "$@"
+exec "$program" "$@"
 
 case "$GIT_VALGRIND_MODE" in
 memcheck-fast)
@@ -29,4 +37,4 @@ exec valgrind -q --error-exitcode=126 \
        --log-fd=4 \
        --input-fd=4 \
        $GIT_VALGRIND_OPTIONS \
-       "$GIT_VALGRIND"/../../"$base" "$@"
+       "$program" "$@"
old mode 100644 (file)
new mode 100755 (executable)