Merge branch 'ng/pack-objects-cleanup'
authorJunio C Hamano <gitster@pobox.com>
Tue, 29 May 2012 20:08:30 +0000 (13:08 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 29 May 2012 20:08:30 +0000 (13:08 -0700)
By Nguyễn Thái Ngọc Duy
* ng/pack-objects-cleanup:
pack-objects: refactor write_object() into helper functions
pack-objects, streaming: turn "xx >= big_file_threshold" to ".. > .."

37 files changed:
Documentation/RelNotes/1.7.10.3.txt
Documentation/RelNotes/1.7.11.txt
Documentation/git-config.txt
Documentation/git-grep.txt
Documentation/git-rev-parse.txt
GIT-VERSION-GEN
archive-tar.c
archive.c
builtin/checkout.c
builtin/fmt-merge-msg.c
builtin/grep.c
builtin/remote.c
cache.h
contrib/completion/git-completion.bash
contrib/credential/osxkeychain/Makefile
diff-no-index.c
dir.c
git-sh-setup.sh
grep.c
grep.h
ident.c
pretty.c
refs.c
sha1_file.c
submodule.c
t/Makefile
t/t3404-rebase-interactive.sh
t/t3411-rebase-preserve-around-merges.sh
t/t4041-diff-submodule-option.sh
t/t4053-diff-no-index.sh [new file with mode: 0755]
t/t6006-rev-list-format.sh
t/t7408-submodule-reference.sh
t/t7810-grep.sh
t/t9300-fast-import.sh
t/t9902-completion.sh
unpack-trees.c
xdiff/xutils.c
index 9c9ec25946666a7b43c18d1e9d2a1cb432d1d30d..703fbf1d60a7c2689af98bd368cd870fc954ea09 100644 (file)
@@ -4,6 +4,8 @@ Git v1.7.10.3 Release Notes
 Fixes since v1.7.10.2
 ---------------------
 
+ * The message file for German translation has been updated a bit.
+
  * Running "git checkout" on an unborn branch used to corrupt HEAD.
 
  * When checking out another commit from an already detached state, we
@@ -15,6 +17,9 @@ Fixes since v1.7.10.2
    "checkout" phase; when run without any "--quiet" option, it should
    give progress to the lengthy operation.
 
+ * The directory path used in "git diff --no-index", when it recurses
+   down, was broken with a recent update after v1.7.10.1 release.
+
  * "log -z --pretty=tformat:..." did not terminate each record with
    NUL.  The fix is not entirely correct when the output also asks for
    --patch and/or --stat, though.
@@ -23,4 +28,16 @@ Fixes since v1.7.10.2
    broken and gave undue precedence to configured log.date, causing
    "git stash list" to show "stash@{time stamp string}".
 
+ * "git status --porcelain" ignored "--branch" option by mistake.  The
+   output for "git status --branch -z" was also incorrect and did not
+   terminate the record for the current branch name with NUL as asked.
+
+ * When a submodule repository uses alternate object store mechanism,
+   some commands that were started from the superproject did not
+   notice it and failed with "No such object" errors.  The subcommands
+   of "git submodule" command that recursed into the submodule in a
+   separate process were OK; only the ones that cheated and peeked
+   directly into the submodule's repository from the primary process
+   were affected.
+
 Also contains minor fixes and documentation updates.
index 94c3615ef93c73a053c548634a2a509e2e3861de..7931f7707659b5184f97e80cbaac84c198389d46 100644 (file)
@@ -79,6 +79,9 @@ Foreign Interface
 
 Performance and Internal Implementation (please report possible regressions)
 
+ * Bash completion script (in contrib/) have been cleaned up to make
+   future work on it simpler.
+
  * An experimental "version 4" format of the index file has been
    introduced to reduce on-disk footprint and I/O overhead.
 
@@ -120,10 +123,26 @@ Unless otherwise noted, all the fixes since v1.7.10 in the maintenance
 releases are contained in this release (see release notes to them for
 details).
 
- * "git status --porcelain" ignored "--branch" option by mistake.  The
-   output for "git status --branch -z" was also incorrect and did not
-   terminate the record for the current branch name with NUL as asked.
-   (merge d4a6bf1 jk/maint-status-porcelain-z-b later to maint).
+ * The progress indicator for a large "git checkout" was sent to
+   stderr even if it is not a terminal.
+   (merge e9fc64c ap/checkout-no-progress-for-non-tty later to maint).
+
+ * A name taken from mailmap was copied into an internal buffer
+   incorrectly and could overun the buffer if it is too long.
+   (merge c9b4e9e jk/format-person-part-buffer-limit later to maint).
+
+ * A malformed commit object that has a header line chomped in the
+   middle could kill git with a NULL pointer dereference.
+   (merge a9c7a8a jk/pretty-commit-header-incomplete-line later to maint).
+
+ * An author/committer name that is a single character was mishandled
+   as an invalid name by mistake.
+   (merge d9955fd jk/ident-split-fix later to maint).
+
+ * "git grep -e '$pattern'", unlike the case where the patterns are
+   read from a file, did not treat individual lines in the given
+   pattern argument as separate regular expressions as it should.
+   (merge ec83061 rs/maint-grep-F later to maint).
 
  * "git diff --stat" used to fully count a binary file with modified
    execution bits whose contents is unmodified, which was not quite
index 3f5d216a09e4c6bf6ed3351d074a72e782f005ed..d9463cb3874181456138d4ca54da4e3540bbeb4f 100644 (file)
@@ -198,9 +198,7 @@ If not set explicitly with '--file', there are three files where
 'git config' will search for configuration options:
 
 $GIT_DIR/config::
-       Repository specific configuration file. (The filename is
-       of course relative to the repository root, not the working
-       directory.)
+       Repository specific configuration file.
 
 ~/.gitconfig::
        User-specific configuration file. Also called "global"
index 4785f1c5c657ec42baa48d6a657f535e86df0595..3bec0368831a04bc3653f11d3a0b1bff5a335907 100644 (file)
@@ -31,7 +31,9 @@ SYNOPSIS
 DESCRIPTION
 -----------
 Look for specified patterns in the tracked files in the work tree, blobs
-registered in the index file, or blobs in given tree objects.
+registered in the index file, or blobs in given tree objects.  Patterns
+are lists of one or more search expressions separated by newline
+characters.  An empty string as search expression matches all lines.
 
 
 CONFIGURATION
index f63b81aad6dd8d0fc7de0c6d9dac5f8e8dc65d6a..4cc3e9586fcfd79ddeb7f636141e1a878285b0b5 100644 (file)
@@ -137,7 +137,8 @@ shown.  If the pattern does not contain a globbing character (`?`,
 
 --git-dir::
        Show `$GIT_DIR` if defined. Otherwise show the path to
-       the .git directory, relative to the current directory.
+       the .git directory. The path shown, when relative, is
+       relative to the current working directory.
 +
 If `$GIT_DIR` is not defined and the current directory
 is not detected to lie in a git repository or work tree
index c92dbed2ecac1061770400af9c338c92d68bd1e5..ebbe8734942b88f7fb76024a50245fa005ee1328 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v1.7.10.GIT
+DEF_VER=v1.7.11-rc0
 
 LF='
 '
index 93387ea336b107340d789240b287bf0a12409f24..dc91c6b50d56ad8fd9921d0e47f5b45cafdcfc4d 100644 (file)
@@ -139,13 +139,13 @@ static void strbuf_append_ext_header(struct strbuf *sb, const char *keyword,
 
 static unsigned int ustar_header_chksum(const struct ustar_header *header)
 {
-       char *p = (char *)header;
+       const char *p = (const char *)header;
        unsigned int chksum = 0;
        while (p < header->chksum)
                chksum += *p++;
        chksum += sizeof(header->chksum) * ' ';
        p += sizeof(header->chksum);
-       while (p < (char *)header + sizeof(struct ustar_header))
+       while (p < (const char *)header + sizeof(struct ustar_header))
                chksum += *p++;
        return chksum;
 }
index cd083eaf9aa2f1ae4cfc57d90fb11b8f808fbfe7..a4844330fb4da325aa364640dc80f052dc7b7ad7 100644 (file)
--- a/archive.c
+++ b/archive.c
@@ -254,18 +254,11 @@ static void parse_treeish_arg(const char **argv,
        /* Remotes are only allowed to fetch actual refs */
        if (remote) {
                char *ref = NULL;
-               const char *refname, *colon = NULL;
-
-               colon = strchr(name, ':');
-               if (colon)
-                       refname = xstrndup(name, colon - name);
-               else
-                       refname = name;
-
-               if (!dwim_ref(refname, strlen(refname), sha1, &ref))
-                       die("no such ref: %s", refname);
-               if (refname != name)
-                       free((void *)refname);
+               const char *colon = strchr(name, ':');
+               int refnamelen = colon ? colon - name : strlen(name);
+
+               if (!dwim_ref(name, refnamelen, sha1, &ref))
+                       die("no such ref: %.*s", refnamelen, name);
                free(ref);
        }
 
index 3ddda34f7a96c56707614dbaac40631467a2b54b..e8c1b1f189f077529ef2a79accb46ef21a9b8fe7 100644 (file)
@@ -343,7 +343,7 @@ static int reset_tree(struct tree *tree, struct checkout_opts *o, int worktree)
        opts.reset = 1;
        opts.merge = 1;
        opts.fn = oneway_merge;
-       opts.verbose_update = !o->quiet;
+       opts.verbose_update = !o->quiet && isatty(2);
        opts.src_index = &the_index;
        opts.dst_index = &the_index;
        parse_tree(tree);
@@ -420,7 +420,7 @@ static int merge_working_tree(struct checkout_opts *opts,
                topts.update = 1;
                topts.merge = 1;
                topts.gently = opts->merge && old->commit;
-               topts.verbose_update = !opts->quiet;
+               topts.verbose_update = !opts->quiet && isatty(2);
                topts.fn = twoway_merge;
                if (opts->overwrite_ignore) {
                        topts.dir = xcalloc(1, sizeof(*topts.dir));
index a517f1794a1c1bcc0939ad8b81d482356c20d2ba..d42015d8672d7a929758f69371eacbbc59c92888 100644 (file)
@@ -462,7 +462,10 @@ static void fmt_tag_signature(struct strbuf *tagbuf,
                strbuf_add(tagbuf, tag_body, buf + len - tag_body);
        }
        strbuf_complete_line(tagbuf);
-       strbuf_add_lines(tagbuf, "# ", sig->buf, sig->len);
+       if (sig->len) {
+               strbuf_addch(tagbuf, '\n');
+               strbuf_add_lines(tagbuf, "# ", sig->buf, sig->len);
+       }
 }
 
 static void fmt_merge_msg_sigs(struct strbuf *out)
@@ -627,8 +630,7 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
                rev.ignore_merges = 1;
                rev.limited = 1;
 
-               if (suffixcmp(out->buf, "\n"))
-                       strbuf_addch(out, '\n');
+               strbuf_complete_line(out);
 
                for (i = 0; i < origins.nr; i++)
                        shortlog(origins.items[i].string,
index 643938d905fb134a1e65e3684e8e5feb06b01a59..fe1726f5ef60d054938eaa849f2ae6020a95f805 100644 (file)
@@ -600,15 +600,12 @@ static int file_callback(const struct option *opt, const char *arg, int unset)
        if (!patterns)
                die_errno(_("cannot open '%s'"), arg);
        while (strbuf_getline(&sb, patterns, '\n') == 0) {
-               char *s;
-               size_t len;
-
                /* ignore empty line like grep does */
                if (sb.len == 0)
                        continue;
 
-               s = strbuf_detach(&sb, &len);
-               append_grep_pat(grep_opt, s, len, arg, ++lno, GREP_PATTERN);
+               append_grep_pat(grep_opt, sb.buf, sb.len, arg, ++lno,
+                               GREP_PATTERN);
        }
        if (!from_stdin)
                fclose(patterns);
index 0f0c594b2fc2194d841cabceaf180ee664376af1..920262d76ec9bdc40a8ad7703cf1eb972a40eb9e 100644 (file)
@@ -674,7 +674,7 @@ static int mv(int argc, const char **argv)
                                      strlen(rename.old), rename.new,
                                      strlen(rename.new));
                } else
-                       warning(_("Not updating non-default fetch respec\n"
+                       warning(_("Not updating non-default fetch refspec\n"
                                  "\t%s\n"
                                  "\tPlease update the configuration manually if necessary."),
                                buf2.buf);
diff --git a/cache.h b/cache.h
index e14ffcd914be8759a5f5a71fa7fc71e4f9774f0e..cc5048c202b6799591e7121de91ee2c6cdce9997 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -947,6 +947,7 @@ extern struct alternate_object_database {
        char base[FLEX_ARRAY]; /* more */
 } *alt_odb_list;
 extern void prepare_alt_odb(void);
+extern void read_info_alternates(const char * relative_base, int depth);
 extern void add_to_alternates_file(const char *reference);
 typedef int alt_odb_fn(struct alternate_object_database *, void *);
 extern void foreach_alt_odb(alt_odb_fn, void*);
index cd92322161a89a23d3f494a7c7b7aaf5867a5781..1689f99539728c87c29cfa94a08ee9a67db3cce2 100755 (executable)
@@ -2597,7 +2597,7 @@ _git_whatchanged ()
        _git_log
 }
 
-_git ()
+_main_git ()
 {
        local i c=1 command __git_dir
 
@@ -2648,7 +2648,7 @@ _git ()
        fi
 }
 
-_gitk ()
+_main_gitk ()
 {
        __git_has_doubledash && return
 
@@ -2700,13 +2700,25 @@ __git_complete ()
                || complete -o default -o nospace -F $wrapper $1
 }
 
-__git_complete git _git
-__git_complete gitk _gitk
+# wrapper for backwards compatibility
+_git ()
+{
+       __git_wrap_main_git
+}
+
+# wrapper for backwards compatibility
+_gitk ()
+{
+       __git_wrap_main_gitk
+}
+
+__git_complete git _main_git
+__git_complete gitk _main_gitk
 
 # The following are necessary only for Cygwin, and only are needed
 # when the user has tab-completed the executable name and consequently
 # included the '.exe' suffix.
 #
 if [ Cygwin = "$(uname -o 2>/dev/null)" ]; then
-__git_complete git.exe _git
+__git_complete git.exe _main_git
 fi
index 75c07f8be4ae6ece8adb5c7190e4de38891f8787..4b3a08a2bac441f3841367d98f425b9b6a5a3598 100644 (file)
@@ -2,10 +2,13 @@ all:: git-credential-osxkeychain
 
 CC = gcc
 RM = rm -f
-CFLAGS = -g -Wall
+CFLAGS = -g -O2 -Wall
+
+-include ../../../config.mak.autogen
+-include ../../../config.mak
 
 git-credential-osxkeychain: git-credential-osxkeychain.o
-       $(CC) -o $@ $< -Wl,-framework -Wl,Security
+       $(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) -Wl,-framework -Wl,Security
 
 git-credential-osxkeychain.o: git-credential-osxkeychain.c
        $(CC) -c $(CFLAGS) $<
index b44473e3c1fd5c2bdc4dce3af7aabc86fd37eb08..f0b0010aedd67f9b34f43426c47e837dfe2a522b 100644 (file)
@@ -68,6 +68,7 @@ static int queue_diff(struct diff_options *o,
                struct string_list p1 = STRING_LIST_INIT_DUP;
                struct string_list p2 = STRING_LIST_INIT_DUP;
                int i1, i2, ret = 0;
+               size_t len1 = 0, len2 = 0;
 
                if (name1 && read_directory(name1, &p1))
                        return -1;
@@ -80,18 +81,23 @@ static int queue_diff(struct diff_options *o,
                        strbuf_addstr(&buffer1, name1);
                        if (buffer1.len && buffer1.buf[buffer1.len - 1] != '/')
                                strbuf_addch(&buffer1, '/');
+                       len1 = buffer1.len;
                }
 
                if (name2) {
                        strbuf_addstr(&buffer2, name2);
                        if (buffer2.len && buffer2.buf[buffer2.len - 1] != '/')
                                strbuf_addch(&buffer2, '/');
+                       len2 = buffer2.len;
                }
 
                for (i1 = i2 = 0; !ret && (i1 < p1.nr || i2 < p2.nr); ) {
                        const char *n1, *n2;
                        int comp;
 
+                       strbuf_setlen(&buffer1, len1);
+                       strbuf_setlen(&buffer2, len2);
+
                        if (i1 == p1.nr)
                                comp = 1;
                        else if (i2 == p2.nr)
@@ -117,8 +123,8 @@ static int queue_diff(struct diff_options *o,
                }
                string_list_clear(&p1, 0);
                string_list_clear(&p2, 0);
-               strbuf_reset(&buffer1);
-               strbuf_reset(&buffer2);
+               strbuf_release(&buffer1);
+               strbuf_release(&buffer2);
 
                return ret;
        } else {
diff --git a/dir.c b/dir.c
index c6a98cc8dd69609bc2bdbe202973ecbd79bcfa32..ed1510fbc808f4c9799eb84a3c38030b7565f3bc 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -74,7 +74,6 @@ char *common_prefix(const char **pathspec)
 
 int fill_directory(struct dir_struct *dir, const char **pathspec)
 {
-       const char *path;
        size_t len;
 
        /*
@@ -82,15 +81,9 @@ int fill_directory(struct dir_struct *dir, const char **pathspec)
         * use that to optimize the directory walk
         */
        len = common_prefix_len(pathspec);
-       path = "";
-
-       if (len)
-               path = xmemdupz(*pathspec, len);
 
        /* Read the directory and prune it */
-       read_directory(dir, path, len, pathspec);
-       if (*path)
-               free((char *)path);
+       read_directory(dir, pathspec ? *pathspec : "", len, pathspec);
        return len;
 }
 
@@ -960,16 +953,17 @@ static int read_directory_recursive(struct dir_struct *dir,
                                    int check_only,
                                    const struct path_simplify *simplify)
 {
-       DIR *fdir = opendir(*base ? base : ".");
+       DIR *fdir;
        int contents = 0;
        struct dirent *de;
        struct strbuf path = STRBUF_INIT;
 
-       if (!fdir)
-               return 0;
-
        strbuf_add(&path, base, baselen);
 
+       fdir = opendir(path.len ? path.buf : ".");
+       if (!fdir)
+               goto out;
+
        while ((de = readdir(fdir)) != NULL) {
                switch (treat_path(dir, de, &path, baselen, simplify)) {
                case path_recurse:
@@ -984,12 +978,11 @@ static int read_directory_recursive(struct dir_struct *dir,
                }
                contents++;
                if (check_only)
-                       goto exit_early;
-               else
-                       dir_add_name(dir, path.buf, path.len);
+                       break;
+               dir_add_name(dir, path.buf, path.len);
        }
-exit_early:
        closedir(fdir);
+ out:
        strbuf_release(&path);
 
        return contents;
index 7b3ae75d7a631fb07404ab85fa6d43ada74d8512..770a86e2b7a5e517e51d9897b274b876a6b9e0e1 100644 (file)
@@ -218,27 +218,8 @@ clear_local_git_env() {
        unset $(git rev-parse --local-env-vars)
 }
 
-# Make sure we are in a valid repository of a vintage we understand,
-# if we require to be in a git repository.
-if test -z "$NONGIT_OK"
-then
-       GIT_DIR=$(git rev-parse --git-dir) || exit
-       if [ -z "$SUBDIRECTORY_OK" ]
-       then
-               test -z "$(git rev-parse --show-cdup)" || {
-                       exit=$?
-                       echo >&2 "You need to run this command from the toplevel of the working tree."
-                       exit $exit
-               }
-       fi
-       test -n "$GIT_DIR" && GIT_DIR=$(cd "$GIT_DIR" && pwd) || {
-               echo >&2 "Unable to determine absolute path of git directory"
-               exit 1
-       }
-       : ${GIT_OBJECT_DIRECTORY="$GIT_DIR/objects"}
-fi
 
-# Fix some commands on Windows
+# Platform specific tweaks to work around some commands
 case $(uname -s) in
 *MINGW*)
        # Windows has its own (incompatible) sort and find
@@ -269,3 +250,23 @@ case $(uname -s) in
                return 1
        }
 esac
+
+# Make sure we are in a valid repository of a vintage we understand,
+# if we require to be in a git repository.
+if test -z "$NONGIT_OK"
+then
+       GIT_DIR=$(git rev-parse --git-dir) || exit
+       if [ -z "$SUBDIRECTORY_OK" ]
+       then
+               test -z "$(git rev-parse --show-cdup)" || {
+                       exit=$?
+                       echo >&2 "You need to run this command from the toplevel of the working tree."
+                       exit $exit
+               }
+       fi
+       test -n "$GIT_DIR" && GIT_DIR=$(cd "$GIT_DIR" && pwd) || {
+               echo >&2 "Unable to determine absolute path of git directory"
+               exit 1
+       }
+       : ${GIT_OBJECT_DIRECTORY="$GIT_DIR/objects"}
+fi
diff --git a/grep.c b/grep.c
index f8ffa46209c0797f2b5f1f1d7470243a4e7654d1..04e3ec6c6e90e8bd96495c7b40bcb014384b07d8 100644 (file)
--- a/grep.c
+++ b/grep.c
@@ -3,18 +3,64 @@
 #include "userdiff.h"
 #include "xdiff-interface.h"
 
-void append_header_grep_pattern(struct grep_opt *opt, enum grep_header_field field, const char *pat)
+static struct grep_pat *create_grep_pat(const char *pat, size_t patlen,
+                                       const char *origin, int no,
+                                       enum grep_pat_token t,
+                                       enum grep_header_field field)
 {
        struct grep_pat *p = xcalloc(1, sizeof(*p));
-       p->pattern = pat;
-       p->patternlen = strlen(pat);
-       p->origin = "header";
-       p->no = 0;
-       p->token = GREP_PATTERN_HEAD;
+       p->pattern = xmemdupz(pat, patlen);
+       p->patternlen = patlen;
+       p->origin = origin;
+       p->no = no;
+       p->token = t;
        p->field = field;
-       *opt->header_tail = p;
-       opt->header_tail = &p->next;
+       return p;
+}
+
+static void do_append_grep_pat(struct grep_pat ***tail, struct grep_pat *p)
+{
+       **tail = p;
+       *tail = &p->next;
        p->next = NULL;
+
+       switch (p->token) {
+       case GREP_PATTERN: /* atom */
+       case GREP_PATTERN_HEAD:
+       case GREP_PATTERN_BODY:
+               for (;;) {
+                       struct grep_pat *new_pat;
+                       size_t len = 0;
+                       char *cp = p->pattern + p->patternlen, *nl = NULL;
+                       while (++len <= p->patternlen) {
+                               if (*(--cp) == '\n') {
+                                       nl = cp;
+                                       break;
+                               }
+                       }
+                       if (!nl)
+                               break;
+                       new_pat = create_grep_pat(nl + 1, len - 1, p->origin,
+                                                 p->no, p->token, p->field);
+                       new_pat->next = p->next;
+                       if (!p->next)
+                               *tail = &new_pat->next;
+                       p->next = new_pat;
+                       *nl = '\0';
+                       p->patternlen -= len;
+               }
+               break;
+       default:
+               break;
+       }
+}
+
+void append_header_grep_pattern(struct grep_opt *opt,
+                               enum grep_header_field field, const char *pat)
+{
+       struct grep_pat *p = create_grep_pat(pat, strlen(pat), "header", 0,
+                                            GREP_PATTERN_HEAD, field);
+       do_append_grep_pat(&opt->header_tail, p);
 }
 
 void append_grep_pattern(struct grep_opt *opt, const char *pat,
@@ -26,15 +72,8 @@ void append_grep_pattern(struct grep_opt *opt, const char *pat,
 void append_grep_pat(struct grep_opt *opt, const char *pat, size_t patlen,
                     const char *origin, int no, enum grep_pat_token t)
 {
-       struct grep_pat *p = xcalloc(1, sizeof(*p));
-       p->pattern = pat;
-       p->patternlen = patlen;
-       p->origin = origin;
-       p->no = no;
-       p->token = t;
-       *opt->pattern_tail = p;
-       opt->pattern_tail = &p->next;
-       p->next = NULL;
+       struct grep_pat *p = create_grep_pat(pat, patlen, origin, no, t, 0);
+       do_append_grep_pat(&opt->pattern_tail, p);
 }
 
 struct grep_opt *grep_opt_dup(const struct grep_opt *opt)
@@ -430,6 +469,7 @@ void free_grep_patterns(struct grep_opt *opt)
                                free_pcre_regexp(p);
                        else
                                regfree(&p->regexp);
+                       free(p->pattern);
                        break;
                default:
                        break;
diff --git a/grep.h b/grep.h
index 36e49d8255e2952828f367a0e35d4fcb027d9772..ed7de6bec8e604a7b3dcb9f9a19053696b7c3fdf 100644 (file)
--- a/grep.h
+++ b/grep.h
@@ -38,7 +38,7 @@ struct grep_pat {
        const char *origin;
        int no;
        enum grep_pat_token token;
-       const char *pattern;
+       char *pattern;
        size_t patternlen;
        enum grep_header_field field;
        regex_t regexp;
diff --git a/ident.c b/ident.c
index 87c697c2b09692ec8a36d557aa0c73de38223492..5df094d175ab91afb9ead68431f0c99bde7fd03f 100644 (file)
--- a/ident.c
+++ b/ident.c
@@ -244,7 +244,7 @@ int split_ident_line(struct ident_split *split, const char *line, int len)
        if (!split->mail_begin)
                return status;
 
-       for (cp = split->mail_begin - 2; line < cp; cp--)
+       for (cp = split->mail_begin - 2; line <= cp; cp--)
                if (!isspace(*cp)) {
                        split->name_end = cp + 1;
                        break;
index 02a0a2bb43570fec656c4152454fa67743111a2c..8b1ea9ffad2a0b5c5cb5c15cc5057a8a7132da07 100644 (file)
--- a/pretty.c
+++ b/pretty.c
@@ -439,12 +439,14 @@ static char *get_header(const struct commit *commit, const char *key)
        int key_len = strlen(key);
        const char *line = commit->buffer;
 
-       for (;;) {
+       while (line) {
                const char *eol = strchr(line, '\n'), *next;
 
                if (line == eol)
                        return NULL;
                if (!eol) {
+                       warning("malformed commit (header is missing newline): %s",
+                               sha1_to_hex(commit->object.sha1));
                        eol = line + strlen(line);
                        next = NULL;
                } else
@@ -456,6 +458,7 @@ static char *get_header(const struct commit *commit, const char *key)
                }
                line = next;
        }
+       return NULL;
 }
 
 static char *replace_encoding_header(char *buf, const char *encoding)
@@ -547,8 +550,10 @@ static size_t format_person_part(struct strbuf *sb, char part,
        mail_end = s.mail_end;
 
        if (part == 'N' || part == 'E') { /* mailmap lookup */
-               strlcpy(person_name, name_start, name_end - name_start + 1);
-               strlcpy(person_mail, mail_start, mail_end - mail_start + 1);
+               snprintf(person_name, sizeof(person_name), "%.*s",
+                        (int)(name_end - name_start), name_start);
+               snprintf(person_mail, sizeof(person_mail), "%.*s",
+                        (int)(mail_end - mail_start), mail_start);
                mailmap_name(person_mail, sizeof(person_mail), person_name, sizeof(person_name));
                name_start = person_name;
                name_end = name_start + strlen(person_name);
diff --git a/refs.c b/refs.c
index d6bdb47ad61dc5e7eb1c786dd4115e17bdb2aab7..010ed07e33d90cbdae4511013319a129c1201ca9 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -273,6 +273,12 @@ static void add_entry_to_dir(struct ref_dir *dir, struct ref_entry *entry)
 {
        ALLOC_GROW(dir->entries, dir->nr + 1, dir->alloc);
        dir->entries[dir->nr++] = entry;
+       /* optimize for the case that entries are added in order */
+       if (dir->nr == 1 ||
+           (dir->nr == dir->sorted + 1 &&
+            strcmp(dir->entries[dir->nr - 2]->name,
+                   dir->entries[dir->nr - 1]->name) < 0))
+               dir->sorted = dir->nr;
 }
 
 /*
index 3c4f1652f13479238dee56674cbb86d299363be1..4ccaf7ac197c28400eddd496abcfc725528ca32b 100644 (file)
@@ -229,7 +229,6 @@ char *sha1_pack_index_name(const unsigned char *sha1)
 struct alternate_object_database *alt_odb_list;
 static struct alternate_object_database **alt_odb_tail;
 
-static void read_info_alternates(const char * alternates, int depth);
 static int git_open_noatime(const char *name);
 
 /*
@@ -354,7 +353,7 @@ static void link_alt_odb_entries(const char *alt, const char *ep, int sep,
        }
 }
 
-static void read_info_alternates(const char * relative_base, int depth)
+void read_info_alternates(const char * relative_base, int depth)
 {
        char *map;
        size_t mapsz;
index 784b58039dd078fc1e0c4554820cd0e99c8e41d2..959d349ea7426344289020ee4216785fa65ec1e6 100644 (file)
@@ -63,6 +63,9 @@ static int add_submodule_odb(const char *path)
        alt_odb->name[40] = '\0';
        alt_odb->name[41] = '\0';
        alt_odb_list = alt_odb;
+
+       /* add possible alternates from the submodule */
+       read_info_alternates(objects_directory.buf, 0);
        prepare_alt_odb();
 done:
        strbuf_release(&objects_directory);
index 6091211f1009679aee741f3f6c2b290033aa5dc6..88e289fc8b790bad258fb29711e8dac675c7c3e9 100644 (file)
@@ -28,7 +28,7 @@ test: pre-clean $(TEST_LINT)
 
 prove: pre-clean $(TEST_LINT)
        @echo "*** prove ***"; GIT_CONFIG=.git/config $(PROVE) --exec '$(SHELL_PATH_SQ)' $(GIT_PROVE_OPTS) $(T) :: $(GIT_TEST_OPTS)
-       $(MAKE) clean
+       $(MAKE) clean-except-prove-cache
 
 $(T):
        @echo "*** $@ ***"; GIT_CONFIG=.git/config '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS)
@@ -36,9 +36,11 @@ $(T):
 pre-clean:
        $(RM) -r test-results
 
-clean:
+clean-except-prove-cache:
        $(RM) -r 'trash directory'.* test-results
        $(RM) -r valgrind/bin
+
+clean: clean-except-prove-cache
        $(RM) .prove
 
 test-lint: test-lint-duplicates test-lint-executable
index 4983bd77753307a7f93963b02534f36ae6fc71bb..025c1c610efee9562343b34a9c815f34f51ed9ac 100755 (executable)
@@ -247,6 +247,7 @@ test_expect_success '-p handles "no changes" gracefully' '
 '
 
 test_expect_failure 'exchange two commits with -p' '
+       git checkout H &&
        FAKE_LINES="2 1" git rebase -i -p HEAD~2 &&
        test H = $(git cat-file commit HEAD^ | sed -ne \$p) &&
        test G = $(git cat-file commit HEAD | sed -ne \$p)
index ace8e54e9b374688751cc470eeb9003ca7f5c48f..dc81bf27eb736d32df0f0c3205de3254898d20b5 100755 (executable)
@@ -56,6 +56,7 @@ test_expect_success 'squash F1 into D1' '
 # And rebase G1..M1 onto E2
 
 test_expect_success 'rebase two levels of merge' '
+       git checkout A1 &&
        test_commit G1 &&
        test_commit H1 &&
        test_commit I1 &&
index bf9a7526bd38a17e0e991739db8c4a1f8541b2f6..6c01d0c056e2608393ed16eea29dd45fc79d786c 100755 (executable)
@@ -458,4 +458,38 @@ EOF
        test_cmp expected actual
 '
 
+test_expect_success 'diff --submodule with objects referenced by alternates' '
+       mkdir sub_alt &&
+       (cd sub_alt &&
+               git init &&
+               echo a >a &&
+               git add a &&
+               git commit -m a
+       ) &&
+       mkdir super &&
+       (cd super &&
+               git clone -s ../sub_alt sub &&
+               git init &&
+               git add sub &&
+               git commit -m "sub a"
+       ) &&
+       (cd sub_alt &&
+               sha1_before=$(git rev-parse --short HEAD)
+               echo b >b &&
+               git add b &&
+               git commit -m b
+               sha1_after=$(git rev-parse --short HEAD)
+               echo "Submodule sub $sha1_before..$sha1_after:
+  > b" >../expected
+       ) &&
+       (cd super &&
+               (cd sub &&
+                       git fetch &&
+                       git checkout origin/master
+               ) &&
+               git diff --submodule > ../actual
+       )
+       test_cmp expected actual
+'
+
 test_done
diff --git a/t/t4053-diff-no-index.sh b/t/t4053-diff-no-index.sh
new file mode 100755 (executable)
index 0000000..4dc8c67
--- /dev/null
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+test_description='diff --no-index'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+       mkdir a &&
+       mkdir b &&
+       echo 1 >a/1 &&
+       echo 2 >a/2
+'
+
+test_expect_success 'git diff --no-index directories' '
+       git diff --no-index a b >cnt
+       test $? = 1 && test_line_count = 14 cnt
+'
+
+test_done
index a01d2445022ecb82fe0e31739527339fa02e44a5..f94f0c48e6337f6bd718b4fc6859a52411e09326 100755 (executable)
@@ -283,4 +283,11 @@ test_expect_success 'oneline with empty message' '
        test_line_count = 5 testg.txt
 '
 
+test_expect_success 'single-character name is parsed correctly' '
+       git commit --author="a <a@example.com>" --allow-empty -m foo &&
+       echo "a <a@example.com>" >expect &&
+       git log -1 --format="%an <%ae>" >actual &&
+       test_cmp expect actual
+'
+
 test_done
index a45fadc58e047aa0e6637b9ef5dce86a28ddc4f1..b770b2f04d56336f92b9394b4a2ce22a241480c4 100755 (executable)
@@ -28,7 +28,7 @@ git prune'
 
 cd "$base_dir"
 
-test_expect_success 'preparing supermodule' \
+test_expect_success 'preparing superproject' \
 'test_create_repo super && cd super &&
 echo file > file &&
 git add file &&
@@ -55,7 +55,7 @@ diff expected current'
 
 cd "$base_dir"
 
-test_expect_success 'cloning supermodule' \
+test_expect_success 'cloning superproject' \
 'git clone super super-clone'
 
 cd "$base_dir"
index d9ad633310a19a9ebbc2e5024875278d4631129e..24e9b1974d17a02dd1c668e888a67f894e7a1209 100755 (executable)
@@ -351,6 +351,11 @@ test_expect_success 'grep -f, multiple patterns' '
        test_cmp expected actual
 '
 
+test_expect_success 'grep, multiple patterns' '
+       git grep "$(cat patterns)" >actual &&
+       test_cmp expected actual
+'
+
 cat >expected <<EOF
 file:foo mmap bar
 file:foo_mmap bar
index 7da0e8da7bfd68c0ac4e0b987664c7340078eb99..2aa1824a940aa955fab408995d2479e50bd42b96 100755 (executable)
@@ -1657,7 +1657,7 @@ M 160000 :6 sub
 INPUT_END
 
 test_expect_success \
-       'P: supermodule & submodule mix' \
+       'P: superproject & submodule mix' \
        'git fast-import <input &&
         git checkout subuse1 &&
         rm -rf sub && mkdir sub && (cd sub &&
index 0f09fd6109386ae408a4441562ed69b6650880ae..9a80c60945839fa66fc3a0dc742a8f9ac977f9e1 100755 (executable)
@@ -63,7 +63,7 @@ run_completion ()
        local _cword
        _words=( $1 )
        (( _cword = ${#_words[@]} - 1 ))
-       __git_wrap_git && print_comp
+       __git_wrap_main_git && print_comp
 }
 
 test_completion ()
index bcee99c52e3a9ee8d67f70c577e57bbde8a8b610..ad40109432971b8b26f107a84b02aeb405e8daf9 100644 (file)
@@ -1210,7 +1210,7 @@ static int verify_uptodate_1(struct cache_entry *ce,
                        return 0;
                /*
                 * NEEDSWORK: the current default policy is to allow
-                * submodule to be out of sync wrt the supermodule
+                * submodule to be out of sync wrt the superproject
                 * index.  This needs to be tightened later for
                 * submodules that are marked to be automatically
                 * checked out.
index ae6ce0d95c9dee16975e43b37ed0b2b9e3ef61ea..9504eaecb8ac45248ea22b0779aa7492cd15d83e 100644 (file)
@@ -251,9 +251,11 @@ static unsigned long xdl_hash_record_with_whitespace(char const **data,
 
 #ifdef XDL_FAST_HASH
 
-#define ONEBYTES       0x0101010101010101ul
-#define NEWLINEBYTES   0x0a0a0a0a0a0a0a0aul
-#define HIGHBITS       0x8080808080808080ul
+#define REPEAT_BYTE(x)  ((~0ul / 0xff) * (x))
+
+#define ONEBYTES       REPEAT_BYTE(0x01)
+#define NEWLINEBYTES   REPEAT_BYTE(0x0a)
+#define HIGHBITS       REPEAT_BYTE(0x80)
 
 /* Return the high bit set in the first byte that is a zero */
 static inline unsigned long has_zero(unsigned long a)
@@ -270,21 +272,19 @@ static inline long count_masked_bytes(unsigned long mask)
                 * that works for the bytemasks without having to
                 * mask them first.
                 */
-               return mask * 0x0001020304050608 >> 56;
-       } else {
                /*
-                * Modified Carl Chatfield G+ version for 32-bit *
+                * return mask * 0x0001020304050608 >> 56;
                 *
-                * (a) gives us
-                *   -1 (0, ff), 0 (ffff) or 1 (ffffff)
-                * (b) gives us
-                *   0 for 0, 1 for (ff ffff ffffff)
-                * (a+b+1) gives us
-                *   correct 0-3 bytemask count result
+                * Doing it like this avoids warnings on 32-bit machines.
                 */
-               long a = (mask - 256) >> 23;
-               long b = mask & 1;
-               return a + b + 1;
+               long a = (REPEAT_BYTE(0x01) / 0xff + 1);
+               return mask * a >> (sizeof(long) * 7);
+       } else {
+               /* Carl Chatfield / Jan Achrenius G+ version for 32-bit */
+               /* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */
+               long a = (0x0ff0001 + mask) >> 23;
+               /* Fix the 1 for 00 case */
+               return a & mask;
        }
 }