possible to checkout same branch in different worktree

classic Classic list List threaded Threaded
117 messages Options
123456
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v3 05/13] worktree.c: mark current worktree

Duy Nguyen
On Fri, May 06, 2016 at 05:21:05PM +0700, Duy Nguyen wrote:

> > Similarly, it looks like 'path' doesn't need to be a strbuf at all
> > since the result of absolute_path() should remain valid long enough
> > for fspathcmp(). It could just be:
> >
> >     const char *path = absolute_path(...);
> >     wt->is_current = !fspathcmp(git_dir, path);
> >
> > But these are very minor; probably not worth a re-roll.
>
> Yeah. I think the use of strbuf is influenced by the code in
> get_worktrees(). But since this code is now in a separate function, it
> makes little sense to go with the strbuf hammer. If there's no big
> change in this series, I'll just do this as a cleanup step in my next
> series, worktree-move.

On second thought, why hold patches back, lengthen the worktree-move
series and make it a pain to review? I moved a few patches from
worktree-move into this series and I took two other out to create
nd/error-errno. So I'm going to take more patches out of it, creating
two bite-sized series, to be sent shortly.

The first one is purely cleanup (ok, 1/7 is not exactly cleanup)

  [1/7] completion: support git-worktree
  [2/7] worktree.c: rewrite mark_current_worktree() to avoid
  [3/7] git-worktree.txt: keep subcommand listing in alphabetical
  [4/7] worktree.c: use is_dot_or_dotdot()
  [5/7] worktree.c: add clear_worktree()
  [6/7] worktree: avoid 0{40}, too many zeroes, hard to read
  [7/7] worktree: simplify prefixing paths

And the second one adds "git worktree lock" and "git worktree
unlock". This series is built on top of the first one, it needs 1/7.

  [1/5] worktree.c: add find_worktree_by_path()
  [2/5] worktree.c: add is_main_worktree()
  [3/5] worktree.c: add is_worktree_locked()
  [4/5] worktree: add "lock" command
  [5/5] worktree: add "unlock" command

After this, worktree-move becomes ~10 patch series.
--
Duy
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

[PATCH 1/7] completion: support git-worktree

Duy Nguyen
Signed-off-by: Nguyễn Thái Ngọc Duy <[hidden email]>
---
 contrib/completion/git-completion.bash | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 3402475..d3ac391 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -2595,6 +2595,29 @@ _git_whatchanged ()
  _git_log
 }
 
