зеркало из https://github.com/microsoft/git.git
Merge branch 'ab/no-more-git-global-super-prefix'
Stop using "git --super-prefix" and narrow the scope of its use to the submodule--helper. * ab/no-more-git-global-super-prefix: read-tree: add "--super-prefix" option, eliminate global submodule--helper: convert "{update,clone}" to their own "--super-prefix" submodule--helper: convert "status" to its own "--super-prefix" submodule--helper: convert "sync" to its own "--super-prefix" submodule--helper: convert "foreach" to its own "--super-prefix" submodule--helper: don't use global --super-prefix in "absorbgitdirs" submodule.c & submodule--helper: pass along "super_prefix" param read-tree + fetch tests: test failing "--super-prefix" interaction submodule absorbgitdirs tests: add missing "Migrating git..." tests
This commit is contained in:
Коммит
d4c5400865
|
@ -13,8 +13,7 @@ SYNOPSIS
|
|||
[--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
|
||||
[-p|--paginate|-P|--no-pager] [--no-replace-objects] [--bare]
|
||||
[--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
|
||||
[--super-prefix=<path>] [--config-env=<name>=<envvar>]
|
||||
<command> [<args>]
|
||||
[--config-env=<name>=<envvar>] <command> [<args>]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
@ -169,11 +168,6 @@ If you just want to run git as if it was started in `<path>` then use
|
|||
details. Equivalent to setting the `GIT_NAMESPACE` environment
|
||||
variable.
|
||||
|
||||
--super-prefix=<path>::
|
||||
Currently for internal use only. Set a prefix which gives a path from
|
||||
above a repository down to its root. One use is to give submodules
|
||||
context about the superproject that invoked it.
|
||||
|
||||
--bare::
|
||||
Treat the repository as a bare repository. If GIT_DIR
|
||||
environment is not set, it is set to the current working
|
||||
|
|
|
@ -51,10 +51,6 @@
|
|||
* on bare repositories.
|
||||
* This only makes sense when `RUN_SETUP` is also set.
|
||||
*
|
||||
* `SUPPORT_SUPER_PREFIX`:
|
||||
*
|
||||
* The built-in supports `--super-prefix`.
|
||||
*
|
||||
* `DELAY_PAGER_CONFIG`:
|
||||
*
|
||||
* If RUN_SETUP or RUN_SETUP_GENTLY is set, git.c normally handles
|
||||
|
|
|
@ -232,7 +232,7 @@ static int checkout_stage(int stage, const struct cache_entry *ce, int pos,
|
|||
pos++;
|
||||
}
|
||||
if (!overlay_mode) {
|
||||
unlink_entry(ce);
|
||||
unlink_entry(ce, NULL);
|
||||
return 0;
|
||||
}
|
||||
if (stage == 2)
|
||||
|
|
|
@ -114,6 +114,7 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix)
|
|||
int prefix_set = 0;
|
||||
struct lock_file lock_file = LOCK_INIT;
|
||||
const struct option read_tree_options[] = {
|
||||
OPT__SUPER_PREFIX(&opts.super_prefix),
|
||||
OPT_CALLBACK_F(0, "index-output", NULL, N_("file"),
|
||||
N_("write resulting index to <file>"),
|
||||
PARSE_OPT_NONEG, index_output_cb),
|
||||
|
|
|
@ -86,7 +86,7 @@ static void submodules_absorb_gitdir_if_needed(void)
|
|||
continue;
|
||||
|
||||
if (!submodule_uses_gitfile(name))
|
||||
absorb_git_dir_into_superproject(name);
|
||||
absorb_git_dir_into_superproject(name, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -113,10 +113,9 @@ static char *resolve_relative_url(const char *rel_url, const char *up_path, int
|
|||
}
|
||||
|
||||
/* the result should be freed by the caller. */
|
||||
static char *get_submodule_displaypath(const char *path, const char *prefix)
|
||||
static char *get_submodule_displaypath(const char *path, const char *prefix,
|
||||
const char *super_prefix)
|
||||
{
|
||||
const char *super_prefix = get_super_prefix();
|
||||
|
||||
if (prefix && super_prefix) {
|
||||
BUG("cannot have prefix '%s' and superprefix '%s'",
|
||||
prefix, super_prefix);
|
||||
|
@ -279,6 +278,7 @@ struct foreach_cb {
|
|||
int argc;
|
||||
const char **argv;
|
||||
const char *prefix;
|
||||
const char *super_prefix;
|
||||
int quiet;
|
||||
int recursive;
|
||||
};
|
||||
|
@ -294,7 +294,8 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
|
|||
struct child_process cp = CHILD_PROCESS_INIT;
|
||||
char *displaypath;
|
||||
|
||||
displaypath = get_submodule_displaypath(path, info->prefix);
|
||||
displaypath = get_submodule_displaypath(path, info->prefix,
|
||||
info->super_prefix);
|
||||
|
||||
sub = submodule_from_path(the_repository, null_oid(), path);
|
||||
|
||||
|
@ -364,10 +365,10 @@ static void runcommand_in_submodule_cb(const struct cache_entry *list_item,
|
|||
cpr.dir = path;
|
||||
prepare_submodule_repo_env(&cpr.env);
|
||||
|
||||
strvec_pushl(&cpr.args, "--super-prefix", NULL);
|
||||
strvec_pushf(&cpr.args, "%s/", displaypath);
|
||||
strvec_pushl(&cpr.args, "submodule--helper", "foreach", "--recursive",
|
||||
NULL);
|
||||
strvec_pushl(&cpr.args, "--super-prefix", NULL);
|
||||
strvec_pushf(&cpr.args, "%s/", displaypath);
|
||||
|
||||
if (info->quiet)
|
||||
strvec_push(&cpr.args, "--quiet");
|
||||
|
@ -391,6 +392,7 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
|
|||
struct pathspec pathspec = { 0 };
|
||||
struct module_list list = MODULE_LIST_INIT;
|
||||
struct option module_foreach_options[] = {
|
||||
OPT__SUPER_PREFIX(&info.super_prefix),
|
||||
OPT__QUIET(&info.quiet, N_("suppress output of entering each submodule command")),
|
||||
OPT_BOOL(0, "recursive", &info.recursive,
|
||||
N_("recurse into nested submodules")),
|
||||
|
@ -435,11 +437,13 @@ static int starts_with_dot_dot_slash(const char *const path)
|
|||
|
||||
struct init_cb {
|
||||
const char *prefix;
|
||||
const char *super_prefix;
|
||||
unsigned int flags;
|
||||
};
|
||||
#define INIT_CB_INIT { 0 }
|
||||
|
||||
static void init_submodule(const char *path, const char *prefix,
|
||||
const char *super_prefix,
|
||||
unsigned int flags)
|
||||
{
|
||||
const struct submodule *sub;
|
||||
|
@ -447,7 +451,7 @@ static void init_submodule(const char *path, const char *prefix,
|
|||
const char *upd;
|
||||
char *url = NULL, *displaypath;
|
||||
|
||||
displaypath = get_submodule_displaypath(path, prefix);
|
||||
displaypath = get_submodule_displaypath(path, prefix, super_prefix);
|
||||
|
||||
sub = submodule_from_path(the_repository, null_oid(), path);
|
||||
|
||||
|
@ -523,7 +527,8 @@ static void init_submodule_cb(const struct cache_entry *list_item, void *cb_data
|
|||
{
|
||||
struct init_cb *info = cb_data;
|
||||
|
||||
init_submodule(list_item->name, info->prefix, info->flags);
|
||||
init_submodule(list_item->name, info->prefix, info->super_prefix,
|
||||
info->flags);
|
||||
}
|
||||
|
||||
static int module_init(int argc, const char **argv, const char *prefix)
|
||||
|
@ -570,6 +575,7 @@ cleanup:
|
|||
|
||||
struct status_cb {
|
||||
const char *prefix;
|
||||
const char *super_prefix;
|
||||
unsigned int flags;
|
||||
};
|
||||
#define STATUS_CB_INIT { 0 }
|
||||
|
@ -608,7 +614,7 @@ static int handle_submodule_head_ref(const char *refname UNUSED,
|
|||
|
||||
static void status_submodule(const char *path, const struct object_id *ce_oid,
|
||||
unsigned int ce_flags, const char *prefix,
|
||||
unsigned int flags)
|
||||
const char *super_prefix, unsigned int flags)
|
||||
{
|
||||
char *displaypath;
|
||||
struct strvec diff_files_args = STRVEC_INIT;
|
||||
|
@ -624,7 +630,7 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
|
|||
die(_("no submodule mapping found in .gitmodules for path '%s'"),
|
||||
path);
|
||||
|
||||
displaypath = get_submodule_displaypath(path, prefix);
|
||||
displaypath = get_submodule_displaypath(path, prefix, super_prefix);
|
||||
|
||||
if ((CE_STAGEMASK & ce_flags) >> CE_STAGESHIFT) {
|
||||
print_status(flags, 'U', path, null_oid(), displaypath);
|
||||
|
@ -682,10 +688,10 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
|
|||
cpr.dir = path;
|
||||
prepare_submodule_repo_env(&cpr.env);
|
||||
|
||||
strvec_push(&cpr.args, "--super-prefix");
|
||||
strvec_pushf(&cpr.args, "%s/", displaypath);
|
||||
strvec_pushl(&cpr.args, "submodule--helper", "status",
|
||||
"--recursive", NULL);
|
||||
strvec_push(&cpr.args, "--super-prefix");
|
||||
strvec_pushf(&cpr.args, "%s/", displaypath);
|
||||
|
||||
if (flags & OPT_CACHED)
|
||||
strvec_push(&cpr.args, "--cached");
|
||||
|
@ -709,7 +715,7 @@ static void status_submodule_cb(const struct cache_entry *list_item,
|
|||
struct status_cb *info = cb_data;
|
||||
|
||||
status_submodule(list_item->name, &list_item->oid, list_item->ce_flags,
|
||||
info->prefix, info->flags);
|
||||
info->prefix, info->super_prefix, info->flags);
|
||||
}
|
||||
|
||||
static int module_status(int argc, const char **argv, const char *prefix)
|
||||
|
@ -719,6 +725,7 @@ static int module_status(int argc, const char **argv, const char *prefix)
|
|||
struct module_list list = MODULE_LIST_INIT;
|
||||
int quiet = 0;
|
||||
struct option module_status_options[] = {
|
||||
OPT__SUPER_PREFIX(&info.super_prefix),
|
||||
OPT__QUIET(&quiet, N_("suppress submodule status output")),
|
||||
OPT_BIT(0, "cached", &info.flags, N_("use commit stored in the index instead of the one stored in the submodule HEAD"), OPT_CACHED),
|
||||
OPT_BIT(0, "recursive", &info.flags, N_("recurse into nested submodules"), OPT_RECURSIVE),
|
||||
|
@ -787,6 +794,7 @@ struct summary_cb {
|
|||
int argc;
|
||||
const char **argv;
|
||||
const char *prefix;
|
||||
const char *super_prefix;
|
||||
unsigned int cached: 1;
|
||||
unsigned int for_status: 1;
|
||||
unsigned int files: 1;
|
||||
|
@ -948,7 +956,8 @@ static void generate_submodule_summary(struct summary_cb *info,
|
|||
dst_abbrev = xstrndup(oid_to_hex(&p->oid_dst), 7);
|
||||
}
|
||||
|
||||
displaypath = get_submodule_displaypath(p->sm_path, info->prefix);
|
||||
displaypath = get_submodule_displaypath(p->sm_path, info->prefix,
|
||||
info->super_prefix);
|
||||
|
||||
if (!missing_src && !missing_dst) {
|
||||
struct child_process cp_rev_list = CHILD_PROCESS_INIT;
|
||||
|
@ -1203,12 +1212,13 @@ static int module_summary(int argc, const char **argv, const char *prefix)
|
|||
|
||||
struct sync_cb {
|
||||
const char *prefix;
|
||||
const char *super_prefix;
|
||||
unsigned int flags;
|
||||
};
|
||||
#define SYNC_CB_INIT { 0 }
|
||||
|
||||
static void sync_submodule(const char *path, const char *prefix,
|
||||
unsigned int flags)
|
||||
const char *super_prefix, unsigned int flags)
|
||||
{
|
||||
const struct submodule *sub;
|
||||
char *remote_key = NULL;
|
||||
|
@ -1239,7 +1249,7 @@ static void sync_submodule(const char *path, const char *prefix,
|
|||
super_config_url = xstrdup("");
|
||||
}
|
||||
|
||||
displaypath = get_submodule_displaypath(path, prefix);
|
||||
displaypath = get_submodule_displaypath(path, prefix, super_prefix);
|
||||
|
||||
if (!(flags & OPT_QUIET))
|
||||
printf(_("Synchronizing submodule url for '%s'\n"),
|
||||
|
@ -1276,10 +1286,11 @@ static void sync_submodule(const char *path, const char *prefix,
|
|||
cpr.dir = path;
|
||||
prepare_submodule_repo_env(&cpr.env);
|
||||
|
||||
strvec_push(&cpr.args, "--super-prefix");
|
||||
strvec_pushf(&cpr.args, "%s/", displaypath);
|
||||
strvec_pushl(&cpr.args, "submodule--helper", "sync",
|
||||
"--recursive", NULL);
|
||||
strvec_push(&cpr.args, "--super-prefix");
|
||||
strvec_pushf(&cpr.args, "%s/", displaypath);
|
||||
|
||||
|
||||
if (flags & OPT_QUIET)
|
||||
strvec_push(&cpr.args, "--quiet");
|
||||
|
@ -1302,7 +1313,8 @@ static void sync_submodule_cb(const struct cache_entry *list_item, void *cb_data
|
|||
{
|
||||
struct sync_cb *info = cb_data;
|
||||
|
||||
sync_submodule(list_item->name, info->prefix, info->flags);
|
||||
sync_submodule(list_item->name, info->prefix, info->super_prefix,
|
||||
info->flags);
|
||||
}
|
||||
|
||||
static int module_sync(int argc, const char **argv, const char *prefix)
|
||||
|
@ -1313,6 +1325,7 @@ static int module_sync(int argc, const char **argv, const char *prefix)
|
|||
int quiet = 0;
|
||||
int recursive = 0;
|
||||
struct option module_sync_options[] = {
|
||||
OPT__SUPER_PREFIX(&info.super_prefix),
|
||||
OPT__QUIET(&quiet, N_("suppress output of synchronizing submodule url")),
|
||||
OPT_BOOL(0, "recursive", &recursive,
|
||||
N_("recurse into nested submodules")),
|
||||
|
@ -1365,7 +1378,7 @@ static void deinit_submodule(const char *path, const char *prefix,
|
|||
if (!sub || !sub->name)
|
||||
goto cleanup;
|
||||
|
||||
displaypath = get_submodule_displaypath(path, prefix);
|
||||
displaypath = get_submodule_displaypath(path, prefix, NULL);
|
||||
|
||||
/* remove the submodule work tree (unless the user already did it) */
|
||||
if (is_directory(path)) {
|
||||
|
@ -1379,7 +1392,7 @@ static void deinit_submodule(const char *path, const char *prefix,
|
|||
".git file by using absorbgitdirs."),
|
||||
displaypath);
|
||||
|
||||
absorb_git_dir_into_superproject(path);
|
||||
absorb_git_dir_into_superproject(path, NULL);
|
||||
|
||||
}
|
||||
|
||||
|
@ -1883,6 +1896,7 @@ static void submodule_update_clone_release(struct submodule_update_clone *suc)
|
|||
|
||||
struct update_data {
|
||||
const char *prefix;
|
||||
const char *super_prefix;
|
||||
char *displaypath;
|
||||
enum submodule_update_type update_default;
|
||||
struct object_id suboid;
|
||||
|
@ -1958,7 +1972,8 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce,
|
|||
enum submodule_update_type update_type;
|
||||
char *key;
|
||||
const struct update_data *ud = suc->update_data;
|
||||
char *displaypath = get_submodule_displaypath(ce->name, ud->prefix);
|
||||
char *displaypath = get_submodule_displaypath(ce->name, ud->prefix,
|
||||
ud->super_prefix);
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
int needs_cloning = 0;
|
||||
int need_free_url = 0;
|
||||
|
@ -2438,11 +2453,11 @@ static void update_data_to_args(const struct update_data *update_data,
|
|||
{
|
||||
enum submodule_update_type update_type = update_data->update_default;
|
||||
|
||||
strvec_pushl(args, "submodule--helper", "update", "--recursive", NULL);
|
||||
if (update_data->displaypath) {
|
||||
strvec_push(args, "--super-prefix");
|
||||
strvec_pushf(args, "%s/", update_data->displaypath);
|
||||
}
|
||||
strvec_pushl(args, "submodule--helper", "update", "--recursive", NULL);
|
||||
strvec_pushf(args, "--jobs=%d", update_data->max_jobs);
|
||||
if (update_data->quiet)
|
||||
strvec_push(args, "--quiet");
|
||||
|
@ -2608,7 +2623,8 @@ static int update_submodules(struct update_data *update_data)
|
|||
goto fail;
|
||||
|
||||
update_data->displaypath = get_submodule_displaypath(
|
||||
update_data->sm_path, update_data->prefix);
|
||||
update_data->sm_path, update_data->prefix,
|
||||
update_data->super_prefix);
|
||||
code = update_submodule(update_data);
|
||||
FREE_AND_NULL(update_data->displaypath);
|
||||
fail:
|
||||
|
@ -2634,6 +2650,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
|
|||
LIST_OBJECTS_FILTER_INIT;
|
||||
int ret;
|
||||
struct option module_update_options[] = {
|
||||
OPT__SUPER_PREFIX(&opt.super_prefix),
|
||||
OPT__FORCE(&opt.force, N_("force checkout updates"), 0),
|
||||
OPT_BOOL(0, "init", &opt.init,
|
||||
N_("initialize uninitialized submodules before update")),
|
||||
|
@ -2730,6 +2747,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
|
|||
module_list_active(&list);
|
||||
|
||||
info.prefix = opt.prefix;
|
||||
info.super_prefix = opt.super_prefix;
|
||||
if (opt.quiet)
|
||||
info.flags |= OPT_QUIET;
|
||||
|
||||
|
@ -2828,7 +2846,9 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
|
|||
int i;
|
||||
struct pathspec pathspec = { 0 };
|
||||
struct module_list list = MODULE_LIST_INIT;
|
||||
const char *super_prefix = NULL;
|
||||
struct option embed_gitdir_options[] = {
|
||||
OPT__SUPER_PREFIX(&super_prefix),
|
||||
OPT_END()
|
||||
};
|
||||
const char *const git_submodule_helper_usage[] = {
|
||||
|
@ -2844,7 +2864,8 @@ static int absorb_git_dirs(int argc, const char **argv, const char *prefix)
|
|||
goto cleanup;
|
||||
|
||||
for (i = 0; i < list.nr; i++)
|
||||
absorb_git_dir_into_superproject(list.entries[i]->name);
|
||||
absorb_git_dir_into_superproject(list.entries[i]->name,
|
||||
super_prefix);
|
||||
|
||||
ret = 0;
|
||||
cleanup:
|
||||
|
@ -2876,7 +2897,7 @@ static int module_set_url(int argc, const char **argv, const char *prefix)
|
|||
config_name = xstrfmt("submodule.%s.url", path);
|
||||
|
||||
config_set_in_gitmodules_file_gently(config_name, newurl);
|
||||
sync_submodule(path, prefix, quiet ? OPT_QUIET : 0);
|
||||
sync_submodule(path, prefix, NULL, quiet ? OPT_QUIET : 0);
|
||||
|
||||
free(config_name);
|
||||
|
||||
|
@ -3353,8 +3374,6 @@ cleanup:
|
|||
|
||||
int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
const char *cmd = argv[0];
|
||||
const char *subcmd;
|
||||
parse_opt_subcommand_fn *fn = NULL;
|
||||
const char *const usage[] = {
|
||||
N_("git submodule--helper <command>"),
|
||||
|
@ -3378,18 +3397,6 @@ int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
|
|||
OPT_END()
|
||||
};
|
||||
argc = parse_options(argc, argv, prefix, options, usage, 0);
|
||||
subcmd = argv[0];
|
||||
|
||||
if (strcmp(subcmd, "clone") && strcmp(subcmd, "update") &&
|
||||
strcmp(subcmd, "foreach") && strcmp(subcmd, "status") &&
|
||||
strcmp(subcmd, "sync") && strcmp(subcmd, "absorbgitdirs") &&
|
||||
get_super_prefix())
|
||||
/*
|
||||
* xstrfmt() rather than "%s %s" to keep the translated
|
||||
* string identical to git.c's.
|
||||
*/
|
||||
die(_("%s doesn't support --super-prefix"),
|
||||
xstrfmt("'%s %s'", cmd, subcmd));
|
||||
|
||||
return fn(argc, argv, prefix);
|
||||
}
|
||||
|
|
2
cache.h
2
cache.h
|
@ -480,7 +480,6 @@ static inline enum object_type object_type(unsigned int mode)
|
|||
#define GIT_NAMESPACE_ENVIRONMENT "GIT_NAMESPACE"
|
||||
#define GIT_WORK_TREE_ENVIRONMENT "GIT_WORK_TREE"
|
||||
#define GIT_PREFIX_ENVIRONMENT "GIT_PREFIX"
|
||||
#define GIT_SUPER_PREFIX_ENVIRONMENT "GIT_INTERNAL_SUPER_PREFIX"
|
||||
#define DEFAULT_GIT_DIR_ENVIRONMENT ".git"
|
||||
#define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
|
||||
#define INDEX_ENVIRONMENT "GIT_INDEX_FILE"
|
||||
|
@ -566,7 +565,6 @@ int get_common_dir_noenv(struct strbuf *sb, const char *gitdir);
|
|||
int get_common_dir(struct strbuf *sb, const char *gitdir);
|
||||
const char *get_git_namespace(void);
|
||||
const char *strip_namespace(const char *namespaced_ref);
|
||||
const char *get_super_prefix(void);
|
||||
const char *get_git_work_tree(void);
|
||||
|
||||
/*
|
||||
|
|
12
entry.c
12
entry.c
|
@ -383,7 +383,7 @@ static int write_entry(struct cache_entry *ce, char *path, struct conv_attrs *ca
|
|||
return error("cannot create submodule directory %s", path);
|
||||
sub = submodule_from_ce(ce);
|
||||
if (sub)
|
||||
return submodule_move_head(ce->name,
|
||||
return submodule_move_head(ce->name, state->super_prefix,
|
||||
NULL, oid_to_hex(&ce->oid),
|
||||
state->force ? SUBMODULE_MOVE_HEAD_FORCE : 0);
|
||||
break;
|
||||
|
@ -476,7 +476,7 @@ int checkout_entry_ca(struct cache_entry *ce, struct conv_attrs *ca,
|
|||
* no pathname to return.
|
||||
*/
|
||||
BUG("Can't remove entry to a path");
|
||||
unlink_entry(ce);
|
||||
unlink_entry(ce, state->super_prefix);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -510,10 +510,10 @@ int checkout_entry_ca(struct cache_entry *ce, struct conv_attrs *ca,
|
|||
if (!(st.st_mode & S_IFDIR))
|
||||
unlink_or_warn(ce->name);
|
||||
|
||||
return submodule_move_head(ce->name,
|
||||
return submodule_move_head(ce->name, state->super_prefix,
|
||||
NULL, oid_to_hex(&ce->oid), 0);
|
||||
} else
|
||||
return submodule_move_head(ce->name,
|
||||
return submodule_move_head(ce->name, state->super_prefix,
|
||||
"HEAD", oid_to_hex(&ce->oid),
|
||||
state->force ? SUBMODULE_MOVE_HEAD_FORCE : 0);
|
||||
}
|
||||
|
@ -560,12 +560,12 @@ int checkout_entry_ca(struct cache_entry *ce, struct conv_attrs *ca,
|
|||
return write_entry(ce, path.buf, ca, state, 0, nr_checkouts);
|
||||
}
|
||||
|
||||
void unlink_entry(const struct cache_entry *ce)
|
||||
void unlink_entry(const struct cache_entry *ce, const char *super_prefix)
|
||||
{
|
||||
const struct submodule *sub = submodule_from_ce(ce);
|
||||
if (sub) {
|
||||
/* state.force is set at the caller. */
|
||||
submodule_move_head(ce->name, "HEAD", NULL,
|
||||
submodule_move_head(ce->name, super_prefix, "HEAD", NULL,
|
||||
SUBMODULE_MOVE_HEAD_FORCE);
|
||||
}
|
||||
if (check_leading_path(ce->name, ce_namelen(ce), 1) >= 0)
|
||||
|
|
6
entry.h
6
entry.h
|
@ -8,6 +8,7 @@ struct checkout {
|
|||
struct index_state *istate;
|
||||
const char *base_dir;
|
||||
int base_dir_len;
|
||||
const char *super_prefix;
|
||||
struct delayed_checkout *delayed_checkout;
|
||||
struct checkout_metadata meta;
|
||||
unsigned force:1,
|
||||
|
@ -48,8 +49,11 @@ int finish_delayed_checkout(struct checkout *state, int show_progress);
|
|||
/*
|
||||
* Unlink the last component and schedule the leading directories for
|
||||
* removal, such that empty directories get removed.
|
||||
*
|
||||
* The "super_prefix" is either NULL, or the "--super-prefix" passed
|
||||
* down from "read-tree" et al.
|
||||
*/
|
||||
void unlink_entry(const struct cache_entry *ce);
|
||||
void unlink_entry(const struct cache_entry *ce, const char *super_prefix);
|
||||
|
||||
void *read_blob_entry(const struct cache_entry *ce, size_t *size);
|
||||
int fstat_checkout_output(int fd, const struct checkout *state, struct stat *st);
|
||||
|
|
|
@ -102,8 +102,6 @@ char *git_work_tree_cfg;
|
|||
|
||||
static char *git_namespace;
|
||||
|
||||
static char *super_prefix;
|
||||
|
||||
/*
|
||||
* Repository-local GIT_* environment variables; see cache.h for details.
|
||||
*/
|
||||
|
@ -121,7 +119,6 @@ const char * const local_repo_env[] = {
|
|||
NO_REPLACE_OBJECTS_ENVIRONMENT,
|
||||
GIT_REPLACE_REF_BASE_ENVIRONMENT,
|
||||
GIT_PREFIX_ENVIRONMENT,
|
||||
GIT_SUPER_PREFIX_ENVIRONMENT,
|
||||
GIT_SHALLOW_FILE_ENVIRONMENT,
|
||||
GIT_COMMON_DIR_ENVIRONMENT,
|
||||
NULL
|
||||
|
@ -234,16 +231,6 @@ const char *strip_namespace(const char *namespaced_ref)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
const char *get_super_prefix(void)
|
||||
{
|
||||
static int initialized;
|
||||
if (!initialized) {
|
||||
super_prefix = xstrdup_or_null(getenv(GIT_SUPER_PREFIX_ENVIRONMENT));
|
||||
initialized = 1;
|
||||
}
|
||||
return super_prefix;
|
||||
}
|
||||
|
||||
static int git_work_tree_initialized;
|
||||
|
||||
/*
|
||||
|
|
41
git.c
41
git.c
|
@ -14,9 +14,8 @@
|
|||
* RUN_SETUP for reading from the configuration file.
|
||||
*/
|
||||
#define NEED_WORK_TREE (1<<3)
|
||||
#define SUPPORT_SUPER_PREFIX (1<<4)
|
||||
#define DELAY_PAGER_CONFIG (1<<5)
|
||||
#define NO_PARSEOPT (1<<6) /* parse-options is not used */
|
||||
#define DELAY_PAGER_CONFIG (1<<4)
|
||||
#define NO_PARSEOPT (1<<5) /* parse-options is not used */
|
||||
|
||||
struct cmd_struct {
|
||||
const char *cmd;
|
||||
|
@ -29,8 +28,7 @@ const char git_usage_string[] =
|
|||
" [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n"
|
||||
" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]\n"
|
||||
" [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n"
|
||||
" [--super-prefix=<path>] [--config-env=<name>=<envvar>]\n"
|
||||
" <command> [<args>]");
|
||||
" [--config-env=<name>=<envvar>] <command> [<args>]");
|
||||
|
||||
const char git_more_info_string[] =
|
||||
N_("'git help -a' and 'git help -g' list available subcommands and some\n"
|
||||
|
@ -226,20 +224,6 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
|
|||
setenv(GIT_WORK_TREE_ENVIRONMENT, cmd, 1);
|
||||
if (envchanged)
|
||||
*envchanged = 1;
|
||||
} else if (!strcmp(cmd, "--super-prefix")) {
|
||||
if (*argc < 2) {
|
||||
fprintf(stderr, _("no prefix given for --super-prefix\n" ));
|
||||
usage(git_usage_string);
|
||||
}
|
||||
setenv(GIT_SUPER_PREFIX_ENVIRONMENT, (*argv)[1], 1);
|
||||
if (envchanged)
|
||||
*envchanged = 1;
|
||||
(*argv)++;
|
||||
(*argc)--;
|
||||
} else if (skip_prefix(cmd, "--super-prefix=", &cmd)) {
|
||||
setenv(GIT_SUPER_PREFIX_ENVIRONMENT, cmd, 1);
|
||||
if (envchanged)
|
||||
*envchanged = 1;
|
||||
} else if (!strcmp(cmd, "--bare")) {
|
||||
char *cwd = xgetcwd();
|
||||
is_bare_repository_cfg = 1;
|
||||
|
@ -449,11 +433,6 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
|
|||
trace_repo_setup(prefix);
|
||||
commit_pager_choice();
|
||||
|
||||
if (!help && get_super_prefix()) {
|
||||
if (!(p->option & SUPPORT_SUPER_PREFIX))
|
||||
die(_("%s doesn't support --super-prefix"), p->cmd);
|
||||
}
|
||||
|
||||
if (!help && p->option & NEED_WORK_TREE)
|
||||
setup_work_tree();
|
||||
|
||||
|
@ -504,7 +483,7 @@ static struct cmd_struct commands[] = {
|
|||
{ "check-ref-format", cmd_check_ref_format, NO_PARSEOPT },
|
||||
{ "checkout", cmd_checkout, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "checkout--worker", cmd_checkout__worker,
|
||||
RUN_SETUP | NEED_WORK_TREE | SUPPORT_SUPER_PREFIX },
|
||||
RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "checkout-index", cmd_checkout_index,
|
||||
RUN_SETUP | NEED_WORK_TREE},
|
||||
{ "cherry", cmd_cherry, RUN_SETUP },
|
||||
|
@ -539,7 +518,7 @@ static struct cmd_struct commands[] = {
|
|||
{ "format-patch", cmd_format_patch, RUN_SETUP },
|
||||
{ "fsck", cmd_fsck, RUN_SETUP },
|
||||
{ "fsck-objects", cmd_fsck, RUN_SETUP },
|
||||
{ "fsmonitor--daemon", cmd_fsmonitor__daemon, SUPPORT_SUPER_PREFIX | RUN_SETUP },
|
||||
{ "fsmonitor--daemon", cmd_fsmonitor__daemon, RUN_SETUP },
|
||||
{ "gc", cmd_gc, RUN_SETUP },
|
||||
{ "get-tar-commit-id", cmd_get_tar_commit_id, NO_PARSEOPT },
|
||||
{ "grep", cmd_grep, RUN_SETUP_GENTLY },
|
||||
|
@ -583,7 +562,7 @@ static struct cmd_struct commands[] = {
|
|||
{ "pull", cmd_pull, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "push", cmd_push, RUN_SETUP },
|
||||
{ "range-diff", cmd_range_diff, RUN_SETUP | USE_PAGER },
|
||||
{ "read-tree", cmd_read_tree, RUN_SETUP | SUPPORT_SUPER_PREFIX},
|
||||
{ "read-tree", cmd_read_tree, RUN_SETUP },
|
||||
{ "rebase", cmd_rebase, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "receive-pack", cmd_receive_pack },
|
||||
{ "reflog", cmd_reflog, RUN_SETUP },
|
||||
|
@ -610,7 +589,7 @@ static struct cmd_struct commands[] = {
|
|||
{ "stash", cmd_stash, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "stripspace", cmd_stripspace },
|
||||
{ "submodule--helper", cmd_submodule__helper, RUN_SETUP | SUPPORT_SUPER_PREFIX },
|
||||
{ "submodule--helper", cmd_submodule__helper, RUN_SETUP },
|
||||
{ "switch", cmd_switch, RUN_SETUP | NEED_WORK_TREE },
|
||||
{ "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
|
||||
{ "tag", cmd_tag, RUN_SETUP | DELAY_PAGER_CONFIG },
|
||||
|
@ -727,9 +706,6 @@ static void execv_dashed_external(const char **argv)
|
|||
struct child_process cmd = CHILD_PROCESS_INIT;
|
||||
int status;
|
||||
|
||||
if (get_super_prefix())
|
||||
die(_("%s doesn't support --super-prefix"), argv[0]);
|
||||
|
||||
if (use_pager == -1 && !is_builtin(argv[0]))
|
||||
use_pager = check_pager_config(argv[0]);
|
||||
commit_pager_choice();
|
||||
|
@ -799,9 +775,6 @@ static int run_argv(int *argcp, const char ***argv)
|
|||
*/
|
||||
trace2_cmd_name("_run_git_alias_");
|
||||
|
||||
if (get_super_prefix())
|
||||
die("%s doesn't support --super-prefix", **argv);
|
||||
|
||||
commit_pager_choice();
|
||||
|
||||
strvec_push(&cmd.args, "git");
|
||||
|
|
|
@ -369,6 +369,10 @@ int parse_opt_tracking_mode(const struct option *, const char *, int);
|
|||
{ OPTION_CALLBACK, 0, "abbrev", (var), N_("n"), \
|
||||
N_("use <n> digits to display object names"), \
|
||||
PARSE_OPT_OPTARG, &parse_opt_abbrev_cb, 0 }
|
||||
#define OPT__SUPER_PREFIX(var) \
|
||||
OPT_STRING_F(0, "super-prefix", (var), N_("prefix"), \
|
||||
N_("prefixed path to initial superproject"), PARSE_OPT_HIDDEN)
|
||||
|
||||
#define OPT__COLOR(var, h) \
|
||||
OPT_COLOR_FLAG(0, "color", (var), (h))
|
||||
#define OPT_COLUMN(s, l, v, h) \
|
||||
|
|
50
submodule.c
50
submodule.c
|
@ -2054,14 +2054,6 @@ void submodule_unset_core_worktree(const struct submodule *sub)
|
|||
strbuf_release(&config_path);
|
||||
}
|
||||
|
||||
static const char *get_super_prefix_or_empty(void)
|
||||
{
|
||||
const char *s = get_super_prefix();
|
||||
if (!s)
|
||||
s = "";
|
||||
return s;
|
||||
}
|
||||
|
||||
static int submodule_has_dirty_index(const struct submodule *sub)
|
||||
{
|
||||
struct child_process cp = CHILD_PROCESS_INIT;
|
||||
|
@ -2080,7 +2072,7 @@ static int submodule_has_dirty_index(const struct submodule *sub)
|
|||
return finish_command(&cp);
|
||||
}
|
||||
|
||||
static void submodule_reset_index(const char *path)
|
||||
static void submodule_reset_index(const char *path, const char *super_prefix)
|
||||
{
|
||||
struct child_process cp = CHILD_PROCESS_INIT;
|
||||
prepare_submodule_repo_env(&cp.env);
|
||||
|
@ -2089,10 +2081,10 @@ static void submodule_reset_index(const char *path)
|
|||
cp.no_stdin = 1;
|
||||
cp.dir = path;
|
||||
|
||||
strvec_pushf(&cp.args, "--super-prefix=%s%s/",
|
||||
get_super_prefix_or_empty(), path);
|
||||
/* TODO: determine if this might overwright untracked files */
|
||||
strvec_pushl(&cp.args, "read-tree", "-u", "--reset", NULL);
|
||||
strvec_pushf(&cp.args, "--super-prefix=%s%s/",
|
||||
(super_prefix ? super_prefix : ""), path);
|
||||
|
||||
strvec_push(&cp.args, empty_tree_oid_hex());
|
||||
|
||||
|
@ -2105,10 +2097,9 @@ static void submodule_reset_index(const char *path)
|
|||
* For edge cases (a submodule coming into existence or removing a submodule)
|
||||
* pass NULL for old or new respectively.
|
||||
*/
|
||||
int submodule_move_head(const char *path,
|
||||
const char *old_head,
|
||||
const char *new_head,
|
||||
unsigned flags)
|
||||
int submodule_move_head(const char *path, const char *super_prefix,
|
||||
const char *old_head, const char *new_head,
|
||||
unsigned flags)
|
||||
{
|
||||
int ret = 0;
|
||||
struct child_process cp = CHILD_PROCESS_INIT;
|
||||
|
@ -2145,7 +2136,8 @@ int submodule_move_head(const char *path,
|
|||
if (!(flags & SUBMODULE_MOVE_HEAD_DRY_RUN)) {
|
||||
if (old_head) {
|
||||
if (!submodule_uses_gitfile(path))
|
||||
absorb_git_dir_into_superproject(path);
|
||||
absorb_git_dir_into_superproject(path,
|
||||
super_prefix);
|
||||
} else {
|
||||
struct strbuf gitdir = STRBUF_INIT;
|
||||
submodule_name_to_gitdir(&gitdir, the_repository,
|
||||
|
@ -2154,7 +2146,7 @@ int submodule_move_head(const char *path,
|
|||
strbuf_release(&gitdir);
|
||||
|
||||
/* make sure the index is clean as well */
|
||||
submodule_reset_index(path);
|
||||
submodule_reset_index(path, super_prefix);
|
||||
}
|
||||
|
||||
if (old_head && (flags & SUBMODULE_MOVE_HEAD_FORCE)) {
|
||||
|
@ -2172,9 +2164,9 @@ int submodule_move_head(const char *path,
|
|||
cp.no_stdin = 1;
|
||||
cp.dir = path;
|
||||
|
||||
strvec_pushf(&cp.args, "--super-prefix=%s%s/",
|
||||
get_super_prefix_or_empty(), path);
|
||||
strvec_pushl(&cp.args, "read-tree", "--recurse-submodules", NULL);
|
||||
strvec_pushf(&cp.args, "--super-prefix=%s%s/",
|
||||
(super_prefix ? super_prefix : ""), path);
|
||||
|
||||
if (flags & SUBMODULE_MOVE_HEAD_DRY_RUN)
|
||||
strvec_push(&cp.args, "-n");
|
||||
|
@ -2274,7 +2266,8 @@ int validate_submodule_git_dir(char *git_dir, const char *submodule_name)
|
|||
* Embeds a single submodules git directory into the superprojects git dir,
|
||||
* non recursively.
|
||||
*/
|
||||
static void relocate_single_git_dir_into_superproject(const char *path)
|
||||
static void relocate_single_git_dir_into_superproject(const char *path,
|
||||
const char *super_prefix)
|
||||
{
|
||||
char *old_git_dir = NULL, *real_old_git_dir = NULL, *real_new_git_dir = NULL;
|
||||
struct strbuf new_gitdir = STRBUF_INIT;
|
||||
|
@ -2304,7 +2297,7 @@ static void relocate_single_git_dir_into_superproject(const char *path)
|
|||
real_new_git_dir = real_pathdup(new_gitdir.buf, 1);
|
||||
|
||||
fprintf(stderr, _("Migrating git directory of '%s%s' from\n'%s' to\n'%s'\n"),
|
||||
get_super_prefix_or_empty(), path,
|
||||
super_prefix ? super_prefix : "", path,
|
||||
real_old_git_dir, real_new_git_dir);
|
||||
|
||||
relocate_gitdir(path, real_old_git_dir, real_new_git_dir);
|
||||
|
@ -2315,7 +2308,8 @@ static void relocate_single_git_dir_into_superproject(const char *path)
|
|||
strbuf_release(&new_gitdir);
|
||||
}
|
||||
|
||||
static void absorb_git_dir_into_superproject_recurse(const char *path)
|
||||
static void absorb_git_dir_into_superproject_recurse(const char *path,
|
||||
const char *super_prefix)
|
||||
{
|
||||
|
||||
struct child_process cp = CHILD_PROCESS_INIT;
|
||||
|
@ -2323,10 +2317,11 @@ static void absorb_git_dir_into_superproject_recurse(const char *path)
|
|||
cp.dir = path;
|
||||
cp.git_cmd = 1;
|
||||
cp.no_stdin = 1;
|
||||
strvec_pushf(&cp.args, "--super-prefix=%s%s/",
|
||||
get_super_prefix_or_empty(), path);
|
||||
strvec_pushl(&cp.args, "submodule--helper",
|
||||
"absorbgitdirs", NULL);
|
||||
strvec_pushf(&cp.args, "--super-prefix=%s%s/", super_prefix ?
|
||||
super_prefix : "", path);
|
||||
|
||||
prepare_submodule_repo_env(&cp.env);
|
||||
if (run_command(&cp))
|
||||
die(_("could not recurse into submodule '%s'"), path);
|
||||
|
@ -2337,7 +2332,8 @@ static void absorb_git_dir_into_superproject_recurse(const char *path)
|
|||
* having its git directory within the working tree to the git dir nested
|
||||
* in its superprojects git dir under modules/.
|
||||
*/
|
||||
void absorb_git_dir_into_superproject(const char *path)
|
||||
void absorb_git_dir_into_superproject(const char *path,
|
||||
const char *super_prefix)
|
||||
{
|
||||
int err_code;
|
||||
const char *sub_git_dir;
|
||||
|
@ -2379,14 +2375,14 @@ void absorb_git_dir_into_superproject(const char *path)
|
|||
char *real_common_git_dir = real_pathdup(get_git_common_dir(), 1);
|
||||
|
||||
if (!starts_with(real_sub_git_dir, real_common_git_dir))
|
||||
relocate_single_git_dir_into_superproject(path);
|
||||
relocate_single_git_dir_into_superproject(path, super_prefix);
|
||||
|
||||
free(real_sub_git_dir);
|
||||
free(real_common_git_dir);
|
||||
}
|
||||
strbuf_release(&gitdir);
|
||||
|
||||
absorb_git_dir_into_superproject_recurse(path);
|
||||
absorb_git_dir_into_superproject_recurse(path, super_prefix);
|
||||
}
|
||||
|
||||
int get_superproject_working_tree(struct strbuf *buf)
|
||||
|
|
|
@ -150,9 +150,8 @@ int validate_submodule_git_dir(char *git_dir, const char *submodule_name);
|
|||
|
||||
#define SUBMODULE_MOVE_HEAD_DRY_RUN (1<<0)
|
||||
#define SUBMODULE_MOVE_HEAD_FORCE (1<<1)
|
||||
int submodule_move_head(const char *path,
|
||||
const char *old,
|
||||
const char *new_head,
|
||||
int submodule_move_head(const char *path, const char *super_prefix,
|
||||
const char *old_head, const char *new_head,
|
||||
unsigned flags);
|
||||
|
||||
void submodule_unset_core_worktree(const struct submodule *sub);
|
||||
|
@ -164,7 +163,8 @@ void submodule_unset_core_worktree(const struct submodule *sub);
|
|||
*/
|
||||
void prepare_submodule_repo_env(struct strvec *env);
|
||||
|
||||
void absorb_git_dir_into_superproject(const char *path);
|
||||
void absorb_git_dir_into_superproject(const char *path,
|
||||
const char *super_prefix);
|
||||
|
||||
/*
|
||||
* Return the absolute path of the working tree of the superproject, which this
|
||||
|
|
|
@ -370,7 +370,7 @@ test_expect_success 'read-tree supports the super-prefix' '
|
|||
cat <<-EOF >expect &&
|
||||
error: Updating '\''fictional/a'\'' would lose untracked files in it
|
||||
EOF
|
||||
test_must_fail git --super-prefix fictional/ read-tree -u -m "$treeH" "$treeM" 2>actual &&
|
||||
test_must_fail git read-tree --super-prefix fictional/ -u -m "$treeH" "$treeM" 2>actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
|
|
|
@ -644,6 +644,49 @@ test_expect_success 'repack does not loosen promisor objects' '
|
|||
grep "loosen_unused_packed_objects/loosened:0" trace
|
||||
'
|
||||
|
||||
test_expect_success 'lazy-fetch in submodule succeeds' '
|
||||
# setup
|
||||
test_config_global protocol.file.allow always &&
|
||||
|
||||
test_when_finished "rm -rf src-sub" &&
|
||||
git init src-sub &&
|
||||
git -C src-sub config uploadpack.allowfilter 1 &&
|
||||
git -C src-sub config uploadpack.allowanysha1inwant 1 &&
|
||||
|
||||
# This blob must be missing in the subsequent commit.
|
||||
echo foo >src-sub/file &&
|
||||
git -C src-sub add file &&
|
||||
git -C src-sub commit -m "submodule one" &&
|
||||
SUB_ONE=$(git -C src-sub rev-parse HEAD) &&
|
||||
|
||||
echo bar >src-sub/file &&
|
||||
git -C src-sub add file &&
|
||||
git -C src-sub commit -m "submodule two" &&
|
||||
SUB_TWO=$(git -C src-sub rev-parse HEAD) &&
|
||||
|
||||
test_when_finished "rm -rf src-super" &&
|
||||
git init src-super &&
|
||||
git -C src-super config uploadpack.allowfilter 1 &&
|
||||
git -C src-super config uploadpack.allowanysha1inwant 1 &&
|
||||
git -C src-super submodule add ../src-sub src-sub &&
|
||||
|
||||
git -C src-super/src-sub checkout $SUB_ONE &&
|
||||
git -C src-super add src-sub &&
|
||||
git -C src-super commit -m "superproject one" &&
|
||||
|
||||
git -C src-super/src-sub checkout $SUB_TWO &&
|
||||
git -C src-super add src-sub &&
|
||||
git -C src-super commit -m "superproject two" &&
|
||||
|
||||
# the fetch
|
||||
test_when_finished "rm -rf client" &&
|
||||
git clone --filter=blob:none --also-filter-submodules \
|
||||
--recurse-submodules "file://$(pwd)/src-super" client &&
|
||||
|
||||
# Trigger lazy-fetch from the superproject
|
||||
git -C client restore --recurse-submodules --source=HEAD^ :/
|
||||
'
|
||||
|
||||
. "$TEST_DIRECTORY"/lib-httpd.sh
|
||||
start_httpd
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ TEST_PASSES_SANITIZE_LEAK=true
|
|||
. ./test-lib.sh
|
||||
|
||||
test_expect_success 'setup a real submodule' '
|
||||
cwd="$(pwd)" &&
|
||||
git init sub1 &&
|
||||
test_commit -C sub1 first &&
|
||||
git submodule add ./sub1 &&
|
||||
|
@ -18,13 +19,21 @@ test_expect_success 'setup a real submodule' '
|
|||
'
|
||||
|
||||
test_expect_success 'absorb the git dir' '
|
||||
>expect &&
|
||||
>actual &&
|
||||
>expect.1 &&
|
||||
>expect.2 &&
|
||||
>actual.1 &&
|
||||
>actual.2 &&
|
||||
git status >expect.1 &&
|
||||
git -C sub1 rev-parse HEAD >expect.2 &&
|
||||
git submodule absorbgitdirs &&
|
||||
cat >expect <<-EOF &&
|
||||
Migrating git directory of '\''sub1'\'' from
|
||||
'\''$cwd/sub1/.git'\'' to
|
||||
'\''$cwd/.git/modules/sub1'\''
|
||||
EOF
|
||||
git submodule absorbgitdirs 2>actual &&
|
||||
test_cmp expect actual &&
|
||||
git fsck &&
|
||||
test -f sub1/.git &&
|
||||
test -d .git/modules/sub1 &&
|
||||
|
@ -37,7 +46,8 @@ test_expect_success 'absorb the git dir' '
|
|||
test_expect_success 'absorbing does not fail for deinitialized submodules' '
|
||||
test_when_finished "git submodule update --init" &&
|
||||
git submodule deinit --all &&
|
||||
git submodule absorbgitdirs &&
|
||||
git submodule absorbgitdirs 2>err &&
|
||||
test_must_be_empty err &&
|
||||
test -d .git/modules/sub1 &&
|
||||
test -d sub1 &&
|
||||
! test -e sub1/.git
|
||||
|
@ -56,7 +66,13 @@ test_expect_success 'setup nested submodule' '
|
|||
test_expect_success 'absorb the git dir in a nested submodule' '
|
||||
git status >expect.1 &&
|
||||
git -C sub1/nested rev-parse HEAD >expect.2 &&
|
||||
git submodule absorbgitdirs &&
|
||||
cat >expect <<-EOF &&
|
||||
Migrating git directory of '\''sub1/nested'\'' from
|
||||
'\''$cwd/sub1/nested/.git'\'' to
|
||||
'\''$cwd/.git/modules/sub1/modules/nested'\''
|
||||
EOF
|
||||
git submodule absorbgitdirs 2>actual &&
|
||||
test_cmp expect actual &&
|
||||
test -f sub1/nested/.git &&
|
||||
test -d .git/modules/sub1/modules/nested &&
|
||||
git status >actual.1 &&
|
||||
|
@ -87,7 +103,13 @@ test_expect_success 're-setup nested submodule' '
|
|||
test_expect_success 'absorb the git dir in a nested submodule' '
|
||||
git status >expect.1 &&
|
||||
git -C sub1/nested rev-parse HEAD >expect.2 &&
|
||||
git submodule absorbgitdirs &&
|
||||
cat >expect <<-EOF &&
|
||||
Migrating git directory of '\''sub1'\'' from
|
||||
'\''$cwd/sub1/.git'\'' to
|
||||
'\''$cwd/.git/modules/sub1'\''
|
||||
EOF
|
||||
git submodule absorbgitdirs 2>actual &&
|
||||
test_cmp expect actual &&
|
||||
test -f sub1/.git &&
|
||||
test -f sub1/nested/.git &&
|
||||
test -d .git/modules/sub1/modules/nested &&
|
||||
|
@ -97,6 +119,27 @@ test_expect_success 'absorb the git dir in a nested submodule' '
|
|||
test_cmp expect.2 actual.2
|
||||
'
|
||||
|
||||
test_expect_success 'absorb the git dir outside of primary worktree' '
|
||||
test_when_finished "rm -rf repo-bare.git" &&
|
||||
git clone --bare . repo-bare.git &&
|
||||
test_when_finished "rm -rf repo-wt" &&
|
||||
git -C repo-bare.git worktree add ../repo-wt &&
|
||||
|
||||
test_when_finished "rm -f .gitconfig" &&
|
||||
test_config_global protocol.file.allow always &&
|
||||
git -C repo-wt submodule update --init &&
|
||||
git init repo-wt/sub2 &&
|
||||
test_commit -C repo-wt/sub2 A &&
|
||||
git -C repo-wt submodule add ./sub2 sub2 &&
|
||||
cat >expect <<-EOF &&
|
||||
Migrating git directory of '\''sub2'\'' from
|
||||
'\''$cwd/repo-wt/sub2/.git'\'' to
|
||||
'\''$cwd/repo-bare.git/worktrees/repo-wt/modules/sub2'\''
|
||||
EOF
|
||||
git -C repo-wt submodule absorbgitdirs 2>actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'setup a gitlink with missing .gitmodules entry' '
|
||||
git init sub2 &&
|
||||
test_commit -C sub2 first &&
|
||||
|
@ -107,7 +150,11 @@ test_expect_success 'setup a gitlink with missing .gitmodules entry' '
|
|||
test_expect_success 'absorbing the git dir fails for incomplete submodules' '
|
||||
git status >expect.1 &&
|
||||
git -C sub2 rev-parse HEAD >expect.2 &&
|
||||
test_must_fail git submodule absorbgitdirs &&
|
||||
cat >expect <<-\EOF &&
|
||||
fatal: could not lookup name for submodule '\''sub2'\''
|
||||
EOF
|
||||
test_must_fail git submodule absorbgitdirs 2>actual &&
|
||||
test_cmp expect actual &&
|
||||
git -C sub2 fsck &&
|
||||
test -d sub2/.git &&
|
||||
git status >actual &&
|
||||
|
@ -127,8 +174,11 @@ test_expect_success 'setup a submodule with multiple worktrees' '
|
|||
'
|
||||
|
||||
test_expect_success 'absorbing fails for a submodule with multiple worktrees' '
|
||||
test_must_fail git submodule absorbgitdirs sub3 2>error &&
|
||||
test_i18ngrep "not supported" error
|
||||
cat >expect <<-\EOF &&
|
||||
fatal: could not lookup name for submodule '\''sub2'\''
|
||||
EOF
|
||||
test_must_fail git submodule absorbgitdirs 2>actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_done
|
||||
|
|
|
@ -866,27 +866,9 @@ test_expect_success 'submodule always visited' '
|
|||
# the submodule, and someone does a `git submodule absorbgitdirs`
|
||||
# in the super, Git will recursively invoke `git submodule--helper`
|
||||
# to do the work and this may try to read the index. This will
|
||||
# try to start the daemon in the submodule *and* pass (either
|
||||
# directly or via inheritance) the `--super-prefix` arg to the
|
||||
# `git fsmonitor--daemon start` command inside the submodule.
|
||||
# This causes a warning because fsmonitor--daemon does take that
|
||||
# global arg (see the table in git.c)
|
||||
#
|
||||
# This causes a warning when trying to start the daemon that is
|
||||
# somewhat confusing. It does not seem to hurt anything because
|
||||
# the fsmonitor code maps the query failure into a trivial response
|
||||
# and does the work anyway.
|
||||
#
|
||||
# It would be nice to silence the warning, however.
|
||||
# try to start the daemon in the submodule.
|
||||
|
||||
have_t2_error_event () {
|
||||
log=$1
|
||||
msg="fsmonitor--daemon doesnQt support --super-prefix" &&
|
||||
|
||||
tr '\047' Q <$1 | grep -e "$msg"
|
||||
}
|
||||
|
||||
test_expect_success "stray submodule super-prefix warning" '
|
||||
test_expect_success "submodule absorbgitdirs implicitly starts daemon" '
|
||||
test_when_finished "rm -rf super; \
|
||||
rm -rf sub; \
|
||||
rm super-sub.trace" &&
|
||||
|
@ -904,10 +886,20 @@ test_expect_success "stray submodule super-prefix warning" '
|
|||
|
||||
test_path_is_dir super/dir_1/dir_2/sub/.git &&
|
||||
|
||||
cwd="$(cd super && pwd)" &&
|
||||
cat >expect <<-EOF &&
|
||||
Migrating git directory of '\''dir_1/dir_2/sub'\'' from
|
||||
'\''$cwd/dir_1/dir_2/sub/.git'\'' to
|
||||
'\''$cwd/.git/modules/dir_1/dir_2/sub'\''
|
||||
EOF
|
||||
GIT_TRACE2_EVENT="$PWD/super-sub.trace" \
|
||||
git -C super submodule absorbgitdirs &&
|
||||
git -C super submodule absorbgitdirs >out 2>actual &&
|
||||
test_cmp expect actual &&
|
||||
test_must_be_empty out &&
|
||||
|
||||
! have_t2_error_event super-sub.trace
|
||||
# Confirm that the trace2 log contains a record of the
|
||||
# daemon starting.
|
||||
test_subcommand git fsmonitor--daemon start <super-sub.trace
|
||||
'
|
||||
|
||||
# On a case-insensitive file system, confirm that the daemon
|
||||
|
|
|
@ -70,7 +70,7 @@ static const char *unpack_plumbing_errors[NB_UNPACK_TREES_WARNING_TYPES] = {
|
|||
? ((o)->msgs[(type)]) \
|
||||
: (unpack_plumbing_errors[(type)]) )
|
||||
|
||||
static const char *super_prefixed(const char *path)
|
||||
static const char *super_prefixed(const char *path, const char *super_prefix)
|
||||
{
|
||||
/*
|
||||
* It is necessary and sufficient to have two static buffers
|
||||
|
@ -82,7 +82,6 @@ static const char *super_prefixed(const char *path)
|
|||
static unsigned idx = ARRAY_SIZE(buf) - 1;
|
||||
|
||||
if (super_prefix_len < 0) {
|
||||
const char *super_prefix = get_super_prefix();
|
||||
if (!super_prefix) {
|
||||
super_prefix_len = 0;
|
||||
} else {
|
||||
|
@ -235,7 +234,8 @@ static int add_rejected_path(struct unpack_trees_options *o,
|
|||
return -1;
|
||||
|
||||
if (!o->show_all_errors)
|
||||
return error(ERRORMSG(o, e), super_prefixed(path));
|
||||
return error(ERRORMSG(o, e), super_prefixed(path,
|
||||
o->super_prefix));
|
||||
|
||||
/*
|
||||
* Otherwise, insert in a list for future display by
|
||||
|
@ -262,7 +262,8 @@ static void display_error_msgs(struct unpack_trees_options *o)
|
|||
error_displayed = 1;
|
||||
for (i = 0; i < rejects->nr; i++)
|
||||
strbuf_addf(&path, "\t%s\n", rejects->items[i].string);
|
||||
error(ERRORMSG(o, e), super_prefixed(path.buf));
|
||||
error(ERRORMSG(o, e), super_prefixed(path.buf,
|
||||
o->super_prefix));
|
||||
strbuf_release(&path);
|
||||
}
|
||||
string_list_clear(rejects, 0);
|
||||
|
@ -289,7 +290,8 @@ static void display_warning_msgs(struct unpack_trees_options *o)
|
|||
warning_displayed = 1;
|
||||
for (i = 0; i < rejects->nr; i++)
|
||||
strbuf_addf(&path, "\t%s\n", rejects->items[i].string);
|
||||
warning(ERRORMSG(o, e), super_prefixed(path.buf));
|
||||
warning(ERRORMSG(o, e), super_prefixed(path.buf,
|
||||
o->super_prefix));
|
||||
strbuf_release(&path);
|
||||
}
|
||||
string_list_clear(rejects, 0);
|
||||
|
@ -311,7 +313,8 @@ static int check_submodule_move_head(const struct cache_entry *ce,
|
|||
if (o->reset)
|
||||
flags |= SUBMODULE_MOVE_HEAD_FORCE;
|
||||
|
||||
if (submodule_move_head(ce->name, old_id, new_id, flags))
|
||||
if (submodule_move_head(ce->name, o->super_prefix, old_id, new_id,
|
||||
flags))
|
||||
return add_rejected_path(o, ERROR_WOULD_LOSE_SUBMODULE, ce->name);
|
||||
return 0;
|
||||
}
|
||||
|
@ -414,6 +417,7 @@ static int check_updates(struct unpack_trees_options *o,
|
|||
int i, pc_workers, pc_threshold;
|
||||
|
||||
trace_performance_enter();
|
||||
state.super_prefix = o->super_prefix;
|
||||
state.force = 1;
|
||||
state.quiet = 1;
|
||||
state.refresh_cache = 1;
|
||||
|
@ -444,7 +448,7 @@ static int check_updates(struct unpack_trees_options *o,
|
|||
|
||||
if (ce->ce_flags & CE_WT_REMOVE) {
|
||||
display_progress(progress, ++cnt);
|
||||
unlink_entry(ce);
|
||||
unlink_entry(ce, o->super_prefix);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2958,8 +2962,8 @@ int bind_merge(const struct cache_entry * const *src,
|
|||
if (a && old)
|
||||
return o->quiet ? -1 :
|
||||
error(ERRORMSG(o, ERROR_BIND_OVERLAP),
|
||||
super_prefixed(a->name),
|
||||
super_prefixed(old->name));
|
||||
super_prefixed(a->name, o->super_prefix),
|
||||
super_prefixed(old->name, o->super_prefix));
|
||||
if (!a)
|
||||
return keep_entry(old, o);
|
||||
else
|
||||
|
@ -3020,7 +3024,7 @@ int stash_worktree_untracked_merge(const struct cache_entry * const *src,
|
|||
|
||||
if (worktree && untracked)
|
||||
return error(_("worktree and untracked commit have duplicate entries: %s"),
|
||||
super_prefixed(worktree->name));
|
||||
super_prefixed(worktree->name, o->super_prefix));
|
||||
|
||||
return merged_entry(worktree ? worktree : untracked, NULL, o);
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@ struct unpack_trees_options {
|
|||
skip_cache_tree_update;
|
||||
enum unpack_trees_reset_type reset;
|
||||
const char *prefix;
|
||||
const char *super_prefix;
|
||||
int cache_bottom;
|
||||
struct pathspec *pathspec;
|
||||
merge_fn_t fn;
|
||||
|
|
Загрузка…
Ссылка в новой задаче