Merge branch 'maint'
authorJunio C Hamano <gitster@pobox.com>
Sat, 15 Mar 2008 07:05:40 +0000 (00:05 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sat, 15 Mar 2008 07:05:40 +0000 (00:05 -0700)
* maint:
Make man page building quiet when DOCBOOK_XSL_172 is defined
git-new-workdir: Share SVN meta data between work dirs and the repository
rev-parse: fix meaning of rev~ vs rev~0.
git-svn: don't blindly append '*' to branch/tags config

1  2 
git-svn.perl
sha1_name.c
diff --combined git-svn.perl
index d8b38c9a47c0b77dd55781a66e42e4dec26fd4b7,e0434099ce6832871df7901f25a5c9f4ee477dd8..bba22c1321056f5daa58a6913ccc406850700b25
@@@ -186,9 -186,6 +186,9 @@@ my %cmd = 
                    "Show info about the latest SVN revision
                     on the current branch",
                    { 'url' => \$_url, } ],
 +      'blame' => [ \&Git::SVN::Log::cmd_blame,
 +                  "Show what revision and author last modified each line of a file",
 +                  {} ],
  );
  
  my $cmd;
@@@ -958,9 -955,10 +958,10 @@@ sub complete_url_ls_init 
                    "wanted to set to: $gs->{url}\n";
        }
        command_oneline('config', $k, $gs->{url}) unless $orig_url;
-       my $remote_path = "$ra->{svn_path}/$repo_path/*";
+       my $remote_path = "$ra->{svn_path}/$repo_path";
        $remote_path =~ s#/+#/#g;
        $remote_path =~ s#^/##g;
+       $remote_path .= "/*" if $remote_path !~ /\*/;
        my ($n) = ($switch =~ /^--(\w+)/);
        if (length $pfx && $pfx !~ m#/$#) {
                die "--prefix='$pfx' must have a trailing slash '/'\n";
@@@ -1251,8 -1249,7 +1252,8 @@@ use File::Path qw/mkpath/
  use File::Copy qw/copy/;
  use IPC::Open3;
  
 -my $_repack_nr;
 +my ($_gc_nr, $_gc_period);
 +
  # properties that we do not log:
  my %SKIP_PROP;
  BEGIN {
@@@ -1413,10 -1410,9 +1414,10 @@@ sub read_all_remotes 
  }
  
  sub init_vars {
 -      $_repack = 1000 unless (defined $_repack && $_repack > 0);
 -      $_repack_nr = $_repack;
 -      $_repack_flags ||= '-d';
 +      $_gc_nr = $_gc_period = 1000;
 +      if (defined $_repack || defined $_repack_flags) {
 +             warn "Repack options are obsolete; they have no effect.\n";
 +      }
  }
  
  sub verify_remotes_sanity {
@@@ -2107,10 -2103,6 +2108,10 @@@ sub restore_commit_header_env 
        }
  }
  
 +sub gc {
 +      command_noisy('gc', '--auto');
 +};
 +
  sub do_git_commit {
        my ($self, $log_entry) = @_;
        my $lr = $self->last_rev;
                                   0, $self->svm_uuid);
        }
        print " = $commit ($self->{ref_id})\n";
 -      if ($_repack && (--$_repack_nr == 0)) {
 -              $_repack_nr = $_repack;
 -              # repack doesn't use any arguments with spaces in them, does it?
 -              print "Running git repack $_repack_flags ...\n";
 -              command_noisy('repack', split(/\s+/, $_repack_flags));
 -              print "Done repacking\n";
 +      if (--$_gc_nr == 0) {
 +              $_gc_nr = $_gc_period;
 +              gc();
        }
        return $commit;
  }
