#define NO_THE_INDEX_COMPATIBILITY_MACROS
#include "cache.h"
+#include "repository.h"
#include "config.h"
#include "dir.h"
#include "tree.h"
#include "dir.h"
#include "submodule.h"
#include "submodule-config.h"
+#include "fsmonitor.h"
+#include "fetch-object.h"
/*
* Error messages expected by scripts out of plumbing commands such as
msgs[ERROR_BIND_OVERLAP] = _("Entry '%s' overlaps with '%s'. Cannot bind.");
msgs[ERROR_SPARSE_NOT_UPTODATE_FILE] =
- _("Cannot update sparse checkout: the following entries are not up-to-date:\n%s");
+ _("Cannot update sparse checkout: the following entries are not up to date:\n%s");
msgs[ERROR_WOULD_LOSE_ORPHANED_OVERWRITTEN] =
_("The following working tree files would be overwritten by sparse checkout update:\n%s");
msgs[ERROR_WOULD_LOSE_ORPHANED_REMOVED] =
static struct cache_entry *dup_entry(const struct cache_entry *ce)
{
unsigned int size = ce_size(ce);
- struct cache_entry *new = xmalloc(size);
+ struct cache_entry *new_entry = xmalloc(size);
- memcpy(new, ce, size);
- return new;
+ memcpy(new_entry, ce, size);
+ return new_entry;
}
static void add_entry(struct unpack_trees_options *o,
{
unsigned flags = SUBMODULE_MOVE_HEAD_DRY_RUN;
const struct submodule *sub = submodule_from_ce(ce);
+
if (!sub)
return 0;
if (o->reset)
flags |= SUBMODULE_MOVE_HEAD_FORCE;
- switch (sub->update_strategy.type) {
- case SM_UPDATE_UNSPECIFIED:
- case SM_UPDATE_CHECKOUT:
- 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 0;
- case SM_UPDATE_NONE:
- return 0;
- case SM_UPDATE_REBASE:
- case SM_UPDATE_MERGE:
- case SM_UPDATE_COMMAND:
- default:
- warning(_("submodule update strategy not supported for submodule '%s'"), ce->name);
- return -1;
- }
+ 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 0;
}
-static void reload_gitmodules_file(struct index_state *index,
- struct checkout *state)
+/*
+ * Preform the loading of the repository's gitmodules file. This function is
+ * used by 'check_update()' to perform loading of the gitmodules file in two
+ * differnt situations:
+ * (1) before removing entries from the working tree if the gitmodules file has
+ * been marked for removal. This situation is specified by 'state' == NULL.
+ * (2) before checking out entries to the working tree if the gitmodules file
+ * has been marked for update. This situation is specified by 'state' != NULL.
+ */
+static void load_gitmodules_file(struct index_state *index,
+ struct checkout *state)
{
- int i;
- for (i = 0; i < index->cache_nr; i++) {
- struct cache_entry *ce = index->cache[i];
- if (ce->ce_flags & CE_UPDATE) {
- int r = strcmp(ce->name, ".gitmodules");
- if (r < 0)
- continue;
- else if (r == 0) {
- submodule_free();
- checkout_entry(ce, state, NULL);
- gitmodules_config();
- git_config(submodule_config, NULL);
- } else
- break;
+ int pos = index_name_pos(index, GITMODULES_FILE, strlen(GITMODULES_FILE));
+
+ if (pos >= 0) {
+ struct cache_entry *ce = index->cache[pos];
+ if (!state && ce->ce_flags & CE_WT_REMOVE) {
+ repo_read_gitmodules(the_repository);
+ } else if (state && (ce->ce_flags & CE_UPDATE)) {
+ submodule_free(the_repository);
+ checkout_entry(ce, state, NULL);
+ repo_read_gitmodules(the_repository);
}
}
}
{
const struct submodule *sub = submodule_from_ce(ce);
if (sub) {
- switch (sub->update_strategy.type) {
- case SM_UPDATE_UNSPECIFIED:
- case SM_UPDATE_CHECKOUT:
- case SM_UPDATE_REBASE:
- case SM_UPDATE_MERGE:
- /* state.force is set at the caller. */
- submodule_move_head(ce->name, "HEAD", NULL,
- SUBMODULE_MOVE_HEAD_FORCE);
- break;
- case SM_UPDATE_NONE:
- case SM_UPDATE_COMMAND:
- return; /* Do not touch the submodule. */
- }
+ /* state.force is set at the caller. */
+ submodule_move_head(ce->name, "HEAD", NULL,
+ SUBMODULE_MOVE_HEAD_FORCE);
}
if (!check_leading_path(ce->name, ce_namelen(ce)))
return;
total++;
}
- return start_progress_delay(_("Checking out files"),
- total, 50, 1);
+ return start_delayed_progress(_("Checking out files"), total);
}
static int check_updates(struct unpack_trees_options *o)
if (o->update)
git_attr_set_direction(GIT_ATTR_CHECKOUT, index);
+
+ if (should_update_submodules() && o->update && !o->dry_run)
+ load_gitmodules_file(index, NULL);
+
for (i = 0; i < index->cache_nr; i++) {
const struct cache_entry *ce = index->cache[i];
remove_scheduled_dirs();
if (should_update_submodules() && o->update && !o->dry_run)
- reload_gitmodules_file(index, &state);
+ load_gitmodules_file(index, &state);
enable_delayed_checkout(&state);
+ if (repository_format_partial_clone && o->update && !o->dry_run) {
+ /*
+ * Prefetch the objects that are to be checked out in the loop
+ * 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 (to_fetch.nr)
+ fetch_objects(repository_format_partial_clone,
+ &to_fetch);
+ fetch_if_missing = fetch_if_missing_store;
+ oid_array_clear(&to_fetch);
+ }
for (i = 0; i < index->cache_nr; i++) {
struct cache_entry *ce = index->cache[i];
}
}
}
- errs |= finish_delayed_checkout(&state);
stop_progress(&progress);
+ errs |= finish_delayed_checkout(&state);
if (o->update)
git_attr_set_direction(GIT_ATTR_CHECKIN, NULL);
return errs != 0;
ce->ce_flags &= ~CE_SKIP_WORKTREE;
if (was_skip_worktree != ce_skip_worktree(ce)) {
ce->ce_flags |= CE_UPDATE_IN_BASE;
+ mark_fsmonitor_invalid(istate, ce);
istate->cache_changed |= CE_ENTRY_CHANGED;
}
else if (i > 1 && are_same_oid(&names[i], &names[i - 2]))
t[i] = t[i - 2];
else {
- const unsigned char *sha1 = NULL;
+ const struct object_id *oid = NULL;
if (dirmask & 1)
- sha1 = names[i].oid->hash;
- buf[nr_buf++] = fill_tree_descriptor(t+i, sha1);
+ oid = names[i].oid;
+ buf[nr_buf++] = fill_tree_descriptor(t + i, oid);
}
}
o->result.timestamp.sec = o->src_index->timestamp.sec;
o->result.timestamp.nsec = o->src_index->timestamp.nsec;
o->result.version = o->src_index->version;
- o->result.split_index = o->src_index->split_index;
- if (o->result.split_index)
+ if (!o->src_index->split_index) {
+ o->result.split_index = NULL;
+ } else if (o->src_index == o->dst_index) {
+ /*
+ * o->dst_index (and thus o->src_index) will be discarded
+ * and overwritten with o->result at the end of this function,
+ * so just use src_index's split_index to avoid having to
+ * create a new one.
+ */
+ o->result.split_index = o->src_index->split_index;
o->result.split_index->refcount++;
+ } else {
+ o->result.split_index = init_split_index(&o->result);
+ }
hashcpy(o->result.sha1, o->src_index->sha1);
o->merge_size = len;
mark_all_ce_unused(o->src_index);
}
}
- o->src_index = NULL;
ret = check_updates(o) ? (-2) : 0;
if (o->dst_index) {
if (!ret) {
WRITE_TREE_SILENT |
WRITE_TREE_REPAIR);
}
- move_index_extensions(&o->result, o->dst_index);
+ move_index_extensions(&o->result, o->src_index);
discard_index(o->dst_index);
*o->dst_index = o->result;
} else {
discard_index(&o->result);
}
+ o->src_index = NULL;
done:
clear_exclude_list(&el);
add_rejected_path(o, error_type, ce->name);
}
-static int verify_uptodate(const struct cache_entry *ce,
- struct unpack_trees_options *o)
+int verify_uptodate(const struct cache_entry *ce,
+ struct unpack_trees_options *o)
{
if (!o->skip_sparse_checkout && (ce->ce_flags & CE_NEW_SKIP_WORKTREE))
return 0;
if (!ce)
return;
cache_tree_invalidate_path(o->src_index, ce->name);
- untracked_cache_invalidate_path(o->src_index, ce->name);
+ untracked_cache_invalidate_path(o->src_index, ce->name, 1);
}
/*
int cnt = 0;
if (S_ISGITLINK(ce->ce_mode)) {
- unsigned char sha1[20];
- int sub_head = resolve_gitlink_ref(ce->name, "HEAD", sha1);
+ struct object_id oid;
+ int sub_head = resolve_gitlink_ref(ce->name, "HEAD", &oid);
/*
* If we are not going to update the submodule, then
* we don't care.
*/
- if (!sub_head && !hashcmp(sha1, ce->oid.hash))
+ if (!sub_head && !oidcmp(&oid, &ce->oid))
return 0;
- return verify_clean_submodule(sub_head ? NULL : sha1_to_hex(sha1),
+ return verify_clean_submodule(sub_head ? NULL : oid_to_hex(&oid),
ce, error_type, o);
}
ie_match_stat(o->src_index, old, &st, CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE))
update |= CE_UPDATE;
}
+ if (o->update && S_ISGITLINK(old->ce_mode) &&
+ should_update_submodules() && !verify_uptodate(old, o))
+ update |= CE_UPDATE;
add_entry(o, old, update, 0);
return 0;
}