Merge 1.5.5.3 in
authorJunio C Hamano <gitster@pobox.com>
Wed, 28 May 2008 05:22:47 +0000 (22:22 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 28 May 2008 05:34:19 +0000 (22:34 -0700)
1  2 
Documentation/git.txt
builtin-commit.c
git-filter-branch.sh
gitweb/gitweb.perl
t/t7003-filter-branch.sh
diff --combined Documentation/git.txt
index 1f68dec541826598caa057f6e2d73b000d4a9dfe,ccaa655d1f25677474b8860077557c5242048629..7182bb7f7e54685839ef7bade6c8d66cd1772c3b
@@@ -20,10 -20,10 +20,10 @@@ Git is a fast, scalable, distributed re
  unusually rich command set that provides both high-level operations
  and full access to internals.
  
 -See this link:tutorial.html[tutorial] to get started, then see
 +See this linkgit:gittutorial[7][tutorial] to get started, then see
  link:everyday.html[Everyday Git] for a useful minimum set of commands, and
  "man git-commandname" for documentation of each command.  CVS users may
 -also want to read link:cvs-migration.html[CVS migration].  See
 +also want to read linkgit:gitcvs-migration[7][CVS migration].  See
  link:user-manual.html[Git User's Manual] for a more in-depth
  introduction.
  
@@@ -46,11 -46,12 +46,12 @@@ Documentation for older releases are av
  * link:v1.5.5/git.html[documentation for release 1.5.5]
  
  * release notes for
+   link:RelNotes-1.5.5.3.txt[1.5.5.3],
    link:RelNotes-1.5.5.2.txt[1.5.5.2],
    link:RelNotes-1.5.5.1.txt[1.5.5.1],
    link:RelNotes-1.5.5.txt[1.5.5].
  
- * link:v1.5.5.2/git.html[documentation for release 1.5.5.2]
+ * link:v1.5.5.3/git.html[documentation for release 1.5.5.3]
  
  * link:v1.5.4.5/git.html[documentation for release 1.5.4.5]
  
@@@ -144,8 -145,7 +145,8 @@@ help ...'
  
  --git-dir=<path>::
        Set the path to the repository. This can also be controlled by
 -      setting the GIT_DIR environment variable.
 +      setting the GIT_DIR environment variable. It can be an absolute
 +      path or relative path to current working directory.
  
  --work-tree=<path>::
        Set the path to the working tree.  The value will not be
        a .git directory (i.e. $GIT_DIR is not set).
        This can also be controlled by setting the GIT_WORK_TREE
        environment variable and the core.worktree configuration
 -      variable.
 +      variable. It can be an absolute path or relative path to
 +      the directory specified by --git-dir or GIT_DIR.
 +      Note: If --git-dir or GIT_DIR are specified but none of
 +      --work-tree, GIT_WORK_TREE and core.worktree is specified,
 +      the current working directory is regarded as the top directory
 +      of your working tree.
  
  --bare::
        Treat the repository as a bare repository.  If GIT_DIR
@@@ -365,7 -360,7 +366,7 @@@ File/Directory Structur
  
  Please see the link:repository-layout.html[repository layout] document.
  
 -Read link:hooks.html[hooks] for more details about each hook.
 +Read linkgit:githooks[5][hooks] for more details about each hook.
  
  Higher level SCMs may provide and manage additional information in the
  `$GIT_DIR`.
diff --combined builtin-commit.c
index 07872c8ea71064c1bcf5813dd66b4a7e5feb9bec,b0fe69ecad6523dd40f8f5f777a7b81e31eefa3d..b294c1f88c1eecde8d96d265c72376c789f24899
@@@ -47,7 -47,6 +47,7 @@@ static enum 
  
  static char *logfile, *force_author, *template_file;
  static char *edit_message, *use_message;
 +static char *author_name, *author_email, *author_date;
  static int all, edit_flag, also, interactive, only, amend, signoff;
  static int quiet, verbose, untracked_files, no_verify, allow_empty;
  /*
@@@ -176,13 -175,10 +176,13 @@@ static void add_remove_files(struct pat
  {
        int i;
        for (i = 0; i < list->nr; i++) {
 +              struct stat st;
                struct path_list_item *p = &(list->items[i]);
 -              if (file_exists(p->path))
 -                      add_file_to_cache(p->path, 0);
 -              else
 +
 +              if (!lstat(p->path, &st)) {
 +                      if (add_to_cache(p->path, &st, 0))
 +                              die("updating files failed");
 +              } else
                        remove_file_from_cache(p->path);
        }
  }
@@@ -223,6 -219,8 +223,8 @@@ static char *prepare_index(int argc, co
  
        if (interactive) {
                interactive_add(argc, argv, prefix);
+               if (read_cache() < 0)
+                       die("index file corrupt");
                commit_style = COMMIT_AS_IS;
                return get_index_file();
        }
         */
        if (all || (also && pathspec && *pathspec)) {
                int fd = hold_locked_index(&index_lock, 1);
 -              add_files_to_cache(0, also ? prefix : NULL, pathspec);
 +              add_files_to_cache(also ? prefix : NULL, pathspec, 0);
                refresh_cache(REFRESH_QUIET);
                if (write_cache(fd, active_cache, active_nr) ||
                    close_lock_file(&index_lock))
@@@ -399,47 -397,6 +401,47 @@@ static int is_a_merge(const unsigned ch
  
  static const char sign_off_header[] = "Signed-off-by: ";
  
 +static void determine_author_info(void)
 +{
 +      char *name, *email, *date;
 +
 +      name = getenv("GIT_AUTHOR_NAME");
 +      email = getenv("GIT_AUTHOR_EMAIL");
 +      date = getenv("GIT_AUTHOR_DATE");
 +
 +      if (use_message) {
 +              const char *a, *lb, *rb, *eol;
 +
 +              a = strstr(use_message_buffer, "\nauthor ");
 +              if (!a)
 +                      die("invalid commit: %s", use_message);
 +
 +              lb = strstr(a + 8, " <");
 +              rb = strstr(a + 8, "> ");
 +              eol = strchr(a + 8, '\n');
 +              if (!lb || !rb || !eol)
 +                      die("invalid commit: %s", use_message);
 +
 +              name = xstrndup(a + 8, lb - (a + 8));
 +              email = xstrndup(lb + 2, rb - (lb + 2));
 +              date = xstrndup(rb + 2, eol - (rb + 2));
 +      }
 +
 +      if (force_author) {
 +              const char *lb = strstr(force_author, " <");
 +              const char *rb = strchr(force_author, '>');
 +
 +              if (!lb || !rb)
 +                      die("malformed --author parameter");
 +              name = xstrndup(force_author, lb - force_author);
 +              email = xstrndup(lb + 2, rb - (lb + 2));
 +      }
 +
 +      author_name = name;
 +      author_email = email;
 +      author_date = date;
 +}
 +
  static int prepare_to_commit(const char *index_file, const char *prefix)
  {
        struct stat statbuf;
        FILE *fp;
        const char *hook_arg1 = NULL;
        const char *hook_arg2 = NULL;
 +      int ident_shown = 0;
  
        if (!no_verify && run_hook(index_file, "pre-commit", NULL))
                return 0;
  
        strbuf_release(&sb);
  
 +      determine_author_info();
 +
 +      /* This checks if committer ident is explicitly given */
 +      git_committer_info(0);
        if (use_editor) {
 +              char *author_ident;
 +              const char *committer_ident;
 +
                if (in_merge)
                        fprintf(fp,
                                "#\n"
                if (only_include_assumed)
                        fprintf(fp, "# %s\n", only_include_assumed);
  
 +              author_ident = xstrdup(fmt_name(author_name, author_email));
 +              committer_ident = fmt_name(getenv("GIT_COMMITTER_NAME"),
 +                                         getenv("GIT_COMMITTER_EMAIL"));
 +              if (strcmp(author_ident, committer_ident))
 +                      fprintf(fp,
 +                              "%s"
 +                              "# Author:    %s\n",
 +                              ident_shown++ ? "" : "#\n",
 +                              author_ident);
 +              free(author_ident);
 +
 +              if (!user_ident_explicitly_given)
 +                      fprintf(fp,
 +                              "%s"
 +                              "# Committer: %s\n",
 +                              ident_shown++ ? "" : "#\n",
 +                              committer_ident);
 +
 +              if (ident_shown)
 +                      fprintf(fp, "#\n");
 +
                saved_color_setting = wt_status_use_color;
                wt_status_use_color = 0;
                commitable = run_status(fp, index_file, prefix, 1);
@@@ -696,6 -624,45 +698,6 @@@ static int message_is_empty(struct strb
        return 1;
  }
  
 -static void determine_author_info(struct strbuf *sb)
 -{
 -      char *name, *email, *date;
 -
 -      name = getenv("GIT_AUTHOR_NAME");
 -      email = getenv("GIT_AUTHOR_EMAIL");
 -      date = getenv("GIT_AUTHOR_DATE");
 -
 -      if (use_message) {
 -              const char *a, *lb, *rb, *eol;
 -
 -              a = strstr(use_message_buffer, "\nauthor ");
 -              if (!a)
 -                      die("invalid commit: %s", use_message);
 -
 -              lb = strstr(a + 8, " <");
 -              rb = strstr(a + 8, "> ");
 -              eol = strchr(a + 8, '\n');
 -              if (!lb || !rb || !eol)
 -                      die("invalid commit: %s", use_message);
 -
 -              name = xstrndup(a + 8, lb - (a + 8));
 -              email = xstrndup(lb + 2, rb - (lb + 2));
 -              date = xstrndup(rb + 2, eol - (rb + 2));
 -      }
 -
 -      if (force_author) {
 -              const char *lb = strstr(force_author, " <");
 -              const char *rb = strchr(force_author, '>');
 -
 -              if (!lb || !rb)
 -                      die("malformed --author parameter");
 -              name = xstrndup(force_author, lb - force_author);
 -              email = xstrndup(lb + 2, rb - (lb + 2));
 -      }
 -
 -      strbuf_addf(sb, "author %s\n", fmt_ident(name, email, date, IDENT_ERROR_ON_NO_NAME));
 -}
 -
  static int parse_and_validate_options(int argc, const char *argv[],
                                      const char * const usage[])
  {
                die("No paths with --include/--only does not make sense.");
        if (argc == 0 && only && amend)
                only_include_assumed = "Clever... amending the last one with dirty index.";
 -      if (argc > 0 && !also && !only) {
 +      if (argc > 0 && !also && !only)
                only_include_assumed = "Explicit paths specified without -i nor -o; assuming --only paths...";
 -              also = 0;
 -      }
        if (!cleanup_arg || !strcmp(cleanup_arg, "default"))
                cleanup_mode = use_editor ? CLEANUP_ALL : CLEANUP_SPACE;
        else if (!strcmp(cleanup_arg, "verbatim"))
@@@ -806,7 -775,7 +808,7 @@@ int cmd_status(int argc, const char **a
        const char *index_file;
        int commitable;
  
 -      git_config(git_status_config);
 +      git_config(git_status_config, NULL);
  
        if (wt_status_use_color == -1)
                wt_status_use_color = git_use_color_default;
@@@ -843,7 -812,7 +845,7 @@@ static void print_summary(const char *p
  
        rev.verbose_header = 1;
        rev.show_root_diff = 1;
 -      rev.commit_format = get_commit_format("format:%h: %s");
 +      get_commit_format("format:%h: %s", &rev);
        rev.always_show_header = 0;
        rev.diffopt.detect_rename = 1;
        rev.diffopt.rename_limit = 100;
        }
  }
  
 -int git_commit_config(const char *k, const char *v)
 +int git_commit_config(const char *k, const char *v, void *cb)
  {
        if (!strcmp(k, "commit.template")) {
                if (!v)
                return 0;
        }
  
 -      return git_status_config(k, v);
 +      return git_status_config(k, v, cb);
  }
  
  static const char commit_utf8_warn[] =
@@@ -897,7 -866,7 +899,7 @@@ int cmd_commit(int argc, const char **a
        unsigned char commit_sha1[20];
        struct ref_lock *ref_lock;
  
 -      git_config(git_commit_config);
 +      git_config(git_commit_config, NULL);
  
        argc = parse_and_validate_options(argc, argv, builtin_commit_usage);
  
                strbuf_addf(&sb, "parent %s\n", sha1_to_hex(head_sha1));
        }
  
 -      determine_author_info(&sb);
 +      strbuf_addf(&sb, "author %s\n",
 +                  fmt_ident(author_name, author_email, author_date, IDENT_ERROR_ON_NO_NAME));
        strbuf_addf(&sb, "committer %s\n", git_committer_info(IDENT_ERROR_ON_NO_NAME));
        if (!is_encoding_utf8(git_commit_encoding))
                strbuf_addf(&sb, "encoding %s\n", git_commit_encoding);
diff --combined git-filter-branch.sh
index 80e99e539477cbd7266b19c1bd90d424cf1341ee,d846cd9c929e290e00da61167a9cb80ce30691eb..d04c346e12fb73539e9910951744e9d5558ad4d3
@@@ -234,7 -234,7 +234,7 @@@ case "$filter_subdir" i
        ;;
  *)
        git rev-list --reverse --topo-order --default HEAD \
-               --parents --full-history "$@" -- "$filter_subdir"
+               --parents "$@" -- "$filter_subdir"
  esac > ../revs || die "Could not get the commits"
  commits=$(wc -l <../revs | tr -d " ")
  
@@@ -406,22 -406,8 +406,22 @@@ if [ "$filter_tag_name" ]; the
                echo "$ref -> $new_ref ($sha1 -> $new_sha1)"
  
                if [ "$type" = "tag" ]; then
 -                      # Warn that we are not rewriting the tag object itself.
 -                      warn "unreferencing tag object $sha1t"
 +                      new_sha1=$(git cat-file tag "$ref" |
 +                              sed -n \
 +                                  -e "1,/^$/{
 +                                        s/^object .*/object $new_sha1/
 +                                        s/^type .*/type commit/
 +                                        s/^tag .*/tag $new_ref/
 +                                      }" \
 +                                  -e '/^-----BEGIN PGP SIGNATURE-----/q' \
 +                                  -e 'p' |
 +                              git mktag) ||
 +                              die "Could not create new tag object for $ref"
 +                      if git cat-file tag "$ref" | \
 +                         grep '^-----BEGIN PGP SIGNATURE-----' >/dev/null 2>&1
 +                      then
 +                              warn "gpg signature stripped from tag object $sha1t"
 +                      fi
                fi
  
                git update-ref "refs/tags/$new_ref" "$new_sha1" ||
@@@ -435,17 -421,11 +435,17 @@@ rm -rf "$tempdir
  trap - 0
  
  unset GIT_DIR GIT_WORK_TREE GIT_INDEX_FILE
 -test -z "$ORIG_GIT_DIR" || GIT_DIR="$ORIG_GIT_DIR" && export GIT_DIR
 -test -z "$ORIG_GIT_WORK_TREE" || GIT_WORK_TREE="$ORIG_GIT_WORK_TREE" &&
 +test -z "$ORIG_GIT_DIR" || {
 +      GIT_DIR="$ORIG_GIT_DIR" && export GIT_DIR
 +}
 +test -z "$ORIG_GIT_WORK_TREE" || {
 +      GIT_WORK_TREE="$ORIG_GIT_WORK_TREE" &&
        export GIT_WORK_TREE
 -test -z "$ORIG_GIT_INDEX_FILE" || GIT_INDEX_FILE="$ORIG_GIT_INDEX_FILE" &&
 +}
 +test -z "$ORIG_GIT_INDEX_FILE" || {
 +      GIT_INDEX_FILE="$ORIG_GIT_INDEX_FILE" &&
        export GIT_INDEX_FILE
 +}
  git read-tree -u -m HEAD
  
  exit $ret
diff --combined gitweb/gitweb.perl
index 8308e2208e2a0064724367f3bcb6d33282b9e587,345acf4520c286ff17a09625ef18c0c0e23621c4..57a19058a4f27f5673d59a2ca97b147c90e8c453
@@@ -369,12 -369,7 +369,12 @@@ sub filter_snapshot_fmts 
  }
  
  our $GITWEB_CONFIG = $ENV{'GITWEB_CONFIG'} || "++GITWEB_CONFIG++";
 -do $GITWEB_CONFIG if -e $GITWEB_CONFIG;
 +if (-e $GITWEB_CONFIG) {
 +      do $GITWEB_CONFIG;
 +} else {
 +      our $GITWEB_CONFIG_SYSTEM = $ENV{'GITWEB_CONFIG_SYSTEM'} || "++GITWEB_CONFIG_SYSTEM++";
 +      do $GITWEB_CONFIG_SYSTEM if -e $GITWEB_CONFIG_SYSTEM;
 +}
  
  # version of the core git binary
  our $git_version = qx($GIT --version) =~ m/git version (.*)$/ ? $1 : "unknown";
@@@ -592,7 -587,7 +592,7 @@@ exit
  ## ======================================================================
  ## action links
  
 -sub href(%) {
 +sub href (%) {
        my %params = @_;
        # default is to use -absolute url() i.e. $my_uri
        my $href = $params{-full} ? $my_url : $my_uri;
@@@ -866,10 -861,6 +866,10 @@@ sub chop_str 
        my $add_len = shift || 10;
        my $where = shift || 'right'; # 'left' | 'center' | 'right'
  
 +      # Make sure perl knows it is utf8 encoded so we don't
 +      # cut in the middle of a utf8 multibyte char.
 +      $str = to_utf8($str);
 +
        # allow only $len chars, but don't cut a word if it would fit in $add_len
        # if it doesn't fit, cut it if it's still longer than the dots we would add
        # remove chopped character entities entirely
@@@ -1452,46 -1443,6 +1452,46 @@@ sub format_snapshot_links 
        }
  }
  
 +## ......................................................................
 +## functions returning values to be passed, perhaps after some
 +## transformation, to other functions; e.g. returning arguments to href()
 +
 +# returns hash to be passed to href to generate gitweb URL
 +# in -title key it returns description of link
 +sub get_feed_info {
 +      my $format = shift || 'Atom';
 +      my %res = (action => lc($format));
 +
 +      # feed links are possible only for project views
 +      return unless (defined $project);
 +      # some views should link to OPML, or to generic project feed,
 +      # or don't have specific feed yet (so they should use generic)
 +      return if ($action =~ /^(?:tags|heads|forks|tag|search)$/x);
 +
 +      my $branch;
 +      # branches refs uses 'refs/heads/' prefix (fullname) to differentiate
 +      # from tag links; this also makes possible to detect branch links
 +      if ((defined $hash_base && $hash_base =~ m!^refs/heads/(.*)$!) ||
 +          (defined $hash      && $hash      =~ m!^refs/heads/(.*)$!)) {
 +              $branch = $1;
 +      }
 +      # find log type for feed description (title)
 +      my $type = 'log';
 +      if (defined $file_name) {
 +              $type  = "history of $file_name";
 +              $type .= "/" if ($action eq 'tree');
 +              $type .= " on '$branch'" if (defined $branch);
 +      } else {
 +              $type = "log of $branch" if (defined $branch);
 +      }
 +
 +      $res{-title} = $type;
 +      $res{'hash'} = (defined $branch ? "refs/heads/$branch" : undef);
 +      $res{'file_name'} = $file_name;
 +
 +      return %res;
 +}
 +
  ## ----------------------------------------------------------------------
  ## git utility subroutines, invoking git commands
  
                }
        }
        if (defined $project) {
 -              printf('<link rel="alternate" title="%s log RSS feed" '.
 -                     'href="%s" type="application/rss+xml" />'."\n",
 -                     esc_param($project), href(action=>"rss"));
 -              printf('<link rel="alternate" title="%s log RSS feed (no merges)" '.
 -                     'href="%s" type="application/rss+xml" />'."\n",
 -                     esc_param($project), href(action=>"rss",
 -                                               extra_options=>"--no-merges"));
 -              printf('<link rel="alternate" title="%s log Atom feed" '.
 -                     'href="%s" type="application/atom+xml" />'."\n",
 -                     esc_param($project), href(action=>"atom"));
 -              printf('<link rel="alternate" title="%s log Atom feed (no merges)" '.
 -                     'href="%s" type="application/atom+xml" />'."\n",
 -                     esc_param($project), href(action=>"atom",
 -                                               extra_options=>"--no-merges"));
 +              my %href_params = get_feed_info();
 +              if (!exists $href_params{'-title'}) {
 +                      $href_params{'-title'} = 'log';
 +              }
 +
 +              foreach my $format qw(RSS Atom) {
 +                      my $type = lc($format);
 +                      my %link_attr = (
 +                              '-rel' => 'alternate',
 +                              '-title' => "$project - $href_params{'-title'} - $format feed",
 +                              '-type' => "application/$type+xml"
 +                      );
 +
 +                      $href_params{'action'} = $type;
 +                      $link_attr{'-href'} = href(%href_params);
 +                      print "<link ".
 +                            "rel=\"$link_attr{'-rel'}\" ".
 +                            "title=\"$link_attr{'-title'}\" ".
 +                            "href=\"$link_attr{'-href'}\" ".
 +                            "type=\"$link_attr{'-type'}\" ".
 +                            "/>\n";
 +
 +                      $href_params{'extra_options'} = '--no-merges';
 +                      $link_attr{'-href'} = href(%href_params);
 +                      $link_attr{'-title'} .= ' (no merges)';
 +                      print "<link ".
 +                            "rel=\"$link_attr{'-rel'}\" ".
 +                            "title=\"$link_attr{'-title'}\" ".
 +                            "href=\"$link_attr{'-href'}\" ".
 +                            "type=\"$link_attr{'-type'}\" ".
 +                            "/>\n";
 +              }
 +
        } else {
                printf('<link rel="alternate" title="%s projects list" '.
 -                     'href="%s" type="text/plain; charset=utf-8"/>'."\n",
 +                     'href="%s" type="text/plain; charset=utf-8" />'."\n",
                       $site_name, href(project=>undef, action=>"project_index"));
                printf('<link rel="alternate" title="%s projects feeds" '.
 -                     'href="%s" type="text/x-opml"/>'."\n",
 +                     'href="%s" type="text/x-opml" />'."\n",
                       $site_name, href(project=>undef, action=>"opml"));
        }
        if (defined $favicon) {
 -              print qq(<link rel="shortcut icon" href="$favicon" type="image/png"/>\n);
 +              print qq(<link rel="shortcut icon" href="$favicon" type="image/png" />\n);
        }
  
        print "</head>\n" .
  }
  
  sub git_footer_html {
 +      my $feed_class = 'rss_logo';
 +
        print "<div class=\"page_footer\">\n";
        if (defined $project) {
                my $descr = git_get_project_description($project);
                if (defined $descr) {
                        print "<div class=\"page_footer_text\">" . esc_html($descr) . "</div>\n";
                }
 -              print $cgi->a({-href => href(action=>"rss"),
 -                            -class => "rss_logo"}, "RSS") . " ";
 -              print $cgi->a({-href => href(action=>"atom"),
 -                            -class => "rss_logo"}, "Atom") . "\n";
 +
 +              my %href_params = get_feed_info();
 +              if (!%href_params) {
 +                      $feed_class .= ' generic';
 +              }
 +              $href_params{'-title'} ||= 'log';
 +
 +              foreach my $format qw(RSS Atom) {
 +                      $href_params{'action'} = lc($format);
 +                      print $cgi->a({-href => href(%href_params),
 +                                    -title => "$href_params{'-title'} $format feed",
 +                                    -class => $feed_class}, $format)."\n";
 +              }
 +
        } else {
                print $cgi->a({-href => href(project=>undef, action=>"opml"),
 -                            -class => "rss_logo"}, "OPML") . " ";
 +                            -class => $feed_class}, "OPML") . " ";
                print $cgi->a({-href => href(project=>undef, action=>"project_index"),
 -                            -class => "rss_logo"}, "TXT") . "\n";
 +                            -class => $feed_class}, "TXT") . "\n";
        }
 -      print "</div>\n" ;
 +      print "</div>\n"; # class="page_footer"
  
        if (-f $site_footer) {
                open (my $fd, $site_footer);
@@@ -2756,7 -2676,7 +2756,7 @@@ sub git_print_page_nav 
  }
  
  sub format_paging_nav {
-       my ($action, $hash, $head, $page, $nrevs) = @_;
+       my ($action, $hash, $head, $page, $has_next_link) = @_;
        my $paging_nav;
  
  
                $paging_nav .= " &sdot; prev";
        }
  
