Merge branch 'tg/t0021-racefix'
[gitweb.git] / unpack-trees.c
index 1ccd343cad92dfad3e66deb304811eaf7af9b4fc..50f257bd5c768ae87f8e526c587fa11afad98ad6 100644 (file)
@@ -219,6 +219,9 @@ static int add_rejected_path(struct unpack_trees_options *o,
                             enum unpack_trees_error_types e,
                             const char *path)
 {
+       if (o->quiet)
+               return -1;
+
        if (!o->show_all_errors)
                return error(ERRORMSG(o, e), super_prefixed(path));
 
@@ -268,8 +271,7 @@ static int check_submodule_move_head(const struct cache_entry *ce,
                flags |= SUBMODULE_MOVE_HEAD_FORCE;
 
        if (submodule_move_head(ce->name, old_id, new_id, flags))
-               return o->gently ? -1 :
-                                  add_rejected_path(o, ERROR_WOULD_LOSE_SUBMODULE, ce->name);
+               return add_rejected_path(o, ERROR_WOULD_LOSE_SUBMODULE, ce->name);
        return 0;
 }
 
@@ -313,7 +315,7 @@ static struct progress *get_progress(struct unpack_trees_options *o)
                        total++;
        }
 
-       return start_delayed_progress(_("Checking out files"), total);
+       return start_delayed_progress(_("Updating files"), total);
 }
 
 static void setup_collided_checkout_detection(struct checkout *state,
@@ -404,20 +406,21 @@ static int check_updates(struct unpack_trees_options *o)
                 * below.
                 */
                struct oid_array to_fetch = OID_ARRAY_INIT;
-               int fetch_if_missing_store = fetch_if_missing;
-               fetch_if_missing = 0;
                for (i = 0; i < index->cache_nr; i++) {
                        struct cache_entry *ce = index->cache[i];
-                       if ((ce->ce_flags & CE_UPDATE) &&
-                           !S_ISGITLINK(ce->ce_mode)) {
-                               if (!has_object_file(&ce->oid))
-                                       oid_array_append(&to_fetch, &ce->oid);
-                       }
+
+                       if (!(ce->ce_flags & CE_UPDATE) ||
+                           S_ISGITLINK(ce->ce_mode))
+                               continue;
+                       if (!oid_object_info_extended(the_repository, &ce->oid,
+                                                     NULL,
+                                                     OBJECT_INFO_FOR_PREFETCH))
+                               continue;
+                       oid_array_append(&to_fetch, &ce->oid);
                }
                if (to_fetch.nr)
                        fetch_objects(repository_format_partial_clone,
                                      to_fetch.oid, to_fetch.nr);
-               fetch_if_missing = fetch_if_missing_store;
                oid_array_clear(&to_fetch);
        }
        for (i = 0; i < index->cache_nr; i++) {
@@ -629,7 +632,7 @@ static int unpack_index_entry(struct cache_entry *ce,
        return ret;
 }
 
-static int find_cache_pos(struct traverse_info *, const struct name_entry *);
+static int find_cache_pos(struct traverse_info *, const char *p, size_t len);
 
 static void restore_cache_bottom(struct traverse_info *info, int bottom)
 {
@@ -648,7 +651,7 @@ static int switch_cache_bottom(struct traverse_info *info)
        if (o->diff_index_cached)
                return 0;
        ret = o->cache_bottom;
-       pos = find_cache_pos(info->prev, &info->name);
+       pos = find_cache_pos(info->prev, info->name, info->namelen);
 
        if (pos < -1)
                o->cache_bottom = -2 - pos;
@@ -683,21 +686,19 @@ static int index_pos_by_traverse_info(struct name_entry *names,
                                      struct traverse_info *info)
 {
        struct unpack_trees_options *o = info->data;
-       int len = traverse_path_len(info, names);
-       char *name = xmalloc(len + 1 /* slash */ + 1 /* NUL */);
+       struct strbuf name = STRBUF_INIT;
        int pos;
 
-       make_traverse_path(name, info, names);
-       name[len++] = '/';
-       name[len] = '\0';
-       pos = index_name_pos(o->src_index, name, len);
+       strbuf_make_traverse_path(&name, info, names->path, names->pathlen);
+       strbuf_addch(&name, '/');
+       pos = index_name_pos(o->src_index, name.buf, name.len);
        if (pos >= 0)
                BUG("This is a directory and should not exist in index");
        pos = -pos - 1;
-       if (!starts_with(o->src_index->cache[pos]->name, name) ||
-           (pos > 0 && starts_with(o->src_index->cache[pos-1]->name, name)))
+       if (!starts_with(o->src_index->cache[pos]->name, name.buf) ||
+           (pos > 0 && starts_with(o->src_index->cache[pos-1]->name, name.buf)))
                BUG("pos must point at the first entry in this directory");
-       free(name);
+       strbuf_release(&name);
        return pos;
 }
 
@@ -707,7 +708,6 @@ static int index_pos_by_traverse_info(struct name_entry *names,
  * instead of ODB since we already know what these trees contain.
  */
 static int traverse_by_cache_tree(int pos, int nr_entries, int nr_names,
-                                 struct name_entry *names,
                                  struct traverse_info *info)
 {
        struct cache_entry *src[MAX_UNPACK_TREES + 1] = { NULL, };
@@ -797,7 +797,7 @@ static int traverse_trees_recursive(int n, unsigned long dirmask,
                 * unprocessed entries before 'pos'.
                 */
                bottom = o->cache_bottom;
-               ret = traverse_by_cache_tree(pos, nr_entries, n, names, info);
+               ret = traverse_by_cache_tree(pos, nr_entries, n, info);
                o->cache_bottom = bottom;
                return ret;
        }
@@ -809,8 +809,10 @@ static int traverse_trees_recursive(int n, unsigned long dirmask,
        newinfo = *info;
        newinfo.prev = info;
        newinfo.pathspec = info->pathspec;
-       newinfo.name = *p;
-       newinfo.pathlen += tree_entry_len(p) + 1;
+       newinfo.name = p->path;
+       newinfo.namelen = p->pathlen;
+       newinfo.mode = p->mode;
+       newinfo.pathlen = st_add3(newinfo.pathlen, tree_entry_len(p), 1);
        newinfo.df_conflicts |= df_conflicts;
 
        /*
@@ -838,7 +840,7 @@ static int traverse_trees_recursive(int n, unsigned long dirmask,
                        const struct object_id *oid = NULL;
                        if (dirmask & 1)
                                oid = &names[i].oid;
-                       buf[nr_buf++] = fill_tree_descriptor(t + i, oid);
+                       buf[nr_buf++] = fill_tree_descriptor(the_repository, t + i, oid);
                }
        }
 
@@ -861,14 +863,18 @@ static int traverse_trees_recursive(int n, unsigned long dirmask,
  * itself - the caller needs to do the final check for the cache
  * entry having more data at the end!
  */
-static int do_compare_entry_piecewise(const struct cache_entry *ce, const struct traverse_info *info, const struct name_entry *n)
+static int do_compare_entry_piecewise(const struct cache_entry *ce,
+                                     const struct traverse_info *info,
+                                     const char *name, size_t namelen,
+                                     unsigned mode)
 {
-       int len, pathlen, ce_len;
+       int pathlen, ce_len;
        const char *ce_name;
 
        if (info->prev) {
                int cmp = do_compare_entry_piecewise(ce, info->prev,
-                                                    &info->name);
+                                                    info->name, info->namelen,
+                                                    info->mode);
                if (cmp)
                        return cmp;
        }
@@ -882,15 +888,15 @@ static int do_compare_entry_piecewise(const struct cache_entry *ce, const struct
        ce_len -= pathlen;
        ce_name = ce->name + pathlen;
 
-       len = tree_entry_len(n);
-       return df_name_compare(ce_name, ce_len, S_IFREG, n->path, len, n->mode);
+       return df_name_compare(ce_name, ce_len, S_IFREG, name, namelen, mode);
 }
 
 static int do_compare_entry(const struct cache_entry *ce,
                            const struct traverse_info *info,
-                           const struct name_entry *n)
+                           const char *name, size_t namelen,
+                           unsigned mode)
 {
-       int len, pathlen, ce_len;
+       int pathlen, ce_len;
        const char *ce_name;
        int cmp;
 
@@ -900,7 +906,7 @@ static int do_compare_entry(const struct cache_entry *ce,
         * it is quicker to use the precomputed version.
         */
        if (!info->traverse_path)
-               return do_compare_entry_piecewise(ce, info, n);
+               return do_compare_entry_piecewise(ce, info, name, namelen, mode);
 
        cmp = strncmp(ce->name, info->traverse_path, info->pathlen);
        if (cmp)
@@ -915,13 +921,12 @@ static int do_compare_entry(const struct cache_entry *ce,
        ce_len -= pathlen;
        ce_name = ce->name + pathlen;
 
-       len = tree_entry_len(n);
-       return df_name_compare(ce_name, ce_len, S_IFREG, n->path, len, n->mode);
+       return df_name_compare(ce_name, ce_len, S_IFREG, name, namelen, mode);
 }
 
 static int compare_entry(const struct cache_entry *ce, const struct traverse_info *info, const struct name_entry *n)
 {
-       int cmp = do_compare_entry(ce, info, n);
+       int cmp = do_compare_entry(ce, info, n->path, n->pathlen, n->mode);
        if (cmp)
                return cmp;
 
@@ -929,7 +934,7 @@ static int compare_entry(const struct cache_entry *ce, const struct traverse_inf
         * Even if the beginning compared identically, the ce should
         * compare as bigger than a directory leading up to it!
         */
-       return ce_namelen(ce) > traverse_path_len(info, n);
+       return ce_namelen(ce) > traverse_path_len(info, tree_entry_len(n));
 }
 
 static int ce_in_traverse_path(const struct cache_entry *ce,
@@ -937,7 +942,8 @@ static int ce_in_traverse_path(const struct cache_entry *ce,
 {
        if (!info->prev)
                return 1;
-       if (do_compare_entry(ce, info->prev, &info->name))
+       if (do_compare_entry(ce, info->prev,
+                            info->name, info->namelen, info->mode))
                return 0;
        /*
         * If ce (blob) is the same name as the path (which is a tree
@@ -952,7 +958,7 @@ static struct cache_entry *create_ce_entry(const struct traverse_info *info,
        struct index_state *istate,
        int is_transient)
 {
-       int len = traverse_path_len(info, n);
+       size_t len = traverse_path_len(info, tree_entry_len(n));
        struct cache_entry *ce =
                is_transient ?
                make_empty_transient_cache_entry(len) :
@@ -962,7 +968,8 @@ static struct cache_entry *create_ce_entry(const struct traverse_info *info,
        ce->ce_flags = create_ce_flags(stage);
        ce->ce_namelen = len;
        oidcpy(&ce->oid, &n->oid);
-       make_traverse_path(ce->name, info, n);
+       /* len+1 because the cache_entry allocates space for NUL */
+       make_traverse_path(ce->name, len + 1, info, n->path, n->pathlen);
 
        return ce;
 }
@@ -1040,7 +1047,7 @@ static int unpack_nondirectories(int n, unsigned long mask,
 static int unpack_failed(struct unpack_trees_options *o, const char *message)
 {
        discard_index(&o->result);
-       if (!o->gently && !o->exiting_early) {
+       if (!o->quiet && !o->exiting_early) {
                if (message)
                        return error("%s", message);
                return -1;
@@ -1055,13 +1062,12 @@ static int unpack_failed(struct unpack_trees_options *o, const char *message)
  * the directory.
  */
 static int find_cache_pos(struct traverse_info *info,
-                         const struct name_entry *p)
+                         const char *p, size_t p_len)
 {
        int pos;
        struct unpack_trees_options *o = info->data;
        struct index_state *index = o->src_index;
        int pfxlen = info->pathlen;
-       int p_len = tree_entry_len(p);
 
        for (pos = o->cache_bottom; pos < index->cache_nr; pos++) {
                const struct cache_entry *ce = index->cache[pos];
@@ -1097,7 +1103,7 @@ static int find_cache_pos(struct traverse_info *info,
                        ce_len = ce_slash - ce_name;
                else
                        ce_len = ce_namelen(ce) - pfxlen;
-               cmp = name_compare(p->path, p_len, ce_name, ce_len);
+               cmp = name_compare(p, p_len, ce_name, ce_len);
                /*
                 * Exact match; if we have a directory we need to
                 * delay returning it.
@@ -1112,7 +1118,7 @@ static int find_cache_pos(struct traverse_info *info,
                 * E.g.  ce_name == "t-i", and p->path == "t"; we may
                 * have "t/a" in the index.
                 */
-               if (p_len < ce_len && !memcmp(ce_name, p->path, p_len) &&
+               if (p_len < ce_len && !memcmp(ce_name, p, p_len) &&
                    ce_name[p_len] < '/')
                        continue; /* keep looking */
                break;
@@ -1123,7 +1129,7 @@ static int find_cache_pos(struct traverse_info *info,
 static struct cache_entry *find_cache_entry(struct traverse_info *info,
                                            const struct name_entry *p)
 {
-       int pos = find_cache_pos(info, p);
+       int pos = find_cache_pos(info, p->path, p->pathlen);
        struct unpack_trees_options *o = info->data;
 
        if (0 <= pos)
@@ -1136,10 +1142,10 @@ static void debug_path(struct traverse_info *info)
 {
        if (info->prev) {
                debug_path(info->prev);
-               if (*info->prev->name.path)
+               if (*info->prev->name)
                        putchar('/');
        }
-       printf("%s", info->name.path);
+       printf("%s", info->name);
 }
 
 static void debug_name_entry(int i, struct name_entry *n)
@@ -1618,6 +1624,8 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
                                                  WRITE_TREE_SILENT |
                                                  WRITE_TREE_REPAIR);
                }
+
+               o->result.updated_workdir = 1;
                discard_index(o->dst_index);
                *o->dst_index = o->result;
        } else {
@@ -1645,8 +1653,7 @@ int unpack_trees(unsigned len, struct tree_desc *t, struct unpack_trees_options
 static int reject_merge(const struct cache_entry *ce,
                        struct unpack_trees_options *o)
 {
-       return o->gently ? -1 :
-               add_rejected_path(o, ERROR_WOULD_OVERWRITE, ce->name);
+       return add_rejected_path(o, ERROR_WOULD_OVERWRITE, ce->name);
 }
 
 static int same(const struct cache_entry *a, const struct cache_entry *b)
@@ -1693,8 +1700,7 @@ static int verify_uptodate_1(const struct cache_entry *ce,
                        int r = check_submodule_move_head(ce,
                                "HEAD", oid_to_hex(&ce->oid), o);
                        if (r)
-                               return o->gently ? -1 :
-                                       add_rejected_path(o, error_type, ce->name);
+                               return add_rejected_path(o, error_type, ce->name);
                        return 0;
                }
 
@@ -1712,8 +1718,7 @@ static int verify_uptodate_1(const struct cache_entry *ce,
        }
        if (errno == ENOENT)
                return 0;
-       return o->gently ? -1 :
-               add_rejected_path(o, error_type, ce->name);
+       return add_rejected_path(o, error_type, ce->name);
 }
 
 int verify_uptodate(const struct cache_entry *ce,
@@ -1759,7 +1764,6 @@ static void invalidate_ce_path(const struct cache_entry *ce,
  */
 static int verify_clean_submodule(const char *old_sha1,
                                  const struct cache_entry *ce,
-                                 enum unpack_trees_error_types error_type,
                                  struct unpack_trees_options *o)
 {
        if (!submodule_from_ce(ce))
@@ -1770,7 +1774,6 @@ static int verify_clean_submodule(const char *old_sha1,
 }
 
 static int verify_clean_subdirectory(const struct cache_entry *ce,
-                                    enum unpack_trees_error_types error_type,
                                     struct unpack_trees_options *o)
 {
        /*
@@ -1793,7 +1796,7 @@ static int verify_clean_subdirectory(const struct cache_entry *ce,
                if (!sub_head && oideq(&oid, &ce->oid))
                        return 0;
                return verify_clean_submodule(sub_head ? NULL : oid_to_hex(&oid),
-                                             ce, error_type, o);
+                                             ce, o);
        }
 
        /*
@@ -1835,8 +1838,7 @@ static int verify_clean_subdirectory(const struct cache_entry *ce,
                d.exclude_per_dir = o->dir->exclude_per_dir;
        i = read_directory(&d, o->src_index, pathbuf, namelen+1, NULL);
        if (i)
-               return o->gently ? -1 :
-                       add_rejected_path(o, ERROR_NOT_UPTODATE_DIR, ce->name);
+               return add_rejected_path(o, ERROR_NOT_UPTODATE_DIR, ce->name);
        free(pathbuf);
        return cnt;
 }
@@ -1889,7 +1891,7 @@ static int check_ok_to_remove(const char *name, int len, int dtype,
                 * files that are in "foo/" we would lose
                 * them.
                 */
-               if (verify_clean_subdirectory(ce, error_type, o) < 0)
+               if (verify_clean_subdirectory(ce, o) < 0)
                        return -1;
                return 0;
        }
@@ -1905,8 +1907,7 @@ static int check_ok_to_remove(const char *name, int len, int dtype,
                        return 0;
        }
 
-       return o->gently ? -1 :
-               add_rejected_path(o, error_type, name);
+       return add_rejected_path(o, error_type, name);
 }
 
 /*
@@ -2346,7 +2347,7 @@ int bind_merge(const struct cache_entry * const *src,
                return error("Cannot do a bind merge of %d trees",
                             o->merge_size);
        if (a && old)
-               return o->gently ? -1 :
+               return o->quiet ? -1 :
                        error(ERRORMSG(o, ERROR_BIND_OVERLAP),
                              super_prefixed(a->name),
                              super_prefixed(old->name));