From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org
Cc: "Junio C Hamano" <gitster@pobox.com>,
"Eric Sunshine" <sunshine@sunshineco.com>,
kaartic.sivaraam@gmail.com,
"Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Subject: [PATCH v2 0/7] nd/worktree-move reboot
Date: Mon, 12 Feb 2018 16:49:33 +0700 [thread overview]
Message-ID: <20180212094940.23834-1-pclouds@gmail.com> (raw)
In-Reply-To: <20180124095357.19645-1-pclouds@gmail.com>
v2 basically fixes lots of comments from Eric (many thanks!): memory
leak, typos, document updates, tests, corner case fixes.
Interdiff:
diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt
index 6f83723d9a..d322acbc67 100644
--- a/Documentation/git-worktree.txt
+++ b/Documentation/git-worktree.txt
@@ -36,10 +36,6 @@ The working tree's administrative files in the repository (see
`git worktree prune` in the main or any linked working tree to
clean up any stale administrative files.
-If you move a linked working tree, you need to manually update the
-administrative files so that they do not get pruned automatically. See
-section "DETAILS" for more information.
-
If a linked working tree is stored on a portable device or network share
which is not always mounted, you can prevent its administrative files from
being pruned by issuing the `git worktree lock` command, optionally
@@ -211,7 +207,7 @@ thumb is do not make any assumption about whether a path belongs to
$GIT_DIR or $GIT_COMMON_DIR when you need to directly access something
inside $GIT_DIR. Use `git rev-parse --git-path` to get the final path.
-If you move a linked working tree, you need to update the 'gitdir' file
+If you manually move a linked working tree, you need to update the 'gitdir' file
in the entry's directory. For example, if a linked working tree is moved
to `/newpath/test-next` and its `.git` file points to
`/path/main/.git/worktrees/test-next`, then update
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 8ce86aef0e..f77ef994c4 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -653,21 +653,19 @@ static int move_worktree(int ac, const char **av, const char *prefix)
die(_("'%s' is not a working tree"), av[0]);
if (is_main_worktree(wt))
die(_("'%s' is a main working tree"), av[0]);
-
- validate_no_submodules(wt);
-
if (is_directory(dst.buf)) {
const char *sep = find_last_dir_sep(wt->path);
if (!sep)
die(_("could not figure out destination name from '%s'"),
wt->path);
+ strbuf_trim_trailing_dir_sep(&dst);
strbuf_addstr(&dst, sep);
- if (file_exists(dst.buf))
- die(_("target '%s' already exists"), dst.buf);
- } else if (file_exists(dst.buf)) {
- die(_("target '%s' already exists"), av[1]);
}
+ if (file_exists(dst.buf))
+ die(_("target '%s' already exists"), dst.buf);
+
+ validate_no_submodules(wt);
reason = is_worktree_locked(wt);
if (reason) {
@@ -677,7 +675,7 @@ static int move_worktree(int ac, const char **av, const char *prefix)
die(_("cannot move a locked working tree"));
}
if (validate_worktree(wt, &errmsg, 0))
- die(_("validation failed, cannot move working tree:\n%s"),
+ die(_("validation failed, cannot move working tree: %s"),
errmsg.buf);
strbuf_release(&errmsg);
@@ -686,6 +684,8 @@ static int move_worktree(int ac, const char **av, const char *prefix)
update_worktree_location(wt, dst.buf);
+ strbuf_release(&dst);
+ free_worktrees(worktrees);
return 0;
}
@@ -708,6 +708,10 @@ static void check_clean_worktree(struct worktree *wt,
char buf[1];
int ret;
+ /*
+ * Until we sort this out, all submodules are "dirty" and
+ * will abort this function.
+ */
validate_no_submodules(wt);
argv_array_pushf(&child_env, "%s=%s/.git",
@@ -724,7 +728,7 @@ static void check_clean_worktree(struct worktree *wt,
cp.out = -1;
ret = start_command(&cp);
if (ret)
- die_errno(_("failed to run git-status on '%s'"),
+ die_errno(_("failed to run 'git status' on '%s'"),
original_path);
ret = xread(cp.out, buf, sizeof(buf));
if (ret)
@@ -733,7 +737,7 @@ static void check_clean_worktree(struct worktree *wt,
close(cp.out);
ret = finish_command(&cp);
if (ret)
- die_errno(_("failed to run git-status on '%s', code %d"),
+ die_errno(_("failed to run 'git status' on '%s', code %d"),
original_path, ret);
}
@@ -748,7 +752,6 @@ static int delete_git_work_tree(struct worktree *wt)
ret = -1;
}
strbuf_release(&sb);
-
return ret;
}
@@ -797,7 +800,7 @@ static int remove_worktree(int ac, const char **av, const char *prefix)
die(_("cannot remove a locked working tree"));
}
if (validate_worktree(wt, &errmsg, WT_VALIDATE_WORKTREE_MISSING_OK))
- die(_("validation failed, cannot remove working tree:\n%s"),
+ die(_("validation failed, cannot remove working tree: %s"),
errmsg.buf);
strbuf_release(&errmsg);
diff --git a/strbuf.c b/strbuf.c
index 1df674e919..46930ad027 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -95,6 +95,7 @@ void strbuf_trim(struct strbuf *sb)
strbuf_rtrim(sb);
strbuf_ltrim(sb);
}
+
void strbuf_rtrim(struct strbuf *sb)
{
while (sb->len > 0 && isspace((unsigned char)sb->buf[sb->len - 1]))
@@ -102,6 +103,13 @@ void strbuf_rtrim(struct strbuf *sb)
sb->buf[sb->len] = '\0';
}
+void strbuf_trim_trailing_dir_sep(struct strbuf *sb)
+{
+ while (sb->len > 0 && is_dir_sep((unsigned char)sb->buf[sb->len - 1]))
+ sb->len--;
+ sb->buf[sb->len] = '\0';
+}
+
void strbuf_ltrim(struct strbuf *sb)
{
char *b = sb->buf;
diff --git a/strbuf.h b/strbuf.h
index 14c8c10d66..e6cae5f439 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -179,6 +179,9 @@ extern void strbuf_trim(struct strbuf *);
extern void strbuf_rtrim(struct strbuf *);
extern void strbuf_ltrim(struct strbuf *);
+/* Strip trailing directory separators */
+extern void strbuf_trim_trailing_dir_sep(struct strbuf *);
+
/**
* Replace the contents of the strbuf with a reencoded form. Returns -1
* on error, 0 on success.
diff --git a/t/t2028-worktree-move.sh b/t/t2028-worktree-move.sh
index 459f676683..082368d8c6 100755
--- a/t/t2028-worktree-move.sh
+++ b/t/t2028-worktree-move.sh
@@ -66,21 +66,16 @@ test_expect_success 'move non-worktree' '
test_expect_success 'move locked worktree' '
git worktree lock source &&
- test_must_fail git worktree move source destination &&
- git worktree unlock source
+ test_when_finished "git worktree unlock source" &&
+ test_must_fail git worktree move source destination
'
test_expect_success 'move worktree' '
toplevel="$(pwd)" &&
git worktree move source destination &&
test_path_is_missing source &&
- git worktree list --porcelain | grep "^worktree" >actual &&
- cat <<-EOF >expected &&
- worktree $toplevel
- worktree $toplevel/destination
- worktree $toplevel/elsewhere
- EOF
- test_cmp expected actual &&
+ git worktree list --porcelain | grep "^worktree.*/destination" &&
+ ! git worktree list --porcelain | grep "^worktree.*/source" >empty &&
git -C destination log --format=%s >actual2 &&
echo init >expected2 &&
test_cmp expected2 actual2
@@ -90,23 +85,38 @@ test_expect_success 'move main worktree' '
test_must_fail git worktree move . def
'
+test_expect_success 'move worktree to another dir' '
+ toplevel="$(pwd)" &&
+ mkdir some-dir &&
+ git worktree move destination some-dir &&
+ test_path_is_missing source &&
+ git worktree list --porcelain | grep "^worktree.*/some-dir/destination" &&
+ git -C some-dir/destination log --format=%s >actual2 &&
+ echo init >expected2 &&
+ test_cmp expected2 actual2
+'
+
test_expect_success 'remove main worktree' '
test_must_fail git worktree remove .
'
+test_expect_success 'move some-dir/destination back' '
+ git worktree move some-dir/destination destination
+'
+
test_expect_success 'remove locked worktree' '
git worktree lock destination &&
- test_must_fail git worktree remove destination &&
- git worktree unlock destination
+ test_when_finished "git worktree unlock destination" &&
+ test_must_fail git worktree remove destination
'
test_expect_success 'remove worktree with dirty tracked file' '
echo dirty >>destination/init.t &&
+ test_when_finished "git -C destination checkout init.t" &&
test_must_fail git worktree remove destination
'
test_expect_success 'remove worktree with untracked file' '
- git -C destination checkout init.t &&
: >destination/untracked &&
test_must_fail git worktree remove destination
'
@@ -124,4 +134,13 @@ test_expect_success 'remove missing worktree' '
test_path_is_missing .git/worktrees/to-be-gone
'
+test_expect_success 'NOT remove missing-but-locked worktree' '
+ git worktree add gone-but-locked &&
+ git worktree lock gone-but-locked &&
+ test -d .git/worktrees/gone-but-locked &&
+ mv gone-but-locked really-gone-now &&
+ test_must_fail git worktree remove gone-but-locked &&
+ test_path_is_dir .git/worktrees/gone-but-locked
+'
+
test_done
diff --git a/worktree.c b/worktree.c
index 542196f0ad..28989cf06e 100644
--- a/worktree.c
+++ b/worktree.c
@@ -340,11 +340,10 @@ void update_worktree_location(struct worktree *wt, const char *path_)
if (is_main_worktree(wt))
die("BUG: can't relocate main worktree");
- strbuf_add_absolute_path(&path, path_);
+ strbuf_realpath(&path, path_, 1);
if (fspathcmp(wt->path, path.buf)) {
- write_file(git_common_path("worktrees/%s/gitdir",
- wt->id),
- "%s/.git", real_path(path.buf));
+ write_file(git_common_path("worktrees/%s/gitdir", wt->id),
+ "%s/.git", path.buf);
free(wt->path);
wt->path = strbuf_detach(&path, NULL);
}
next prev parent reply other threads:[~2018-02-12 9:50 UTC|newest]
Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-01-24 9:53 [PATCH 0/7] nd/worktree-move reboot Nguyễn Thái Ngọc Duy
2018-01-24 9:53 ` [PATCH 1/7] worktree.c: add validate_worktree() Nguyễn Thái Ngọc Duy
2018-01-24 9:53 ` [PATCH 2/7] worktree.c: add update_worktree_location() Nguyễn Thái Ngọc Duy
2018-02-02 8:23 ` Eric Sunshine
2018-02-02 9:35 ` Duy Nguyen
2018-01-24 9:53 ` [PATCH 3/7] worktree move: new command Nguyễn Thái Ngọc Duy
2018-02-02 9:15 ` Eric Sunshine
2018-02-02 11:23 ` Eric Sunshine
2018-02-05 13:28 ` Duy Nguyen
2018-02-06 2:13 ` Jeff King
2018-02-06 20:05 ` Martin Ågren
2018-02-12 9:56 ` Duy Nguyen
2018-02-12 22:15 ` Martin Ågren
2018-02-13 0:27 ` Duy Nguyen
2018-02-14 3:16 ` Jeff King
2018-02-14 9:07 ` Duy Nguyen
2018-02-14 17:35 ` Junio C Hamano
2018-02-14 21:56 ` [PATCH] t/known-leaky: add list of known-leaky test scripts Martin Ågren
2018-02-19 21:29 ` Jeff King
2018-02-20 20:44 ` Martin Ågren
2018-02-20 21:08 ` Jeff King
2018-02-21 16:53 ` Junio C Hamano
2018-02-21 18:25 ` Jeff King
2018-02-25 3:48 ` Kaartic Sivaraam
2018-02-26 21:22 ` Martin Ågren
2018-01-24 9:53 ` [PATCH 4/7] worktree move: accept destination as directory Nguyễn Thái Ngọc Duy
2018-02-02 9:35 ` Eric Sunshine
2018-01-24 9:53 ` [PATCH 5/7] worktree move: refuse to move worktrees with submodules Nguyễn Thái Ngọc Duy
2018-02-02 10:06 ` Eric Sunshine
2018-01-24 9:53 ` [PATCH 6/7] worktree remove: new command Nguyễn Thái Ngọc Duy
2018-02-02 11:47 ` Eric Sunshine
2018-02-12 9:26 ` Duy Nguyen
2018-01-24 9:53 ` [PATCH 7/7] worktree remove: allow it when $GIT_WORK_TREE is already gone Nguyễn Thái Ngọc Duy
2018-02-02 12:59 ` Eric Sunshine
2018-01-24 20:42 ` [PATCH 0/7] nd/worktree-move reboot Junio C Hamano
2018-02-12 9:49 ` Nguyễn Thái Ngọc Duy [this message]
2018-02-12 9:49 ` [PATCH v2 1/7] worktree.c: add validate_worktree() Nguyễn Thái Ngọc Duy
2018-02-12 9:49 ` [PATCH v2 2/7] worktree.c: add update_worktree_location() Nguyễn Thái Ngọc Duy
2018-02-12 9:49 ` [PATCH v2 3/7] worktree move: new command Nguyễn Thái Ngọc Duy
2018-02-12 9:49 ` [PATCH v2 4/7] worktree move: accept destination as directory Nguyễn Thái Ngọc Duy
2018-02-12 9:49 ` [PATCH v2 5/7] worktree move: refuse to move worktrees with submodules Nguyễn Thái Ngọc Duy
2018-02-12 9:49 ` [PATCH v2 6/7] worktree remove: new command Nguyễn Thái Ngọc Duy
2018-02-12 9:49 ` [PATCH v2 7/7] worktree remove: allow it when $GIT_WORK_TREE is already gone Nguyễn Thái Ngọc Duy
2018-03-04 5:26 ` [PATCH] t2028: fix minor error and issues in newly-added "worktree move" tests Eric Sunshine
2018-03-05 9:32 ` Duy Nguyen
2018-03-05 12:48 ` SZEDER Gábor
2018-03-05 18:37 ` Junio C Hamano
2018-03-05 18:44 ` Eric Sunshine
2018-03-04 5:36 ` [PATCH v2 0/7] nd/worktree-move reboot Eric Sunshine
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180212094940.23834-1-pclouds@gmail.com \
--to=pclouds@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=kaartic.sivaraam@gmail.com \
--cc=sunshine@sunshineco.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.