Code

Merge branch 'maint'
authorJunio C Hamano <gitster@pobox.com>
Wed, 4 Jul 2007 05:56:59 +0000 (22:56 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 4 Jul 2007 05:56:59 +0000 (22:56 -0700)
* maint:
  Document -<n> for git-format-patch
  glossary: add 'reflog'
  diff --no-index: fix --name-status with added files
  Don't smash stack when $GIT_ALTERNATE_OBJECT_DIRECTORIES is too long

1  2 
Documentation/git-format-patch.txt
diff.c
sha1_file.c
t/t4013-diff-various.sh

index e5638102ec50aba1550ed8ed1345666d601d3c94,0ca58a7eb36fb4b29ea485a098a12660360a2252..6cbcf937bcd3128b27fbce673d8500590a3f66ce
@@@ -11,8 -11,7 +11,8 @@@ SYNOPSI
  [verse]
  'git-format-patch' [-n | -k] [-o <dir> | --stdout] [--thread]
                     [--attach[=<boundary>] | --inline[=<boundary>]]
 -                   [-s | --signoff] [<common diff options>] [--start-number <n>]
 +                   [-s | --signoff] [<common diff options>]
 +                   [--start-number <n>] [--numbered-files]
                     [--in-reply-to=Message-Id] [--suffix=.<sfx>]
                     [--ignore-if-in-upstream]
                     [--subject-prefix=Subject-Prefix]
@@@ -31,11 -30,9 +31,11 @@@ gitlink:git-rev-parse[1]
  The output of this command is convenient for e-mail submission or
  for use with gitlink:git-am[1].
  
 -Each output file is numbered sequentially from 1, and uses the
 +By default, each output file is numbered sequentially from 1, and uses the
  first line of the commit message (massaged for pathname safety) as
 -the filename. The names of the output files are printed to standard
 +the filename. With the --numbered-files option, the output file names
 +will only be numbers, without the first line of the commit appended.
 +The names of the output files are printed to standard
  output, unless the --stdout option is specified.
  
  If -o is specified, output files are created in <dir>.  Otherwise
@@@ -53,6 -50,9 +53,9 @@@ OPTION
  -------
  include::diff-options.txt[]
  
+ -<n>::
+       Limits the number of patches to prepare.
  -o|--output-directory <dir>::
        Use <dir> to store the resulting files, instead of the
        current working directory.
  --start-number <n>::
        Start numbering the patches at <n> instead of 1.
  
 +--numbered-files::
 +      Output file names will be a simple number sequence
 +      without the default first line of the commit appended.
 +      Mutually exclusive with the --stdout option.
 +
  -k|--keep-subject::
        Do not strip/add '[PATCH]' from the first line of the
        commit log message.
@@@ -126,13 -121,12 +129,13 @@@ not add any suffix
  CONFIGURATION
  -------------
  You can specify extra mail header lines to be added to each
 -message in the repository configuration.  Also you can specify
 -the default suffix different from the built-in one:
 +message in the repository configuration.  You can also specify
 +new defaults for the subject prefix and file suffix.
  
  ------------
  [format]
          headers = "Organization: git-foo\n"
 +        subjectprefix = CHANGE
          suffix = .txt
  ------------
  
@@@ -179,3 -173,4 +182,3 @@@ Documentation by Junio C Hamano and th
  GIT
  ---
  Part of the gitlink:git[7] suite
 -
diff --combined diff.c
index b6eb72be029c9cd2f2b33977f3a3f02099b68106,da992dd4851dd67ab9a307c1b08ebed442e406cb..19589707c4cf40e622b0f7b98b8fd07704b37c01
--- 1/diff.c
--- 2/diff.c
+++ b/diff.c
@@@ -1460,7 -1460,7 +1460,7 @@@ int diff_populate_filespec(struct diff_
        if (size_only && 0 < s->size)
                return 0;
  
 -      if (S_ISDIRLNK(s->mode))
 +      if (S_ISGITLINK(s->mode))
                return diff_populate_gitlink(s, size_only);
  
        if (!s->sha1_valid ||
@@@ -1813,11 -1813,6 +1813,11 @@@ static void diff_fill_sha1_info(struct 
                hashclr(one->sha1);
  }
  
 +static int similarity_index(struct diff_filepair *p)
 +{
 +      return p->score * 100 / MAX_SCORE;
 +}
 +
  static void run_diff(struct diff_filepair *p, struct diff_options *o)
  {
        const char *pgm = external_diff();
                                "similarity index %d%%\n"
                                "copy from %s\n"
                                "copy to %s\n",
 -                              (int)(0.5 + p->score * 100.0/MAX_SCORE),
 -                              name_munged, other_munged);
 +                              similarity_index(p), name_munged, other_munged);
                break;
        case DIFF_STATUS_RENAMED:
                len += snprintf(msg + len, sizeof(msg) - len,
                                "similarity index %d%%\n"
                                "rename from %s\n"
                                "rename to %s\n",
 -                              (int)(0.5 + p->score * 100.0/MAX_SCORE),
 -                              name_munged, other_munged);
 +                              similarity_index(p), name_munged, other_munged);
                break;
        case DIFF_STATUS_MODIFIED:
                if (p->score) {
                        len += snprintf(msg + len, sizeof(msg) - len,
                                        "dissimilarity index %d%%\n",
 -                                      (int)(0.5 + p->score *
 -                                            100.0/MAX_SCORE));
 +                                      similarity_index(p));
                        complete_rewrite = 1;
                        break;
                }
