Merge branch 'master' into mk/rename
authorJunio C Hamano <junkio@cox.net>
Tue, 8 Aug 2006 22:42:20 +0000 (15:42 -0700)
committerJunio C Hamano <junkio@cox.net>
Tue, 8 Aug 2006 22:42:20 +0000 (15:42 -0700)
17 files changed:
Documentation/git-rev-list.txt
GIT-VERSION-GEN
Makefile
builtin-grep.c
builtin-log.c
builtin-mv.c
builtin-tar-tree.c
git-annotate.perl
git-clone.sh
git-compat-util.h
git.c
http-fetch.c
local-fetch.c
log-tree.c
setup.c
ssh-fetch.c
t/t7002-grep.sh [new file with mode: 0755]
index f60eacd93e96a080689569b1afd6736c05554ab7..dd9fff16d3067fe939642170258fffc427c77729 100644 (file)
@@ -22,6 +22,7 @@ SYNOPSIS
             [ [\--objects | \--objects-edge] [ \--unpacked ] ]
             [ \--pretty | \--header ]
             [ \--bisect ]
+            [ \--merge ]
             <commit>... [ \-- <paths>... ]
 
 DESCRIPTION
@@ -123,6 +124,10 @@ OPTIONS
        topological order (i.e. descendant commits are shown
        before their parents).
 
+--merge::
+       After a failed merge, show refs that touch files having a
+       conflict and don't exist on all heads to merge.
+
 Author
 ------
 Written by Linus Torvalds <torvalds@osdl.org>
index 1ce217dd7ba020e0aca1caf0008f65ad83eb309e..14923c973bdcb87aaacb27f98eecc6215d5293b6 100755 (executable)
@@ -3,9 +3,17 @@
 GVF=GIT-VERSION-FILE
 DEF_VER=v1.4.2.GIT
 
+LF='
+'
+
 # First try git-describe, then see if there is a version file
 # (included in release tarballs), then default
-if VN=$(git describe --abbrev=4 HEAD 2>/dev/null); then
+if VN=$(git describe --abbrev=4 HEAD 2>/dev/null) &&
+   case "$VN" in
+   *$LF*) (exit 1) ;;
+   v[0-9]*) : happy ;;
+   esac
+then
        VN=$(echo "$VN" | sed -e 's/-/./g');
 elif test -f version
 then
index dc39f72f1eb8b3a05c03ffe16e62b056924cf573..733fa660d9032fee8f7ad32fffa9803a113b11af 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -334,9 +334,9 @@ ifeq ($(uname_O),Cygwin)
        NO_D_TYPE_IN_DIRENT = YesPlease
        NO_D_INO_IN_DIRENT = YesPlease
        NO_STRCASESTR = YesPlease
-       NO_STRLCPY = YesPlease
        NO_SYMLINK_HEAD = YesPlease
        NEEDS_LIBICONV = YesPlease
+       NO_C99_FORMAT = YesPlease
        # There are conflicting reports about this.
        # On some boxes NO_MMAP is needed, and not so elsewhere.
        # Try uncommenting this if you see things break -- YMMV.
