Merge branch 'maint'
authorJunio C Hamano <gitster@pobox.com>
Tue, 17 Jun 2008 00:39:50 +0000 (17:39 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 17 Jun 2008 00:39:50 +0000 (17:39 -0700)
* maint:
diff.c: fix emit_line() again not to add extra line

1  2 
diff.c
diff --combined diff.c
index f23657bd347a62729d2211e8c64536279a5ea910,20135cbe7c8209835dca8d52d1d48e7aa871c1b3..526249008662d4041e5623914c1a420f3443c4d4
--- 1/diff.c
--- 2/diff.c
+++ b/diff.c
@@@ -19,7 -19,7 +19,7 @@@
  #endif
  
  static int diff_detect_rename_default;
 -static int diff_rename_limit_default = 100;
 +static int diff_rename_limit_default = 200;
  int diff_use_color_default = -1;
  static const char *external_diff_cmd_cfg;
  int diff_auto_refresh_index = 1;
@@@ -129,7 -129,7 +129,7 @@@ static int parse_funcname_pattern(cons
   * never be affected by the setting of diff.renames
   * the user happens to have in the configuration file.
   */
 -int git_diff_ui_config(const char *var, const char *value)
 +int git_diff_ui_config(const char *var, const char *value, void *cb)
  {
        if (!strcmp(var, "diff.renamelimit")) {
                diff_rename_limit_default = git_config_int(var, value);
                        return parse_lldiff_command(var, ep, value);
        }
  
 -      return git_diff_basic_config(var, value);
 +      return git_diff_basic_config(var, value, cb);
  }
  
 -int git_diff_basic_config(const char *var, const char *value)
 +int git_diff_basic_config(const char *var, const char *value, void *cb)
  {
        if (!prefixcmp(var, "diff.color.") || !prefixcmp(var, "color.diff.")) {
                int slot = parse_diff_color_slot(var, 11);
                }
        }
  
 -      return git_color_default_config(var, value);
 +      return git_color_default_config(var, value, cb);
  }
  
  static char *quote_two(const char *one, const char *two)
@@@ -514,13 -514,15 +514,15 @@@ const char *diff_get_color(int diff_use
  
  static void emit_line(FILE *file, const char *set, const char *reset, const char *line, int len)
  {
-       if (len > 0 && line[len-1] == '\n')
+       int has_trailing_newline = (len > 0 && line[len-1] == '\n');
+       if (has_trailing_newline)
                len--;
  
        fputs(set, file);
        fwrite(line, len, 1, file);
        fputs(reset, file);
-       fputc('\n', file);
+       if (has_trailing_newline)
+               fputc('\n', file);
  }
  
  static void emit_add_line(const char *reset, struct emit_callback *ecbdata, const char *line, int len)
@@@ -995,23 -997,18 +997,23 @@@ static void show_numstat(struct diffsta
        }
  }
  
 -struct diffstat_dir {
 -      struct diffstat_file **files;
 -      int nr, percent, cumulative;
 +struct dirstat_file {
 +      const char *name;
 +      unsigned long changed;
 +};
 +
 +struct dirstat_dir {
 +      struct dirstat_file *files;
 +      int alloc, nr, percent, cumulative;
  };
  
 -static long gather_dirstat(FILE *file, struct diffstat_dir *dir, unsigned long changed, const char *base, int baselen)
 +static long gather_dirstat(FILE *file, struct dirstat_dir *dir, unsigned long changed, const char *base, int baselen)
  {
        unsigned long this_dir = 0;
        unsigned int sources = 0;
  
        while (dir->nr) {
 -              struct diffstat_file *f = *dir->files;
 +              struct dirstat_file *f = dir->files;
                int namelen = strlen(f->name);
                unsigned long this;
                char *slash;
                        this = gather_dirstat(file, dir, changed, f->name, newbaselen);
                        sources++;
                } else {
 -                      if (f->is_unmerged || f->is_binary)
 -                              this = 0;
 -                      else
 -                              this = f->added + f->deleted;
 +                      this = f->changed;
                        dir->files++;
                        dir->nr--;
                        sources += 2;
        return this_dir;
  }
  
 -static void show_dirstat(struct diffstat_t *data, struct diff_options *options)
 +static void show_dirstat(struct diff_options *options)
  {
        int i;
        unsigned long changed;
 -      struct diffstat_dir dir;
 +      struct dirstat_dir dir;
 +      struct diff_queue_struct *q = &diff_queued_diff;
 +
 +      dir.files = NULL;
 +      dir.alloc = 0;
 +      dir.nr = 0;
 +      dir.percent = options->dirstat_percent;
 +      dir.cumulative = options->output_format & DIFF_FORMAT_CUMULATIVE;
  
 -      /* Calculate total changes */
        changed = 0;
 -      for (i = 0; i < data->nr; i++) {
 -              if (data->files[i]->is_binary || data->files[i]->is_unmerged)
 +      for (i = 0; i < q->nr; i++) {
 +              struct diff_filepair *p = q->queue[i];
 +              const char *name;
 +              unsigned long copied, added, damage;
 +
 +              name = p->one->path ? p->one->path : p->two->path;
 +
 +              if (DIFF_FILE_VALID(p->one) && DIFF_FILE_VALID(p->two)) {
 +                      diff_populate_filespec(p->one, 0);
 +                      diff_populate_filespec(p->two, 0);
 +                      diffcore_count_changes(p->one, p->two, NULL, NULL, 0,
 +                                             &copied, &added);
 +                      diff_free_filespec_data(p->one);
 +                      diff_free_filespec_data(p->two);
 +              } else if (DIFF_FILE_VALID(p->one)) {
 +                      diff_populate_filespec(p->one, 1);
 +                      copied = added = 0;
 +                      diff_free_filespec_data(p->one);
 +              } else if (DIFF_FILE_VALID(p->two)) {
 +                      diff_populate_filespec(p->two, 1);
 +                      copied = 0;
 +                      added = p->two->size;
 +                      diff_free_filespec_data(p->two);
 +              } else
                        continue;
 -              changed += data->files[i]->added;
 -              changed += data->files[i]->deleted;
 +
 +              /*
 +               * Original minus copied is the removed material,
 +               * added is the new material.  They are both damages
 +               * made to the preimage.
 +               */
 +              damage = (p->one->size - copied) + added;
 +
 +              ALLOC_GROW(dir.files, dir.nr + 1, dir.alloc);
 +              dir.files[dir.nr].name = name;
 +              dir.files[dir.nr].changed = damage;
 +              changed += damage;
 +              dir.nr++;
        }
  
        /* This can happen even with many files, if everything was renames */
                return;
  
        /* Show all directories with more than x% of the changes */
 -      dir.files = data->files;
 -      dir.nr = data->nr;
 -      dir.percent = options->dirstat_percent;
 -      dir.cumulative = options->output_format & DIFF_FORMAT_CUMULATIVE;
        gather_dirstat(options->file, &dir, changed, "", 0);
  }
  
@@@ -2224,6 -2189,7 +2226,6 @@@ void diff_setup(struct diff_options *op
        options->rename_limit = -1;
        options->dirstat_percent = 3;
        options->context = 3;
 -      options->msg_sep = "";
  
        options->change = diff_change;
        options->add_remove = diff_addremove;
@@@ -2500,8 -2466,6 +2502,8 @@@ int diff_opt_parse(struct diff_options 
                DIFF_OPT_SET(options, ALLOW_EXTERNAL);
        else if (!strcmp(arg, "--no-ext-diff"))
                DIFF_OPT_CLR(options, ALLOW_EXTERNAL);
 +      else if (!strcmp(arg, "--ignore-submodules"))
 +              DIFF_OPT_SET(options, IGNORE_SUBMODULES);
  
        /* misc options */
        else if (!strcmp(arg, "-z"))
@@@ -3137,7 -3101,7 +3139,7 @@@ void diff_flush(struct diff_options *op
                separator++;
        }
  
 -      if (output_format & (DIFF_FORMAT_DIFFSTAT|DIFF_FORMAT_SHORTSTAT|DIFF_FORMAT_NUMSTAT|DIFF_FORMAT_DIRSTAT)) {
 +      if (output_format & (DIFF_FORMAT_DIFFSTAT|DIFF_FORMAT_SHORTSTAT|DIFF_FORMAT_NUMSTAT)) {
                struct diffstat_t diffstat;
  
                memset(&diffstat, 0, sizeof(struct diffstat_t));
                        if (check_pair_status(p))
                                diff_flush_stat(p, options, &diffstat);
                }
 -              if (output_format & DIFF_FORMAT_DIRSTAT)
 -                      show_dirstat(&diffstat, options);
                if (output_format & DIFF_FORMAT_NUMSTAT)
                        show_numstat(&diffstat, options);
                if (output_format & DIFF_FORMAT_DIFFSTAT)
                free_diffstat_info(&diffstat);
                separator++;
        }
 +      if (output_format & DIFF_FORMAT_DIRSTAT)
 +              show_dirstat(options);
  
        if (output_format & DIFF_FORMAT_SUMMARY && !is_summary_empty(q)) {
                for (i = 0; i < q->nr; i++)
@@@ -3361,9 -3325,6 +3363,9 @@@ void diff_addremove(struct diff_option
        char concatpath[PATH_MAX];
        struct diff_filespec *one, *two;
  
 +      if (DIFF_OPT_TST(options, IGNORE_SUBMODULES) && S_ISGITLINK(mode))
 +              return;
 +
        /* This may look odd, but it is a preparation for
         * feeding "there are unchanged files which should
         * not produce diffs, but when you are doing copy
@@@ -3408,10 -3369,6 +3410,10 @@@ void diff_change(struct diff_options *o
        char concatpath[PATH_MAX];
        struct diff_filespec *one, *two;
  
 +      if (DIFF_OPT_TST(options, IGNORE_SUBMODULES) && S_ISGITLINK(old_mode)
 +                      && S_ISGITLINK(new_mode))
 +              return;
 +
        if (DIFF_OPT_TST(options, REVERSE_DIFF)) {
                unsigned tmp;
                const unsigned char *tmp_c;