]> git.ipfire.org Git - thirdparty/git.git/blobdiff - unpack-trees.c
Sync with maint
[thirdparty/git.git] / unpack-trees.c
index a75b068d3353a4a665968df4c5b50d0add14a077..2399b6818be6ddb9a6f4103cec667b2e2a9c24d0 100644 (file)
@@ -1269,7 +1269,8 @@ static int clear_ce_flags_1(struct index_state *istate,
                            struct strbuf *prefix,
                            int select_mask, int clear_mask,
                            struct pattern_list *pl,
-                           enum pattern_match_result default_match);
+                           enum pattern_match_result default_match,
+                           int progress_nr);
 
 /* Whole directory matching */
 static int clear_ce_flags_dir(struct index_state *istate,
@@ -1278,20 +1279,23 @@ static int clear_ce_flags_dir(struct index_state *istate,
                              char *basename,
                              int select_mask, int clear_mask,
                              struct pattern_list *pl,
-                             enum pattern_match_result default_match)
+                             enum pattern_match_result default_match,
+                             int progress_nr)
 {
        struct cache_entry **cache_end;
        int dtype = DT_DIR;
        int rc;
-       enum pattern_match_result ret;
-       ret = path_matches_pattern_list(prefix->buf, prefix->len,
-                                       basename, &dtype, pl, istate);
+       enum pattern_match_result ret, orig_ret;
+       orig_ret = path_matches_pattern_list(prefix->buf, prefix->len,
+                                            basename, &dtype, pl, istate);
 
        strbuf_addch(prefix, '/');
 
        /* If undecided, use matching result of parent dir in defval */
-       if (ret == UNDECIDED)
+       if (orig_ret == UNDECIDED)
                ret = default_match;
+       else
+               ret = orig_ret;
 
        for (cache_end = cache; cache_end != cache + nr; cache_end++) {
                struct cache_entry *ce = *cache_end;
@@ -1299,17 +1303,24 @@ static int clear_ce_flags_dir(struct index_state *istate,
                        break;
        }
 
-       /*
-        * TODO: check pl, 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 path_matches_pattern_list() on every entry.
-        */
-       rc = clear_ce_flags_1(istate, cache, cache_end - cache,
-                             prefix,
-                             select_mask, clear_mask,
-                             pl, ret);
+       if (pl->use_cone_patterns && orig_ret == MATCHED_RECURSIVE) {
+               struct cache_entry **ce = cache;
+               rc = (cache_end - cache) / sizeof(struct cache_entry *);
+
+               while (ce < cache_end) {
+                       (*ce)->ce_flags &= ~clear_mask;
+                       ce++;
+               }
+       } else if (pl->use_cone_patterns && orig_ret == NOT_MATCHED) {
+               rc = (cache_end - cache) / sizeof(struct cache_entry *);
+       } else {
+               rc = clear_ce_flags_1(istate, cache, cache_end - cache,
+                                     prefix,
+                                     select_mask, clear_mask,
+                                     pl, ret,
+                                     progress_nr);
+       }
+
        strbuf_setlen(prefix, prefix->len - 1);
        return rc;
 }
@@ -1334,7 +1345,8 @@ static int clear_ce_flags_1(struct index_state *istate,
                            struct strbuf *prefix,
                            int select_mask, int clear_mask,
                            struct pattern_list *pl,
-                           enum pattern_match_result default_match)
+                           enum pattern_match_result default_match,
+                           int progress_nr)
 {
        struct cache_entry **cache_end = cache + nr;
 
@@ -1348,8 +1360,11 @@ static int clear_ce_flags_1(struct index_state *istate,
                int len, dtype;
                enum pattern_match_result ret;
 
+               display_progress(istate->progress, progress_nr);
+
                if (select_mask && !(ce->ce_flags & select_mask)) {
                        cache++;
+                       progress_nr++;
                        continue;
                }
 
@@ -1370,20 +1385,26 @@ static int clear_ce_flags_1(struct index_state *istate,
                                                       prefix,
                                                       prefix->buf + prefix->len - len,
                                                       select_mask, clear_mask,
-                                                      pl, default_match);
+                                                      pl, default_match,
+                                                      progress_nr);
 
                        /* clear_c_f_dir eats a whole dir already? */
                        if (processed) {
                                cache += processed;
+                               progress_nr += processed;
                                strbuf_setlen(prefix, prefix->len - len);
                                continue;
                        }
 
                        strbuf_addch(prefix, '/');
-                       cache += clear_ce_flags_1(istate, cache, cache_end - cache,
-                                                 prefix,
-                                                 select_mask, clear_mask, pl,
-                                                 default_match);
+                       processed = clear_ce_flags_1(istate, cache, cache_end - cache,
+                                                    prefix,
+                                                    select_mask, clear_mask, pl,
+                                                    default_match, progress_nr);
+
+                       cache += processed;
+                       progress_nr += processed;
+
                        strbuf_setlen(prefix, prefix->len - len - 1);
                        continue;
                }
