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:
commit
d4c5400865
@ -13,8 +13,7 @@ SYNOPSIS
|
|||||||
[--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
|
[--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
|
||||||
[-p|--paginate|-P|--no-pager] [--no-replace-objects] [--bare]
|
[-p|--paginate|-P|--no-pager] [--no-replace-objects] [--bare]
|
||||||
[--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
|
[--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
|
||||||
[--super-prefix=<path>] [--config-env=<name>=<envvar>]
|
[--config-env=<name>=<envvar>] <command> [<args>]
|
||||||
<command> [<args>]
|
|
||||||
|
|
||||||
DESCRIPTION
|
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
|
details. Equivalent to setting the `GIT_NAMESPACE` environment
|
||||||
variable.
|
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::
|
--bare::
|
||||||
Treat the repository as a bare repository. If GIT_DIR
|
Treat the repository as a bare repository. If GIT_DIR
|
||||||
environment is not set, it is set to the current working
|
environment is not set, it is set to the current working
|
||||||
|
@ -51,10 +51,6 @@
|
|||||||
* on bare repositories.
|
* on bare repositories.
|
||||||
* This only makes sense when `RUN_SETUP` is also set.
|
* This only makes sense when `RUN_SETUP` is also set.
|
||||||
*
|
*
|
||||||
* `SUPPORT_SUPER_PREFIX`:
|
|
||||||
*
|
|
||||||
* The built-in supports `--super-prefix`.
|
|
||||||
*
|
|
||||||
* `DELAY_PAGER_CONFIG`:
|
* `DELAY_PAGER_CONFIG`:
|
||||||
*
|
*
|
||||||
* If RUN_SETUP or RUN_SETUP_GENTLY is set, git.c normally handles
|
* 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++;
|
pos++;
|
||||||
}
|
}
|
||||||
if (!overlay_mode) {
|
if (!overlay_mode) {
|
||||||
unlink_entry(ce);
|
unlink_entry(ce, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (stage == 2)
|
if (stage == 2)
|
||||||
|
@ -114,6 +114,7 @@ int cmd_read_tree(int argc, const char **argv, const char *cmd_prefix)
|
|||||||
int prefix_set = 0;
|
int prefix_set = 0;
|
||||||
struct lock_file lock_file = LOCK_INIT;
|
struct lock_file lock_file = LOCK_INIT;
|
||||||
const struct option read_tree_options[] = {
|
const struct option read_tree_options[] = {
|
||||||
|
OPT__SUPER_PREFIX(&opts.super_prefix),
|
||||||
OPT_CALLBACK_F(0, "index-output", NULL, N_("file"),
|
OPT_CALLBACK_F(0, "index-output", NULL, N_("file"),
|
||||||
N_("write resulting index to <file>"),
|
N_("write resulting index to <file>"),
|
||||||
PARSE_OPT_NONEG, index_output_cb),
|
PARSE_OPT_NONEG, index_output_cb),
|
||||||
|
@ -86,7 +86,7 @@ static void submodules_absorb_gitdir_if_needed(void)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!submodule_uses_gitfile(name))
|
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. */
|
/* 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) {
|
if (prefix && super_prefix) {
|
||||||
BUG("cannot have prefix '%s' and superprefix '%s'",
|
BUG("cannot have prefix '%s' and superprefix '%s'",
|
||||||
prefix, super_prefix);
|
prefix, super_prefix);
|
||||||
@ -279,6 +278,7 @@ struct foreach_cb {
|
|||||||
int argc;
|
int argc;
|
||||||
const char **argv;
|
const char **argv;
|
||||||
const char *prefix;
|
const char *prefix;
|
||||||
|
const char *super_prefix;
|
||||||
int quiet;
|
int quiet;
|
||||||
int recursive;
|
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;
|
struct child_process cp = CHILD_PROCESS_INIT;
|
||||||
char *displaypath;
|
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);
|
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;
|
cpr.dir = path;
|
||||||
prepare_submodule_repo_env(&cpr.env);
|
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",
|
strvec_pushl(&cpr.args, "submodule--helper", "foreach", "--recursive",
|
||||||
NULL);
|
NULL);
|
||||||
|
strvec_pushl(&cpr.args, "--super-prefix", NULL);
|
||||||
|
strvec_pushf(&cpr.args, "%s/", displaypath);
|
||||||
|
|
||||||
if (info->quiet)
|
if (info->quiet)
|
||||||
strvec_push(&cpr.args, "--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 pathspec pathspec = { 0 };
|
||||||
struct module_list list = MODULE_LIST_INIT;
|
struct module_list list = MODULE_LIST_INIT;
|
||||||
struct option module_foreach_options[] = {
|
struct option module_foreach_options[] = {
|
||||||
|
OPT__SUPER_PREFIX(&info.super_prefix),
|
||||||
OPT__QUIET(&info.quiet, N_("suppress output of entering each submodule command")),
|
OPT__QUIET(&info.quiet, N_("suppress output of entering each submodule command")),
|
||||||
OPT_BOOL(0, "recursive", &info.recursive,
|
OPT_BOOL(0, "recursive", &info.recursive,
|
||||||
N_("recurse into nested submodules")),
|
N_("recurse into nested submodules")),
|
||||||
@ -435,11 +437,13 @@ static int starts_with_dot_dot_slash(const char *const path)
|
|||||||
|
|
||||||
struct init_cb {
|
struct init_cb {
|
||||||
const char *prefix;
|
const char *prefix;
|
||||||
|
const char *super_prefix;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
};
|
};
|
||||||
#define INIT_CB_INIT { 0 }
|
#define INIT_CB_INIT { 0 }
|
||||||
|
|
||||||
static void init_submodule(const char *path, const char *prefix,
|
static void init_submodule(const char *path, const char *prefix,
|
||||||
|
const char *super_prefix,
|
||||||
unsigned int flags)
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
const struct submodule *sub;
|
const struct submodule *sub;
|
||||||
@ -447,7 +451,7 @@ static void init_submodule(const char *path, const char *prefix,
|
|||||||
const char *upd;
|
const char *upd;
|
||||||
char *url = NULL, *displaypath;
|
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);
|
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;
|
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)
|
static int module_init(int argc, const char **argv, const char *prefix)
|
||||||
@ -570,6 +575,7 @@ cleanup:
|
|||||||
|
|
||||||
struct status_cb {
|
struct status_cb {
|
||||||
const char *prefix;
|
const char *prefix;
|
||||||
|
const char *super_prefix;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
};
|
};
|
||||||
#define STATUS_CB_INIT { 0 }
|
#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,
|
static void status_submodule(const char *path, const struct object_id *ce_oid,
|
||||||
unsigned int ce_flags, const char *prefix,
|
unsigned int ce_flags, const char *prefix,
|
||||||
unsigned int flags)
|
const char *super_prefix, unsigned int flags)
|
||||||
{
|
{
|
||||||
char *displaypath;
|
char *displaypath;
|
||||||
struct strvec diff_files_args = STRVEC_INIT;
|
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'"),
|
die(_("no submodule mapping found in .gitmodules for path '%s'"),
|
||||||
path);
|
path);
|
||||||
|
|
||||||
displaypath = get_submodule_displaypath(path, prefix);
|
displaypath = get_submodule_displaypath(path, prefix, super_prefix);
|
||||||
|
|
||||||
if ((CE_STAGEMASK & ce_flags) >> CE_STAGESHIFT) {
|
if ((CE_STAGEMASK & ce_flags) >> CE_STAGESHIFT) {
|
||||||
print_status(flags, 'U', path, null_oid(), displaypath);
|
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;
|
cpr.dir = path;
|
||||||
prepare_submodule_repo_env(&cpr.env);
|
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",
|
strvec_pushl(&cpr.args, "submodule--helper", "status",
|
||||||
"--recursive", NULL);
|
"--recursive", NULL);
|
||||||
|
strvec_push(&cpr.args, "--super-prefix");
|
||||||
|
strvec_pushf(&cpr.args, "%s/", displaypath);
|
||||||
|
|
||||||
if (flags & OPT_CACHED)
|
if (flags & OPT_CACHED)
|
||||||
strvec_push(&cpr.args, "--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;
|
struct status_cb *info = cb_data;
|
||||||
|
|
||||||
status_submodule(list_item->name, &list_item->oid, list_item->ce_flags,
|
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)
|
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;
|
struct module_list list = MODULE_LIST_INIT;
|
||||||
int quiet = 0;
|
int quiet = 0;
|
||||||
struct option module_status_options[] = {
|
struct option module_status_options[] = {
|
||||||
|
OPT__SUPER_PREFIX(&info.super_prefix),
|
||||||
OPT__QUIET(&quiet, N_("suppress submodule status output")),
|
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, "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),
|
OPT_BIT(0, "recursive", &info.flags, N_("recurse into nested submodules"), OPT_RECURSIVE),
|
||||||
@ -787,6 +794,7 @@ struct summary_cb {
|
|||||||
int argc;
|
int argc;
|
||||||
const char **argv;
|
const char **argv;
|
||||||
const char *prefix;
|
const char *prefix;
|
||||||
|
const char *super_prefix;
|
||||||
unsigned int cached: 1;
|
unsigned int cached: 1;
|
||||||
unsigned int for_status: 1;
|
unsigned int for_status: 1;
|
||||||
unsigned int files: 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);
|
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) {
|
if (!missing_src && !missing_dst) {
|
||||||
struct child_process cp_rev_list = CHILD_PROCESS_INIT;
|
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 {
|
struct sync_cb {
|
||||||
const char *prefix;
|
const char *prefix;
|
||||||
|
const char *super_prefix;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
};
|
};
|
||||||
#define SYNC_CB_INIT { 0 }
|
#define SYNC_CB_INIT { 0 }
|
||||||
|
|
||||||
static void sync_submodule(const char *path, const char *prefix,
|
static void sync_submodule(const char *path, const char *prefix,
|
||||||
unsigned int flags)
|
const char *super_prefix, unsigned int flags)
|
||||||
{
|
{
|
||||||
const struct submodule *sub;
|
const struct submodule *sub;
|
||||||
char *remote_key = NULL;
|
char *remote_key = NULL;
|
||||||
@ -1239,7 +1249,7 @@ static void sync_submodule(const char *path, const char *prefix,
|
|||||||
super_config_url = xstrdup("");
|
super_config_url = xstrdup("");
|
||||||
}
|
}
|
||||||
|
|
||||||
displaypath = get_submodule_displaypath(path, prefix);
|
displaypath = get_submodule_displaypath(path, prefix, super_prefix);
|
||||||
|
|
||||||
if (!(flags & OPT_QUIET))
|
if (!(flags & OPT_QUIET))
|
||||||
printf(_("Synchronizing submodule url for '%s'\n"),
|
printf(_("Synchronizing submodule url for '%s'\n"),
|
||||||
@ -1276,10 +1286,11 @@ static void sync_submodule(const char *path, const char *prefix,
|
|||||||
cpr.dir = path;
|
cpr.dir = path;
|
||||||
prepare_submodule_repo_env(&cpr.env);
|
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",
|
strvec_pushl(&cpr.args, "submodule--helper", "sync",
|
||||||
"--recursive", NULL);
|
"--recursive", NULL);
|
||||||
|
strvec_push(&cpr.args, "--super-prefix");
|
||||||
|
strvec_pushf(&cpr.args, "%s/", displaypath);
|
||||||
|
|
||||||
|
|
||||||
if (flags & OPT_QUIET)
|
if (flags & OPT_QUIET)
|
||||||
strvec_push(&cpr.args, "--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;
|
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)
|
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 quiet = 0;
|
||||||
int recursive = 0;
|
int recursive = 0;
|
||||||
struct option module_sync_options[] = {
|
struct option module_sync_options[] = {
|
||||||
|
OPT__SUPER_PREFIX(&info.super_prefix),
|
||||||
OPT__QUIET(&quiet, N_("suppress output of synchronizing submodule url")),
|
OPT__QUIET(&quiet, N_("suppress output of synchronizing submodule url")),
|
||||||
OPT_BOOL(0, "recursive", &recursive,
|
OPT_BOOL(0, "recursive", &recursive,
|
||||||
N_("recurse into nested submodules")),
|
N_("recurse into nested submodules")),
|
||||||
@ -1365,7 +1378,7 @@ static void deinit_submodule(const char *path, const char *prefix,
|
|||||||
if (!sub || !sub->name)
|
if (!sub || !sub->name)
|
||||||
goto cleanup;
|
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) */
|
/* remove the submodule work tree (unless the user already did it) */
|
||||||
if (is_directory(path)) {
|
if (is_directory(path)) {
|
||||||
@ -1379,7 +1392,7 @@ static void deinit_submodule(const char *path, const char *prefix,
|
|||||||
".git file by using absorbgitdirs."),
|
".git file by using absorbgitdirs."),
|
||||||
displaypath);
|
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 {
|
struct update_data {
|
||||||
const char *prefix;
|
const char *prefix;
|
||||||
|
const char *super_prefix;
|
||||||
char *displaypath;
|
char *displaypath;
|
||||||
enum submodule_update_type update_default;
|
enum submodule_update_type update_default;
|
||||||
struct object_id suboid;
|
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;
|
enum submodule_update_type update_type;
|
||||||
char *key;
|
char *key;
|
||||||
const struct update_data *ud = suc->update_data;
|
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;
|
struct strbuf sb = STRBUF_INIT;
|
||||||
int needs_cloning = 0;
|
int needs_cloning = 0;
|
||||||
int need_free_url = 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;
|
enum submodule_update_type update_type = update_data->update_default;
|
||||||
|
|
||||||
|
strvec_pushl(args, "submodule--helper", "update", "--recursive", NULL);
|
||||||
if (update_data->displaypath) {
|
if (update_data->displaypath) {
|
||||||
strvec_push(args, "--super-prefix");
|
strvec_push(args, "--super-prefix");
|
||||||
strvec_pushf(args, "%s/", update_data->displaypath);
|
strvec_pushf(args, "%s/", update_data->displaypath);
|
||||||
}
|
}
|
||||||
strvec_pushl(args, "submodule--helper", "update", "--recursive", NULL);
|
|
||||||
strvec_pushf(args, "--jobs=%d", update_data->max_jobs);
|
strvec_pushf(args, "--jobs=%d", update_data->max_jobs);
|
||||||
if (update_data->quiet)
|
if (update_data->quiet)
|
||||||
strvec_push(args, "--quiet");
|
strvec_push(args, "--quiet");
|
||||||
@ -2608,7 +2623,8 @@ static int update_submodules(struct update_data *update_data)
|
|||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
update_data->displaypath = get_submodule_displaypath(
|
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);
|
code = update_submodule(update_data);
|
||||||
FREE_AND_NULL(update_data->displaypath);
|
FREE_AND_NULL(update_data->displaypath);
|
||||||
fail:
|
fail:
|
||||||
@ -2634,6 +2650,7 @@ static int module_update(int argc, const char **argv, const char *prefix)
|
|||||||
LIST_OBJECTS_FILTER_INIT;
|
LIST_OBJECTS_FILTER_INIT;
|
||||||
int ret;
|
int ret;
|
||||||
struct option module_update_options[] = {
|
struct option module_update_options[] = {
|
||||||
|
OPT__SUPER_PREFIX(&opt.super_prefix),
|
||||||
OPT__FORCE(&opt.force, N_("force checkout updates"), 0),
|
OPT__FORCE(&opt.force, N_("force checkout updates"), 0),
|
||||||
OPT_BOOL(0, "init", &opt.init,
|
OPT_BOOL(0, "init", &opt.init,
|
||||||
N_("initialize uninitialized submodules before update")),
|
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);
|
module_list_active(&list);
|
||||||
|
|
||||||
info.prefix = opt.prefix;
|
info.prefix = opt.prefix;
|
||||||
|
info.super_prefix = opt.super_prefix;
|
||||||
if (opt.quiet)
|
if (opt.quiet)
|
||||||
info.flags |= 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;
|
int i;
|
||||||
struct pathspec pathspec = { 0 };
|
struct pathspec pathspec = { 0 };
|
||||||
struct module_list list = MODULE_LIST_INIT;
|
struct module_list list = MODULE_LIST_INIT;
|
||||||
|
const char *super_prefix = NULL;
|
||||||
struct option embed_gitdir_options[] = {
|
struct option embed_gitdir_options[] = {
|
||||||
|
OPT__SUPER_PREFIX(&super_prefix),
|
||||||
OPT_END()
|
OPT_END()
|
||||||
};
|
};
|
||||||
const char *const git_submodule_helper_usage[] = {
|
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;
|
goto cleanup;
|
||||||
|
|
||||||
for (i = 0; i < list.nr; i++)
|
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;
|
ret = 0;
|
||||||
cleanup:
|
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_name = xstrfmt("submodule.%s.url", path);
|
||||||
|
|
||||||
config_set_in_gitmodules_file_gently(config_name, newurl);
|
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);
|
free(config_name);
|
||||||
|
|
||||||
@ -3353,8 +3374,6 @@ cleanup:
|
|||||||
|
|
||||||
int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
|
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;
|
parse_opt_subcommand_fn *fn = NULL;
|
||||||
const char *const usage[] = {
|
const char *const usage[] = {
|
||||||
N_("git submodule--helper <command>"),
|
N_("git submodule--helper <command>"),
|
||||||
@ -3378,18 +3397,6 @@ int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
|
|||||||
OPT_END()
|
OPT_END()
|
||||||
};
|
};
|
||||||
argc = parse_options(argc, argv, prefix, options, usage, 0);
|
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);
|
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_NAMESPACE_ENVIRONMENT "GIT_NAMESPACE"
|
||||||
#define GIT_WORK_TREE_ENVIRONMENT "GIT_WORK_TREE"
|
#define GIT_WORK_TREE_ENVIRONMENT "GIT_WORK_TREE"
|
||||||
#define GIT_PREFIX_ENVIRONMENT "GIT_PREFIX"
|
#define GIT_PREFIX_ENVIRONMENT "GIT_PREFIX"
|
||||||
#define GIT_SUPER_PREFIX_ENVIRONMENT "GIT_INTERNAL_SUPER_PREFIX"
|
|
||||||
#define DEFAULT_GIT_DIR_ENVIRONMENT ".git"
|
#define DEFAULT_GIT_DIR_ENVIRONMENT ".git"
|
||||||
#define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
|
#define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
|
||||||
#define INDEX_ENVIRONMENT "GIT_INDEX_FILE"
|
#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);
|
int get_common_dir(struct strbuf *sb, const char *gitdir);
|
||||||
const char *get_git_namespace(void);
|
const char *get_git_namespace(void);
|
||||||
const char *strip_namespace(const char *namespaced_ref);
|
const char *strip_namespace(const char *namespaced_ref);
|
||||||
const char *get_super_prefix(void);
|
|
||||||
const char *get_git_work_tree(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);
|
return error("cannot create submodule directory %s", path);
|
||||||
sub = submodule_from_ce(ce);
|
sub = submodule_from_ce(ce);
|
||||||
if (sub)
|
if (sub)
|
||||||
return submodule_move_head(ce->name,
|
return submodule_move_head(ce->name, state->super_prefix,
|
||||||
NULL, oid_to_hex(&ce->oid),
|
NULL, oid_to_hex(&ce->oid),
|
||||||
state->force ? SUBMODULE_MOVE_HEAD_FORCE : 0);
|
state->force ? SUBMODULE_MOVE_HEAD_FORCE : 0);
|
||||||
break;
|
break;
|
||||||
@ -476,7 +476,7 @@ int checkout_entry_ca(struct cache_entry *ce, struct conv_attrs *ca,
|
|||||||
* no pathname to return.
|
* no pathname to return.
|
||||||
*/
|
*/
|
||||||
BUG("Can't remove entry to a path");
|
BUG("Can't remove entry to a path");
|
||||||
unlink_entry(ce);
|
unlink_entry(ce, state->super_prefix);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -510,10 +510,10 @@ int checkout_entry_ca(struct cache_entry *ce, struct conv_attrs *ca,
|
|||||||
if (!(st.st_mode & S_IFDIR))
|
if (!(st.st_mode & S_IFDIR))
|
||||||
unlink_or_warn(ce->name);
|
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);
|
NULL, oid_to_hex(&ce->oid), 0);
|
||||||
} else
|
} else
|
||||||
return submodule_move_head(ce->name,
|
return submodule_move_head(ce->name, state->super_prefix,
|
||||||
"HEAD", oid_to_hex(&ce->oid),
|
"HEAD", oid_to_hex(&ce->oid),
|
||||||
state->force ? SUBMODULE_MOVE_HEAD_FORCE : 0);
|
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);
|
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);
|
const struct submodule *sub = submodule_from_ce(ce);
|
||||||
if (sub) {
|
if (sub) {
|
||||||
/* state.force is set at the caller. */
|
/* 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);
|
SUBMODULE_MOVE_HEAD_FORCE);
|
||||||
}
|
}
|
||||||
if (check_leading_path(ce->name, ce_namelen(ce), 1) >= 0)
|
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;
|
struct index_state *istate;
|
||||||
const char *base_dir;
|
const char *base_dir;
|
||||||
int base_dir_len;
|
int base_dir_len;
|
||||||
|
const char *super_prefix;
|
||||||
struct delayed_checkout *delayed_checkout;
|
struct delayed_checkout *delayed_checkout;
|
||||||
struct checkout_metadata meta;
|
struct checkout_metadata meta;
|
||||||
unsigned force:1,
|
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
|
* Unlink the last component and schedule the leading directories for
|
||||||
* removal, such that empty directories get removed.
|
* 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);
|
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);
|
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 *git_namespace;
|
||||||
|
|
||||||
static char *super_prefix;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Repository-local GIT_* environment variables; see cache.h for details.
|
* Repository-local GIT_* environment variables; see cache.h for details.
|
||||||
*/
|
*/
|
||||||
@ -121,7 +119,6 @@ const char * const local_repo_env[] = {
|
|||||||
NO_REPLACE_OBJECTS_ENVIRONMENT,
|
NO_REPLACE_OBJECTS_ENVIRONMENT,
|
||||||
GIT_REPLACE_REF_BASE_ENVIRONMENT,
|
GIT_REPLACE_REF_BASE_ENVIRONMENT,
|
||||||
GIT_PREFIX_ENVIRONMENT,
|
GIT_PREFIX_ENVIRONMENT,
|
||||||
GIT_SUPER_PREFIX_ENVIRONMENT,
|
|
||||||
GIT_SHALLOW_FILE_ENVIRONMENT,
|
GIT_SHALLOW_FILE_ENVIRONMENT,
|
||||||
GIT_COMMON_DIR_ENVIRONMENT,
|
GIT_COMMON_DIR_ENVIRONMENT,
|
||||||
NULL
|
NULL
|
||||||
@ -234,16 +231,6 @@ const char *strip_namespace(const char *namespaced_ref)
|
|||||||
return NULL;
|
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;
|
static int git_work_tree_initialized;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
41
git.c
41
git.c
@ -14,9 +14,8 @@
|
|||||||
* RUN_SETUP for reading from the configuration file.
|
* RUN_SETUP for reading from the configuration file.
|
||||||
*/
|
*/
|
||||||
#define NEED_WORK_TREE (1<<3)
|
#define NEED_WORK_TREE (1<<3)
|
||||||
#define SUPPORT_SUPER_PREFIX (1<<4)
|
#define DELAY_PAGER_CONFIG (1<<4)
|
||||||
#define DELAY_PAGER_CONFIG (1<<5)
|
#define NO_PARSEOPT (1<<5) /* parse-options is not used */
|
||||||
#define NO_PARSEOPT (1<<6) /* parse-options is not used */
|
|
||||||
|
|
||||||
struct cmd_struct {
|
struct cmd_struct {
|
||||||
const char *cmd;
|
const char *cmd;
|
||||||
@ -29,8 +28,7 @@ const char git_usage_string[] =
|
|||||||
" [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n"
|
" [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n"
|
||||||
" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]\n"
|
" [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]\n"
|
||||||
" [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n"
|
" [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n"
|
||||||
" [--super-prefix=<path>] [--config-env=<name>=<envvar>]\n"
|
" [--config-env=<name>=<envvar>] <command> [<args>]");
|
||||||
" <command> [<args>]");
|
|
||||||
|
|
||||||
const char git_more_info_string[] =
|
const char git_more_info_string[] =
|
||||||
N_("'git help -a' and 'git help -g' list available subcommands and some\n"
|
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);
|
setenv(GIT_WORK_TREE_ENVIRONMENT, cmd, 1);
|
||||||
if (envchanged)
|
if (envchanged)
|
||||||
*envchanged = 1;
|
*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")) {
|
} else if (!strcmp(cmd, "--bare")) {
|
||||||
char *cwd = xgetcwd();
|
char *cwd = xgetcwd();
|
||||||
is_bare_repository_cfg = 1;
|
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);
|
trace_repo_setup(prefix);
|
||||||
commit_pager_choice();
|
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)
|
if (!help && p->option & NEED_WORK_TREE)
|
||||||
setup_work_tree();
|
setup_work_tree();
|
||||||
|
|
||||||
@ -504,7 +483,7 @@ static struct cmd_struct commands[] = {
|
|||||||
{ "check-ref-format", cmd_check_ref_format, NO_PARSEOPT },
|
{ "check-ref-format", cmd_check_ref_format, NO_PARSEOPT },
|
||||||
{ "checkout", cmd_checkout, RUN_SETUP | NEED_WORK_TREE },
|
{ "checkout", cmd_checkout, RUN_SETUP | NEED_WORK_TREE },
|
||||||
{ "checkout--worker", cmd_checkout__worker,
|
{ "checkout--worker", cmd_checkout__worker,
|
||||||
RUN_SETUP | NEED_WORK_TREE | SUPPORT_SUPER_PREFIX },
|
RUN_SETUP | NEED_WORK_TREE },
|
||||||
{ "checkout-index", cmd_checkout_index,
|
{ "checkout-index", cmd_checkout_index,
|
||||||
RUN_SETUP | NEED_WORK_TREE},
|
RUN_SETUP | NEED_WORK_TREE},
|
||||||
{ "cherry", cmd_cherry, RUN_SETUP },
|
{ "cherry", cmd_cherry, RUN_SETUP },
|
||||||
@ -539,7 +518,7 @@ static struct cmd_struct commands[] = {
|
|||||||
{ "format-patch", cmd_format_patch, RUN_SETUP },
|
{ "format-patch", cmd_format_patch, RUN_SETUP },
|
||||||
{ "fsck", cmd_fsck, RUN_SETUP },
|
{ "fsck", cmd_fsck, RUN_SETUP },
|
||||||
{ "fsck-objects", 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 },
|
{ "gc", cmd_gc, RUN_SETUP },
|
||||||
{ "get-tar-commit-id", cmd_get_tar_commit_id, NO_PARSEOPT },
|
{ "get-tar-commit-id", cmd_get_tar_commit_id, NO_PARSEOPT },
|
||||||
{ "grep", cmd_grep, RUN_SETUP_GENTLY },
|
{ "grep", cmd_grep, RUN_SETUP_GENTLY },
|
||||||
@ -583,7 +562,7 @@ static struct cmd_struct commands[] = {
|
|||||||
{ "pull", cmd_pull, RUN_SETUP | NEED_WORK_TREE },
|
{ "pull", cmd_pull, RUN_SETUP | NEED_WORK_TREE },
|
||||||
{ "push", cmd_push, RUN_SETUP },
|
{ "push", cmd_push, RUN_SETUP },
|
||||||
{ "range-diff", cmd_range_diff, RUN_SETUP | USE_PAGER },
|
{ "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 },
|
{ "rebase", cmd_rebase, RUN_SETUP | NEED_WORK_TREE },
|
||||||
{ "receive-pack", cmd_receive_pack },
|
{ "receive-pack", cmd_receive_pack },
|
||||||
{ "reflog", cmd_reflog, RUN_SETUP },
|
{ "reflog", cmd_reflog, RUN_SETUP },
|
||||||
@ -610,7 +589,7 @@ static struct cmd_struct commands[] = {
|
|||||||
{ "stash", cmd_stash, RUN_SETUP | NEED_WORK_TREE },
|
{ "stash", cmd_stash, RUN_SETUP | NEED_WORK_TREE },
|
||||||
{ "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
|
{ "status", cmd_status, RUN_SETUP | NEED_WORK_TREE },
|
||||||
{ "stripspace", cmd_stripspace },
|
{ "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 },
|
{ "switch", cmd_switch, RUN_SETUP | NEED_WORK_TREE },
|
||||||
{ "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
|
{ "symbolic-ref", cmd_symbolic_ref, RUN_SETUP },
|
||||||
{ "tag", cmd_tag, RUN_SETUP | DELAY_PAGER_CONFIG },
|
{ "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;
|
struct child_process cmd = CHILD_PROCESS_INIT;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
if (get_super_prefix())
|
|
||||||
die(_("%s doesn't support --super-prefix"), argv[0]);
|
|
||||||
|
|
||||||
if (use_pager == -1 && !is_builtin(argv[0]))
|
if (use_pager == -1 && !is_builtin(argv[0]))
|
||||||
use_pager = check_pager_config(argv[0]);
|
use_pager = check_pager_config(argv[0]);
|
||||||
commit_pager_choice();
|
commit_pager_choice();
|
||||||
@ -799,9 +775,6 @@ static int run_argv(int *argcp, const char ***argv)
|
|||||||
*/
|
*/
|
||||||
trace2_cmd_name("_run_git_alias_");
|
trace2_cmd_name("_run_git_alias_");
|
||||||
|
|
||||||
if (get_super_prefix())
|
|
||||||
die("%s doesn't support --super-prefix", **argv);
|
|
||||||
|
|
||||||
commit_pager_choice();
|
commit_pager_choice();
|
||||||
|
|
||||||
strvec_push(&cmd.args, "git");
|
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"), \
|
{ OPTION_CALLBACK, 0, "abbrev", (var), N_("n"), \
|
||||||
N_("use <n> digits to display object names"), \
|
N_("use <n> digits to display object names"), \
|
||||||
PARSE_OPT_OPTARG, &parse_opt_abbrev_cb, 0 }
|
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) \
|
#define OPT__COLOR(var, h) \
|
||||||
OPT_COLOR_FLAG(0, "color", (var), (h))
|
OPT_COLOR_FLAG(0, "color", (var), (h))
|
||||||
#define OPT_COLUMN(s, l, v, 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);
|
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)
|
static int submodule_has_dirty_index(const struct submodule *sub)
|
||||||
{
|
{
|
||||||
struct child_process cp = CHILD_PROCESS_INIT;
|
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);
|
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;
|
struct child_process cp = CHILD_PROCESS_INIT;
|
||||||
prepare_submodule_repo_env(&cp.env);
|
prepare_submodule_repo_env(&cp.env);
|
||||||
@ -2089,10 +2081,10 @@ static void submodule_reset_index(const char *path)
|
|||||||
cp.no_stdin = 1;
|
cp.no_stdin = 1;
|
||||||
cp.dir = path;
|
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 */
|
/* TODO: determine if this might overwright untracked files */
|
||||||
strvec_pushl(&cp.args, "read-tree", "-u", "--reset", NULL);
|
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());
|
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)
|
* For edge cases (a submodule coming into existence or removing a submodule)
|
||||||
* pass NULL for old or new respectively.
|
* pass NULL for old or new respectively.
|
||||||
*/
|
*/
|
||||||
int submodule_move_head(const char *path,
|
int submodule_move_head(const char *path, const char *super_prefix,
|
||||||
const char *old_head,
|
const char *old_head, const char *new_head,
|
||||||
const char *new_head,
|
unsigned flags)
|
||||||
unsigned flags)
|
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct child_process cp = CHILD_PROCESS_INIT;
|
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 (!(flags & SUBMODULE_MOVE_HEAD_DRY_RUN)) {
|
||||||
if (old_head) {
|
if (old_head) {
|
||||||
if (!submodule_uses_gitfile(path))
|
if (!submodule_uses_gitfile(path))
|
||||||
absorb_git_dir_into_superproject(path);
|
absorb_git_dir_into_superproject(path,
|
||||||
|
super_prefix);
|
||||||
} else {
|
} else {
|
||||||
struct strbuf gitdir = STRBUF_INIT;
|
struct strbuf gitdir = STRBUF_INIT;
|
||||||
submodule_name_to_gitdir(&gitdir, the_repository,
|
submodule_name_to_gitdir(&gitdir, the_repository,
|
||||||
@ -2154,7 +2146,7 @@ int submodule_move_head(const char *path,
|
|||||||
strbuf_release(&gitdir);
|
strbuf_release(&gitdir);
|
||||||
|
|
||||||
/* make sure the index is clean as well */
|
/* 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)) {
|
if (old_head && (flags & SUBMODULE_MOVE_HEAD_FORCE)) {
|
||||||
@ -2172,9 +2164,9 @@ int submodule_move_head(const char *path,
|
|||||||
cp.no_stdin = 1;
|
cp.no_stdin = 1;
|
||||||
cp.dir = path;
|
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_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)
|
if (flags & SUBMODULE_MOVE_HEAD_DRY_RUN)
|
||||||
strvec_push(&cp.args, "-n");
|
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,
|
* Embeds a single submodules git directory into the superprojects git dir,
|
||||||
* non recursively.
|
* 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;
|
char *old_git_dir = NULL, *real_old_git_dir = NULL, *real_new_git_dir = NULL;
|
||||||
struct strbuf new_gitdir = STRBUF_INIT;
|
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);
|
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"),
|
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);
|
real_old_git_dir, real_new_git_dir);
|
||||||
|
|
||||||
relocate_gitdir(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);
|
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;
|
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.dir = path;
|
||||||
cp.git_cmd = 1;
|
cp.git_cmd = 1;
|
||||||
cp.no_stdin = 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",
|
strvec_pushl(&cp.args, "submodule--helper",
|
||||||
"absorbgitdirs", NULL);
|
"absorbgitdirs", NULL);
|
||||||
|
strvec_pushf(&cp.args, "--super-prefix=%s%s/", super_prefix ?
|
||||||
|
super_prefix : "", path);
|
||||||
|
|
||||||
prepare_submodule_repo_env(&cp.env);
|
prepare_submodule_repo_env(&cp.env);
|
||||||
if (run_command(&cp))
|
if (run_command(&cp))
|
||||||
die(_("could not recurse into submodule '%s'"), path);
|
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
|
* having its git directory within the working tree to the git dir nested
|
||||||
* in its superprojects git dir under modules/.
|
* 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;
|
int err_code;
|
||||||
const char *sub_git_dir;
|
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);
|
char *real_common_git_dir = real_pathdup(get_git_common_dir(), 1);
|
||||||
|
|
||||||
if (!starts_with(real_sub_git_dir, real_common_git_dir))
|
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_sub_git_dir);
|
||||||
free(real_common_git_dir);
|
free(real_common_git_dir);
|
||||||
}
|
}
|
||||||
strbuf_release(&gitdir);
|
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)
|
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_DRY_RUN (1<<0)
|
||||||
#define SUBMODULE_MOVE_HEAD_FORCE (1<<1)
|
#define SUBMODULE_MOVE_HEAD_FORCE (1<<1)
|
||||||
int submodule_move_head(const char *path,
|
int submodule_move_head(const char *path, const char *super_prefix,
|
||||||
const char *old,
|
const char *old_head, const char *new_head,
|
||||||
const char *new_head,
|
|
||||||
unsigned flags);
|
unsigned flags);
|
||||||
|
|
||||||
void submodule_unset_core_worktree(const struct submodule *sub);
|
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 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
|
* 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 &&
|
cat <<-EOF >expect &&
|
||||||
error: Updating '\''fictional/a'\'' would lose untracked files in it
|
error: Updating '\''fictional/a'\'' would lose untracked files in it
|
||||||
EOF
|
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
|
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
|
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
|
. "$TEST_DIRECTORY"/lib-httpd.sh
|
||||||
start_httpd
|
start_httpd
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ TEST_PASSES_SANITIZE_LEAK=true
|
|||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
|
|
||||||
test_expect_success 'setup a real submodule' '
|
test_expect_success 'setup a real submodule' '
|
||||||
|
cwd="$(pwd)" &&
|
||||||
git init sub1 &&
|
git init sub1 &&
|
||||||
test_commit -C sub1 first &&
|
test_commit -C sub1 first &&
|
||||||
git submodule add ./sub1 &&
|
git submodule add ./sub1 &&
|
||||||
@ -18,13 +19,21 @@ test_expect_success 'setup a real submodule' '
|
|||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'absorb the git dir' '
|
test_expect_success 'absorb the git dir' '
|
||||||
|
>expect &&
|
||||||
|
>actual &&
|
||||||
>expect.1 &&
|
>expect.1 &&
|
||||||
>expect.2 &&
|
>expect.2 &&
|
||||||
>actual.1 &&
|
>actual.1 &&
|
||||||
>actual.2 &&
|
>actual.2 &&
|
||||||
git status >expect.1 &&
|
git status >expect.1 &&
|
||||||
git -C sub1 rev-parse HEAD >expect.2 &&
|
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 &&
|
git fsck &&
|
||||||
test -f sub1/.git &&
|
test -f sub1/.git &&
|
||||||
test -d .git/modules/sub1 &&
|
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_expect_success 'absorbing does not fail for deinitialized submodules' '
|
||||||
test_when_finished "git submodule update --init" &&
|
test_when_finished "git submodule update --init" &&
|
||||||
git submodule deinit --all &&
|
git submodule deinit --all &&
|
||||||
git submodule absorbgitdirs &&
|
git submodule absorbgitdirs 2>err &&
|
||||||
|
test_must_be_empty err &&
|
||||||
test -d .git/modules/sub1 &&
|
test -d .git/modules/sub1 &&
|
||||||
test -d sub1 &&
|
test -d sub1 &&
|
||||||
! test -e sub1/.git
|
! 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' '
|
test_expect_success 'absorb the git dir in a nested submodule' '
|
||||||
git status >expect.1 &&
|
git status >expect.1 &&
|
||||||
git -C sub1/nested rev-parse HEAD >expect.2 &&
|
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 -f sub1/nested/.git &&
|
||||||
test -d .git/modules/sub1/modules/nested &&
|
test -d .git/modules/sub1/modules/nested &&
|
||||||
git status >actual.1 &&
|
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' '
|
test_expect_success 'absorb the git dir in a nested submodule' '
|
||||||
git status >expect.1 &&
|
git status >expect.1 &&
|
||||||
git -C sub1/nested rev-parse HEAD >expect.2 &&
|
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/.git &&
|
||||||
test -f sub1/nested/.git &&
|
test -f sub1/nested/.git &&
|
||||||
test -d .git/modules/sub1/modules/nested &&
|
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_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' '
|
test_expect_success 'setup a gitlink with missing .gitmodules entry' '
|
||||||
git init sub2 &&
|
git init sub2 &&
|
||||||
test_commit -C sub2 first &&
|
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' '
|
test_expect_success 'absorbing the git dir fails for incomplete submodules' '
|
||||||
git status >expect.1 &&
|
git status >expect.1 &&
|
||||||
git -C sub2 rev-parse HEAD >expect.2 &&
|
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 &&
|
git -C sub2 fsck &&
|
||||||
test -d sub2/.git &&
|
test -d sub2/.git &&
|
||||||
git status >actual &&
|
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_expect_success 'absorbing fails for a submodule with multiple worktrees' '
|
||||||
test_must_fail git submodule absorbgitdirs sub3 2>error &&
|
cat >expect <<-\EOF &&
|
||||||
test_i18ngrep "not supported" error
|
fatal: could not lookup name for submodule '\''sub2'\''
|
||||||
|
EOF
|
||||||
|
test_must_fail git submodule absorbgitdirs 2>actual &&
|
||||||
|
test_cmp expect actual
|
||||||
'
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
@ -866,27 +866,9 @@ test_expect_success 'submodule always visited' '
|
|||||||
# the submodule, and someone does a `git submodule absorbgitdirs`
|
# the submodule, and someone does a `git submodule absorbgitdirs`
|
||||||
# in the super, Git will recursively invoke `git submodule--helper`
|
# in the super, Git will recursively invoke `git submodule--helper`
|
||||||
# to do the work and this may try to read the index. This will
|
# 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
|
# try to start the daemon in the submodule.
|
||||||
# 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.
|
|
||||||
|
|
||||||
have_t2_error_event () {
|
test_expect_success "submodule absorbgitdirs implicitly starts daemon" '
|
||||||
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_when_finished "rm -rf super; \
|
test_when_finished "rm -rf super; \
|
||||||
rm -rf sub; \
|
rm -rf sub; \
|
||||||
rm super-sub.trace" &&
|
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 &&
|
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_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
|
# 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)]) \
|
? ((o)->msgs[(type)]) \
|
||||||
: (unpack_plumbing_errors[(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
|
* 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;
|
static unsigned idx = ARRAY_SIZE(buf) - 1;
|
||||||
|
|
||||||
if (super_prefix_len < 0) {
|
if (super_prefix_len < 0) {
|
||||||
const char *super_prefix = get_super_prefix();
|
|
||||||
if (!super_prefix) {
|
if (!super_prefix) {
|
||||||
super_prefix_len = 0;
|
super_prefix_len = 0;
|
||||||
} else {
|
} else {
|
||||||
@ -235,7 +234,8 @@ static int add_rejected_path(struct unpack_trees_options *o,
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (!o->show_all_errors)
|
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
|
* 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;
|
error_displayed = 1;
|
||||||
for (i = 0; i < rejects->nr; i++)
|
for (i = 0; i < rejects->nr; i++)
|
||||||
strbuf_addf(&path, "\t%s\n", rejects->items[i].string);
|
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);
|
strbuf_release(&path);
|
||||||
}
|
}
|
||||||
string_list_clear(rejects, 0);
|
string_list_clear(rejects, 0);
|
||||||
@ -289,7 +290,8 @@ static void display_warning_msgs(struct unpack_trees_options *o)
|
|||||||
warning_displayed = 1;
|
warning_displayed = 1;
|
||||||
for (i = 0; i < rejects->nr; i++)
|
for (i = 0; i < rejects->nr; i++)
|
||||||
strbuf_addf(&path, "\t%s\n", rejects->items[i].string);
|
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);
|
strbuf_release(&path);
|
||||||
}
|
}
|
||||||
string_list_clear(rejects, 0);
|
string_list_clear(rejects, 0);
|
||||||
@ -311,7 +313,8 @@ static int check_submodule_move_head(const struct cache_entry *ce,
|
|||||||
if (o->reset)
|
if (o->reset)
|
||||||
flags |= SUBMODULE_MOVE_HEAD_FORCE;
|
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 add_rejected_path(o, ERROR_WOULD_LOSE_SUBMODULE, ce->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -414,6 +417,7 @@ static int check_updates(struct unpack_trees_options *o,
|
|||||||
int i, pc_workers, pc_threshold;
|
int i, pc_workers, pc_threshold;
|
||||||
|
|
||||||
trace_performance_enter();
|
trace_performance_enter();
|
||||||
|
state.super_prefix = o->super_prefix;
|
||||||
state.force = 1;
|
state.force = 1;
|
||||||
state.quiet = 1;
|
state.quiet = 1;
|
||||||
state.refresh_cache = 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) {
|
if (ce->ce_flags & CE_WT_REMOVE) {
|
||||||
display_progress(progress, ++cnt);
|
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)
|
if (a && old)
|
||||||
return o->quiet ? -1 :
|
return o->quiet ? -1 :
|
||||||
error(ERRORMSG(o, ERROR_BIND_OVERLAP),
|
error(ERRORMSG(o, ERROR_BIND_OVERLAP),
|
||||||
super_prefixed(a->name),
|
super_prefixed(a->name, o->super_prefix),
|
||||||
super_prefixed(old->name));
|
super_prefixed(old->name, o->super_prefix));
|
||||||
if (!a)
|
if (!a)
|
||||||
return keep_entry(old, o);
|
return keep_entry(old, o);
|
||||||
else
|
else
|
||||||
@ -3020,7 +3024,7 @@ int stash_worktree_untracked_merge(const struct cache_entry * const *src,
|
|||||||
|
|
||||||
if (worktree && untracked)
|
if (worktree && untracked)
|
||||||
return error(_("worktree and untracked commit have duplicate entries: %s"),
|
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);
|
return merged_entry(worktree ? worktree : untracked, NULL, o);
|
||||||
}
|
}
|
||||||
|
@ -75,6 +75,7 @@ struct unpack_trees_options {
|
|||||||
skip_cache_tree_update;
|
skip_cache_tree_update;
|
||||||
enum unpack_trees_reset_type reset;
|
enum unpack_trees_reset_type reset;
|
||||||
const char *prefix;
|
const char *prefix;
|
||||||
|
const char *super_prefix;
|
||||||
int cache_bottom;
|
int cache_bottom;
|
||||||
struct pathspec *pathspec;
|
struct pathspec *pathspec;
|
||||||
merge_fn_t fn;
|
merge_fn_t fn;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user