Merge branch 'lt/objlist'
authorJunio C Hamano <junkio@cox.net>
Thu, 22 Jun 2006 09:15:22 +0000 (02:15 -0700)
committerJunio C Hamano <junkio@cox.net>
Thu, 22 Jun 2006 09:15:22 +0000 (02:15 -0700)
* lt/objlist:
Add "named object array" concept

Documentation/git-send-email.txt
Makefile
builtin-grep.c
contrib/git-svn/Makefile
contrib/git-svn/git-svn.perl
contrib/git-svn/t/t0002-deep-rmdir.sh [new file with mode: 0644]
daemon.c
git-checkout.sh
git-send-email.perl
object-refs.c
index ad1b9cf2e9b2532c02c0abd3450ecf6272673472..481b3f50e3d690f5cd47ffa2c2d8bb645114e315 100644 (file)
@@ -24,9 +24,16 @@ OPTIONS
 -------
 The options available are:
 
+--bcc::
+       Specify a "Bcc:" value for each email.
+
+       The --bcc option must be repeated for each user you want on the bcc list.
+
 --cc::
        Specify a starting "Cc:" value for each email.
 
+       The --cc option must be repeated for each user you want on the cc list.
+
 --chain-reply-to, --no-chain-reply-to::
        If this is set, each email will be sent as a reply to the previous
        email sent.  If disabled with "--no-chain-reply-to", all emails after
@@ -76,6 +83,8 @@ The options available are:
        Generally, this will be the upstream maintainer of the
        project involved.
 
+       The --to option must be repeated for each user you want on the to list.
+
 
 Author
 ------
index 0887945ffa6977e49214f89be93fff4da1cd6048..d45f3dcf6214f8a60f3e636d1c5067d273551f0c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -472,7 +472,6 @@ PYTHON_PATH_SQ = $(subst ','\'',$(PYTHON_PATH))
 GIT_PYTHON_DIR_SQ = $(subst ','\'',$(GIT_PYTHON_DIR))
 
 ALL_CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER_SQ)' $(COMPAT_CFLAGS)
-ALL_CFLAGS += -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"'
 LIB_OBJS += $(COMPAT_OBJS)
 export prefix TAR INSTALL DESTDIR SHELL_PATH template_dir
 ### Build rules
@@ -548,6 +547,8 @@ git$X git.spec \
 
 exec_cmd.o: exec_cmd.c GIT-CFLAGS
        $(CC) -o $*.o -c $(ALL_CFLAGS) '-DGIT_EXEC_PATH="$(gitexecdir_SQ)"' $<
+builtin-init-db.o: builtin-init-db.c GIT-CFLAGS
+       $(CC) -o $*.o -c $(ALL_CFLAGS) -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' $<
 
 http.o: http.c GIT-CFLAGS
        $(CC) -o $*.o -c $(ALL_CFLAGS) -DGIT_USER_AGENT='"git/$(GIT_VERSION)"' $<
@@ -611,7 +612,7 @@ tags:
        find . -name '*.[hcS]' -print | xargs ctags -a
 
 ### Detect prefix changes
-TRACK_CFLAGS = $(subst ','\'',$(ALL_CFLAGS)):$(GIT_VERSION):\
+TRACK_CFLAGS = $(subst ','\'',$(ALL_CFLAGS)):$(GIT_PYTHON_DIR_SQ):\
              $(bindir_SQ):$(gitexecdir_SQ):$(template_dir_SQ):$(prefix_SQ)
 
 GIT-CFLAGS: .FORCE-GIT-CFLAGS
index 6a240fb6e908d95a1981ea2437fcd4bea27a6ba9..2e7986cecefc964f665b10d363569951c1f40293 100644 (file)
@@ -29,10 +29,11 @@ static int pathspec_matches(const char **paths, const char *name)
                int matchlen = strlen(match);
                const char *cp, *meta;
 
