#include "refs.h"
#include "run-command.h"
#include "sigchain.h"
+#include "submodule.h"
#include "refs.h"
#include "utf8.h"
#include "worktree.h"
if (!wt)
goto done;
- locked = !!is_worktree_locked(wt);
+ locked = !!worktree_lock_reason(wt);
if ((!locked && opts->force) || (locked && opts->force > 1)) {
if (delete_git_dir(wt->id))
die(_("unable to re-add worktree '%s'"), path);
struct strbuf sb_git = STRBUF_INIT, sb_repo = STRBUF_INIT;
struct strbuf sb = STRBUF_INIT;
const char *name;
- struct stat st;
struct child_process cp = CHILD_PROCESS_INIT;
struct argv_array child_env = ARGV_ARRAY_INIT;
- int counter = 0, len, ret;
+ unsigned int counter = 0;
+ int len, ret;
struct strbuf symref = STRBUF_INIT;
struct commit *commit = NULL;
int is_branch = 0;
+ struct strbuf sb_name = STRBUF_INIT;
validate_worktree_add(path, opts);
die(_("invalid reference: %s"), refname);
name = worktree_basename(path, &len);
- git_path_buf(&sb_repo, "worktrees/%.*s", (int)(path + len - name), name);
+ strbuf_add(&sb, name, path + len - name);
+ sanitize_refname_component(sb.buf, &sb_name);
+ if (!sb_name.len)
+ BUG("How come '%s' becomes empty after sanitization?", sb.buf);
+ strbuf_reset(&sb);
+ name = sb_name.buf;
+ git_path_buf(&sb_repo, "worktrees/%s", name);
len = sb_repo.len;
if (safe_create_leading_directories_const(sb_repo.buf))
die_errno(_("could not create leading directories of '%s'"),
sb_repo.buf);
- while (!stat(sb_repo.buf, &st)) {
+
+ while (mkdir(sb_repo.buf, 0777)) {
counter++;
+ if ((errno != EEXIST) || !counter /* overflow */)
+ die_errno(_("could not create directory of '%s'"),
+ sb_repo.buf);
strbuf_setlen(&sb_repo, len);
strbuf_addf(&sb_repo, "%d", counter);
}
atexit(remove_junk);
sigchain_push_common(remove_junk_on_signal);
- if (mkdir(sb_repo.buf, 0777))
- die_errno(_("could not create directory of '%s'"), sb_repo.buf);
junk_git_dir = xstrdup(sb_repo.buf);
is_junk = 1;
cp.dir = path;
cp.env = env;
cp.argv = NULL;
+ cp.trace2_hook_name = "post-checkout";
argv_array_pushl(&cp.args, absolute_path(hook),
oid_to_hex(&null_oid),
oid_to_hex(&commit->object.oid),
strbuf_release(&symref);
strbuf_release(&sb_repo);
strbuf_release(&sb_git);
+ strbuf_release(&sb_name);
return ret;
}
if (is_main_worktree(wt))
die(_("The main working tree cannot be locked or unlocked"));
- old_reason = is_worktree_locked(wt);
+ old_reason = worktree_lock_reason(wt);
if (old_reason) {
if (*old_reason)
die(_("'%s' is already locked, reason: %s"),
die(_("'%s' is not a working tree"), av[0]);
if (is_main_worktree(wt))
die(_("The main working tree cannot be locked or unlocked"));
- if (!is_worktree_locked(wt))
+ if (!worktree_lock_reason(wt))
die(_("'%s' is not locked"), av[0]);
ret = unlink_or_warn(git_common_path("worktrees/%s/locked", wt->id));
free_worktrees(worktrees);
static void validate_no_submodules(const struct worktree *wt)
{
struct index_state istate = { NULL };
+ struct strbuf path = STRBUF_INIT;
int i, found_submodules = 0;
- if (read_index_from(&istate, worktree_git_path(wt, "index"),
- get_worktree_git_dir(wt)) > 0) {
+ if (is_directory(worktree_git_path(wt, "modules"))) {
+ /*
+ * There could be false positives, e.g. the "modules"
+ * directory exists but is empty. But it's a rare case and
+ * this simpler check is probably good enough for now.
+ */
+ found_submodules = 1;
+ } else if (read_index_from(&istate, worktree_git_path(wt, "index"),
+ get_worktree_git_dir(wt)) > 0) {
for (i = 0; i < istate.cache_nr; i++) {
struct cache_entry *ce = istate.cache[i];
+ int err;
- if (S_ISGITLINK(ce->ce_mode)) {
- found_submodules = 1;
- break;
- }
+ if (!S_ISGITLINK(ce->ce_mode))
+ continue;
+
+ strbuf_reset(&path);
+ strbuf_addf(&path, "%s/%s", wt->path, ce->name);
+ if (!is_submodule_populated_gently(path.buf, &err))
+ continue;
+
+ found_submodules = 1;
+ break;
}
}
discard_index(&istate);
+ strbuf_release(&path);
if (found_submodules)
die(_("working trees containing submodules cannot be moved or removed"));
validate_no_submodules(wt);
if (force < 2)
- reason = is_worktree_locked(wt);
+ reason = worktree_lock_reason(wt);
if (reason) {
if (*reason)
die(_("cannot move a locked working tree, lock reason: %s\nuse 'move -f -f' to override or unlock first"),
if (is_main_worktree(wt))
die(_("'%s' is a main working tree"), av[0]);
if (force < 2)
- reason = is_worktree_locked(wt);
+ reason = worktree_lock_reason(wt);
if (reason) {
if (*reason)
die(_("cannot remove a locked working tree, lock reason: %s\nuse 'remove -f -f' to override or unlock first"),