index 69b7c4862af3bfcbc9aea2cb52abaa65b3e8490b..93b7e07b30ced0b4f4bad544d9bd8dbedadf452c 100644 (file)
@@ -410,8 +410,10 @@ static int fixmatch(const char *pattern, char *line, regmatch_t *match)
 static int match_one_pattern(struct grep_opt *opt, struct grep_pat *p, char *bol, char *eol)
 {
        int hit = 0;
+       int at_true_bol = 1;
        regmatch_t pmatch[10];
 
+ again:
        if (!opt->fixed) {
                regex_t *exp = &p->regexp;
                hit = !regexec(exp, bol, ARRAY_SIZE(pmatch),
@@ -422,22 +424,35 @@ static int match_one_pattern(struct grep_opt *opt, struct grep_pat *p, char *bol
        }
 
        if (hit && opt->word_regexp) {
-               /* Match beginning must be either
-                * beginning of the line, or at word
-                * boundary (i.e. the last char must
-                * not be alnum or underscore).
-                */
                if ((pmatch[0].rm_so < 0) ||
                    (eol - bol) <= pmatch[0].rm_so ||
                    (pmatch[0].rm_eo < 0) ||
                    (eol - bol) < pmatch[0].rm_eo)
                        die("regexp returned nonsense");
-               if (pmatch[0].rm_so != 0 &&
-                   word_char(bol[pmatch[0].rm_so-1]))
-                       hit = 0;
-               if (pmatch[0].rm_eo != (eol-bol) &&
-                   word_char(bol[pmatch[0].rm_eo]))
+
+               /* Match beginning must be either beginning of the
+                * line, or at word boundary (i.e. the last char must
+                * not be a word char).  Similarly, match end must be
+                * either end of the line, or at word boundary
+                * (i.e. the next char must not be a word char).
+                */
+               if ( ((pmatch[0].rm_so == 0 && at_true_bol) ||
+                     !word_char(bol[pmatch[0].rm_so-1])) &&
+                    ((pmatch[0].rm_eo == (eol-bol)) ||
+                     !word_char(bol[pmatch[0].rm_eo])) )
+                       ;
+               else
                        hit = 0;
+
+               if (!hit && pmatch[0].rm_so + bol + 1 < eol) {
+                       /* There could be more than one match on the
+                        * line, and the first match might not be
+                        * strict word match.  But later ones could be!
+                        */
+                       bol = pmatch[0].rm_so + bol + 1;
+                       at_true_bol = 0;
+                       goto again;
+               }
        }
        return hit;
 }
index bba1496bf20fb14ad994f8ddacc82ec990d412d8..691cf3aef785950132c6be65f8aab39d4b12207e 100644 (file)
@@ -257,6 +257,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
        char message_id[1024];
        char ref_message_id[1024];
 
+       setup_ident();
        git_config(git_format_config);
        init_revisions(&rev, prefix);
        rev.commit_format = CMIT_FMT_EMAIL;
@@ -306,7 +307,6 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
                         !strcmp(argv[i], "-s")) {
                        const char *committer;
                        const char *endpos;
-                       setup_ident();
                        committer = git_committer_info(1);
                        endpos = strchr(committer, '>');
                        if (!endpos)
index e47942c13522b2bc8a83203c61071697c9a03307..ce8187c1e96833e1a6db2fa368a84b02fec7b0c2 100644 (file)
@@ -48,7 +48,8 @@ static const char *add_slash(const char *path)
        if (path[len - 1] != '/') {
                char *with_slash = xmalloc(len + 2);
                memcpy(with_slash, path, len);
-               strcat(with_slash + len, "/");
+               with_slash[len++] = '/';
+               with_slash[len] = 0;
                return with_slash;
        }
        return path;
index 7c48db9ec85adb1b8866b2cc1dc0eccd2d1816c7..215892b6967ab3b42ef3826e3e934001de1f5162 100644 (file)
@@ -314,6 +314,7 @@ static int generate_tar(int argc, const char **argv, const char *prefix)
        struct commit *commit;
        struct tree_desc tree;
        struct strbuf current_path;
+       void *buffer;
 
        current_path.buf = xmalloc(PATH_MAX);
        current_path.alloc = PATH_MAX;
@@ -341,8 +342,8 @@ static int generate_tar(int argc, const char **argv, const char *prefix)
        } else
                archive_time = time(NULL);
 
-       tree.buf = read_object_with_reference(sha1, tree_type, &tree.size,
-                                             tree_sha1);
+       tree.buf = buffer = read_object_with_reference(sha1, tree_type,
+                                                      &tree.size, tree_sha1);
        if (!tree.buf)
                die("not a reference to a tag, commit or tree object: %s",
                    sha1_to_hex(sha1));
@@ -351,6 +352,7 @@ static int generate_tar(int argc, const char **argv, const char *prefix)
                write_entry(tree_sha1, &current_path, 040777, NULL, 0);
        traverse_tree(&tree, &current_path);
        write_trailer();
+       free(buffer);
        free(current_path.buf);
        return 0;
 }