@@ -1398,24 +1419,41 @@ static int clear_ce_flags_1(struct index_state *istate,
                if (ret == MATCHED)
                        ce->ce_flags &= ~clear_mask;
                cache++;
+               progress_nr++;
        }
+
+       display_progress(istate->progress, progress_nr);
        return nr - (cache_end - cache);
 }
 
 static int clear_ce_flags(struct index_state *istate,
                          int select_mask, int clear_mask,
-                         struct pattern_list *pl)
+                         struct pattern_list *pl,
+                         int show_progress)
 {
        static struct strbuf prefix = STRBUF_INIT;
+       char label[100];
+       int rval;
 
        strbuf_reset(&prefix);
-
-       return clear_ce_flags_1(istate,
+       if (show_progress)
+               istate->progress = start_delayed_progress(
+                                       _("Updating index flags"),
+                                       istate->cache_nr);
+
+       xsnprintf(label, sizeof(label), "clear_ce_flags(0x%08lx,0x%08lx)",
+                 (unsigned long)select_mask, (unsigned long)clear_mask);
+       trace2_region_enter("unpack_trees", label, the_repository);
+       rval = clear_ce_flags_1(istate,
                                istate->cache,
                                istate->cache_nr,
                                &prefix,
                                select_mask, clear_mask,
-                               pl, 0);
+                               pl, 0, 0);
+       trace2_region_leave("unpack_trees", label, the_repository);
+
+       stop_progress(&istate->progress);
+       return rval;
 }
 
 /*
@@ -1423,7 +1461,8 @@ static int clear_ce_flags(struct index_state *istate,
  */
 static void mark_new_skip_worktree(struct pattern_list *pl,
                                   struct index_state *istate,
-                                  int select_flag, int skip_wt_flag)
+                                  int select_flag, int skip_wt_flag,
+                                  int show_progress)
 {
        int i;
 
@@ -1447,7 +1486,7 @@ static void mark_new_skip_worktree(struct pattern_list *pl,
         * 2. Widen worktree according to sparse-checkout file.
         * Matched entries will have skip_wt_flag cleared (i.e. "in")
         */
-       clear_ce_flags(istate, select_flag, skip_wt_flag, pl);
+       clear_ce_flags(istate, select_flag, skip_wt_flag, pl, show_progress);
 }
 
 static int verify_absent(const struct cache_entry *,
@@ -1472,8 +1511,9 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
        memset(&pl, 0, sizeof(pl));
        if (!core_apply_sparse_checkout || !o->update)
                o->skip_sparse_checkout = 1;
-       if (!o->skip_sparse_checkout) {
+       if (!o->skip_sparse_checkout && !o->pl) {
                char *sparse = git_pathdup("info/sparse-checkout");
+               pl.use_cone_patterns = core_sparse_checkout_cone;
                if (add_patterns_from_file_to_list(sparse, "", 0, &pl, NULL) < 0)
                        o->skip_sparse_checkout = 1;
                else
@@ -1511,7 +1551,8 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
         * Sparse checkout loop #1: set NEW_SKIP_WORKTREE on existing entries
         */
        if (!o->skip_sparse_checkout)
-               mark_new_skip_worktree(o->pl, o->src_index, 0, CE_NEW_SKIP_WORKTREE);
+               mark_new_skip_worktree(o->pl, o->src_index, 0,
+                                      CE_NEW_SKIP_WORKTREE, o->verbose_update);
 
        if (!dfc)
                dfc = xcalloc(1, cache_entry_size(0));
@@ -1576,7 +1617,9 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
                 * If the will have NEW_SKIP_WORKTREE, also set CE_SKIP_WORKTREE
                 * so apply_sparse_checkout() won't attempt to remove it from worktree
                 */
-               mark_new_skip_worktree(o->pl, &o->result, CE_ADDED, CE_SKIP_WORKTREE | CE_NEW_SKIP_WORKTREE);
+               mark_new_skip_worktree(o->pl, &o->result,
+                                      CE_ADDED, CE_SKIP_WORKTREE | CE_NEW_SKIP_WORKTREE,
+                                      o->verbose_update);
 
                ret = 0;
                for (i = 0; i < o->result.cache_nr; i++) {
@@ -1644,7 +1687,8 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 
 done:
        trace_performance_leave("unpack_trees");
-       clear_pattern_list(&pl);
+       if (!o->keep_pattern_list)
+               clear_pattern_list(&pl);
        return ret;
 
 return_failed: