Merge branch 'maint'
authorJunio C Hamano <junkio@cox.net>
Tue, 31 Oct 2006 03:38:50 +0000 (19:38 -0800)
committerJunio C Hamano <junkio@cox.net>
Tue, 31 Oct 2006 03:38:50 +0000 (19:38 -0800)
* maint:
revision traversal: --unpacked does not limit commit list anymore.
Continue traversal when rev-list --unpacked finds a packed commit.
Use memmove instead of memcpy for overlapping areas
quote.c: ensure the same quoting across platforms.
Surround "#define DEBUG 0" with "#ifndef DEBUG..#endif"

1  2 
blame.c
quote.c
revision.c
diff --combined blame.c
index e664813cb48f555fa8968995eda4170a02a99f42,3e227d27124ff3eb09409a781c532de5bfc52369..3ec1c8f1b287654cccb0f2427810d0afead5c44b
+++ b/blame.c
  #include "diffcore.h"
  #include "revision.h"
  #include "xdiff-interface.h"
 +#include "quote.h"
  
+ #ifndef DEBUG
  #define DEBUG 0
+ #endif
  
 -static const char blame_usage[] = "git-blame [-c] [-l] [-t] [-S <revs-file>] [--] file [commit]\n"
 -      "  -c, --compatibility Use the same output mode as git-annotate (Default: off)\n"
 -      "  -l, --long          Show long commit SHA1 (Default: off)\n"
 -      "  -t, --time          Show raw timestamp (Default: off)\n"
 -      "  -S, --revs-file     Use revisions from revs-file instead of calling git-rev-list\n"
 -      "  -h, --help          This message";
 +static const char blame_usage[] =
 +"git-blame [-c] [-l] [-t] [-f] [-n] [-p] [-S <revs-file>] [--] file [commit]\n"
 +"  -c, --compatibility Use the same output mode as git-annotate (Default: off)\n"
 +"  -l, --long          Show long commit SHA1 (Default: off)\n"
 +"  -t, --time          Show raw timestamp (Default: off)\n"
 +"  -f, --show-name     Show original filename (Default: auto)\n"
 +"  -n, --show-number   Show original linenumber (Default: off)\n"
 +"  -p, --porcelain     Show in a format designed for machine consumption\n"
 +"  -S revs-file        Use revisions from revs-file instead of calling git-rev-list\n"
 +"  -h, --help          This message";
  
  static struct commit **blame_lines;
  static int num_blame_lines;
 -static charblame_contents;
 +static char *blame_contents;
  static int blame_len;
  
  struct util_info {
        char *buf;
        unsigned long size;
        int num_lines;
 -      const char* pathname;
 +      const char *pathname;
 +      unsigned meta_given:1;
  
 -      voidtopo_data;
 +      void *topo_data;
  };
  
  struct chunk {
@@@ -162,10 -158,11 +164,10 @@@ static int get_blob_sha1_internal(cons
                                  unsigned mode, int stage);
  
  static unsigned char blob_sha1[20];
 -static const charblame_file;
 +static const char *blame_file;
  static int get_blob_sha1(struct tree *t, const char *pathname,
                         unsigned char *sha1)
  {
 -      int i;
        const char *pathspec[2];
        blame_file = pathname;
        pathspec[0] = pathname;
        hashclr(blob_sha1);
        read_tree_recursive(t, "", 0, 0, pathspec, get_blob_sha1_internal);
  
 -      for (i = 0; i < 20; i++) {
 -              if (blob_sha1[i] != 0)
 -                      break;
 -      }
 -
 -      if (i == 20)
 +      if (is_null_sha1(blob_sha1))
                return -1;
  
        hashcpy(sha1, blob_sha1);
@@@ -232,6 -234,9 +234,9 @@@ static void print_map(struct commit *cm
            util2->num_lines ? util->num_lines : util2->num_lines;
        int num;
  
+       if (print_map == NULL)
+               ; /* to avoid "unused function" warning */
        for (i = 0; i < max; i++) {
                printf("i: %d ", i);
                num = -1;
                if (i < util->num_lines) {
                        num = util->line_map[i];
                        printf("%d\t", num);
 -              } else
 +              }
 +              else
                        printf("\t");
  
                if (i < util2->num_lines) {
                        printf("%d\t", num2);
                        if (num != -1 && num2 != num)
                                printf("---");
 -              } else
 +              }
 +              else
                        printf("\t");
  
                printf("\n");
@@@ -268,12 -271,12 +273,12 @@@ static void fill_line_map(struct commi
        int cur_chunk = 0;
        int i1, i2;
  
 -      if (p->num && DEBUG)
 -              print_patch(p);
 -
 -      if (DEBUG)
 +      if (DEBUG) {
 +              if (p->num)
 +                      print_patch(p);
                printf("num lines 1: %d num lines 2: %d\n", util->num_lines,
                       util2->num_lines);
 +      }
  
        for (i1 = 0, i2 = 0; i1 < util->num_lines; i1++, i2++) {
                struct chunk *chunk = NULL;
                                i2 += chunk->len2;
  
                        cur_chunk++;
 -              } else {
 +              }
 +              else {
                        if (i2 >= util2->num_lines)
                                break;
  
@@@ -330,15 -332,19 +335,15 @@@ static int map_line(struct commit *comm
        return info->line_map[line];
  }
  
 -static struct util_infoget_util(struct commit *commit)
 +static struct util_info *get_util(struct commit *commit)
  {
        struct util_info *util = commit->util;
  
        if (util)
                return util;
  
 -      util = xmalloc(sizeof(struct util_info));
 -      util->buf = NULL;
 -      util->size = 0;
 -      util->line_map = NULL;
 +      util = xcalloc(1, sizeof(struct util_info));
        util->num_lines = -1;
 -      util->pathname = NULL;
        commit->util = util;
        return util;
  }
@@@ -368,7 -374,7 +373,7 @@@ static void alloc_line_map(struct commi
                if (util->buf[i] == '\n')
                        util->num_lines++;
        }
 -      if(util->buf[util->size - 1] != '\n')
 +      if (util->buf[util->size - 1] != '\n')
                util->num_lines++;
  
        util->line_map = xmalloc(sizeof(int) * util->num_lines);
                util->line_map[i] = -1;
  }
  
 -static void init_first_commit(struct commit* commit, const char* filename)
 +static void init_first_commit(struct commit *commit, const char *filename)
  {
 -      struct util_infoutil = commit->util;
 +      struct util_info *util = commit->util;
        int i;
  
        util->pathname = filename;
                util->line_map[i] = i;
  }
  
 -
  static void process_commits(struct rev_info *rev, const char *path,
 -                          struct commit** initial)
 +                          struct commit **initial)
  {
        int i;
 -      struct util_infoutil;
 +      struct util_info *util;
        int lines_left;
        int *blame_p;
        int *new_lines;
        int new_lines_len;
  
 -      struct commitcommit = get_revision(rev);
 +      struct commit *commit = get_revision(rev);
        assert(commit);
        init_first_commit(commit, path);
  
                     parents != NULL; parents = parents->next)
                        num_parents++;
  
 -              if(num_parents == 0)
 +              if (num_parents == 0)
                        *initial = commit;
  
                if (fill_util_info(commit))
        } while ((commit = get_revision(rev)) != NULL);
  }
  
 -
 -static int compare_tree_path(struct rev_info* revs,
 -                           struct commit* c1, struct commit* c2)
 +static int compare_tree_path(struct rev_info *revs,
 +                           struct commit *c1, struct commit *c2)
  {
        int ret;
 -      const charpaths[2];
 -      struct util_infoutil = c2->util;
 +      const char *paths[2];
 +      struct util_info *util = c2->util;
        paths[0] = util->pathname;
        paths[1] = NULL;
  
        return ret;
  }
  
 -
 -static int same_tree_as_empty_path(struct rev_info *revs, struct tree* t1,
 -                                 const char* path)
 +static int same_tree_as_empty_path(struct rev_info *revs, struct tree *t1,
 +                                 const char *path)
  {
        int ret;
 -      const charpaths[2];
 +      const char *paths[2];
        paths[0] = path;
        paths[1] = NULL;
  
        return ret;
  }
  
 -static const char* find_rename(struct commit* commit, struct commit* parent)
 +static const char *find_rename(struct commit *commit, struct commit *parent)
  {
 -      struct util_infocutil = commit->util;
 +      struct util_info *cutil = commit->util;
        struct diff_options diff_opts;
        const char *paths[1];
        int i;
        for (i = 0; i < diff_queued_diff.nr; i++) {
                struct diff_filepair *p = diff_queued_diff.queue[i];
  
 -              if (p->status == 'R' && !strcmp(p->one->path, cutil->pathname)) {
 +              if (p->status == 'R' &&
 +                  !strcmp(p->one->path, cutil->pathname)) {
                        if (DEBUG)
 -                              printf("rename %s -> %s\n", p->one->path, p->two->path);
 +                              printf("rename %s -> %s\n",
 +                                     p->one->path, p->two->path);
                        return p->two->path;
                }
        }
@@@ -580,7 -587,7 +585,7 @@@ static void simplify_commit(struct rev_
                return;
  
        if (!commit->parents) {
 -              struct util_infoutil = commit->util;
 +              struct util_info *util = commit->util;
                if (!same_tree_as_empty_path(revs, commit->tree,
                                             util->pathname))
                        commit->object.flags |= TREECHANGE;
  
                case REV_TREE_NEW:
                {
 -
 -                      struct util_info* util = commit->util;
 +                      struct util_info *util = commit->util;
                        if (revs->remove_empty_trees &&
                            same_tree_as_empty_path(revs, p->tree,
                                                    util->pathname)) {
 -                              const charnew_name = find_rename(commit, p);
 +                              const char *new_name = find_rename(commit, p);
                                if (new_name) {
 -                                      struct util_infoputil = get_util(p);
 +                                      struct util_info *putil = get_util(p);
                                        if (!putil->pathname)
                                                putil->pathname = xstrdup(new_name);
 -                              } else {
 +                              }
 +                              else {
                                        *pp = parent->next;
                                        continue;
                                }
        commit->object.flags |= TREECHANGE;
  }
  
 -
  struct commit_info
  {
 -      charauthor;
 -      charauthor_mail;
 +      char *author;
 +      char *author_mail;
        unsigned long author_time;
 -      char* author_tz;
 +      char *author_tz;
 +
 +      /* filled only when asked for details */
 +      char *committer;
 +      char *committer_mail;
 +      unsigned long committer_time;
 +      char *committer_tz;
 +
 +      char *summary;
  };
  
 -static void get_commit_info(struct commit* commit, struct commit_info* ret)
 +static void get_ac_line(const char *inbuf, const char *what,
 +                      int bufsz, char *person, char **mail,
 +                      unsigned long *time, char **tz)
  {
        int len;
 -      char* tmp;
 -      static char author_buf[1024];
 -
 -      tmp = strstr(commit->buffer, "\nauthor ") + 8;
 -      len = strchr(tmp, '\n') - tmp;
 -      ret->author = author_buf;
 -      memcpy(ret->author, tmp, len);
 +      char *tmp, *endp;
 +
 +      tmp = strstr(inbuf, what);
 +      if (!tmp)
 +              goto error_out;
 +      tmp += strlen(what);
 +      endp = strchr(tmp, '\n');
 +      if (!endp)
 +              len = strlen(tmp);
 +      else
 +              len = endp - tmp;
 +      if (bufsz <= len) {
 +      error_out:
 +              /* Ugh */
 +              person = *mail = *tz = "(unknown)";
 +              *time = 0;
 +              return;
 +      }
 +      memcpy(person, tmp, len);
  
 -      tmp = ret->author;
 +      tmp = person;
        tmp += len;
        *tmp = 0;
 -      while(*tmp != ' ')
 +      while (*tmp != ' ')
                tmp--;
 -      ret->author_tz = tmp+1;
 +      *tz = tmp+1;
  
        *tmp = 0;
 -      while(*tmp != ' ')
 +      while (*tmp != ' ')
                tmp--;
 -      ret->author_time = strtoul(tmp, NULL, 10);
 +      *time = strtoul(tmp, NULL, 10);
  
        *tmp = 0;
 -      while(*tmp != ' ')
 +      while (*tmp != ' ')
                tmp--;
 -      ret->author_mail = tmp + 1;
 -
 +      *mail = tmp + 1;
        *tmp = 0;
  }
  
 -static const char* format_time(unsigned long time, const char* tz_str,
 +static void get_commit_info(struct commit *commit, struct commit_info *ret, int detailed)
 +{
 +      int len;
 +      char *tmp, *endp;
 +      static char author_buf[1024];
 +      static char committer_buf[1024];
 +      static char summary_buf[1024];
 +
 +      ret->author = author_buf;
 +      get_ac_line(commit->buffer, "\nauthor ",
 +                  sizeof(author_buf), author_buf, &ret->author_mail,
 +                  &ret->author_time, &ret->author_tz);
 +
 +      if (!detailed)
 +              return;
 +
 +      ret->committer = committer_buf;
 +      get_ac_line(commit->buffer, "\ncommitter ",
 +                  sizeof(committer_buf), committer_buf, &ret->committer_mail,
 +                  &ret->committer_time, &ret->committer_tz);
 +
 +      ret->summary = summary_buf;
 +      tmp = strstr(commit->buffer, "\n\n");
 +      if (!tmp) {
 +      error_out:
 +              sprintf(summary_buf, "(%s)", sha1_to_hex(commit->object.sha1));
 +              return;
 +      }
 +      tmp += 2;
 +      endp = strchr(tmp, '\n');
 +      if (!endp)
 +              goto error_out;
 +      len = endp - tmp;
 +      if (len >= sizeof(summary_buf))
 +              goto error_out;
 +      memcpy(summary_buf, tmp, len);
 +      summary_buf[len] = 0;
 +}
 +
 +static const char *format_time(unsigned long time, const char *tz_str,
                               int show_raw_time)
  {
        static char time_buf[128];
        return time_buf;
  }
  
 -static void topo_setter(struct commit* c, void* data)
 +static void topo_setter(struct commit *c, void *data)
  {
 -      struct util_infoutil = c->util;
 +      struct util_info *util = c->util;
        util->topo_data = data;
  }
  
 -static void* topo_getter(struct commit* c)
 +static void *topo_getter(struct commit *c)
  {
 -      struct util_infoutil = c->util;
 +      struct util_info *util = c->util;
        return util->topo_data;
  }
  
@@@ -792,101 -740,6 +797,101 @@@ static int read_ancestry(const char *gr
        return 0;
  }
  
 +static int lineno_width(int lines)
 +{
 +      int i, width;
 +
 +      for (width = 1, i = 10; i <= lines + 1; width++)
 +              i *= 10;
 +      return width;
 +}
 +
 +static int find_orig_linenum(struct util_info *u, int lineno)
 +{
 +      int i;
 +
 +      for (i = 0; i < u->num_lines; i++)
 +              if (lineno == u->line_map[i])
 +                      return i + 1;
 +      return 0;
 +}
 +
 +static void emit_meta(struct commit *c, int lno,
 +                    int sha1_len, int compatibility, int porcelain,
 +                    int show_name, int show_number, int show_raw_time,
 +                    int longest_file, int longest_author,
 +                    int max_digits, int max_orig_digits)
 +{
 +      struct util_info *u;
 +      int lineno;
 +      struct commit_info ci;
 +
 +      u = c->util;
 +      lineno = find_orig_linenum(u, lno);
 +
 +      if (porcelain) {
 +              int group_size = -1;
 +              struct commit *cc = (lno == 0) ? NULL : blame_lines[lno-1];
 +              if (cc != c) {
 +                      /* This is the beginning of this group */
 +                      int i;
 +                      for (i = lno + 1; i < num_blame_lines; i++)
 +                              if (blame_lines[i] != c)
 +                                      break;
 +                      group_size = i - lno;
 +              }
 +              if (0 < group_size)
 +                      printf("%s %d %d %d\n", sha1_to_hex(c->object.sha1),
 +                             lineno, lno + 1, group_size);
 +              else
 +                      printf("%s %d %d\n", sha1_to_hex(c->object.sha1),
 +                             lineno, lno + 1);
 +              if (!u->meta_given) {
 +                      get_commit_info(c, &ci, 1);
 +                      printf("author %s\n", ci.author);
 +                      printf("author-mail %s\n", ci.author_mail);
 +                      printf("author-time %lu\n", ci.author_time);
 +                      printf("author-tz %s\n", ci.author_tz);
 +                      printf("committer %s\n", ci.committer);
 +                      printf("committer-mail %s\n", ci.committer_mail);
 +                      printf("committer-time %lu\n", ci.committer_time);
 +                      printf("committer-tz %s\n", ci.committer_tz);
 +                      printf("filename ");
 +                      if (quote_c_style(u->pathname, NULL, NULL, 0))
 +                              quote_c_style(u->pathname, NULL, stdout, 0);
 +                      else
 +                              fputs(u->pathname, stdout);
 +                      printf("\nsummary %s\n", ci.summary);
 +
 +                      u->meta_given = 1;
 +              }
 +              putchar('\t');
 +              return;
 +      }
 +
 +      get_commit_info(c, &ci, 0);
 +      fwrite(sha1_to_hex(c->object.sha1), sha1_len, 1, stdout);
 +      if (compatibility) {
 +              printf("\t(%10s\t%10s\t%d)", ci.author,
 +                     format_time(ci.author_time, ci.author_tz,
 +                                 show_raw_time),
 +                     lno + 1);
 +      }
 +      else {
 +              if (show_name)
 +                      printf(" %-*.*s", longest_file, longest_file,
 +                             u->pathname);
 +              if (show_number)
 +                      printf(" %*d", max_orig_digits,
 +                             lineno);
 +              printf(" (%-*.*s %10s %*d) ",
 +                     longest_author, longest_author, ci.author,
 +                     format_time(ci.author_time, ci.author_tz,
 +                                 show_raw_time),
 +                     max_digits, lno + 1);
 +      }
 +}
 +
  int main(int argc, const char **argv)
  {
        int i;
        int compatibility = 0;
        int show_raw_time = 0;
        int options = 1;
 -      struct commitstart_commit;
 +      struct commit *start_commit;
  
 -      const charargs[10];
 +      const char *args[10];
        struct rev_info rev;
  
        struct commit_info ci;
        const char *buf;
 -      int max_digits;
 -      int longest_file, longest_author;
 -      int found_rename;
 +      int max_digits, max_orig_digits;
 +      int longest_file, longest_author, longest_file_lines;
 +      int show_name = 0;
 +      int show_number = 0;
 +      int porcelain = 0;
  
 -      const charprefix = setup_git_directory();
 +      const char *prefix = setup_git_directory();
        git_config(git_default_config);
  
 -      for(i = 1; i < argc; i++) {
 -              if(options) {
 -                      if(!strcmp(argv[i], "-h") ||
 +      for (i = 1; i < argc; i++) {
 +              if (options) {
 +                      if (!strcmp(argv[i], "-h") ||
                           !strcmp(argv[i], "--help"))
                                usage(blame_usage);
 -                      else if(!strcmp(argv[i], "-l") ||
 -                              !strcmp(argv[i], "--long")) {
 +                      if (!strcmp(argv[i], "-l") ||
 +                          !strcmp(argv[i], "--long")) {
                                sha1_len = 40;
                                continue;
 -                      } else if(!strcmp(argv[i], "-c") ||
 -                                !strcmp(argv[i], "--compatibility")) {
 +                      }
 +                      if (!strcmp(argv[i], "-c") ||
 +                          !strcmp(argv[i], "--compatibility")) {
                                compatibility = 1;
                                continue;
 -                      } else if(!strcmp(argv[i], "-t") ||
 -                                !strcmp(argv[i], "--time")) {
 +                      }
 +                      if (!strcmp(argv[i], "-t") ||
 +                          !strcmp(argv[i], "--time")) {
                                show_raw_time = 1;
                                continue;
 -                      } else if(!strcmp(argv[i], "-S")) {
 +                      }
 +                      if (!strcmp(argv[i], "-S")) {
                                if (i + 1 < argc &&
                                    !read_ancestry(argv[i + 1], &sha1_p)) {
                                        compatibility = 1;
                                        continue;
                                }
                                usage(blame_usage);
 -                      } else if(!strcmp(argv[i], "--")) {
 +                      }
 +                      if (!strcmp(argv[i], "-f") ||
 +                          !strcmp(argv[i], "--show-name")) {
 +                              show_name = 1;
 +                              continue;
 +                      }
 +                      if (!strcmp(argv[i], "-n") ||
 +                          !strcmp(argv[i], "--show-number")) {
 +                              show_number = 1;
 +                              continue;
 +                      }
 +                      if (!strcmp(argv[i], "-p") ||
 +                          !strcmp(argv[i], "--porcelain")) {
 +                              porcelain = 1;
 +                              sha1_len = 40;
 +                              show_raw_time = 1;
 +                              continue;
 +                      }
 +                      if (!strcmp(argv[i], "--")) {
                                options = 0;
                                continue;
 -                      } else if(argv[i][0] == '-')
 +                      }
 +                      if (argv[i][0] == '-')
                                usage(blame_usage);
 -                      else
 -                              options = 0;
 +                      options = 0;
                }
  
 -              if(!options) {
 -                      if(!filename)
 +              if (!options) {
 +                      if (!filename)
                                filename = argv[i];
 -                      else if(!commit)
 +                      else if (!commit)
                                commit = argv[i];
                        else
                                usage(blame_usage);
                }
        }
  
 -      if(!filename)
 +      if (!filename)
                usage(blame_usage);
        if (commit && sha1_p)
                usage(blame_usage);
 -      else if(!commit)
 +      else if (!commit)
                commit = "HEAD";
  
 -      if(prefix)
 +      if (prefix)
                sprintf(filename_buf, "%s%s", prefix, filename);
        else
                strcpy(filename_buf, filename);
                return 1;
        }
  
 -
        init_revisions(&rev, setup_git_directory());
        rev.remove_empty_trees = 1;
        rev.topo_order = 1;
        prepare_revision_walk(&rev);
        process_commits(&rev, filename, &initial);
  
 +      for (i = 0; i < num_blame_lines; i++)
 +              if (!blame_lines[i])
 +                      blame_lines[i] = initial;
 +
        buf = blame_contents;
 -      for (max_digits = 1, i = 10; i <= num_blame_lines + 1; max_digits++)
 -              i *= 10;
 +      max_digits = lineno_width(num_blame_lines);
  
        longest_file = 0;
        longest_author = 0;
 -      found_rename = 0;
 +      longest_file_lines = 0;
        for (i = 0; i < num_blame_lines; i++) {
                struct commit *c = blame_lines[i];
 -              struct util_info* u;
 -              if (!c)
 -                      c = initial;
 +              struct util_info *u;
                u = c->util;
  
 -              if (!found_rename && strcmp(filename, u->pathname))
 -                      found_rename = 1;
 +              if (!show_name && strcmp(filename, u->pathname))
 +                      show_name = 1;
                if (longest_file < strlen(u->pathname))
                        longest_file = strlen(u->pathname);
 -              get_commit_info(c, &ci);
 +              if (longest_file_lines < u->num_lines)
 +                      longest_file_lines = u->num_lines;
 +              get_commit_info(c, &ci, 0);
                if (longest_author < strlen(ci.author))
                        longest_author = strlen(ci.author);
        }
  
 -      for (i = 0; i < num_blame_lines; i++) {
 -              struct commit *c = blame_lines[i];
 -              struct util_info* u;
 +      max_orig_digits = lineno_width(longest_file_lines);
  
 -              if (!c)
 -                      c = initial;
 -
 -              u = c->util;
 -              get_commit_info(c, &ci);
 -              fwrite(sha1_to_hex(c->object.sha1), sha1_len, 1, stdout);
 -              if(compatibility) {
 -                      printf("\t(%10s\t%10s\t%d)", ci.author,
 -                             format_time(ci.author_time, ci.author_tz,
 -                                         show_raw_time),
 -                             i+1);
 -              } else {
 -                      if (found_rename)
 -                              printf(" %-*.*s", longest_file, longest_file,
 -                                     u->pathname);
 -                      printf(" (%-*.*s %10s %*d) ",
 -                             longest_author, longest_author, ci.author,
 -                             format_time(ci.author_time, ci.author_tz,
 -                                         show_raw_time),
 -                             max_digits, i+1);
 -              }
 +      for (i = 0; i < num_blame_lines; i++) {
 +              emit_meta(blame_lines[i], i,
 +                        sha1_len, compatibility, porcelain,
 +                        show_name, show_number, show_raw_time,
 +                        longest_file, longest_author,
 +                        max_digits, max_orig_digits);
  
 -              if(i == num_blame_lines - 1) {
 +              if (i == num_blame_lines - 1) {
                        fwrite(buf, blame_len - (buf - blame_contents),
                               1, stdout);
 -                      if(blame_contents[blame_len-1] != '\n')
 +                      if (blame_contents[blame_len-1] != '\n')
                                putc('\n', stdout);
 -              } else {
 -                      char* next_buf = strchr(buf, '\n') + 1;
 +              }
 +              else {
 +                      char *next_buf = strchr(buf, '\n') + 1;
                        fwrite(buf, next_buf - buf, 1, stdout);
                        buf = next_buf;
                }
diff --combined quote.c
index ee7d62c751272f511d46894e5c5cd32e4403c721,dc5c0a7715e4782024ede6dd90b150f6e71022ee..a418a0f803f91d218b66ae89a1e8615a94ff27bc
+++ b/quote.c
@@@ -209,7 -209,7 +209,7 @@@ static int quote_c_style_counted(const 
                if (!ch)
                        break;
                if ((ch < ' ') || (ch == '"') || (ch == '\\') ||
-                   (ch == 0177)) {
+                   (ch >= 0177)) {
                        needquote = 1;
                        switch (ch) {
                        case '\a': EMITQ(); ch = 'a'; break;
@@@ -349,41 -349,3 +349,41 @@@ void write_name_quoted(const char *pref
        else
                goto no_quote;
  }
 +
 +/* quoting as a string literal for other languages */
 +
 +void perl_quote_print(FILE *stream, const char *src)
 +{
 +      const char sq = '\'';
 +      const char bq = '\\';
 +      char c;
 +
 +      fputc(sq, stream);
 +      while ((c = *src++)) {
 +              if (c == sq || c == bq)
 +                      fputc(bq, stream);
 +              fputc(c, stream);
 +      }
 +      fputc(sq, stream);
 +}
 +
 +void python_quote_print(FILE *stream, const char *src)
 +{
 +      const char sq = '\'';
 +      const char bq = '\\';
 +      const char nl = '\n';
 +      char c;
 +
 +      fputc(sq, stream);
 +      while ((c = *src++)) {
 +              if (c == nl) {
 +                      fputc(bq, stream);
 +                      fputc('n', stream);
 +                      continue;
 +              }
 +              if (c == sq || c == bq)
 +                      fputc(bq, stream);
 +              fputc(c, stream);
 +      }
 +      fputc(sq, stream);
 +}
diff --combined revision.c
index f1e0caaae3d2a96de6cf9bad12e8641c19d788dd,36cdfcd1ad80caf8545cc02da7881fa92414d665..04fa7e517153d2fa8a08da961070e8c54372cc5e
@@@ -418,9 -418,6 +418,6 @@@ static void limit_list(struct rev_info 
  
                if (revs->max_age != -1 && (commit->date < revs->max_age))
                        obj->flags |= UNINTERESTING;
-               if (revs->unpacked &&
-                   has_sha1_pack(obj->sha1, revs->ignore_packed))
-                       obj->flags |= UNINTERESTING;
                add_parents_to_list(revs, commit, &list);
                if (obj->flags & UNINTERESTING) {
                        mark_parents_uninteresting(commit);
@@@ -732,7 -729,6 +729,7 @@@ int setup_revisions(int argc, const cha
        int i, flags, seen_dashdash, show_merge;
        const char **unrecognized = argv + 1;
        int left = 1;
 +      int all_match = 0;
  
        /* First, search for "--" */
        seen_dashdash = 0;
                                add_message_grep(revs, arg+7);
                                continue;
                        }
 +                      if (!strcmp(arg, "--all-match")) {
 +                              all_match = 1;
 +                              continue;
 +                      }
  
                        opts = diff_opt_parse(&revs->diffopt, argv+i, argc-i);
                        if (opts > 0) {
                add_pending_object(revs, object, def);
        }
  
-       if (revs->topo_order || revs->unpacked)
+       if (revs->topo_order)
                revs->limited = 1;
  
        if (revs->prune_data) {
        if (diff_setup_done(&revs->diffopt) < 0)
                die("diff_setup_done failed");
  
 -      if (revs->grep_filter)
 +      if (revs->grep_filter) {
 +              revs->grep_filter->all_match = all_match;
                compile_grep_patterns(revs->grep_filter);
 +      }
  
        return left;
  }
@@@ -1149,17 -1139,18 +1146,18 @@@ struct commit *get_revision(struct rev_
                 * that we'd otherwise have done in limit_list().
                 */
                if (!revs->limited) {
-                       if ((revs->unpacked &&
-                            has_sha1_pack(commit->object.sha1,
-                                          revs->ignore_packed)) ||
-                           (revs->max_age != -1 &&
-                            (commit->date < revs->max_age)))
+                       if (revs->max_age != -1 &&
+                           (commit->date < revs->max_age))
                                continue;
                        add_parents_to_list(revs, commit, &revs->commits);
                }
                if (commit->object.flags & SHOWN)
                        continue;
  
+               if (revs->unpacked && has_sha1_pack(commit->object.sha1,
+                                                   revs->ignore_packed))
+                   continue;
                /* We want to show boundary commits only when their
                 * children are shown.  When path-limiter is in effect,
                 * rewrite_parents() drops some commits from getting shown,