index 505b5ccb280e16e4279569810ed1f41cf247e570..215ed26f3aff4b12139359ca841a9a80c567a6e6 100755 (executable)
@@ -147,7 +147,7 @@ sub init_claim {
 
 
 sub handle_rev {
-       my $i = 0;
+       my $revseen = 0;
        my %seen;
        while (my $rev = shift @revqueue) {
                next if $seen{$rev}++;
@@ -247,22 +247,129 @@ sub git_find_parent {
        return $parent;
 }
 
+sub git_find_all_parents {
+       my ($rev) = @_;
+
+       my $revparent = open_pipe("git-rev-list","--remove-empty", "--parents","--max-count=1","$rev")
+               or die "Failed to open git-rev-list to find a single parent: $!";
+
+       my $parentline = <$revparent>;
+       chomp $parentline;
+       my ($origrev, @parents) = split m/\s+/, $parentline;
+
+       close($revparent);
+
+       return @parents;
+}
+
+sub git_merge_base {
+       my ($rev1, $rev2) = @_;
+
+       my $mb = open_pipe("git-merge-base", $rev1, $rev2)
+               or die "Failed to open git-merge-base: $!";
+
+       my $base = <$mb>;
+       chomp $base;
+
+       close($mb);
+
+       return $base;
+}
+
+# Construct a set of pseudo parents that are in the same order,
+# and the same quantity as the real parents,
+# but whose SHA1s are as similar to the logical parents
+# as possible.
+sub get_pseudo_parents {
+       my ($all, $fake) = @_;
+
+       my @all = @$all;
+       my @fake = @$fake;
+
+       my @pseudo;
+
+       my %fake = map {$_ => 1} @fake;
+       my %seenfake;
+
+       my $fakeidx = 0;
+       foreach my $p (@all) {
+               if (exists $fake{$p}) {
+                       if ($fake[$fakeidx] ne $p) {
+                               die sprintf("parent mismatch: %s != %s\nall:%s\nfake:%s\n",
+                                           $fake[$fakeidx], $p,
+                                           join(", ", @all),
+                                           join(", ", @fake),
+                                          );
+                       }
+
+                       push @pseudo, $p;
+                       $fakeidx++;
+                       $seenfake{$p}++;
+
+               } else {
+                       my $base = git_merge_base($fake[$fakeidx], $p);
+                       if ($base ne $fake[$fakeidx]) {
+                               die sprintf("Result of merge-base doesn't match fake: %s,%s != %s\n",
+                                      $fake[$fakeidx], $p, $base);
+                       }
+
+                       # The details of how we parse the diffs
+                       # mean that we cannot have a duplicate
+                       # revision in the list, so if we've already
+                       # seen the revision we would normally add, just use
+                       # the actual revision.
+                       if ($seenfake{$base}) {
+                               push @pseudo, $p;
+                       } else {
+                               push @pseudo, $base;
+                               $seenfake{$base}++;
+                       }
+               }
+       }
+
+       return @pseudo;
+}
+
 
 # Get a diff between the current revision and a parent.
 # Record the commit information that results.
 sub git_diff_parse {
        my ($parents, $rev, %revinfo) = @_;
 
+       my @pseudo_parents;
+       my @command = ("git-diff-tree");
+       my $revision_spec;
+
+       if (scalar @$parents == 1) {
+
+               $revision_spec = join("..", $parents->[0], $rev);
+               @pseudo_parents = @$parents;
+       } else {
+               my @all_parents = git_find_all_parents($rev);
+
+               if (@all_parents !=  @$parents) {
+                       @pseudo_parents = get_pseudo_parents(\@all_parents, $parents);
+               } else {
+                       @pseudo_parents = @$parents;
+               }
+
+               $revision_spec = $rev;
+               push @command, "-c";
+       }
+
        my @filenames = ( $revs{$rev}{'filename'} );
+
        foreach my $parent (@$parents) {
                push @filenames, $revs{$parent}{'filename'};
        }
 
-       my $diff = open_pipe("git-diff-tree","-M","-p","-c",$rev,"--",
-                               @filenames )
+       push @command, "-p", "-M", $revision_spec, "--", @filenames;
+
+
+       my $diff = open_pipe( @command )
                or die "Failed to call git-diff for annotation: $!";
 
-       _git_diff_parse($diff, $parents, $rev, %revinfo);
+       _git_diff_parse($diff, \@pseudo_parents, $rev, %revinfo);
 
        close($diff);
 }
@@ -283,6 +390,7 @@ sub _git_diff_parse {
        $diff_header_regexp .= "@" x @$parents;
        $diff_header_regexp .= ' -\d+,\d+' x @$parents;
        $diff_header_regexp .= ' \+(\d+),\d+';
+       $diff_header_regexp .= " " . ("@" x @$parents);
 
        my %claim_regexps;
        my $allparentplus = '^' . '\\+' x @$parents . '(.*)$';
@@ -311,6 +419,7 @@ sub _git_diff_parse {
        DIFF:
        while(<$diff>) {
                chomp;
+               #printf("%d:%s:\n", $gotheader, $_);
                if (m/$diff_header_regexp/) {
                        $remstart = $1 - 1;
                        # (0-based arrays)
@@ -391,10 +500,17 @@ sub _git_diff_parse {
                                                printf("parent %s is on line %d\n", $parent, $pi{$parent});
                                        }
 
+                                       my @context;
+                                       for (my $i = -2; $i < 2; $i++) {
+                                               push @context, get_line($slines, $ri + $i);
+                                       }
+                                       my $context = join("\n", @context);
+
+                                       my $justline = substr($_, scalar @$parents);
                                        die sprintf("Line %d, does not match:\n|%s|\n|%s|\n%s\n",
                                                    $ri,
-                                               substr($_,scalar @$parents),
-                                               get_line($slines,$ri), $rev);
+                                                   $justline,
+                                                   $context);
                                }
                                foreach my $parent (@$parents) {
                                        $plines{$parent}[$pi{$parent}++] = $slines->[$ri];
index acc7a51b97c2ade58ab64299eb16c940a724c260..7060bdab01f696c4a664fb243aac96b9a786f2f7 100755 (executable)
@@ -298,7 +298,7 @@ yes,yes)
                fi
                git-ls-remote "$repo" >"$GIT_DIR/CLONE_HEAD" || exit 1
                ;;
-       http://*)
+       https://*|http://*)
                if test -z "@@NO_CURL@@"
                then
                        clone_dumb_http "$repo" "$D"
index 93f558056dec457570bf2867dc6c75cd5891d2f2..3bcf5b13f2c7bab387b02bd3075629a9d14c5feb 100644 (file)
@@ -91,6 +91,9 @@ static inline void *xmalloc(size_t size)
                ret = malloc(1);
        if (!ret)
                die("Out of memory, malloc failed");
+#ifdef XMALLOC_POISON
+       memset(ret, 0xA5, size);
+#endif
        return ret;
 }
 
diff --git a/git.c b/git.c
index 96e596b1a385266a5c0e0638b0e682b06c55c506..db0f86790dd413a96064f2778f7865aedd068e05 100644 (file)
--- a/git.c
+++ b/git.c
@@ -252,7 +252,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
                { "pack-objects", cmd_pack_objects, RUN_SETUP },
                { "prune", cmd_prune, RUN_SETUP },
                { "prune-packed", cmd_prune_packed, RUN_SETUP },
-               { "push", cmd_push },
+               { "push", cmd_push, RUN_SETUP },
                { "read-tree", cmd_read_tree, RUN_SETUP },
                { "repo-config", cmd_repo_config },
                { "rev-list", cmd_rev_list, RUN_SETUP },
index 1aad39b4d830d32b9ac4034153a06ddc08c72bcb..36af3e5b94bb87f8d452aac99c27cba0097abf13 100644 (file)
@@ -1226,6 +1226,7 @@ int main(int argc, const char **argv)
        int arg = 1;
        int rc = 0;
 
+       setup_ident();
        setup_git_directory();
        git_config(git_default_config);
 
index b216bdd55742ef8214ed1193ef184f8bba70eb70..4bf86fbbe2703514cd3ab39fd9c81accac662aaf 100644 (file)
@@ -210,6 +210,7 @@ int main(int argc, const char **argv)
        char **commit_id;
        int arg = 1;
 
+       setup_ident();
        setup_git_directory();
        git_config(git_default_config);
 
index b67b8dd17af9643e00152d9bd768dca89e08b4ce..05ede0c175c8af08c2a5834b328ade87df7aa7ff 100644 (file)
@@ -59,7 +59,7 @@ void show_log(struct rev_info *opt, const char *sep)
                fputs(diff_unique_abbrev(commit->object.sha1, abbrev_commit), stdout);
                if (opt->parents)
                        show_parents(commit, abbrev_commit);
-               putchar('\n');
+               putchar(opt->diffopt.line_termination);
                return;
        }
 
diff --git a/setup.c b/setup.c
index 358e139d84c422a9bd0a9500807a31cbf7695f02..2afdba414a073705440f887593a1b5daa1023758 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -184,7 +184,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
                }
                return NULL;
        bad_dir_environ:
-               if (!nongit_ok) {
+               if (nongit_ok) {
                        *nongit_ok = 1;
                        return NULL;
                }
index 6e16568f88f6fcbbb79d23c1f6187860c8cfb453..c7d8fa80e425695374f11746ae6592f52d8401d5 100644 (file)
@@ -132,6 +132,7 @@ int main(int argc, char **argv)
        prog = getenv("GIT_SSH_PUSH");
        if (!prog) prog = "git-ssh-upload";
 
+       setup_ident();
        setup_git_directory();
        git_config(git_default_config);
 
diff --git a/t/t7002-grep.sh b/t/t7002-grep.sh
new file mode 100755 (executable)
index 0000000..00a7d76
--- /dev/null
@@ -0,0 +1,85 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 Junio C Hamano
+#
+
+test_description='git grep -w
+'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+       {
+               echo foo mmap bar
+               echo foo_mmap bar
+               echo foo_mmap bar mmap
+               echo foo mmap bar_mmap
+               echo foo_mmap bar mmap baz
+       } >file &&
+       echo x x xx x >x &&
+       echo y yy >y &&
+       echo zzz > z &&
+       git add file x y z &&
+       git commit -m initial
+'
+
+for H in HEAD ''
+do
+       case "$H" in
+       HEAD)   HC='HEAD:' L='HEAD' ;;
+       '')     HC= L='in working tree' ;;
+       esac
+
+       test_expect_success "grep -w $L" '
+               {
+                       echo ${HC}file:1:foo mmap bar
+                       echo ${HC}file:3:foo_mmap bar mmap
+                       echo ${HC}file:4:foo mmap bar_mmap
+                       echo ${HC}file:5:foo_mmap bar mmap baz
+               } >expected &&
+               git grep -n -w -e mmap $H >actual &&
+               diff expected actual
+       '
+
+       test_expect_success "grep -w $L (x)" '
+               {
+                       echo ${HC}x:1:x x xx x
+               } >expected &&
+               git grep -n -w -e "x xx* x" $H >actual &&
+               diff expected actual
+       '
+
+       test_expect_success "grep -w $L (y-1)" '
+               {
+                       echo ${HC}y:1:y yy
+               } >expected &&
+               git grep -n -w -e "^y" $H >actual &&
+               diff expected actual
+       '
+
+       test_expect_success "grep -w $L (y-2)" '
+               : >expected &&
+               if git grep -n -w -e "^y y" $H >actual
+               then
+                       echo should not have matched
+                       cat actual
+                       false
+               else
+                       diff expected actual
+               fi
+       '
+
+       test_expect_success "grep -w $L (z)" '
+               : >expected &&
+               if git grep -n -w -e "^z" $H >actual
+               then
+                       echo should not have matched
+                       cat actual
+                       false
+               else
+                       diff expected actual
+               fi
+       '
+done
+
+test_done