@@@ -2105,8 -2103,6 +2105,8 @@@ static int opt_arg(const char *arg, in
        return 1;
  }
  
 +static int diff_scoreopt_parse(const char *opt);
 +
  int diff_opt_parse(struct diff_options *options, const char **av, int ac)
  {
        const char *arg = av[0];
                options->detect_rename = DIFF_DETECT_RENAME;
        }
        else if (!prefixcmp(arg, "-C")) {
 +              if (options->detect_rename == DIFF_DETECT_COPY)
 +                      options->find_copies_harder = 1;
                if ((options->rename_score =
                     diff_scoreopt_parse(arg)) == -1)
                        return -1;
        }
        else if (!strcmp(arg, "--find-copies-harder"))
                options->find_copies_harder = 1;
 +      else if (!strcmp(arg, "--follow"))
 +              options->follow_renames = 1;
        else if (!strcmp(arg, "--abbrev"))
                options->abbrev = DEFAULT_ABBREV;
        else if (!prefixcmp(arg, "--abbrev=")) {
                options->exit_with_status = 1;
        else if (!strcmp(arg, "--quiet"))
                options->quiet = 1;
 +      else if (!strcmp(arg, "--ext-diff"))
 +              options->allow_external = 1;
 +      else if (!strcmp(arg, "--no-ext-diff"))
 +              options->allow_external = 0;
        else
                return 0;
        return 1;
@@@ -2286,7 -2274,7 +2286,7 @@@ static int parse_num(const char **cp_p
        return (int)((num >= scale) ? MAX_SCORE : (MAX_SCORE * num / scale));
  }
  
 -int diff_scoreopt_parse(const char *opt)
 +static int diff_scoreopt_parse(const char *opt)
  {
        int opt1, opt2, cmd;
  
@@@ -2393,7 -2381,8 +2393,7 @@@ static void diff_flush_raw(struct diff_
        }
  
        if (p->score)
 -              sprintf(status, "%c%03d", p->status,
 -                      (int)(0.5 + p->score * 100.0/MAX_SCORE));
 +              sprintf(status, "%c%03d", p->status, similarity_index(p));
        else {
                status[0] = p->status;
                status[1] = 0;
                printf("%s ",
                       diff_unique_abbrev(p->two->sha1, abbrev));
        }
-       printf("%s%c%s", status, inter_name_termination, path_one);
+       printf("%s%c%s", status, inter_name_termination,
+                       two_paths || p->one->mode ?  path_one : path_two);
        if (two_paths)
                printf("%c%s", inter_name_termination, path_two);
        putchar(line_termination);
@@@ -2675,7 -2665,8 +2676,7 @@@ static void show_rename_copy(const cha
  {
        char *names = pprint_rename(p->one->path, p->two->path);
  
 -      printf(" %s %s (%d%%)\n", renamecopy, names,
 -             (int)(0.5 + p->score * 100.0/MAX_SCORE));
 +      printf(" %s %s (%d%%)\n", renamecopy, names, similarity_index(p));
        free(names);
        show_mode_change(p, 0);
  }
@@@ -2699,7 -2690,7 +2700,7 @@@ static void diff_summary(struct diff_fi
                if (p->score) {
                        char *name = quote_one(p->two->path);
                        printf(" rewrite %s (%d%%)\n", name,
 -                              (int)(0.5 + p->score * 100.0/MAX_SCORE));
 +                             similarity_index(p));
                        free(name);
                        show_mode_change(p, 0);
                } else  show_mode_change(p, 1);
@@@ -3009,22 -3000,6 +3010,22 @@@ void diffcore_std(struct diff_options *
  {
        if (options->quiet)
                return;
 +
 +      /*
 +       * break/rename count similarity differently depending on
 +       * the binary-ness.
 +       */
 +      if ((options->break_opt != -1) || (options->detect_rename)) {
 +              struct diff_queue_struct *q = &diff_queued_diff;
 +              int i;
 +
 +              for (i = 0; i < q->nr; i++) {
 +                      struct diff_filepair *p = q->queue[i];
 +                      p->one->is_binary = file_is_binary(p->one);
 +                      p->two->is_binary = file_is_binary(p->two);
 +              }
 +      }
 +
        if (options->break_opt != -1)
                diffcore_break(options->break_opt);
        if (options->detect_rename)
@@@ -3057,7 -3032,7 +3058,7 @@@ void diff_addremove(struct diff_option
         * entries to the diff-core.  They will be prefixed
         * with something like '=' or '*' (I haven't decided
         * which but should not make any difference).
 -       * Feeding the same new and old to diff_change() 
 +       * Feeding the same new and old to diff_change()
         * also has the same effect.
         * Before the final output happens, they are pruned after
         * merged into rename/copy pairs as appropriate.
@@@ -3084,7 -3059,7 +3085,7 @@@ void diff_change(struct diff_options *o
                 unsigned old_mode, unsigned new_mode,
                 const unsigned char *old_sha1,
                 const unsigned char *new_sha1,
 -               const char *base, const char *path) 
 +               const char *base, const char *path)
  {
        char concatpath[PATH_MAX];
        struct diff_filespec *one, *two;
diff --combined sha1_file.c
index f2b1ae0325ea16e4e46152c3d3d2d3d7f2b32e3d,1d328c8d61d97314c4fd7f83888b0d30b22ac301..1efd9ae19a84dbc2765d4011ea06b2145e86ebb3
@@@ -193,7 -193,7 +193,7 @@@ char *sha1_pack_name(const unsigned cha
                *buf++ = hex[val >> 4];
                *buf++ = hex[val & 0xf];
        }
 -      
 +
        return base;
  }
  
@@@ -218,7 -218,7 +218,7 @@@ char *sha1_pack_index_name(const unsign
                *buf++ = hex[val >> 4];
                *buf++ = hex[val & 0xf];
        }
 -      
 +
        return base;
  }
  
@@@ -352,10 -352,14 +352,14 @@@ static void read_info_alternates(const 
        char *map;
        size_t mapsz;
        struct stat st;
-       char path[PATH_MAX];
+       const char alt_file_name[] = "info/alternates";
+       /* Given that relative_base is no longer than PATH_MAX,
+          ensure that "path" has enough space to append "/", the
+          file name, "info/alternates", and a trailing NUL.  */
+       char path[PATH_MAX + 1 + sizeof alt_file_name];
        int fd;
  
-       sprintf(path, "%s/info/alternates", relative_base);
+       sprintf(path, "%s/%s", relative_base, alt_file_name);
        fd = open(path, O_RDONLY);
        if (fd < 0)
                return;
@@@ -376,12 -380,11 +380,12 @@@ void prepare_alt_odb(void
  {
        const char *alt;
  
 +      if (alt_odb_tail)
 +              return;
 +
        alt = getenv(ALTERNATE_DB_ENVIRONMENT);
        if (!alt) alt = "";
  
 -      if (alt_odb_tail)
 -              return;
        alt_odb_tail = &alt_odb_list;
        link_alt_odb_entries(alt, alt + strlen(alt), ':', NULL, 0);
  
@@@ -413,7 -416,7 +417,7 @@@ static size_t peak_pack_mapped
  static size_t pack_mapped;
  struct packed_git *packed_git;
  
 -void pack_report()
 +void pack_report(void)
  {
        fprintf(stderr,
                "pack_report: getpagesize()            = %10" SZ_FMT "\n"
@@@ -534,21 -537,6 +538,21 @@@ static int check_packed_git_idx(const c
        return 0;
  }
  
 +int open_pack_index(struct packed_git *p)
 +{
 +      char *idx_name;
 +      int ret;
 +
 +      if (p->index_data)
 +              return 0;
 +
 +      idx_name = xstrdup(p->pack_name);
 +      strcpy(idx_name + strlen(idx_name) - strlen(".pack"), ".idx");
 +      ret = check_packed_git_idx(idx_name, p);
 +      free(idx_name);
 +      return ret;
 +}
 +
  static void scan_windows(struct packed_git *p,
        struct packed_git **lru_p,
        struct pack_window **lru_w,
@@@ -624,9 -612,6 +628,9 @@@ static int open_packed_git_1(struct pac
        unsigned char *idx_sha1;
        long fd_flag;
  
 +      if (!p->index_data && open_pack_index(p))
 +              return error("packfile %s index unavailable", p->pack_name);
 +
        p->pack_fd = open(p->pack_name, O_RDONLY);
        if (p->pack_fd < 0 || fstat(p->pack_fd, &st))
                return -1;
@@@ -779,7 -764,8 +783,7 @@@ struct packed_git *add_packed_git(cons
                return NULL;
        memcpy(p->pack_name, path, path_len);
        strcpy(p->pack_name + path_len, ".pack");
 -      if (stat(p->pack_name, &st) || !S_ISREG(st.st_mode) ||
 -          check_packed_git_idx(path, p)) {
 +      if (stat(p->pack_name, &st) || !S_ISREG(st.st_mode)) {
                free(p);
                return NULL;
        }
        /* ok, it looks sane as far as we can check without
         * actually mapping the pack file.
         */
 +      p->index_version = 0;
 +      p->index_data = NULL;
 +      p->index_size = 0;
 +      p->num_objects = 0;
        p->pack_size = st.st_size;
        p->next = NULL;
        p->windows = NULL;
@@@ -836,7 -818,10 +840,10 @@@ void install_packed_git(struct packed_g
  
  static void prepare_packed_git_one(char *objdir, int local)
  {
-       char path[PATH_MAX];
+       /* Ensure that this buffer is large enough so that we can
+          append "/pack/" without clobbering the stack even if
+          strlen(objdir) were PATH_MAX.  */
+       char path[PATH_MAX + 1 + 4 + 1 + 1];
        int len;
        DIR *dir;
        struct dirent *de;
                if (!has_extension(de->d_name, ".idx"))
                        continue;
  
+               if (len + namelen + 1 > sizeof(path))
+                       continue;
                /* Don't reopen a pack we already have. */
                strcpy(path + len, de->d_name);
                for (p = packed_git; p; p = p->next) {
@@@ -962,7 -950,7 +972,7 @@@ int check_sha1_signature(const unsigne
        return hashcmp(sha1, real_sha1) ? -1 : 0;
  }
  
 -void *map_sha1_file(const unsigned char *sha1, unsigned long *size)
 +static void *map_sha1_file(const unsigned char *sha1, unsigned long *size)
  {
        struct stat st;
        void *map;
        return map;
  }
  
 -int legacy_loose_object(unsigned char *map)
 +static int legacy_loose_object(unsigned char *map)
  {
        unsigned int word;
  
@@@ -1059,14 -1047,6 +1069,14 @@@ static int unpack_sha1_header(z_stream 
                return inflate(stream, 0);
        }
  
 +
 +      /*
 +       * There used to be a second loose object header format which
 +       * was meant to mimic the in-pack format, allowing for direct
 +       * copy of the object data.  This format turned up not to be
 +       * really worth it and we don't write it any longer.  But we
 +       * can still read it.
 +       */
        used = unpack_object_header_gently(map, mapsize, &type, &size);
        if (!used || !valid_loose_object_type[type])
                return -1;
@@@ -1142,7 -1122,7 +1152,7 @@@ static int parse_sha1_header(const cha
        unsigned long size;
  
        /*
 -       * The type can be at most ten bytes (including the 
 +       * The type can be at most ten bytes (including the
         * terminating '\0' that we add), and is followed by
         * a space.
         */
@@@ -1597,15 -1577,10 +1607,15 @@@ void *unpack_entry(struct packed_git *p
        return data;
  }
  
 -const unsigned char *nth_packed_object_sha1(const struct packed_git *p,
 +const unsigned char *nth_packed_object_sha1(struct packed_git *p,
                                            uint32_t n)
  {
        const unsigned char *index = p->index_data;
 +      if (!index) {
 +              if (open_pack_index(p))
 +                      return NULL;
 +              index = p->index_data;
 +      }
        if (n >= p->num_objects)
                return NULL;
        index += 4 * 256;
@@@ -1642,12 -1617,6 +1652,12 @@@ off_t find_pack_entry_one(const unsigne
        const unsigned char *index = p->index_data;
        unsigned hi, lo;
  
 +      if (!index) {
 +              if (open_pack_index(p))
 +                      return 0;
 +              level1_ofs = p->index_data;
 +              index = p->index_data;
 +      }
        if (p->index_version > 1) {
                level1_ofs += 2;
                index += 8;
@@@ -1690,25 -1659,20 +1700,25 @@@ static int matches_pack_name(struct pac
  
  static int find_pack_entry(const unsigned char *sha1, struct pack_entry *e, const char **ignore_packed)
  {
 +      static struct packed_git *last_found = (void *)1;
        struct packed_git *p;
        off_t offset;
  
        prepare_packed_git();
 +      if (!packed_git)
 +              return 0;
 +      p = (last_found == (void *)1) ? packed_git : last_found;
  
 -      for (p = packed_git; p; p = p->next) {
 +      do {
                if (ignore_packed) {
                        const char **ig;
                        for (ig = ignore_packed; *ig; ig++)
                                if (!matches_pack_name(p, *ig))
                                        break;
                        if (*ig)
 -                              continue;
 +                              goto next;
                }
 +
                offset = find_pack_entry_one(sha1, p);
                if (offset) {
                        /*
                         */
                        if (p->pack_fd == -1 && open_packed_git(p)) {
                                error("packfile %s cannot be accessed", p->pack_name);
 -                              continue;
 +                              goto next;
                        }
                        e->offset = offset;
                        e->p = p;
                        hashcpy(e->sha1, sha1);
 +                      last_found = p;
                        return 1;
                }
 -      }
 +
 +              next:
 +              if (p == last_found)
 +                      p = packed_git;
 +              else
 +                      p = p->next;
 +              if (p == last_found)
 +                      p = p->next;
 +      } while (p);
        return 0;
  }
  
 -struct packed_git *find_sha1_pack(const unsigned char *sha1, 
 +struct packed_git *find_sha1_pack(const unsigned char *sha1,
                                  struct packed_git *packs)
  {
        struct packed_git *p;
@@@ -2020,6 -1975,40 +2030,6 @@@ static int write_buffer(int fd, const v
        return 0;
  }
  
 -static int write_binary_header(unsigned char *hdr, enum object_type type, unsigned long len)
 -{
 -      int hdr_len;
 -      unsigned char c;
 -
 -      c = (type << 4) | (len & 15);
 -      len >>= 4;
 -      hdr_len = 1;
 -      while (len) {
 -              *hdr++ = c | 0x80;
 -              hdr_len++;
 -              c = (len & 0x7f);
 -              len >>= 7;
 -      }
 -      *hdr = c;
 -      return hdr_len;
 -}
 -
 -static void setup_object_header(z_stream *stream, const char *type, unsigned long len)
 -{
 -      int obj_type, hdrlen;
 -
 -      if (use_legacy_headers) {
 -              while (deflate(stream, 0) == Z_OK)
 -                      /* nothing */;
 -              return;
 -      }
 -      obj_type = type_from_string(type);
 -      hdrlen = write_binary_header(stream->next_out, obj_type, len);
 -      stream->total_out = hdrlen;
 -      stream->next_out += hdrlen;
 -      stream->avail_out -= hdrlen;
 -}
 -
  int hash_sha1_file(const void *buf, unsigned long len, const char *type,
                     unsigned char *sha1)
  {
@@@ -2086,8 -2075,7 +2096,8 @@@ int write_sha1_file(void *buf, unsigne
        /* First header.. */
        stream.next_in = (unsigned char *)hdr;
        stream.avail_in = hdrlen;
 -      setup_object_header(&stream, type, len);
 +      while (deflate(&stream, 0) == Z_OK)
 +              /* nothing */;
  
        /* Then the data itself.. */
        stream.next_in = buf;
diff --combined t/t4013-diff-various.sh
index b453b42af7b0836d8c523352fe3b1f34e30f363e,4e7d68dda28a54cdc4f46e11717e113fa8dd479c..9eec754221d85856613b01ec878ef4cb492aceb0
@@@ -17,6 -17,7 +17,7 @@@ test_expect_success setup 
        export GIT_AUTHOR_DATE GIT_COMMITTER_DATE &&
  
        mkdir dir &&
+       mkdir dir2 &&
        for i in 1 2 3; do echo $i; done >file0 &&
        for i in A B; do echo $i; done >dir/sub &&
        cat file0 >file2 &&
@@@ -242,8 -243,6 +243,8 @@@ format-patch --inline --stdout initial.
  format-patch --inline --stdout initial..master^
  format-patch --inline --stdout initial..master
  format-patch --inline --stdout --subject-prefix=TESTCASE initial..master
 +config format.subjectprefix DIFFERENT_PREFIX
 +format-patch --inline --stdout initial..master^^
  
  diff --abbrev initial..side
  diff -r initial..side
@@@ -254,6 -253,7 +255,7 @@@ diff --patch-with-stat initial..sid
  diff --patch-with-raw initial..side
  diff --patch-with-stat -r initial..side
  diff --patch-with-raw -r initial..side
+ diff --name-status dir2 dir
  EOF
  
  test_done