-       if ($nrevs >= (100 * ($page+1)-1)) {
+       if ($has_next_link) {
                $paging_nav .= " &sdot; " .
                        $cgi->a({-href => href(-replay=>1, page=>$page+1),
                                 -accesskey => "n", -title => "Alt-n"}, "next");
@@@ -4665,7 -4585,7 +4665,7 @@@ sub git_log 
  
        my @commitlist = parse_commits($hash, 101, (100 * $page));
  
-       my $paging_nav = format_paging_nav('log', $hash, $head, $page, (100 * ($page+1)));
+       my $paging_nav = format_paging_nav('log', $hash, $head, $page, $#commitlist >= 100);
  
        git_header_html();
        git_print_page_nav('log','', $hash,undef,undef, $paging_nav);
@@@ -5585,7 -5505,7 +5585,7 @@@ sub git_shortlog 
  
        my @commitlist = parse_commits($hash, 101, (100 * $page));
  
-       my $paging_nav = format_paging_nav('shortlog', $hash, $head, $page, (100 * ($page+1)));
+       my $paging_nav = format_paging_nav('shortlog', $hash, $head, $page, $#commitlist >= 100);
        my $next_link = '';
        if ($#commitlist >= 100) {
                $next_link =
diff --combined t/t7003-filter-branch.sh
index 1e8a205e536c918569d6537883ee35d3bdcd515f,f126204d49c92fad701bf4e3f292a528b7e27d84..e26f72693071ae1037ccf739b6ba2bb63ce95a21
@@@ -97,7 -97,7 +97,7 @@@ test_expect_success 'subdirectory filte
        test_must_fail git show sub:subdir
  '
  
- test_expect_success 'setup and filter history that requires --full-history' '
+ test_expect_success 'more setup' '
        git checkout master &&
        mkdir subdir &&
        echo A > subdir/new &&
        git rm a &&
        test_tick &&
        git commit -m "again subdir on master" &&
-       git merge branch &&
-       git branch sub-master &&
-       git-filter-branch -f --subdirectory-filter subdir sub-master
- '
- test_expect_success 'subdirectory filter result looks okay' '
-       test 3 = $(git rev-list -1 --parents sub-master | wc -w) &&
-       git show sub-master^:new &&
-       git show sub-master^2:new &&
-       test_must_fail git show sub:subdir
+       git merge branch
  '
  
  test_expect_success 'use index-filter to move into a subdirectory' '
                 "git ls-files -s | sed \"s-\\t-&newsubdir/-\" |
                  GIT_INDEX_FILE=\$GIT_INDEX_FILE.new \
                        git update-index --index-info &&
 -                mv \$GIT_INDEX_FILE.new \$GIT_INDEX_FILE" directorymoved &&
 +                mv \"\$GIT_INDEX_FILE.new\" \"\$GIT_INDEX_FILE\"" directorymoved &&
        test -z "$(git diff HEAD directorymoved:newsubdir)"'
  
  test_expect_success 'stops when msg filter fails' '
@@@ -219,36 -210,4 +210,36 @@@ test_expect_success 'Subdirectory filte
        test $(git rev-list master | wc -l) = 3
  '
  
 +test_expect_success 'Tag name filtering retains tag message' '
 +      git tag -m atag T &&
 +      git cat-file tag T > expect &&
 +      git filter-branch -f --tag-name-filter cat &&
 +      git cat-file tag T > actual &&
 +      test_cmp expect actual
 +'
 +
 +faux_gpg_tag='object XXXXXX
 +type commit
 +tag S
 +tagger T A Gger <tagger@example.com> 1206026339 -0500
 +
 +This is a faux gpg signed tag.
 +-----BEGIN PGP SIGNATURE-----
 +Version: FauxGPG v0.0.0 (FAUX/Linux)
 +
 +gdsfoewhxu/6l06f1kxyxhKdZkrcbaiOMtkJUA9ITAc1mlamh0ooasxkH1XwMbYQ
 +acmwXaWET20H0GeAGP+7vow=
 +=agpO
 +-----END PGP SIGNATURE-----
 +'
 +test_expect_success 'Tag name filtering strips gpg signature' '
 +      sha1=$(git rev-parse HEAD) &&
 +      sha1t=$(echo "$faux_gpg_tag" | sed -e s/XXXXXX/$sha1/ | git mktag) &&
 +      git update-ref "refs/tags/S" "$sha1t" &&
 +      echo "$faux_gpg_tag" | sed -e s/XXXXXX/$sha1/ | head -n 6 > expect &&
 +      git filter-branch -f --tag-name-filter cat &&
 +      git cat-file tag S > actual &&
 +      test_cmp expect actual
 +'
 +
  test_done