-               if ((matchlen <= namelen) &&
-                   !strncmp(name, match, matchlen) &&
-                   (match[matchlen-1] == '/' ||
-                    name[matchlen] == '\0' || name[matchlen] == '/'))
+               if (!matchlen ||
+                   ((matchlen <= namelen) &&
+                    !strncmp(name, match, matchlen) &&
+                    (match[matchlen-1] == '/' ||
+                     name[matchlen] == '\0' || name[matchlen] == '/')))
                        return 1;
                if (!fnmatch(match, name, 0))
                        return 1;
index 6aedb10f1261bbcef6a48ef65e1f47d9edc1afda..7c209469438bcef2a5cee0988448a41a56ec30cc 100644 (file)
@@ -29,8 +29,7 @@ git-svn.html : git-svn.txt
        asciidoc -b xhtml11 -d manpage \
                -f ../../Documentation/asciidoc.conf $<
 test: git-svn
-       cd t && $(SHELL) ./t0000-contrib-git-svn.sh $(TEST_FLAGS)
-       cd t && $(SHELL) ./t0001-contrib-git-svn-props.sh $(TEST_FLAGS)
+       cd t && for i in t????-*.sh; do $(SHELL) ./$$i $(TEST_FLAGS); done
 
 # we can test NO_OPTIMIZE_COMMITS independently of LC_ALL
 full-test:
index da0ff9ad8a56f41c351946990ee17d1e80f533e8..08c30103f5c247559e15ebd4bb20d7177889ed88 100755 (executable)
@@ -479,17 +479,18 @@ sub commit_lib {
        my @lock = $SVN::Core::VERSION ge '1.2.0' ? (undef, 0) : ();
        my $commit_msg = "$GIT_SVN_DIR/.svn-commit.tmp.$$";
 
+       if (defined $LC_ALL) {
+               $ENV{LC_ALL} = $LC_ALL;
+       } else {
+               delete $ENV{LC_ALL};
+       }
        foreach my $c (@revs) {
+               my $log_msg = get_commit_message($c, $commit_msg);
+
                # fork for each commit because there's a memory leak I
                # can't track down... (it's probably in the SVN code)
                defined(my $pid = open my $fh, '-|') or croak $!;
                if (!$pid) {
-                       if (defined $LC_ALL) {
-                               $ENV{LC_ALL} = $LC_ALL;
-                       } else {
-                               delete $ENV{LC_ALL};
-                       }
-                       my $log_msg = get_commit_message($c, $commit_msg);
                        my $ed = SVN::Git::Editor->new(
                                        {       r => $r_last,
                                                ra => $SVN,
@@ -535,6 +536,7 @@ sub commit_lib {
                        ($r_last, $cmt_last) = ($r_new, $cmt_new);
                }
        }
+       $ENV{LC_ALL} = 'C';
        unlink $commit_msg;
 }
 
@@ -2841,13 +2843,20 @@ sub rmdirs {
                exec qw/git-ls-tree --name-only -r -z/, $self->{c} or croak $!;
        }
        local $/ = "\0";
+       my @svn_path = split m#/#, $self->{svn_path};
        while (<$fh>) {
                chomp;
-               $_ = $self->{svn_path} . '/' . $_;
-               my ($dn) = ($_ =~ m#^(.*?)/?(?:[^/]+)$#);
-               delete $rm->{$dn};
-               last unless %$rm;
+               my @dn = (@svn_path, (split m#/#, $_));
+               while (pop @dn) {
+                       delete $rm->{join '/', @dn};
+               }
+               unless (%$rm) {
+                       close $fh;
+                       return;
+               }
        }
+       close $fh;
+
        my ($r, $p, $bat) = ($self->{r}, $self->{pool}, $self->{bat});
        foreach my $d (sort { $b =~ tr#/#/# <=> $a =~ tr#/#/# } keys %$rm) {
                $self->close_directory($bat->{$d}, $p);
diff --git a/contrib/git-svn/t/t0002-deep-rmdir.sh b/contrib/git-svn/t/t0002-deep-rmdir.sh
new file mode 100644 (file)
index 0000000..d693d18
--- /dev/null
@@ -0,0 +1,29 @@
+test_description='git-svn rmdir'
+. ./lib-git-svn.sh
+
+test_expect_success 'initialize repo' "
+       mkdir import &&
+       cd import &&
+       mkdir -p deeply/nested/directory/number/1 &&
+       mkdir -p deeply/nested/directory/number/2 &&
+       echo foo > deeply/nested/directory/number/1/file &&
+       echo foo > deeply/nested/directory/number/2/another &&
+       svn import -m 'import for git-svn' . $svnrepo &&
+       cd ..
+       "
+
+test_expect_success 'mirror via git-svn' "
+       git-svn init $svnrepo &&
+       git-svn fetch &&
+       git checkout -f -b test-rmdir remotes/git-svn
+       "
+
+test_expect_success 'Try a commit on rmdir' "
+       git rm -f deeply/nested/directory/number/2/another &&
+       git commit -a -m 'remove another' &&
+       git-svn commit --rmdir HEAD &&
+       svn ls -R $svnrepo | grep ^deeply/nested/directory/number/1
+       "
+
+
+test_done
index 2f03f99d2d9f2ed9a23932e5104456f69b721116..bdfe80d2e4f4fc13ad45bd35aeeeb3ec71422a4f 100644 (file)
--- a/daemon.c
+++ b/daemon.c
@@ -264,11 +264,34 @@ static int upload(char *dir)
        return -1;
 }
 
-static int execute(void)
+static int execute(struct sockaddr *addr)
 {
        static char line[1000];
        int pktlen, len;
 
+       if (addr) {
+               char addrbuf[256] = "";
+               int port = -1;
+
+               if (addr->sa_family == AF_INET) {
+                       struct sockaddr_in *sin_addr = (void *) addr;
+                       inet_ntop(addr->sa_family, &sin_addr->sin_addr, addrbuf, sizeof(addrbuf));
+                       port = sin_addr->sin_port;
+#ifndef NO_IPV6
+               } else if (addr && addr->sa_family == AF_INET6) {
+                       struct sockaddr_in6 *sin6_addr = (void *) addr;
+
+                       char *buf = addrbuf;
+                       *buf++ = '['; *buf = '\0'; /* stpcpy() is cool */
+                       inet_ntop(AF_INET6, &sin6_addr->sin6_addr, buf, sizeof(addrbuf) - 1);
+                       strcat(buf, "]");
+
+                       port = sin6_addr->sin6_port;
+#endif
+               }
+               loginfo("Connection from %s:%d", addrbuf, port);
+       }
+
        alarm(init_timeout ? init_timeout : timeout);
        pktlen = packet_read_line(0, line, sizeof(line));
        alarm(0);
@@ -414,8 +437,6 @@ static void check_max_connections(void)
 static void handle(int incoming, struct sockaddr *addr, int addrlen)
 {
        pid_t pid = fork();
-       char addrbuf[256] = "";
-       int port = -1;
 
        if (pid) {
                unsigned idx;
@@ -436,26 +457,7 @@ static void handle(int incoming, struct sockaddr *addr, int addrlen)
        dup2(incoming, 1);
        close(incoming);
 
-       if (addr->sa_family == AF_INET) {
-               struct sockaddr_in *sin_addr = (void *) addr;
-               inet_ntop(AF_INET, &sin_addr->sin_addr, addrbuf, sizeof(addrbuf));
-               port = sin_addr->sin_port;
-
-#ifndef NO_IPV6
-       } else if (addr->sa_family == AF_INET6) {
-               struct sockaddr_in6 *sin6_addr = (void *) addr;
-
-               char *buf = addrbuf;
-               *buf++ = '['; *buf = '\0'; /* stpcpy() is cool */
-               inet_ntop(AF_INET6, &sin6_addr->sin6_addr, buf, sizeof(addrbuf) - 1);
-               strcat(buf, "]");
-
-               port = sin6_addr->sin6_port;
-#endif
-       }
-       loginfo("Connection from %s:%d", addrbuf, port);
-
-       exit(execute());
+       exit(execute(addr));
 }
 
 static void child_handler(int signo)
@@ -751,8 +753,16 @@ int main(int argc, char **argv)
        }
 
        if (inetd_mode) {
+               struct sockaddr_storage ss;
+               struct sockaddr *peer = (struct sockaddr *)&ss;
+               socklen_t slen = sizeof(ss);
+
                fclose(stderr); //FIXME: workaround
-               return execute();
+
+               if (getpeername(0, peer, &slen))
+                       peer = NULL;
+
+               return execute(peer);
        }
 
        return serve(port);
index 564117f0064aba32e190a49106eaecfdb422b31e..77c25938091b75f51eb3cc5922d67db6333e1e74 100755 (executable)
@@ -137,8 +137,7 @@ fi
 
 if [ "$force" ]
 then
-    git-read-tree --reset $new &&
-       git-checkout-index -q -f -u -a
+    git-read-tree --reset -u $new
 else
     git-update-index --refresh >/dev/null
     merge_error=$(git-read-tree -m -u $old $new 2>&1) || (
index 7b1cca70abcfcbf12c171c91d3f71ad4e43b0474..c5d9e733512ddd4d266c85d4f5cdec4a7d74fa56 100755 (executable)
                    "no-signed-off-cc|no-signed-off-by-cc" => \$no_signed_off_cc,
         );
 
+# Verify the user input
+
+foreach my $entry (@to) {
+       die "Comma in --to entry: $entry'\n" unless $entry !~ m/,/;
+}
+
+foreach my $entry (@initial_cc) {
+       die "Comma in --cc entry: $entry'\n" unless $entry !~ m/,/;
+}
+
+foreach my $entry (@bcclist) {
+       die "Comma in --bcclist entry: $entry'\n" unless $entry !~ m/,/;
+}
+
 # Now, let's fill any that aren't set in with defaults:
 
 sub gitvar {
index 8afa2276fbe9e79bba700b99b1ef345bb6d7f5e8..b1b8065851b2723a57e5d6ab0859ca72e52fd55f 100644 (file)
@@ -12,6 +12,18 @@ static unsigned int hash_obj(struct object *obj, unsigned int n)
        return hash % n;
 }
 
+static void insert_ref_hash(struct object_refs *ref, struct object_refs **hash, unsigned int size)
+{
+       int j = hash_obj(ref->base, size);
+
+       while (hash[j]) {
+               j++;
+               if (j >= size)
+                       j = 0;
+       }
+       hash[j] = ref;
+}
+
 static void grow_refs_hash(void)
 {
        int i;
@@ -20,30 +32,16 @@ static void grow_refs_hash(void)
 
        new_hash = calloc(new_hash_size, sizeof(struct object_refs *));
        for (i = 0; i < refs_hash_size; i++) {
-               int j;
                struct object_refs *ref = refs_hash[i];
                if (!ref)
                        continue;
-               j = hash_obj(ref->base, new_hash_size);
-               new_hash[j] = ref;
+               insert_ref_hash(ref, new_hash, new_hash_size);
        }
        free(refs_hash);
        refs_hash = new_hash;
        refs_hash_size = new_hash_size;
 }
 
-static void insert_ref_hash(struct object_refs *ref)
-{
-       int j = hash_obj(ref->base, refs_hash_size);
-
-       while (refs_hash[j]) {
-               j++;
-               if (j >= refs_hash_size)
-                       j = 0;
-       }
-       refs_hash[j] = ref;
-}
-
 static void add_object_refs(struct object *obj, struct object_refs *ref)
 {
        int nr = nr_object_refs + 1;
@@ -51,7 +49,7 @@ static void add_object_refs(struct object *obj, struct object_refs *ref)
        if (nr > refs_hash_size * 2 / 3)
                grow_refs_hash();
        ref->base = obj;
-       insert_ref_hash(ref);
+       insert_ref_hash(ref, refs_hash, refs_hash_size);
        nr_object_refs = nr;
 }
 
@@ -127,6 +125,9 @@ void mark_reachable(struct object *obj, unsigned int mask)
 
        if (!track_object_refs)
                die("cannot do reachability with object refs turned off");
+       /* nothing to lookup */
+       if (!refs_hash_size)
+               return;
        /* If we've been here already, don't bother */
        if (obj->flags & mask)
                return;