Merge branch 'jc/diff-index-quick-exit-early'
authorJunio C Hamano <gitster@pobox.com>
Thu, 30 Jun 2011 00:03:11 +0000 (17:03 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 30 Jun 2011 00:03:11 +0000 (17:03 -0700)
* jc/diff-index-quick-exit-early:
diff-index --quiet: learn the "stop feeding the backend early" logic

Conflicts:
unpack-trees.h

1  2 
unpack-trees.c
unpack-trees.h
diff --combined unpack-trees.c
index 07f83642443601d107e0a2425407b3250c022dcd,b2b6a901b20c513e4fd9333412802a758006dd88..3a61d821ee85a9cfb026909c6ae90def360a7681
@@@ -203,7 -203,7 +203,7 @@@ static int check_updates(struct unpack_
  
                if (ce->ce_flags & CE_WT_REMOVE) {
                        display_progress(progress, ++cnt);
 -                      if (o->update)
 +                      if (o->update && !o->dry_run)
                                unlink_entry(ce);
                        continue;
                }
                if (ce->ce_flags & CE_UPDATE) {
                        display_progress(progress, ++cnt);
                        ce->ce_flags &= ~CE_UPDATE;
 -                      if (o->update) {
 +                      if (o->update && !o->dry_run) {
                                errs |= checkout_entry(ce, &state, NULL);
                        }
                }
@@@ -593,7 -593,7 +593,7 @@@ static int unpack_nondirectories(int n
  static int unpack_failed(struct unpack_trees_options *o, const char *message)
  {
        discard_index(&o->result);
-       if (!o->gently) {
+       if (!o->gently && !o->exiting_early) {
                if (message)
                        return error("%s", message);
                return -1;
@@@ -814,45 -814,43 +814,45 @@@ static int unpack_callback(int n, unsig
        return mask;
  }
  
 +static int clear_ce_flags_1(struct cache_entry **cache, int nr,
 +                          char *prefix, int prefix_len,
 +                          int select_mask, int clear_mask,
 +                          struct exclude_list *el, int defval);
 +
  /* Whole directory matching */
  static int clear_ce_flags_dir(struct cache_entry **cache, int nr,
                              char *prefix, int prefix_len,
                              char *basename,
                              int select_mask, int clear_mask,
 -                            struct exclude_list *el)
 +                            struct exclude_list *el, int defval)
  {
 -      struct cache_entry **cache_end = cache + nr;
 +      struct cache_entry **cache_end;
        int dtype = DT_DIR;
        int ret = excluded_from_list(prefix, prefix_len, basename, &dtype, el);
  
        prefix[prefix_len++] = '/';
  
 -      /* included, no clearing for any entries under this directory */
 -      if (!ret) {
 -              for (; cache != cache_end; cache++) {
 -                      struct cache_entry *ce = *cache;
 -                      if (strncmp(ce->name, prefix, prefix_len))
 -                              break;
 -              }
 -              return nr - (cache_end - cache);
 -      }
 +      /* If undecided, use matching result of parent dir in defval */
 +      if (ret < 0)
 +              ret = defval;
  
 -      /* excluded, clear all selected entries under this directory. */
 -      if (ret == 1) {
 -              for (; cache != cache_end; cache++) {
 -                      struct cache_entry *ce = *cache;
 -                      if (select_mask && !(ce->ce_flags & select_mask))
 -                              continue;
 -                      if (strncmp(ce->name, prefix, prefix_len))
 -                              break;
 -                      ce->ce_flags &= ~clear_mask;
 -              }
 -              return nr - (cache_end - cache);
 +      for (cache_end = cache; cache_end != cache + nr; cache_end++) {
 +              struct cache_entry *ce = *cache_end;
 +              if (strncmp(ce->name, prefix, prefix_len))
 +                      break;
        }
  
 -      return 0;
 +      /*
 +       * TODO: check el, if there are no patterns that may conflict
 +       * with ret (iow, we know in advance the incl/excl
 +       * decision for the entire directory), clear flag here without
 +       * calling clear_ce_flags_1(). That function will call
 +       * the expensive excluded_from_list() on every entry.
 +       */
 +      return clear_ce_flags_1(cache, cache_end - cache,
 +                              prefix, prefix_len,
 +                              select_mask, clear_mask,
 +                              el, ret);
  }
  
  /*
  static int clear_ce_flags_1(struct cache_entry **cache, int nr,
                            char *prefix, int prefix_len,
                            int select_mask, int clear_mask,
 -                          struct exclude_list *el)
 +                          struct exclude_list *el, int defval)
  {
        struct cache_entry **cache_end = cache + nr;
  
        while(cache != cache_end) {
                struct cache_entry *ce = *cache;
                const char *name, *slash;
 -              int len, dtype;
 +              int len, dtype, ret;
  
                if (select_mask && !(ce->ce_flags & select_mask)) {
                        cache++;
                                                       prefix, prefix_len + len,
                                                       prefix + prefix_len,
                                                       select_mask, clear_mask,
 -                                                     el);
 +                                                     el, defval);
  
                        /* clear_c_f_dir eats a whole dir already? */
                        if (processed) {
                        prefix[prefix_len + len++] = '/';
                        cache += clear_ce_flags_1(cache, cache_end - cache,
                                                  prefix, prefix_len + len,
 -                                                select_mask, clear_mask, el);
 +                                                select_mask, clear_mask, el, defval);
                        continue;
                }
  
                /* Non-directory */
                dtype = ce_to_dtype(ce);
 -              if (excluded_from_list(ce->name, ce_namelen(ce), name, &dtype, el) > 0)
 +              ret = excluded_from_list(ce->name, ce_namelen(ce), name, &dtype, el);
 +              if (ret < 0)
 +                      ret = defval;
 +              if (ret > 0)
                        ce->ce_flags &= ~clear_mask;
                cache++;
        }
@@@ -948,7 -943,7 +948,7 @@@ static int clear_ce_flags(struct cache_
        return clear_ce_flags_1(cache, nr,
                                prefix, 0,
                                select_mask, clear_mask,
 -                              el);
 +                              el, 0);
  }
  
  /*
@@@ -1133,6 -1128,8 +1133,8 @@@ return_failed
                display_error_msgs(o);
        mark_all_ce_unused(o->src_index);
        ret = unpack_failed(o, NULL);
+       if (o->exiting_early)
+               ret = 0;
        goto done;
  }
  
diff --combined unpack-trees.h
index 64f02cb03ab242ac08ea0f1afbb24e71cf6664aa,4c6c54033e2d319a305e9a82d06e48e570f4f871..79989483079970e9dad42512e522eef8ea2a75a4
@@@ -46,8 -46,8 +46,9 @@@ struct unpack_trees_options 
                     debug_unpack,
                     skip_sparse_checkout,
                     gently,
 -                   show_all_errors;
+                    exiting_early,
 +                   show_all_errors,
 +                   dry_run;
        const char *prefix;
        int cache_bottom;
        struct dir_struct *dir;