send-email: extract_valid_address use qr// regexes
[gitweb.git] / unpack-trees.c
index 7267ae7c632b075d263c06d837af7b0b3629456b..803445aa7be140c3707bcebc72aaf6fc6af45e4b 100644 (file)
@@ -50,8 +50,10 @@ const char *unpack_plumbing_errors[NB_UNPACK_TREES_ERROR_TYPES] = {
          ? ((o)->msgs[(type)])      \
          : (unpack_plumbing_errors[(type)]) )
 
-void setup_unpack_trees_porcelain(const char **msgs, const char *cmd)
+void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
+                                 const char *cmd)
 {
+       const char **msgs = opts->msgs;
        const char *msg;
        char *tmp;
        const char *cmd2 = strcmp(cmd, "checkout") ? cmd : "switch branches";
@@ -92,6 +94,8 @@ void setup_unpack_trees_porcelain(const char **msgs, const char *cmd)
                "The following Working tree files would be overwritten by sparse checkout update:\n%s";
        msgs[ERROR_WOULD_LOSE_ORPHANED_REMOVED] =
                "The following Working tree files would be removed by sparse checkout update:\n%s";
+
+       opts->show_all_errors = 1;
 }
 
 static void add_entry(struct unpack_trees_options *o, struct cache_entry *ce,
@@ -102,6 +106,9 @@ static void add_entry(struct unpack_trees_options *o, struct cache_entry *ce,
 
        clear |= CE_HASHED | CE_UNHASHED;
 
+       if (set & CE_REMOVE)
+               set |= CE_WT_REMOVE;
+
        memcpy(new, ce, size);
        new->next = NULL;
        new->ce_flags = (new->ce_flags & ~clear) | set;
@@ -118,12 +125,6 @@ static int add_rejected_path(struct unpack_trees_options *o,
                             const char *path)
 {
        struct rejected_paths_list *newentry;
-       int porcelain = o && (o)->msgs[e];
-       /*
-        * simply display the given error message if in plumbing mode
-        */
-       if (!porcelain)
-               o->show_all_errors = 0;
        if (!o->show_all_errors)
                return error(ERRORMSG(o, e), path);
 
@@ -200,7 +201,7 @@ static int check_updates(struct unpack_trees_options *o)
        if (o->update && o->verbose_update) {
                for (total = cnt = 0; cnt < index->cache_nr; cnt++) {
                        struct cache_entry *ce = index->cache[cnt];
-                       if (ce->ce_flags & (CE_UPDATE | CE_REMOVE | CE_WT_REMOVE))
+                       if (ce->ce_flags & (CE_UPDATE | CE_WT_REMOVE))
                                total++;
                }
 
@@ -220,12 +221,6 @@ static int check_updates(struct unpack_trees_options *o)
                                unlink_entry(ce);
                        continue;
                }
-
-               if (ce->ce_flags & CE_REMOVE) {
-                       display_progress(progress, ++cnt);
-                       if (o->update)
-                               unlink_entry(ce);
-               }
        }
        remove_marked_cache_entries(&o->result);
        remove_scheduled_dirs();
@@ -254,9 +249,6 @@ static int will_have_skip_worktree(const struct cache_entry *ce, struct unpack_t
 {
        const char *basename;
 
-       if (ce_stage(ce))
-               return 0;
-
        basename = strrchr(ce->name, '/');
        basename = basename ? basename+1 : ce->name;
        return excluded_from_list(ce->name, ce_namelen(ce), basename, NULL, o->el) <= 0;
@@ -266,19 +258,36 @@ static int apply_sparse_checkout(struct cache_entry *ce, struct unpack_trees_opt
 {
        int was_skip_worktree = ce_skip_worktree(ce);
 
-       if (will_have_skip_worktree(ce, o))
+       if (!ce_stage(ce) && will_have_skip_worktree(ce, o))
                ce->ce_flags |= CE_SKIP_WORKTREE;
        else
                ce->ce_flags &= ~CE_SKIP_WORKTREE;
 
        /*
-        * We only care about files getting into the checkout area
-        * If merge strategies want to remove some, go ahead, this
-        * flag will be removed eventually in unpack_trees() if it's
-        * outside checkout area.
+        * if (!was_skip_worktree && !ce_skip_worktree()) {
+        *      This is perfectly normal. Move on;
+        * }
         */
-       if (ce->ce_flags & CE_REMOVE)
-               return 0;
+
+       /*
+        * Merge strategies may set CE_UPDATE|CE_REMOVE outside checkout
+        * area as a result of ce_skip_worktree() shortcuts in
+        * verify_absent() and verify_uptodate().
+        * Make sure they don't modify worktree if they are already
+        * outside checkout area
+        */
+       if (was_skip_worktree && ce_skip_worktree(ce)) {
+               ce->ce_flags &= ~CE_UPDATE;
+
+               /*
+                * By default, when CE_REMOVE is on, CE_WT_REMOVE is also
+                * on to get that file removed from both index and worktree.
+                * If that file is already outside worktree area, don't
+                * bother remove it.
+                */
+               if (ce->ce_flags & CE_REMOVE)
+                       ce->ce_flags &= ~CE_WT_REMOVE;
+       }
 
        if (!was_skip_worktree && ce_skip_worktree(ce)) {
                /*
@@ -445,6 +454,7 @@ static int traverse_trees_recursive(int n, unsigned long dirmask, unsigned long
 {
        int i, ret, bottom;
        struct tree_desc t[MAX_UNPACK_TREES];
+       void *buf[MAX_UNPACK_TREES];
        struct traverse_info newinfo;
        struct name_entry *p;
 
@@ -462,12 +472,16 @@ static int traverse_trees_recursive(int n, unsigned long dirmask, unsigned long
                const unsigned char *sha1 = NULL;
                if (dirmask & 1)
                        sha1 = names[i].sha1;
-               fill_tree_descriptor(t+i, sha1);
+               buf[i] = fill_tree_descriptor(t+i, sha1);
        }
 
        bottom = switch_cache_bottom(&newinfo);
        ret = traverse_trees(n, t, &newinfo);
        restore_cache_bottom(&newinfo, bottom);
+
+       for (i = 0; i < n; i++)
+               free(buf[i]);
+
        return ret;
 }
 
@@ -915,14 +929,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
                                ret = -1;
                                goto done;
                        }
-                       /*
-                        * Merge strategies may set CE_UPDATE|CE_REMOVE outside checkout
-                        * area as a result of ce_skip_worktree() shortcuts in
-                        * verify_absent() and verify_uptodate(). Clear them.
-                        */
-                       if (ce_skip_worktree(ce))
-                               ce->ce_flags &= ~(CE_UPDATE | CE_REMOVE);
-                       else
+                       if (!ce_skip_worktree(ce))
                                empty_worktree = 0;
 
                }
@@ -1221,6 +1228,8 @@ static int merged_entry(struct cache_entry *merge, struct cache_entry *old,
        if (!old) {
                if (verify_absent(merge, ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN, o))
                        return -1;
+               if (!o->skip_sparse_checkout && will_have_skip_worktree(merge, o))
+                       update |= CE_SKIP_WORKTREE;
                invalidate_ce_path(merge, o);
        } else if (!(old->ce_flags & CE_CONFLICTED)) {
                /*