@@@ -2238,12 -2233,7 +2239,12 @@@ sub find_parent_branch 
                # just grow a tail if we're not unique enough :x
                $ref_id .= '-' while find_ref($ref_id);
                print STDERR "Initializing parent: $ref_id\n";
 -              $gs = Git::SVN->init($new_url, '', $ref_id, $ref_id, 1);
 +              my ($u, $p) = ($new_url, '');
 +              if ($u =~ s#^\Q$url\E(/|$)##) {
 +                      $p = $u;
 +                      $u = $url;
 +              }
 +              $gs = Git::SVN->init($u, $p, $self->{repo_id}, $ref_id, 1);
        }
        my ($r0, $parent) = $gs->find_rev_before($r, 1);
        if (!defined $r0 || !defined $parent) {
@@@ -4001,7 -3991,6 +4002,7 @@@ sub gs_fetch_loop_common 
                $max += $inc;
                $max = $head if ($max > $head);
        }
 +      Git::SVN::gc();
  }
  
  sub match_globs {
        print commit_log_separator unless $incremental || $oneline;
  }
  
 +sub cmd_blame {
 +      my $path = shift;
 +
 +      config_pager();
 +      run_pager();
 +
 +      my ($fh, $ctx) = command_output_pipe('blame', @_, $path);
 +      while (my $line = <$fh>) {
 +              if ($line =~ /^\^?([[:xdigit:]]+)\s/) {
 +                      my (undef, $rev, undef) = ::cmt_metadata($1);
 +                      $rev = sprintf('%-10s', $rev);
 +                      $line =~ s/^\^?[[:xdigit:]]+(\s)/$rev$1/;
 +              }
 +              print $line;
 +      }
 +      command_close_pipe($fh, $ctx);
 +}
 +
  package Git::SVN::Migration;
  # these version numbers do NOT correspond to actual version numbers
  # of git nor git-svn.  They are just relative.
diff --combined sha1_name.c
index 8b6c76f68ed1433caddfa8aab6132db667197433,6c9c1c75adefe2d5e38212b75302368293c9137b..491d2e7ebf19d5c582adbc5ece28d931b09b8a6d
@@@ -192,25 -192,26 +192,25 @@@ static int get_short_sha1(const char *n
  
  const char *find_unique_abbrev(const unsigned char *sha1, int len)
  {
 -      int status, is_null;
 +      int status, exists;
        static char hex[41];
  
 -      is_null = is_null_sha1(sha1);
 +      exists = has_sha1_file(sha1);
        memcpy(hex, sha1_to_hex(sha1), 40);
        if (len == 40 || !len)
                return hex;
        while (len < 40) {
                unsigned char sha1_ret[20];
                status = get_short_sha1(hex, len, sha1_ret, 1);
 -              if (!status ||
 -                  (is_null && status != SHORT_NAME_AMBIGUOUS)) {
 +              if (exists
 +                  ? !status
 +                  : status == SHORT_NAME_NOT_FOUND) {
                        hex[len] = 0;
                        return hex;
                }
 -              if (status != SHORT_NAME_AMBIGUOUS)
 -                      return NULL;
                len++;
        }
 -      return NULL;
 +      return hex;
  }
  
  static int ambiguous_path(const char *path, int len)
@@@ -407,52 -408,25 +407,56 @@@ static int get_nth_ancestor(const char 
                            unsigned char *result, int generation)
  {
        unsigned char sha1[20];
-       int ret = get_sha1_1(name, len, sha1);
+       struct commit *commit;
+       int ret;
+       ret = get_sha1_1(name, len, sha1);
        if (ret)
                return ret;
+       commit = lookup_commit_reference(sha1);
+       if (!commit)
+               return -1;
  
        while (generation--) {
-               struct commit *commit = lookup_commit_reference(sha1);
-               if (!commit || parse_commit(commit) || !commit->parents)
+               if (parse_commit(commit) || !commit->parents)
                        return -1;
-               hashcpy(sha1, commit->parents->item->object.sha1);
+               commit = commit->parents->item;
        }
-       hashcpy(result, sha1);
+       hashcpy(result, commit->object.sha1);
        return 0;
  }
  
 +struct object *peel_to_type(const char *name, int namelen,
 +                          struct object *o, enum object_type expected_type)
 +{
 +      if (name && !namelen)
 +              namelen = strlen(name);
 +      if (!o) {
 +              unsigned char sha1[20];
 +              if (get_sha1_1(name, namelen, sha1))
 +                      return NULL;
 +              o = parse_object(sha1);
 +      }
 +      while (1) {
 +              if (!o || (!o->parsed && !parse_object(o->sha1)))
 +                      return NULL;
 +              if (o->type == expected_type)
 +                      return o;
 +              if (o->type == OBJ_TAG)
 +                      o = ((struct tag*) o)->tagged;
 +              else if (o->type == OBJ_COMMIT)
 +                      o = &(((struct commit *) o)->tree->object);
 +              else {
 +                      if (name)
 +                              error("%.*s: expected %s type, but the object "
 +                                    "dereferences to %s type",
 +                                    namelen, name, typename(expected_type),
 +                                    typename(o->type));
 +                      return NULL;
 +              }
 +      }
 +}
 +
  static int peel_onion(const char *name, int len, unsigned char *sha1)
  {
        unsigned char outer[20];
                hashcpy(sha1, o->sha1);
        }
        else {
 -              /* At this point, the syntax look correct, so
 +              /*
 +               * At this point, the syntax look correct, so
                 * if we do not get the needed object, we should
                 * barf.
                 */
 -
 -              while (1) {
 -                      if (!o || (!o->parsed && !parse_object(o->sha1)))
 -                              return -1;
 -                      if (o->type == expected_type) {
 -                              hashcpy(sha1, o->sha1);
 -                              return 0;
 -                      }
 -                      if (o->type == OBJ_TAG)
 -                              o = ((struct tag*) o)->tagged;
 -                      else if (o->type == OBJ_COMMIT)
 -                              o = &(((struct commit *) o)->tree->object);
 -                      else
 -                              return error("%.*s: expected %s type, but the object dereferences to %s type",
 -                                           len, name, typename(expected_type),
 -                                           typename(o->type));
 -                      if (!o->parsed)
 -                              parse_object(o->sha1);
 +              o = peel_to_type(name, len, o, expected_type);
 +              if (o) {
 +                      hashcpy(sha1, o->sha1);
 +                      return 0;
                }
 +              return -1;
        }
        return 0;
  }
@@@ -544,9 -530,8 +548,8 @@@ static int get_sha1_1(const char *name
        int ret, has_suffix;
        const char *cp;
  
-       /* "name~3" is "name^^^",
-        * "name~" and "name~0" are name -- not "name^0"!
-        * "name^" is not "name^0"; it is "name^1".
+       /*
+        * "name~3" is "name^^^", "name~" is "name~1", and "name^" is "name^1".
         */
        has_suffix = 0;
        for (cp = name + len - 1; name <= cp; cp--) {
                cp++;
                while (cp < name + len)
                        num = num * 10 + *cp++ - '0';
-               if (has_suffix == '^') {
-                       if (!num && len1 == len - 1)
-                               num = 1;
+               if (!num && len1 == len - 1)
+                       num = 1;
+               if (has_suffix == '^')
                        return get_parent(name, len1, sha1, num);
-               }
                /* else if (has_suffix == '~') -- goes without saying */
                return get_nth_ancestor(name, len1, sha1, num);
        }
@@@ -596,11 -580,8 +598,11 @@@ static int handle_one_ref(const char *p
        struct object *object = parse_object(sha1);
        if (!object)
                return 0;
 -      if (object->type == OBJ_TAG)
 +      if (object->type == OBJ_TAG) {
                object = deref_tag(object, path, strlen(path));
 +              if (!object)
 +                      return 0;
 +      }
        if (object->type != OBJ_COMMIT)
                return 0;
        insert_by_date((struct commit *)object, list);
@@@ -638,9 -619,9 +640,9 @@@ static int get_sha1_oneline(const char 
                unsigned long size;
  
                commit = pop_most_recent_commit(&list, ONELINE_SEEN);
 -              parse_object(commit->object.sha1);
 -              if (temp_commit_buffer)
 -                      free(temp_commit_buffer);
 +              if (!parse_object(commit->object.sha1))
 +                      continue;
 +              free(temp_commit_buffer);
                if (commit->buffer)
                        p = commit->buffer;
                else {
                        break;
                }
        }
 -      if (temp_commit_buffer)
 -              free(temp_commit_buffer);
 +      free(temp_commit_buffer);
        free_commit_list(list);
        for (l = backup; l; l = l->next)
                clear_commit_marks(l->item, ONELINE_SEEN);
@@@ -715,7 -697,7 +717,7 @@@ int get_sha1_with_mode(const char *name
                                break;
                        if (ce_stage(ce) == stage) {
                                hashcpy(sha1, ce->sha1);
 -                              *mode = ntohl(ce->ce_mode);
 +                              *mode = ce->ce_mode;
                                return 0;
                        }
                        pos++;