+_git_worktree ()
+{
+ local subcommands="add list prune"
+ local subcommand="$(__git_find_on_cmdline "$subcommands")"
+ if [ -z "$subcommand" ]; then
+ __gitcomp "$subcommands"
+ else
+ case "$subcommand,$cur" in
+ add,--*)
+ __gitcomp "--detach --force"
+ ;;
+ list,--*)
+ __gitcomp "--porcelain"
+ ;;
+ prune,--*)
+ __gitcomp "--dry-run --expire --verbose"
+ ;;
+ *)
+ ;;
+ esac
+ fi
+}
+
 __git_main ()
 {
  local i c=1 command __git_dir
--
2.8.2.524.g6ff3d78

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

[PATCH 2/7] worktree.c: rewrite mark_current_worktree() to avoid strbuf

Duy Nguyen
strbuf is a bit overkill for this function. What we need is call
absolute_path() twice and make sure the second call does not destroy the
result of the first. One buffer allocation is enough.

Signed-off-by: Nguyễn Thái Ngọc Duy <[hidden email]>
---
 worktree.c | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/worktree.c b/worktree.c
index 4817d60..6a11611 100644
--- a/worktree.c
+++ b/worktree.c
@@ -153,21 +153,19 @@ done:
 
 static void mark_current_worktree(struct worktree **worktrees)
 {
- struct strbuf git_dir = STRBUF_INIT;
- struct strbuf path = STRBUF_INIT;
+ char *git_dir = xstrdup(absolute_path(get_git_dir()));
  int i;
 
- strbuf_addstr(&git_dir, absolute_path(get_git_dir()));
  for (i = 0; worktrees[i]; i++) {
  struct worktree *wt = worktrees[i];
- strbuf_addstr(&path, absolute_path(get_worktree_git_dir(wt)));
- wt->is_current = !fspathcmp(git_dir.buf, path.buf);
- strbuf_reset(&path);
- if (wt->is_current)
+ const char *wt_git_dir = get_worktree_git_dir(wt);
+
+ if (!fspathcmp(git_dir, absolute_path(wt_git_dir))) {
+ wt->is_current = 1;
  break;
+ }
  }
- strbuf_release(&git_dir);
- strbuf_release(&path);
+ free(git_dir);
 }
 
 struct worktree **get_worktrees(void)
--
2.8.2.524.g6ff3d78

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

[PATCH 3/7] git-worktree.txt: keep subcommand listing in alphabetical order

Duy Nguyen
In reply to this post by Duy Nguyen
This is probably not the best order. But it makes it no-brainer to know
where to insert new commands. At some point we might want to reorder at
least the synopsis part again, grouping commonly use subcommands together.

Signed-off-by: Nguyễn Thái Ngọc Duy <[hidden email]>
---
 Documentation/git-worktree.txt | 10 +++++-----
 builtin/worktree.c             |  2 +-
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt
index c622345..27feff6 100644
--- a/Documentation/git-worktree.txt
+++ b/Documentation/git-worktree.txt
@@ -10,8 +10,8 @@ SYNOPSIS
 --------
 [verse]
 'git worktree add' [-f] [--detach] [--checkout] [-b <new-branch>] <path> [<branch>]
-'git worktree prune' [-n] [-v] [--expire <expire>]
 'git worktree list' [--porcelain]
+'git worktree prune' [-n] [-v] [--expire <expire>]
 
 DESCRIPTION
 -----------
@@ -54,10 +54,6 @@ If `<branch>` is omitted and neither `-b` nor `-B` nor `--detached` used,
 then, as a convenience, a new branch based at HEAD is created automatically,
 as if `-b $(basename <path>)` was specified.
 
-prune::
-
-Prune working tree information in $GIT_DIR/worktrees.
-
 list::
 
 List details of each worktree.  The main worktree is listed first, followed by
@@ -65,6 +61,10 @@ each of the linked worktrees.  The output details include if the worktree is
 bare, the revision currently checked out, and the branch currently checked out
 (or 'detached HEAD' if none).
 
+prune::
+
+Prune working tree information in $GIT_DIR/worktrees.
+
 OPTIONS
 -------
 
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 12c0af7..bf80111 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -13,8 +13,8 @@
 
 static const char * const worktree_usage[] = {
  N_("git worktree add [<options>] <path> [<branch>]"),
- N_("git worktree prune [<options>]"),
  N_("git worktree list [<options>]"),
+ N_("git worktree prune [<options>]"),
  NULL
 };
 
--
2.8.2.524.g6ff3d78

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

[PATCH 4/7] worktree.c: use is_dot_or_dotdot()

Duy Nguyen
In reply to this post by Duy Nguyen
Signed-off-by: Nguyễn Thái Ngọc Duy <[hidden email]>
---
 builtin/worktree.c | 2 +-
 worktree.c         | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/builtin/worktree.c b/builtin/worktree.c
index bf80111..aaee0e2 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -95,7 +95,7 @@ static void prune_worktrees(void)
  if (!dir)
  return;
  while ((d = readdir(dir)) != NULL) {
- if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
+ if (is_dot_or_dotdot(d->d_name))
  continue;
  strbuf_reset(&reason);
  if (!prune_worktree(d->d_name, &reason))
diff --git a/worktree.c b/worktree.c
index 6a11611..f4a4f38 100644
--- a/worktree.c
+++ b/worktree.c
@@ -187,7 +187,7 @@ struct worktree **get_worktrees(void)
  if (dir) {
  while ((d = readdir(dir)) != NULL) {
  struct worktree *linked = NULL;
- if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
+ if (is_dot_or_dotdot(d->d_name))
  continue;
 
  if ((linked = get_linked_worktree(d->d_name))) {
--
2.8.2.524.g6ff3d78

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

[PATCH 5/7] worktree.c: add clear_worktree()

Duy Nguyen
In reply to this post by Duy Nguyen
The use case is keep some worktree and discard the rest of the worktree
list.

Signed-off-by: Nguyễn Thái Ngọc Duy <[hidden email]>
---
 worktree.c | 14 +++++++++++---
 worktree.h |  5 +++++
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/worktree.c b/worktree.c
index f4a4f38..335c58f 100644
--- a/worktree.c
+++ b/worktree.c
@@ -5,14 +5,22 @@
 #include "dir.h"
 #include "wt-status.h"
 
+void clear_worktree(struct worktree *wt)
+{
+ if (!wt)
+ return;
+ free(wt->path);
+ free(wt->id);
+ free(wt->head_ref);
+ memset(wt, 0, sizeof(*wt));
+}
+
 void free_worktrees(struct worktree **worktrees)
 {
  int i = 0;
 
  for (i = 0; worktrees[i]; i++) {
- free(worktrees[i]->path);
- free(worktrees[i]->id);
- free(worktrees[i]->head_ref);
+ clear_worktree(worktrees[i]);
  free(worktrees[i]);
  }
  free (worktrees);
diff --git a/worktree.h b/worktree.h
index 1394909..7430a4e 100644
--- a/worktree.h
+++ b/worktree.h
@@ -29,6 +29,11 @@ extern struct worktree **get_worktrees(void);
  */
 extern const char *get_worktree_git_dir(const struct worktree *wt);
 
+/*
+ * Free up the memory for worktree
+ */
+extern void clear_worktree(struct worktree *);
+
 /*
  * Free up the memory for worktree(s)
  */
--
2.8.2.524.g6ff3d78

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

[PATCH 6/7] worktree: avoid 0{40}, too many zeroes, hard to read

Duy Nguyen
In reply to this post by Duy Nguyen
Signed-off-by: Nguyễn Thái Ngọc Duy <[hidden email]>
---
 builtin/worktree.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/builtin/worktree.c b/builtin/worktree.c
index aaee0e2..b53f802 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -262,7 +262,7 @@ static int add_worktree(const char *path, const char *refname,
  */
  strbuf_reset(&sb);
  strbuf_addf(&sb, "%s/HEAD", sb_repo.buf);
- write_file(sb.buf, "0000000000000000000000000000000000000000");
+ write_file(sb.buf, sha1_to_hex(null_sha1));
  strbuf_reset(&sb);
  strbuf_addf(&sb, "%s/commondir", sb_repo.buf);
  write_file(sb.buf, "../..");
--
2.8.2.524.g6ff3d78

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

[PATCH 7/7] worktree: simplify prefixing paths

Duy Nguyen
In reply to this post by Duy Nguyen
Signed-off-by: Nguyễn Thái Ngọc Duy <[hidden email]>
---
 builtin/worktree.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/builtin/worktree.c b/builtin/worktree.c
index b53f802..f9dac37 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -337,7 +337,7 @@ static int add(int ac, const char **av, const char *prefix)
  if (ac < 1 || ac > 2)
  usage_with_options(worktree_usage, options);
 
- path = prefix ? prefix_filename(prefix, strlen(prefix), av[0]) : av[0];
+ path = prefix_filename(prefix, strlen(prefix), av[0]);
  branch = ac < 2 ? "HEAD" : av[1];
 
  opts.force_new_branch = !!new_branch_force;
@@ -467,6 +467,8 @@ int cmd_worktree(int ac, const char **av, const char *prefix)
 
  if (ac < 2)
  usage_with_options(worktree_usage, options);
+ if (!prefix)
+ prefix = "";
  if (!strcmp(av[1], "add"))
  return add(ac - 1, av + 1, prefix);
  if (!strcmp(av[1], "prune"))
--
2.8.2.524.g6ff3d78

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

[PATCH 1/5] worktree.c: add find_worktree_by_path()

Duy Nguyen
In reply to this post by Duy Nguyen
So far we haven't needed to identify an existing worktree from command
line. Future commands such as lock or move will need it. There are of
course other options for identifying a worktree, for example by branch
or even by internal id. They may be added later if proved useful.

Signed-off-by: Nguyễn Thái Ngọc Duy <[hidden email]>
---
 worktree.c | 16 ++++++++++++++++
 worktree.h |  6 ++++++
 2 files changed, 22 insertions(+)

diff --git a/worktree.c b/worktree.c
index 335c58f..a6d1ad1 100644
--- a/worktree.c
+++ b/worktree.c
@@ -222,6 +222,22 @@ const char *get_worktree_git_dir(const struct worktree *wt)
  return git_common_path("worktrees/%s", wt->id);
 }
 
+struct worktree *find_worktree_by_path(struct worktree **list,
+       const char *path_)
+{
+ char *path = xstrdup(real_path(path_));
+ struct worktree *wt = NULL;
+
+ while (*list) {
+ wt = *list++;
+ if (!fspathcmp(path, real_path(wt->path)))
+ break;
+ wt = NULL;
+ }
+ free(path);
+ return wt;
+}
+
 int is_worktree_being_rebased(const struct worktree *wt,
       const char *target)
 {
diff --git a/worktree.h b/worktree.h
index 7430a4e..7775d1b 100644
--- a/worktree.h
+++ b/worktree.h
@@ -29,6 +29,12 @@ extern struct worktree **get_worktrees(void);
  */
 extern const char *get_worktree_git_dir(const struct worktree *wt);
 
+/*
+ * Search a worktree by its path. Paths are normalized internally.
+ */
+extern struct worktree *find_worktree_by_path(struct worktree **list,
+      const char *path_);
+
 /*
  * Free up the memory for worktree
  */
--
2.8.2.524.g6ff3d78

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

[PATCH 2/5] worktree.c: add is_main_worktree()

Duy Nguyen
Main worktree _is_ different. You can lock a linked worktree but not the
main one, for example. Provide an API for checking that.

Signed-off-by: Nguyễn Thái Ngọc Duy <[hidden email]>
---
 worktree.c | 5 +++++
 worktree.h | 5 +++++
 2 files changed, 10 insertions(+)

diff --git a/worktree.c b/worktree.c
index a6d1ad1..37fea3d 100644
--- a/worktree.c
+++ b/worktree.c
@@ -238,6 +238,11 @@ struct worktree *find_worktree_by_path(struct worktree **list,
  return wt;
 }
 
+int is_main_worktree(const struct worktree *wt)
+{
+ return wt && !wt->id;
+}
+
 int is_worktree_being_rebased(const struct worktree *wt,
       const char *target)
 {
diff --git a/worktree.h b/worktree.h
index 7775d1b..77a9e09 100644
--- a/worktree.h
+++ b/worktree.h
@@ -35,6 +35,11 @@ extern const char *get_worktree_git_dir(const struct worktree *wt);
 extern struct worktree *find_worktree_by_path(struct worktree **list,
       const char *path_);
 
+/*
+ * Return true if the given worktree is the main one.
+ */
+extern int is_main_worktree(const struct worktree *wt);
+
 /*
  * Free up the memory for worktree
  */
--
2.8.2.524.g6ff3d78

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

[PATCH 3/5] worktree.c: add is_worktree_locked()

Duy Nguyen
In reply to this post by Duy Nguyen
This provides an API for checking if a worktree is locked. We need to
check this to avoid double locking a worktree, or try to unlock one when
it's not even locked.

Signed-off-by: Nguyễn Thái Ngọc Duy <[hidden email]>
---
 worktree.c | 18 ++++++++++++++++++
 worktree.h |  6 ++++++
 2 files changed, 24 insertions(+)

diff --git a/worktree.c b/worktree.c
index 37fea3d..6805deb 100644
--- a/worktree.c
+++ b/worktree.c
@@ -243,6 +243,24 @@ int is_main_worktree(const struct worktree *wt)
  return wt && !wt->id;
 }
 
+const char *is_worktree_locked(const struct worktree *wt)
+{
+ static struct strbuf sb = STRBUF_INIT;
+
+ if (!file_exists(git_common_path("worktrees/%s/locked", wt->id)))
+ return NULL;
+
+ strbuf_reset(&sb);
+ if (strbuf_read_file(&sb,
+     git_common_path("worktrees/%s/locked", wt->id),
+     0) < 0)
+ die_errno(_("failed to read '%s'"),
+  git_common_path("worktrees/%s/locked", wt->id));
+
+ strbuf_rtrim(&sb);
+ return sb.buf;
+}
+
 int is_worktree_being_rebased(const struct worktree *wt,
       const char *target)
 {
diff --git a/worktree.h b/worktree.h
index 77a9e09..12906be 100644
--- a/worktree.h
+++ b/worktree.h
@@ -40,6 +40,12 @@ extern struct worktree *find_worktree_by_path(struct worktree **list,
  */
 extern int is_main_worktree(const struct worktree *wt);
 
+/*
+ * Return the reason string if the given worktree is locked. Return
+ * NULL otherwise.
+ */
+extern const char *is_worktree_locked(const struct worktree *wt);
+
 /*
  * Free up the memory for worktree
  */
--
2.8.2.524.g6ff3d78

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

[PATCH 4/5] worktree: add "lock" command

Duy Nguyen
In reply to this post by Duy Nguyen
Signed-off-by: Nguyễn Thái Ngọc Duy <[hidden email]>
---
 Documentation/git-worktree.txt         | 12 ++++++++--
 builtin/worktree.c                     | 41 ++++++++++++++++++++++++++++++++++
 contrib/completion/git-completion.bash |  5 ++++-
 t/t2028-worktree-move.sh (new +x)      | 34 ++++++++++++++++++++++++++++
 4 files changed, 89 insertions(+), 3 deletions(-)
 create mode 100755 t/t2028-worktree-move.sh

diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt
index 27feff6..74583c1 100644
--- a/Documentation/git-worktree.txt
+++ b/Documentation/git-worktree.txt
@@ -11,6 +11,7 @@ SYNOPSIS
 [verse]
 'git worktree add' [-f] [--detach] [--checkout] [-b <new-branch>] <path> [<branch>]
 'git worktree list' [--porcelain]
+'git worktree lock' [--reason <string>] <path>
 'git worktree prune' [-n] [-v] [--expire <expire>]
 
 DESCRIPTION
@@ -61,6 +62,12 @@ each of the linked worktrees.  The output details include if the worktree is
 bare, the revision currently checked out, and the branch currently checked out
 (or 'detached HEAD' if none).
 
+lock::
+
+When a worktree is locked, it cannot be pruned, moved or deleted. For
+example, if the worktree is on portable device that is not available
+when "git worktree <command>" is executed.
+
 prune::
 
 Prune working tree information in $GIT_DIR/worktrees.
@@ -110,6 +117,9 @@ OPTIONS
 --expire <time>::
  With `prune`, only expire unused working trees older than <time>.
 
+--reason <string>:
+ An explanation why the worktree is locked.
+
 DETAILS
 -------
 Each linked working tree has a private sub-directory in the repository's
@@ -226,8 +236,6 @@ performed manually, such as:
 - `remove` to remove a linked working tree and its administrative files (and
   warn if the working tree is dirty)
 - `mv` to move or rename a working tree and update its administrative files
-- `lock` to prevent automatic pruning of administrative files (for instance,
-  for a working tree on a portable device)
 
 GIT
 ---
diff --git a/builtin/worktree.c b/builtin/worktree.c
index f9dac37..51fa103 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -14,6 +14,7 @@
 static const char * const worktree_usage[] = {
  N_("git worktree add [<options>] <path> [<branch>]"),
  N_("git worktree list [<options>]"),
+ N_("git worktree lock [<options>] <path>"),
  N_("git worktree prune [<options>]"),
  NULL
 };
@@ -459,6 +460,44 @@ static int list(int ac, const char **av, const char *prefix)
  return 0;
 }
 
+static int lock_worktree(int ac, const char **av, const char *prefix)
+{
+ const char *reason = "", *old_reason;
+ struct option options[] = {
+ OPT_STRING(0, "reason", &reason, N_("string"),
+   N_("reason for locking")),
+ OPT_END()
+ };
+ struct worktree **worktrees, *wt;
+ struct strbuf dst = STRBUF_INIT;
+
+ ac = parse_options(ac, av, prefix, options, worktree_usage, 0);
+ if (ac != 1)
+ usage_with_options(worktree_usage, options);
+
+ strbuf_addstr(&dst, prefix_filename(prefix,
+    strlen(prefix),
+    av[0]));
+
+ worktrees = get_worktrees();
+ wt = find_worktree_by_path(worktrees, dst.buf);
+ if (!wt)
+ die(_("'%s' is not a working directory"), av[0]);
+ if (is_main_worktree(wt))
+ die(_("'%s' is a main working directory"), av[0]);
+
+ old_reason = is_worktree_locked(wt);
+ if (old_reason) {
+ if (*old_reason)
+ die(_("already locked, reason: %s"), old_reason);
+ die(_("already locked, no reason"));
+ }
+
+ write_file(git_common_path("worktrees/%s/locked", wt->id),
+   "%s", reason);
+ return 0;
+}
+
 int cmd_worktree(int ac, const char **av, const char *prefix)
 {
  struct option options[] = {
@@ -475,5 +514,7 @@ int cmd_worktree(int ac, const char **av, const char *prefix)
  return prune(ac - 1, av + 1, prefix);
  if (!strcmp(av[1], "list"))
  return list(ac - 1, av + 1, prefix);
+ if (!strcmp(av[1], "lock"))
+ return lock_worktree(ac - 1, av + 1, prefix);
  usage_with_options(worktree_usage, options);
 }
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index d3ac391..6c321aa 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -2597,7 +2597,7 @@ _git_whatchanged ()
 
 _git_worktree ()
 {
- local subcommands="add list prune"
+ local subcommands="add list lock prune"
  local subcommand="$(__git_find_on_cmdline "$subcommands")"
  if [ -z "$subcommand" ]; then
  __gitcomp "$subcommands"
@@ -2609,6 +2609,9 @@ _git_worktree ()
  list,--*)
  __gitcomp "--porcelain"
  ;;
+ lock,--*)
+ __gitcomp "--reason"
+ ;;
  prune,--*)
  __gitcomp "--dry-run --expire --verbose"
  ;;
diff --git a/t/t2028-worktree-move.sh b/t/t2028-worktree-move.sh
new file mode 100755
index 0000000..97434be
--- /dev/null
+++ b/t/t2028-worktree-move.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+test_description='test git worktree move, remove, lock and unlock'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ test_commit init &&
+ git worktree add source &&
+ git worktree list --porcelain | grep "^worktree" >actual &&
+ cat <<-EOF >expected &&
+ worktree $TRASH_DIRECTORY
+ worktree $TRASH_DIRECTORY/source
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'lock main worktree' '
+ test_must_fail git worktree lock .
+'
+
+test_expect_success 'lock linked worktree' '
+ git worktree lock --reason hahaha source &&
+ echo hahaha >expected &&
+ test_cmp expected .git/worktrees/source/locked
+'
+
+test_expect_success 'lock worktree twice' '
+ test_must_fail git worktree lock source &&
+ echo hahaha >expected &&
+ test_cmp expected .git/worktrees/source/locked
+'
+
+test_done
--
2.8.2.524.g6ff3d78

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

[PATCH 5/5] worktree: add "unlock" command

Duy Nguyen
In reply to this post by Duy Nguyen
Signed-off-by: Nguyễn Thái Ngọc Duy <[hidden email]>
---
 Documentation/git-worktree.txt         |  5 +++++
 builtin/worktree.c                     | 31 +++++++++++++++++++++++++++++++
 contrib/completion/git-completion.bash |  2 +-
 t/t2028-worktree-move.sh               | 14 ++++++++++++++
 4 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt
index 74583c1..9ac1129 100644
--- a/Documentation/git-worktree.txt
+++ b/Documentation/git-worktree.txt
@@ -13,6 +13,7 @@ SYNOPSIS
 'git worktree list' [--porcelain]
 'git worktree lock' [--reason <string>] <path>
 'git worktree prune' [-n] [-v] [--expire <expire>]
+'git worktree unlock' <path>
 
 DESCRIPTION
 -----------
@@ -72,6 +73,10 @@ prune::
 
 Prune working tree information in $GIT_DIR/worktrees.
 
+unlock::
+
+Unlock a worktree, allowing it to be pruned, moved or deleted.
+
 OPTIONS
 -------
 
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 51fa103..53e5f5a 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -16,6 +16,7 @@ static const char * const worktree_usage[] = {
  N_("git worktree list [<options>]"),
  N_("git worktree lock [<options>] <path>"),
  N_("git worktree prune [<options>]"),
+ N_("git worktree unlock <path>"),
  NULL
 };
 
@@ -498,6 +499,34 @@ static int lock_worktree(int ac, const char **av, const char *prefix)
  return 0;
 }
 
+static int unlock_worktree(int ac, const char **av, const char *prefix)
+{
+ struct option options[] = {
+ OPT_END()
+ };
+ struct worktree **worktrees, *wt;
+ struct strbuf dst = STRBUF_INIT;
+
+ ac = parse_options(ac, av, prefix, options, worktree_usage, 0);
+ if (ac != 1)
+ usage_with_options(worktree_usage, options);
+
+ strbuf_addstr(&dst, prefix_filename(prefix,
+    strlen(prefix),
+    av[0]));
+
+ worktrees = get_worktrees();
+ wt = find_worktree_by_path(worktrees, dst.buf);
+ if (!wt)
+ die(_("'%s' is not a working directory"), av[0]);
+ if (is_main_worktree(wt))
+ die(_("'%s' is a main working directory"), av[0]);
+ if (!is_worktree_locked(wt))
+ die(_("not locked"));
+
+ return unlink_or_warn(git_common_path("worktrees/%s/locked", wt->id));
+}
+
 int cmd_worktree(int ac, const char **av, const char *prefix)
 {
  struct option options[] = {
@@ -516,5 +545,7 @@ int cmd_worktree(int ac, const char **av, const char *prefix)
  return list(ac - 1, av + 1, prefix);
  if (!strcmp(av[1], "lock"))
  return lock_worktree(ac - 1, av + 1, prefix);
+ if (!strcmp(av[1], "unlock"))
+ return unlock_worktree(ac - 1, av + 1, prefix);
  usage_with_options(worktree_usage, options);
 }
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 6c321aa..db4b0e7 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -2597,7 +2597,7 @@ _git_whatchanged ()
 
 _git_worktree ()
 {
- local subcommands="add list lock prune"
+ local subcommands="add list lock prune unlock"
  local subcommand="$(__git_find_on_cmdline "$subcommands")"
  if [ -z "$subcommand" ]; then
  __gitcomp "$subcommands"
diff --git a/t/t2028-worktree-move.sh b/t/t2028-worktree-move.sh
index 97434be..f4b2816 100755
--- a/t/t2028-worktree-move.sh
+++ b/t/t2028-worktree-move.sh
@@ -31,4 +31,18 @@ test_expect_success 'lock worktree twice' '
  test_cmp expected .git/worktrees/source/locked
 '
 
+test_expect_success 'unlock main worktree' '
+ test_must_fail git worktree unlock .
+'
+
+test_expect_success 'unlock linked worktree' '
+ git worktree unlock source &&
+ test_path_is_missing .git/worktrees/source/locked
+'
+
+test_expect_success 'unlock worktree twice' '
+ test_must_fail git worktree unlock source &&
+ test_path_is_missing .git/worktrees/source/locked
+'
+
 test_done
--
2.8.2.524.g6ff3d78

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v3 05/13] worktree.c: mark current worktree

Junio C Hamano
In reply to this post by Duy Nguyen
Duy Nguyen <[hidden email]> writes:

> On second thought, why hold patches back, lengthen the worktree-move
> series and make it a pain to review? I moved a few patches from
> worktree-move into this series and I took two other out to create
> nd/error-errno. So I'm going to take more patches out of it, creating
> two bite-sized series, to be sent shortly.
>
> The first one is purely cleanup (ok, 1/7 is not exactly cleanup)
>
>   [1/7] completion: support git-worktree
>   [2/7] worktree.c: rewrite mark_current_worktree() to avoid
>   [3/7] git-worktree.txt: keep subcommand listing in alphabetical
>   [4/7] worktree.c: use is_dot_or_dotdot()
>   [5/7] worktree.c: add clear_worktree()
>   [6/7] worktree: avoid 0{40}, too many zeroes, hard to read
>   [7/7] worktree: simplify prefixing paths
>
> And the second one adds "git worktree lock" and "git worktree
> unlock". This series is built on top of the first one, it needs 1/7.
>
>   [1/5] worktree.c: add find_worktree_by_path()
>   [2/5] worktree.c: add is_main_worktree()
>   [3/5] worktree.c: add is_worktree_locked()
>   [4/5] worktree: add "lock" command
>   [5/5] worktree: add "unlock" command
>
> After this, worktree-move becomes ~10 patch series.

Yay.  Thanks; will take a look.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v3 05/13] worktree.c: mark current worktree

Junio C Hamano
In reply to this post by Duy Nguyen
Duy Nguyen <[hidden email]> writes:

> On second thought, why hold patches back, lengthen the worktree-move
> series and make it a pain to review? I moved a few patches from
> worktree-move into this series and I took two other out to create
> nd/error-errno. So I'm going to take more patches out of it, creating
> two bite-sized series, to be sent shortly.
>
> The first one is purely cleanup (ok, 1/7 is not exactly cleanup)
>
>   [1/7] completion: support git-worktree
>   [2/7] worktree.c: rewrite mark_current_worktree() to avoid
>   [3/7] git-worktree.txt: keep subcommand listing in alphabetical
>   [4/7] worktree.c: use is_dot_or_dotdot()
>   [5/7] worktree.c: add clear_worktree()
>   [6/7] worktree: avoid 0{40}, too many zeroes, hard to read
>   [7/7] worktree: simplify prefixing paths

Where are these patches designed to apply?

It appears that this depends on something in 'next' (probably
nd/worktree-various-heads topic?)

>
> And the second one adds "git worktree lock" and "git worktree
> unlock". This series is built on top of the first one, it needs 1/7.
>
>   [1/5] worktree.c: add find_worktree_by_path()
>   [2/5] worktree.c: add is_main_worktree()
>   [3/5] worktree.c: add is_worktree_locked()
>   [4/5] worktree: add "lock" command
>   [5/5] worktree: add "unlock" command
>
> After this, worktree-move becomes ~10 patch series.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 7/7] worktree: simplify prefixing paths

Junio C Hamano
In reply to this post by Duy Nguyen
Nguyễn Thái Ngọc Duy  <[hidden email]> writes:

> Signed-off-by: Nguyễn Thái Ngọc Duy <[hidden email]>
> ---

This changes semantics, doesn't it?  prefix_filename() seems to do a
lot more than just strbuf_vadd("%s%s", prefix, filename); would do.

It may be a good change (e.g. turn '\' into '/' on Windows), but
this is way more than "simplify prefixing".  It is something else
whose effect needs to be explained.

>  builtin/worktree.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/builtin/worktree.c b/builtin/worktree.c
> index b53f802..f9dac37 100644
> --- a/builtin/worktree.c
> +++ b/builtin/worktree.c
> @@ -337,7 +337,7 @@ static int add(int ac, const char **av, const char *prefix)
>   if (ac < 1 || ac > 2)
>   usage_with_options(worktree_usage, options);
>  
> - path = prefix ? prefix_filename(prefix, strlen(prefix), av[0]) : av[0];
> + path = prefix_filename(prefix, strlen(prefix), av[0]);
>   branch = ac < 2 ? "HEAD" : av[1];
>  
>   opts.force_new_branch = !!new_branch_force;
> @@ -467,6 +467,8 @@ int cmd_worktree(int ac, const char **av, const char *prefix)
>  
>   if (ac < 2)
>   usage_with_options(worktree_usage, options);
> + if (!prefix)
> + prefix = "";
>   if (!strcmp(av[1], "add"))
>   return add(ac - 1, av + 1, prefix);
>   if (!strcmp(av[1], "prune"))
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v3 05/13] worktree.c: mark current worktree

Duy Nguyen
In reply to this post by Junio C Hamano
On Wed, May 11, 2016 at 6:03 AM, Junio C Hamano <[hidden email]> wrote:

> Duy Nguyen <[hidden email]> writes:
>
>> On second thought, why hold patches back, lengthen the worktree-move
>> series and make it a pain to review? I moved a few patches from
>> worktree-move into this series and I took two other out to create
>> nd/error-errno. So I'm going to take more patches out of it, creating
>> two bite-sized series, to be sent shortly.
>>
>> The first one is purely cleanup (ok, 1/7 is not exactly cleanup)
>>
>>   [1/7] completion: support git-worktree
>>   [2/7] worktree.c: rewrite mark_current_worktree() to avoid
>>   [3/7] git-worktree.txt: keep subcommand listing in alphabetical
>>   [4/7] worktree.c: use is_dot_or_dotdot()
>>   [5/7] worktree.c: add clear_worktree()
>>   [6/7] worktree: avoid 0{40}, too many zeroes, hard to read
>>   [7/7] worktree: simplify prefixing paths
>
> Where are these patches designed to apply?
>
> It appears that this depends on something in 'next' (probably
> nd/worktree-various-heads topic?)

Yes. Sorry I forgot to mention that. Though if you move 2/7 to
nd/worktree-various-heads (and deal with some conflicts in worktree.c)
then it may become independent.
--
Duy
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 7/7] worktree: simplify prefixing paths

Duy Nguyen
In reply to this post by Junio C Hamano
On Wed, May 11, 2016 at 6:07 AM, Junio C Hamano <[hidden email]> wrote:

> Nguyễn Thái Ngọc Duy  <[hidden email]> writes:
>
>> Signed-off-by: Nguyễn Thái Ngọc Duy <[hidden email]>
>> ---
>
> This changes semantics, doesn't it?  prefix_filename() seems to do a
> lot more than just strbuf_vadd("%s%s", prefix, filename); would do.
>
> It may be a good change (e.g. turn '\' into '/' on Windows), but
> this is way more than "simplify prefixing".  It is something else
> whose effect needs to be explained.

On Wed, May 11, 2016 at 6:07 AM, Junio C Hamano <[hidden email]> wrote:

> Nguyễn Thái Ngọc Duy  <[hidden email]> writes:
>
>> Signed-off-by: Nguyễn Thái Ngọc Duy <[hidden email]>
>> ---
>
> This changes semantics, doesn't it?  prefix_filename() seems to do a
> lot more than just strbuf_vadd("%s%s", prefix, filename); would do.
>
> It may be a good change (e.g. turn '\' into '/' on Windows), but
> this is way more than "simplify prefixing".  It is something else
> whose effect needs to be explained.

I admit I forgot about Windows part in prefix_filename(). For
non-Windows code, it's exactly the same behavior. Maybe we should do
this to emphasize that prefix_filename() is no-op when pfx_len is
zero? The same pattern is used elsewhere too (or I'm spreading it in
my local tree..) Unless of course if convert_slashes() is a good thing
to always do, then I need to update my commit message (+Johannes for
this question).

diff --git a/abspath.c b/abspath.c
index 2825de8..bf454e0 100644
--- a/abspath.c
+++ b/abspath.c
@@ -160,8 +160,11 @@ const char *absolute_path(const char *path)
 const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)
 {
  static struct strbuf path = STRBUF_INIT;
+
+ if (!pfx_len)
+ return arg;
 #ifndef GIT_WINDOWS_NATIVE
- if (!pfx_len || is_absolute_path(arg))
+ if (is_absolute_path(arg))
  return arg;
  strbuf_reset(&path);
  strbuf_add(&path, pfx, pfx_len);

>
>>  builtin/worktree.c | 4 +++-
>>  1 file changed, 3 insertions(+), 1 deletion(-)
>>
>> diff --git a/builtin/worktree.c b/builtin/worktree.c
>> index b53f802..f9dac37 100644
>> --- a/builtin/worktree.c
>> +++ b/builtin/worktree.c
>> @@ -337,7 +337,7 @@ static int add(int ac, const char **av, const char *prefix)
>>       if (ac < 1 || ac > 2)
>>               usage_with_options(worktree_usage, options);
>>
>> -     path = prefix ? prefix_filename(prefix, strlen(prefix), av[0]) : av[0];
>> +     path = prefix_filename(prefix, strlen(prefix), av[0]);
>>       branch = ac < 2 ? "HEAD" : av[1];
>>
>>       opts.force_new_branch = !!new_branch_force;
>> @@ -467,6 +467,8 @@ int cmd_worktree(int ac, const char **av, const char *prefix)
>>
>>       if (ac < 2)
>>               usage_with_options(worktree_usage, options);
>> +     if (!prefix)
>> +             prefix = "";
>>       if (!strcmp(av[1], "add"))
>>               return add(ac - 1, av + 1, prefix);
>>       if (!strcmp(av[1], "prune"))
--
Duy
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH v3 12/13] worktree.c: check whether branch is bisected in another worktree

Eric Sunshine
In reply to this post by Duy Nguyen
On Fri, Apr 22, 2016 at 9:01 AM, Nguyễn Thái Ngọc Duy <[hidden email]> wrote:
> Similar to the rebase case, we want to detect if "HEAD" in some worktree
> is being bisected because
>
> 1) we do not want to checkout this branch in another worktree, after
>    bisect is done it will want to go back to this branch
>
> 2) we do not want to delete the branch is either or git bisect will
>    fail to return to the (long gone) branch

I'm very far behind with my reviews and I see that this series is
already in 'next', so perhaps these comments are too late...

> Signed-off-by: Nguyễn Thái Ngọc Duy <[hidden email]>
> ---
> diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh
> @@ -263,4 +263,17 @@ test_expect_success 'check out from current worktree branch ok' '
> +test_expect_success 'checkout a branch under bisect' '
> +       git worktree add under-bisect &&
> +       (
> +               cd under-bisect &&
> +               git bisect start &&
> +               git bisect bad &&
> +               git bisect good HEAD~2 &&
> +               git worktree list | grep "under-bisect.*detached HEAD" &&
> +               test_must_fail git worktree add new-bisect under-bisect &&

Nit: I realize that the checking 'worktree add' is sufficient, but
it's a bit confusing to read in the commit message about how deleting
the branch would be bad, but then see it testing only 'add'.

> +               ! test -d new-bisect
> +       )
> +'
> diff --git a/worktree.c b/worktree.c
> @@ -234,6 +234,21 @@ static int is_worktree_being_rebased(const struct worktree *wt,
> +static int is_worktree_being_bisected(const struct worktree *wt,
> +                                     const char *target)
> +{
> +       struct wt_status_state state;
> +       int found_rebase;

s/rebase/bisect/ perhaps?

> +       memset(&state, 0, sizeof(state));
> +       found_rebase = wt_status_check_bisect(wt, &state) &&
> +               state.branch &&
> +               starts_with(target, "refs/heads/") &&
> +               !strcmp(state.branch, target + strlen("refs/heads/"));
> +       free(state.branch);
> +       return found_rebase;
> +}
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 1/7] completion: support git-worktree

Eric Sunshine
In reply to this post by Duy Nguyen
On Tue, May 10, 2016 at 10:15 AM, Nguyễn Thái Ngọc Duy
<[hidden email]> wrote:
> completion: support git-worktree

See [1] and, especially, [2] for previous attempts...

[1]: http://thread.gmane.org/gmane.comp.version-control.git/274526
[2]: http://thread.gmane.org/gmane.comp.version-control.git/274526/focus=276333

> Signed-off-by: Nguyễn Thái Ngọc Duy <[hidden email]>
> ---
> diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
> index 3402475..d3ac391 100644
> --- a/contrib/completion/git-completion.bash
> +++ b/contrib/completion/git-completion.bash
> @@ -2595,6 +2595,29 @@ _git_whatchanged ()
>         _git_log
>  }
>
> +_git_worktree ()
> +{
> +       local subcommands="add list prune"
> +       local subcommand="$(__git_find_on_cmdline "$subcommands")"
> +       if [ -z "$subcommand" ]; then
> +               __gitcomp "$subcommands"
> +       else
> +               case "$subcommand,$cur" in
> +               add,--*)
> +                       __gitcomp "--detach --force"
> +                       ;;
> +               list,--*)
> +                       __gitcomp "--porcelain"
> +                       ;;
> +               prune,--*)
> +                       __gitcomp "--dry-run --expire --verbose"
> +                       ;;
> +               *)
> +                       ;;
> +               esac
> +       fi
> +}
> +
>  __git_main ()
>  {
>         local i c=1 command __git_dir
> --
> 2.8.2.524.g6ff3d78
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
123456