|
14 | 14 | #include "blob.h" |
15 | 15 | #include "thread-utils.h" |
16 | 16 | #include "quote.h" |
| 17 | +#include "worktree.h" |
17 | 18 |
|
18 | 19 | static int config_fetch_recurse_submodules = RECURSE_SUBMODULES_ON_DEMAND; |
19 | 20 | static int parallel_jobs = 1; |
@@ -1237,3 +1238,105 @@ void prepare_submodule_repo_env(struct argv_array *out) |
1237 | 1238 | } |
1238 | 1239 | argv_array_push(out, "GIT_DIR=.git"); |
1239 | 1240 | } |
| 1241 | + |
| 1242 | +/* |
| 1243 | + * Embeds a single submodules git directory into the superprojects git dir, |
| 1244 | + * non recursively. |
| 1245 | + */ |
| 1246 | +static void relocate_single_git_dir_into_superproject(const char *prefix, |
| 1247 | + const char *path) |
| 1248 | +{ |
| 1249 | + char *old_git_dir = NULL, *real_old_git_dir = NULL, *real_new_git_dir = NULL; |
| 1250 | + const char *new_git_dir; |
| 1251 | + const struct submodule *sub; |
| 1252 | + |
| 1253 | + if (submodule_uses_worktrees(path)) |
| 1254 | + die(_("relocate_gitdir for submodule '%s' with " |
| 1255 | + "more than one worktree not supported"), path); |
| 1256 | + |
| 1257 | + old_git_dir = xstrfmt("%s/.git", path); |
| 1258 | + if (read_gitfile(old_git_dir)) |
| 1259 | + /* If it is an actual gitfile, it doesn't need migration. */ |
| 1260 | + return; |
| 1261 | + |
| 1262 | + real_old_git_dir = xstrdup(real_path(old_git_dir)); |
| 1263 | + |
| 1264 | + sub = submodule_from_path(null_sha1, path); |
| 1265 | + if (!sub) |
| 1266 | + die(_("could not lookup name for submodule '%s'"), path); |
| 1267 | + |
| 1268 | + new_git_dir = git_path("modules/%s", sub->name); |
| 1269 | + if (safe_create_leading_directories_const(new_git_dir) < 0) |
| 1270 | + die(_("could not create directory '%s'"), new_git_dir); |
| 1271 | + real_new_git_dir = xstrdup(real_path(new_git_dir)); |
| 1272 | + |
| 1273 | + if (!prefix) |
| 1274 | + prefix = get_super_prefix(); |
| 1275 | + |
| 1276 | + fprintf(stderr, _("Migrating git directory of '%s%s' from\n'%s' to\n'%s'\n"), |
| 1277 | + prefix ? prefix : "", path, |
| 1278 | + real_old_git_dir, real_new_git_dir); |
| 1279 | + |
| 1280 | + relocate_gitdir(path, real_old_git_dir, real_new_git_dir); |
| 1281 | + |
| 1282 | + free(old_git_dir); |
| 1283 | + free(real_old_git_dir); |
| 1284 | + free(real_new_git_dir); |
| 1285 | +} |
| 1286 | + |
| 1287 | +/* |
| 1288 | + * Migrate the git directory of the submodule given by path from |
| 1289 | + * having its git directory within the working tree to the git dir nested |
| 1290 | + * in its superprojects git dir under modules/. |
| 1291 | + */ |
| 1292 | +void absorb_git_dir_into_superproject(const char *prefix, |
| 1293 | + const char *path, |
| 1294 | + unsigned flags) |
| 1295 | +{ |
| 1296 | + const char *sub_git_dir, *v; |
| 1297 | + char *real_sub_git_dir = NULL, *real_common_git_dir = NULL; |
| 1298 | + struct strbuf gitdir = STRBUF_INIT; |
| 1299 | + |
| 1300 | + strbuf_addf(&gitdir, "%s/.git", path); |
| 1301 | + sub_git_dir = resolve_gitdir(gitdir.buf); |
| 1302 | + |
| 1303 | + /* Not populated? */ |
| 1304 | + if (!sub_git_dir) |
| 1305 | + goto out; |
| 1306 | + |
| 1307 | + /* Is it already absorbed into the superprojects git dir? */ |
| 1308 | + real_sub_git_dir = xstrdup(real_path(sub_git_dir)); |
| 1309 | + real_common_git_dir = xstrdup(real_path(get_git_common_dir())); |
| 1310 | + if (!skip_prefix(real_sub_git_dir, real_common_git_dir, &v)) |
| 1311 | + relocate_single_git_dir_into_superproject(prefix, path); |
| 1312 | + |
| 1313 | + if (flags & ABSORB_GITDIR_RECURSE_SUBMODULES) { |
| 1314 | + struct child_process cp = CHILD_PROCESS_INIT; |
| 1315 | + struct strbuf sb = STRBUF_INIT; |
| 1316 | + |
| 1317 | + if (flags & ~ABSORB_GITDIR_RECURSE_SUBMODULES) |
| 1318 | + die("BUG: we don't know how to pass the flags down?"); |
| 1319 | + |
| 1320 | + if (get_super_prefix()) |
| 1321 | + strbuf_addstr(&sb, get_super_prefix()); |
| 1322 | + strbuf_addstr(&sb, path); |
| 1323 | + strbuf_addch(&sb, '/'); |
| 1324 | + |
| 1325 | + cp.dir = path; |
| 1326 | + cp.git_cmd = 1; |
| 1327 | + cp.no_stdin = 1; |
| 1328 | + argv_array_pushl(&cp.args, "--super-prefix", sb.buf, |
| 1329 | + "submodule--helper", |
| 1330 | + "absorb-git-dirs", NULL); |
| 1331 | + prepare_submodule_repo_env(&cp.env_array); |
| 1332 | + if (run_command(&cp)) |
| 1333 | + die(_("could not recurse into submodule '%s'"), path); |
| 1334 | + |
| 1335 | + strbuf_release(&sb); |
| 1336 | + } |
| 1337 | + |
| 1338 | +out: |
| 1339 | + strbuf_release(&gitdir); |
| 1340 | + free(real_sub_git_dir); |
| 1341 | + free(real_common_git_dir); |
| 1342 | +} |
0 commit comments