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 v2 04/12] worktree.c: mark current worktree

Jeff King
On Thu, Apr 21, 2016 at 10:23:09AM -0400, Eric Sunshine wrote:

> > While we're at it, how about renaming it to pathcmp (and its friend
> > strncmp_icase to pathncmp)?
>
> Yes, that seems like a good idea. For anyone familiar with
> strcasecmp() or stricmp(), having "icase" in the name makes it seem as
> though it's unconditionally case-insensitive, so dropping it from the
> name would likely be beneficial.

Seconded (thirded?). I have been caught by this confusion in the past,
too.

-Peff
--
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 v2 04/12] worktree.c: mark current worktree

Junio C Hamano
Jeff King <[hidden email]> writes:

> On Thu, Apr 21, 2016 at 10:23:09AM -0400, Eric Sunshine wrote:
>
>> > While we're at it, how about renaming it to pathcmp (and its friend
>> > strncmp_icase to pathncmp)?
>>
>> Yes, that seems like a good idea. For anyone familiar with
>> strcasecmp() or stricmp(), having "icase" in the name makes it seem as
>> though it's unconditionally case-insensitive, so dropping it from the
>> name would likely be beneficial.
>
> Seconded (thirded?). I have been caught by this confusion in the past,
> too.

I agree that strcmp_icase() gives a false impression that it always
ignores case differences, but a new name that does not at all hint
that it may do icase comparison as necessary will catch me by an
opposite confusion in the future.

I have not yet formed a firm opinion if pathcmp() conveys enough
hint.
--
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 v2 04/12] worktree.c: mark current worktree

Jeff King
On Thu, Apr 21, 2016 at 08:37:32AM -0700, Junio C Hamano wrote:

> >> > While we're at it, how about renaming it to pathcmp (and its friend
> >> > strncmp_icase to pathncmp)?
> >>
> >> Yes, that seems like a good idea. For anyone familiar with
> >> strcasecmp() or stricmp(), having "icase" in the name makes it seem as
> >> though it's unconditionally case-insensitive, so dropping it from the
> >> name would likely be beneficial.
> >
> > Seconded (thirded?). I have been caught by this confusion in the past,
> > too.
>
> I agree that strcmp_icase() gives a false impression that it always
> ignores case differences, but a new name that does not at all hint
> that it may do icase comparison as necessary will catch me by an
> opposite confusion in the future.

To me, the benefit is that you don't have to care about ignore_case. You
have asked to compare two paths, and any system-appropriate magic should
be applied. That may be icase, or it may be weird unicode normalization.

I think the key thing missing is that this is only about _filesystem_
paths. You would not want to use it for tree-to-tree pathname
comparisons. So maybe "fspath" or something would be more descriptive.

-Peff
--
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 v2 04/12] worktree.c: mark current worktree

Junio C Hamano
Jeff King <[hidden email]> writes:

> To me, the benefit is that you don't have to care about ignore_case. You
> have asked to compare two paths, and any system-appropriate magic should
> be applied. That may be icase, or it may be weird unicode normalization.
>
> I think the key thing missing is that this is only about _filesystem_
> paths. You would not want to use it for tree-to-tree pathname
> comparisons. So maybe "fspath" or something would be more descriptive.

Yup, I would be very happy with "fs" in the name.
--
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 v3 00/13] nd/worktree-various-heads

Duy Nguyen
In reply to this post by Duy Nguyen
v3 fixes all the things found in v2, deletes unused stuff and adds a
new patch 01/13 that renames str(n)cmp_icase to fspath(n)cmp.

Interdiff

diff --git a/branch.c b/branch.c
index 8e323d3..a5a8dcb 100644
--- a/branch.c
+++ b/branch.c
@@ -338,12 +338,12 @@ void die_if_checked_out(const char *branch, int ignore_current_worktree)
 {
  const struct worktree *wt;
 
- wt = find_shared_symref("HEAD", branch, ignore_current_worktree);
- if (wt) {
- skip_prefix(branch, "refs/heads/", &branch);
- die(_("'%s' is already checked out at '%s'"),
-    branch, wt->path);
- }
+ wt = find_shared_symref("HEAD", branch);
+ if (!wt || (ignore_current_worktree && wt->is_current))
+ return;
+ skip_prefix(branch, "refs/heads/", &branch);
+ die(_("'%s' is already checked out at '%s'"),
+    branch, wt->path);
 }
 
 int replace_each_worktree_head_symref(const char *oldref, const char *newref)
diff --git a/builtin/branch.c b/builtin/branch.c
index 3a2eceb..b488c3f 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -221,7 +221,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
 
  if (kinds == FILTER_REFS_BRANCHES) {
  const struct worktree *wt =
- find_shared_symref("HEAD", name, 0);
+ find_shared_symref("HEAD", name);
  if (wt) {
  error(_("Cannot delete branch '%s' "
  "checked out at '%s'"),
diff --git a/builtin/notes.c b/builtin/notes.c
index f154a69..c65b59a 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -852,7 +852,7 @@ static int merge(int argc, const char **argv, const char *prefix)
  update_ref(msg.buf, "NOTES_MERGE_PARTIAL", result_sha1, NULL,
    0, UPDATE_REFS_DIE_ON_ERR);
  /* Store ref-to-be-updated into .git/NOTES_MERGE_REF */
- wt = find_shared_symref("NOTES_MERGE_REF", default_notes_ref(), 0);
+ wt = find_shared_symref("NOTES_MERGE_REF", default_notes_ref());
  if (wt)
  die(_("A notes merge into %s is already in-progress at %s"),
     default_notes_ref(), wt->path);
diff --git a/dir.c b/dir.c
index 996653b..f04bd3b 100644
--- a/dir.c
+++ b/dir.c
@@ -53,13 +53,12 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
  int check_only, const struct path_simplify *simplify);
 static int get_dtype(struct dirent *de, const char *path, int len);
 
-/* helper string functions with support for the ignore_case flag */
-int strcmp_icase(const char *a, const char *b)
+int fspathcmp(const char *a, const char *b)
 {
  return ignore_case ? strcasecmp(a, b) : strcmp(a, b);
 }
 
-int strncmp_icase(const char *a, const char *b, size_t count)
+int fspathncmp(const char *a, const char *b, size_t count)
 {
  return ignore_case ? strncasecmp(a, b, count) : strncmp(a, b, count);
 }
@@ -802,12 +801,12 @@ int match_basename(const char *basename, int basenamelen,
 {
  if (prefix == patternlen) {
  if (patternlen == basenamelen &&
-    !strncmp_icase(pattern, basename, basenamelen))
+    !fspathncmp(pattern, basename, basenamelen))
  return 1;
  } else if (flags & EXC_FLAG_ENDSWITH) {
  /* "*literal" matching against "fooliteral" */
  if (patternlen - 1 <= basenamelen &&
-    !strncmp_icase(pattern + 1,
+    !fspathncmp(pattern + 1,
    basename + basenamelen - (patternlen - 1),
    patternlen - 1))
  return 1;
@@ -844,7 +843,7 @@ int match_pathname(const char *pathname, int pathlen,
  */
  if (pathlen < baselen + 1 ||
     (baselen && pathname[baselen] != '/') ||
-    strncmp_icase(pathname, base, baselen))
+    fspathncmp(pathname, base, baselen))
  return 0;
 
  namelen = baselen ? pathlen - baselen - 1 : pathlen;
@@ -858,7 +857,7 @@ int match_pathname(const char *pathname, int pathlen,
  if (prefix > namelen)
  return 0;
 
- if (strncmp_icase(pattern, name, prefix))
+ if (fspathncmp(pattern, name, prefix))
  return 0;
  pattern += prefix;
  patternlen -= prefix;
diff --git a/dir.h b/dir.h
index 301b737..e34d555 100644
--- a/dir.h
+++ b/dir.h
@@ -270,8 +270,8 @@ extern int remove_dir_recursively(struct strbuf *path, int flag);
 /* tries to remove the path with empty directories along it, ignores ENOENT */
 extern int remove_path(const char *path);
 
-extern int strcmp_icase(const char *a, const char *b);
-extern int strncmp_icase(const char *a, const char *b, size_t count);
+extern int fspathcmp(const char *a, const char *b);
+extern int fspathncmp(const char *a, const char *b, size_t count);
 extern int fnmatch_icase(const char *pattern, const char *string, int flags);
 
 /*
diff --git a/fast-import.c b/fast-import.c
index 9fc7093..339cd38 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -1512,7 +1512,7 @@ static int tree_content_set(
  t = root->tree;
  for (i = 0; i < t->entry_count; i++) {
  e = t->entries[i];
- if (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) {
+ if (e->name->str_len == n && !fspathncmp(p, e->name->str_dat, n)) {
  if (!*slash1) {
  if (!S_ISDIR(mode)
  && e->versions[1].mode == mode
@@ -1602,7 +1602,7 @@ static int tree_content_remove(
  t = root->tree;
  for (i = 0; i < t->entry_count; i++) {
  e = t->entries[i];
- if (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) {
+ if (e->name->str_len == n && !fspathncmp(p, e->name->str_dat, n)) {
  if (*slash1 && !S_ISDIR(e->versions[1].mode))
  /*
  * If p names a file in some subdirectory, and a
@@ -1669,7 +1669,7 @@ static int tree_content_get(
  t = root->tree;
  for (i = 0; i < t->entry_count; i++) {
  e = t->entries[i];
- if (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) {
+ if (e->name->str_len == n && !fspathncmp(p, e->name->str_dat, n)) {
  if (!*slash1)
  goto found_entry;
  if (!S_ISDIR(e->versions[1].mode))
diff --git a/path.c b/path.c
index c421d37..8fdd187 100644
--- a/path.c
+++ b/path.c
@@ -466,16 +466,6 @@ const char *worktree_git_path(const struct worktree *wt, const char *fmt, ...)
  return pathname->buf;
 }
 
-char *worktree_git_pathdup(const struct worktree *wt, const char *fmt, ...)
-{
- struct strbuf path = STRBUF_INIT;
- va_list args;
- va_start(args, fmt);
- do_git_path(wt, &path, fmt, args);
- va_end(args);
- return strbuf_detach(&path, NULL);
-}
-
 static void do_submodule_path(struct strbuf *buf, const char *path,
       const char *fmt, va_list args)
 {
diff --git a/sha1_file.c b/sha1_file.c
index d0f2aa0..ea6381b 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -301,7 +301,7 @@ static int link_alt_odb_entry(const char *entry, const char *relative_base,
  return -1;
  }
  }
- if (!strcmp_icase(ent->base, normalized_objdir)) {
+ if (!fspathcmp(ent->base, normalized_objdir)) {
  free(ent);
  return -1;
  }
diff --git a/worktree.c b/worktree.c
index 8a3d394..4817d60 100644
--- a/worktree.c
+++ b/worktree.c
@@ -151,14 +151,32 @@ done:
  return worktree;
 }
 
+static void mark_current_worktree(struct worktree **worktrees)
+{
+ struct strbuf git_dir = STRBUF_INIT;
+ struct strbuf path = STRBUF_INIT;
+ 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)
+ break;
+ }
+ strbuf_release(&git_dir);
+ strbuf_release(&path);
+}
+
 struct worktree **get_worktrees(void)
 {
  struct worktree **list = NULL;
- struct strbuf git_dir = STRBUF_INIT;
  struct strbuf path = STRBUF_INIT;
  DIR *dir;
  struct dirent *d;
- int i, counter = 0, alloc = 2;
+ int counter = 0, alloc = 2;
 
  list = xmalloc(alloc * sizeof(struct worktree *));
 
@@ -184,17 +202,7 @@ struct worktree **get_worktrees(void)
  ALLOC_GROW(list, counter + 1, alloc);
  list[counter] = NULL;
 
- strbuf_addstr(&git_dir, absolute_path(get_git_dir()));
- for (i = 0; i < counter; i++) {
- struct worktree *wt = list[i];
- strbuf_addstr(&path, absolute_path(get_worktree_git_dir(wt)));
- wt->is_current = !strcmp_icase(git_dir.buf, path.buf);
- strbuf_reset(&path);
- if (wt->is_current)
- break;
- }
- strbuf_release(&git_dir);
- strbuf_release(&path);
+ mark_current_worktree(list);
  return list;
 }
 
@@ -241,9 +249,14 @@ int is_worktree_being_bisected(const struct worktree *wt,
  return found_rebase;
 }
 
+/*
+ * note: this function should be able to detect shared symref even if
+ * HEAD is temporarily detached (e.g. in the middle of rebase or
+ * bisect). New commands that do similar things should update this
+ * function as well.
+ */
 const struct worktree *find_shared_symref(const char *symref,
-  const char *target,
-  int ignore_current_worktree)
+  const char *target)
 {
  const struct worktree *existing = NULL;
  struct strbuf path = STRBUF_INIT;
@@ -258,9 +271,6 @@ const struct worktree *find_shared_symref(const char *symref,
  for (i = 0; worktrees[i]; i++) {
  struct worktree *wt = worktrees[i];
 
- if (ignore_current_worktree && wt->is_current)
- continue;
-
  if (wt->is_detached && !strcmp(symref, "HEAD")) {
  if (is_worktree_being_rebased(wt, target)) {
  existing = wt;
diff --git a/worktree.h b/worktree.h
index d4a3534..1394909 100644
--- a/worktree.h
+++ b/worktree.h
@@ -36,26 +36,21 @@ extern void free_worktrees(struct worktree **);
 
 /*
  * Check if a per-worktree symref points to a ref in the main worktree
- * or any linked worktree, and return the path to the exising worktree
- * if it is. Returns NULL if there is no existing ref. The result
- * may be destroyed by the next call.
+ * or any linked worktree, and return the worktree that holds the ref,
+ * or NULL otherwise. The result may be destroyed by the next call.
  */
 extern const struct worktree *find_shared_symref(const char *symref,
- const char *target,
- int ignore_current_worktree);
+ const char *target);
 
 int is_worktree_being_rebased(const struct worktree *wt, const char *target);
 int is_worktree_being_bisected(const struct worktree *wt, const char *target);
 
 /*
- * Similar to git_path() and git_pathdup() but can produce paths for a
- * specified worktree instead of current one
+ * Similar to git_path() but can produce paths for a specified
+ * worktree instead of current one
  */
 extern const char *worktree_git_path(const struct worktree *wt,
      const char *fmt, ...)
  __attribute__((format (printf, 2, 3)));
-extern char *worktree_git_pathdup(const struct worktree *wt,
-  const char *fmt, ...)
- __attribute__((format (printf, 2, 3)));
 
 #endif
diff --git a/wt-status.c b/wt-status.c
index 971e071..0032ef5 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -1410,7 +1410,7 @@ void wt_status_get_state(struct wt_status_state *state,
  if (!stat(git_path_merge_head(), &st)) {
  state->merge_in_progress = 1;
  } else if (wt_status_check_rebase(NULL, state)) {
- ; /* all set */
+ ; /* all set */
  } else if (!stat(git_path_cherry_pick_head(), &st) &&
  !get_sha1("CHERRY_PICK_HEAD", sha1)) {
  state->cherry_pick_in_progress = 1;

  [01/13] dir.c: rename str(n)cmp_icase to fspath(n)cmp
  [02/13] path.c: add git_common_path() and strbuf_git_common_path()
  [03/13] worktree.c: store "id" instead of "git_dir"
  [04/13] worktree.c: make find_shared_symref() return struct worktree *
  [05/13] worktree.c: mark current worktree
  [06/13] path.c: refactor and add worktree_git_path()
  [07/13] wt-status.c: split rebase detection out of wt_status_get_state()
  [08/13] wt-status.c: make wt_status_check_rebase() work on any worktree
  [09/13] worktree.c: avoid referencing to worktrees[i] multiple times
  [10/13] worktree.c: check whether branch is rebased in another worktree
  [11/13] wt-status.c: split bisect detection out of wt_status_get_state()
  [12/13] worktree.c: check whether branch is bisected in another worktree
  [13/13] branch: do not rename a branch under bisect or rebase

Total 17 files changed, 344 insertions(+), 82 deletions(-)
--
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 v3 01/13] dir.c: rename str(n)cmp_icase to fspath(n)cmp

Duy Nguyen
These functions compare two paths that are taken from file system.
Depending on the running file system, paths may need to be compared
case-sensitively or not, and maybe even something else in future. The
current names do not convey that well.

Signed-off-by: Nguyễn Thái Ngọc Duy <[hidden email]>
---
 dir.c         | 13 ++++++-------
 dir.h         |  4 ++--
 fast-import.c |  6 +++---
 sha1_file.c   |  2 +-
 4 files changed, 12 insertions(+), 13 deletions(-)

diff --git a/dir.c b/dir.c
index 996653b..f04bd3b 100644
--- a/dir.c
+++ b/dir.c
@@ -53,13 +53,12 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
  int check_only, const struct path_simplify *simplify);
 static int get_dtype(struct dirent *de, const char *path, int len);
 
-/* helper string functions with support for the ignore_case flag */
-int strcmp_icase(const char *a, const char *b)
+int fspathcmp(const char *a, const char *b)
 {
  return ignore_case ? strcasecmp(a, b) : strcmp(a, b);
 }
 
-int strncmp_icase(const char *a, const char *b, size_t count)
+int fspathncmp(const char *a, const char *b, size_t count)
 {
  return ignore_case ? strncasecmp(a, b, count) : strncmp(a, b, count);
 }
@@ -802,12 +801,12 @@ int match_basename(const char *basename, int basenamelen,
 {
  if (prefix == patternlen) {
  if (patternlen == basenamelen &&
-    !strncmp_icase(pattern, basename, basenamelen))
+    !fspathncmp(pattern, basename, basenamelen))
  return 1;
  } else if (flags & EXC_FLAG_ENDSWITH) {
  /* "*literal" matching against "fooliteral" */
  if (patternlen - 1 <= basenamelen &&
-    !strncmp_icase(pattern + 1,
+    !fspathncmp(pattern + 1,
    basename + basenamelen - (patternlen - 1),
    patternlen - 1))
  return 1;
@@ -844,7 +843,7 @@ int match_pathname(const char *pathname, int pathlen,
  */
  if (pathlen < baselen + 1 ||
     (baselen && pathname[baselen] != '/') ||
-    strncmp_icase(pathname, base, baselen))
+    fspathncmp(pathname, base, baselen))
  return 0;
 
  namelen = baselen ? pathlen - baselen - 1 : pathlen;
@@ -858,7 +857,7 @@ int match_pathname(const char *pathname, int pathlen,
  if (prefix > namelen)
  return 0;
 
- if (strncmp_icase(pattern, name, prefix))
+ if (fspathncmp(pattern, name, prefix))
  return 0;
  pattern += prefix;
  patternlen -= prefix;
diff --git a/dir.h b/dir.h
index 301b737..e34d555 100644
--- a/dir.h
+++ b/dir.h
@@ -270,8 +270,8 @@ extern int remove_dir_recursively(struct strbuf *path, int flag);
 /* tries to remove the path with empty directories along it, ignores ENOENT */
 extern int remove_path(const char *path);
 
-extern int strcmp_icase(const char *a, const char *b);
-extern int strncmp_icase(const char *a, const char *b, size_t count);
+extern int fspathcmp(const char *a, const char *b);
+extern int fspathncmp(const char *a, const char *b, size_t count);
 extern int fnmatch_icase(const char *pattern, const char *string, int flags);
 
 /*
diff --git a/fast-import.c b/fast-import.c
index 9fc7093..339cd38 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -1512,7 +1512,7 @@ static int tree_content_set(
  t = root->tree;
  for (i = 0; i < t->entry_count; i++) {
  e = t->entries[i];
- if (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) {
+ if (e->name->str_len == n && !fspathncmp(p, e->name->str_dat, n)) {
  if (!*slash1) {
  if (!S_ISDIR(mode)
  && e->versions[1].mode == mode
@@ -1602,7 +1602,7 @@ static int tree_content_remove(
  t = root->tree;
  for (i = 0; i < t->entry_count; i++) {
  e = t->entries[i];
- if (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) {
+ if (e->name->str_len == n && !fspathncmp(p, e->name->str_dat, n)) {
  if (*slash1 && !S_ISDIR(e->versions[1].mode))
  /*
  * If p names a file in some subdirectory, and a
@@ -1669,7 +1669,7 @@ static int tree_content_get(
  t = root->tree;
  for (i = 0; i < t->entry_count; i++) {
  e = t->entries[i];
- if (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) {
+ if (e->name->str_len == n && !fspathncmp(p, e->name->str_dat, n)) {
  if (!*slash1)
  goto found_entry;
  if (!S_ISDIR(e->versions[1].mode))
diff --git a/sha1_file.c b/sha1_file.c
index d0f2aa0..ea6381b 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -301,7 +301,7 @@ static int link_alt_odb_entry(const char *entry, const char *relative_base,
  return -1;
  }
  }
- if (!strcmp_icase(ent->base, normalized_objdir)) {
+ if (!fspathcmp(ent->base, normalized_objdir)) {
  free(ent);
  return -1;
  }
--
2.8.0.rc0.210.gd302cd2

--
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 v3 02/13] path.c: add git_common_path() and strbuf_git_common_path()

Duy Nguyen
In reply to this post by Duy Nguyen
These are mostly convenient functions to reduce code duplication. Most
of the time, we should be able to get by with git_path() which handles
$GIT_COMMON_DIR internally. However there are a few cases where we need
to construct paths manually, for example some paths from a specific
worktree. These functions will enable that.

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

diff --git a/cache.h b/cache.h
index 2711048..c04a17f 100644
--- a/cache.h
+++ b/cache.h
@@ -799,11 +799,14 @@ extern void check_repository_format(void);
  */
 extern const char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
 extern const char *git_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
+extern const char *git_common_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
 
 extern char *mksnpath(char *buf, size_t n, const char *fmt, ...)
  __attribute__((format (printf, 3, 4)));
 extern void strbuf_git_path(struct strbuf *sb, const char *fmt, ...)
  __attribute__((format (printf, 2, 3)));
+extern void strbuf_git_common_path(struct strbuf *sb, const char *fmt, ...)
+ __attribute__((format (printf, 2, 3)));
 extern char *git_path_buf(struct strbuf *buf, const char *fmt, ...)
  __attribute__((format (printf, 2, 3)));
 extern void strbuf_git_path_submodule(struct strbuf *sb, const char *path,
diff --git a/path.c b/path.c
index bbaea5a..2ebb23d 100644
--- a/path.c
+++ b/path.c
@@ -503,6 +503,35 @@ void strbuf_git_path_submodule(struct strbuf *buf, const char *path,
  va_end(args);
 }
 
+static void do_git_common_path(struct strbuf *buf,
+       const char *fmt,
+       va_list args)
+{
+ strbuf_addstr(buf, get_git_common_dir());
+ if (buf->len && !is_dir_sep(buf->buf[buf->len - 1]))
+ strbuf_addch(buf, '/');
+ strbuf_vaddf(buf, fmt, args);
+ strbuf_cleanup_path(buf);
+}
+
+const char *git_common_path(const char *fmt, ...)
+{
+ struct strbuf *pathname = get_pathname();
+ va_list args;
+ va_start(args, fmt);
+ do_git_common_path(pathname, fmt, args);
+ va_end(args);
+ return pathname->buf;
+}
+
+void strbuf_git_common_path(struct strbuf *sb, const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ do_git_common_path(sb, fmt, args);
+ va_end(args);
+}
+
 int validate_headref(const char *path)
 {
  struct stat st;
--
2.8.0.rc0.210.gd302cd2

--
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 v3 03/13] worktree.c: store "id" instead of "git_dir"

Duy Nguyen
In reply to this post by Duy Nguyen
We can reconstruct git_dir from id quite easily. It's a bit hackier to
do the reverse.

Signed-off-by: Nguyễn Thái Ngọc Duy <[hidden email]>
---
 branch.c   |  3 ++-
 worktree.c | 31 ++++++++++++++++++-------------
 worktree.h |  8 +++++++-
 3 files changed, 27 insertions(+), 15 deletions(-)

diff --git a/branch.c b/branch.c
index 4162443..0674a99 100644
--- a/branch.c
+++ b/branch.c
@@ -357,7 +357,8 @@ int replace_each_worktree_head_symref(const char *oldref, const char *newref)
  if (strcmp(oldref, worktrees[i]->head_ref))
  continue;
 
- if (set_worktree_head_symref(worktrees[i]->git_dir, newref)) {
+ if (set_worktree_head_symref(get_worktree_git_dir(worktrees[i]),
+     newref)) {
  ret = -1;
  error(_("HEAD of working tree %s is not updated"),
       worktrees[i]->path);
diff --git a/worktree.c b/worktree.c
index 6181a66..5ae54f0 100644
--- a/worktree.c
+++ b/worktree.c
@@ -9,7 +9,7 @@ void free_worktrees(struct worktree **worktrees)
 
  for (i = 0; worktrees[i]; i++) {
  free(worktrees[i]->path);
- free(worktrees[i]->git_dir);
+ free(worktrees[i]->id);
  free(worktrees[i]->head_ref);
  free(worktrees[i]);
  }
@@ -74,13 +74,11 @@ static struct worktree *get_main_worktree(void)
  struct worktree *worktree = NULL;
  struct strbuf path = STRBUF_INIT;
  struct strbuf worktree_path = STRBUF_INIT;
- struct strbuf gitdir = STRBUF_INIT;
  struct strbuf head_ref = STRBUF_INIT;
  int is_bare = 0;
  int is_detached = 0;
 
- strbuf_addf(&gitdir, "%s", absolute_path(get_git_common_dir()));
- strbuf_addbuf(&worktree_path, &gitdir);
+ strbuf_addstr(&worktree_path, absolute_path(get_git_common_dir()));
  is_bare = !strbuf_strip_suffix(&worktree_path, "/.git");
  if (is_bare)
  strbuf_strip_suffix(&worktree_path, "/.");
@@ -92,7 +90,7 @@ static struct worktree *get_main_worktree(void)
 
  worktree = xmalloc(sizeof(struct worktree));
  worktree->path = strbuf_detach(&worktree_path, NULL);
- worktree->git_dir = strbuf_detach(&gitdir, NULL);
+ worktree->id = NULL;
  worktree->is_bare = is_bare;
  worktree->head_ref = NULL;
  worktree->is_detached = is_detached;
@@ -100,7 +98,6 @@ static struct worktree *get_main_worktree(void)
 
 done:
  strbuf_release(&path);
- strbuf_release(&gitdir);
  strbuf_release(&worktree_path);
  strbuf_release(&head_ref);
  return worktree;
@@ -111,16 +108,13 @@ static struct worktree *get_linked_worktree(const char *id)
  struct worktree *worktree = NULL;
  struct strbuf path = STRBUF_INIT;
  struct strbuf worktree_path = STRBUF_INIT;
- struct strbuf gitdir = STRBUF_INIT;
  struct strbuf head_ref = STRBUF_INIT;
  int is_detached = 0;
 
  if (!id)
  die("Missing linked worktree name");
 
- strbuf_addf(&gitdir, "%s/worktrees/%s",
- absolute_path(get_git_common_dir()), id);
- strbuf_addf(&path, "%s/gitdir", gitdir.buf);
+ strbuf_git_common_path(&path, "worktrees/%s/gitdir", id);
  if (strbuf_read_file(&worktree_path, path.buf, 0) <= 0)
  /* invalid gitdir file */
  goto done;
@@ -140,7 +134,7 @@ static struct worktree *get_linked_worktree(const char *id)
 
  worktree = xmalloc(sizeof(struct worktree));
  worktree->path = strbuf_detach(&worktree_path, NULL);
- worktree->git_dir = strbuf_detach(&gitdir, NULL);
+ worktree->id = xstrdup(id);
  worktree->is_bare = 0;
  worktree->head_ref = NULL;
  worktree->is_detached = is_detached;
@@ -148,7 +142,6 @@ static struct worktree *get_linked_worktree(const char *id)
 
 done:
  strbuf_release(&path);
- strbuf_release(&gitdir);
  strbuf_release(&worktree_path);
  strbuf_release(&head_ref);
  return worktree;
@@ -188,6 +181,16 @@ struct worktree **get_worktrees(void)
  return list;
 }
 
+const char *get_worktree_git_dir(const struct worktree *wt)
+{
+ if (!wt)
+ return get_git_dir();
+ else if (!wt->id)
+ return get_git_common_dir();
+ else
+ return git_common_path("worktrees/%s", wt->id);
+}
+
 char *find_shared_symref(const char *symref, const char *target)
 {
  char *existing = NULL;
@@ -199,7 +202,9 @@ char *find_shared_symref(const char *symref, const char *target)
  for (i = 0; worktrees[i]; i++) {
  strbuf_reset(&path);
  strbuf_reset(&sb);
- strbuf_addf(&path, "%s/%s", worktrees[i]->git_dir, symref);
+ strbuf_addf(&path, "%s/%s",
+    get_worktree_git_dir(worktrees[i]),
+    symref);
 
  if (parse_ref(path.buf, &sb, NULL)) {
  continue;
diff --git a/worktree.h b/worktree.h
index b4b3dda..3198c8d 100644
--- a/worktree.h
+++ b/worktree.h
@@ -3,7 +3,7 @@
 
 struct worktree {
  char *path;
- char *git_dir;
+ char *id;
  char *head_ref;
  unsigned char head_sha1[20];
  int is_detached;
@@ -23,6 +23,12 @@ struct worktree {
 extern struct worktree **get_worktrees(void);
 
 /*
+ * Return git dir of the worktree. Note that the path may be relative.
+ * If wt is NULL, git dir of current worktree is returned.
+ */
+extern const char *get_worktree_git_dir(const struct worktree *wt);
+
+/*
  * Free up the memory for worktree(s)
  */
 extern void free_worktrees(struct worktree **);
--
2.8.0.rc0.210.gd302cd2

--
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 v3 04/13] worktree.c: make find_shared_symref() return struct worktree *

Duy Nguyen
In reply to this post by Duy Nguyen
This gives the caller more information and they can answer things like,
"is it the main worktree" or "is it the current worktree". The latter
question is needed for the "checkout a rebase branch" case later.

Signed-off-by: Nguyễn Thái Ngọc Duy <[hidden email]>
---
 branch.c         | 13 +++++++------
 builtin/branch.c |  8 ++++----
 builtin/notes.c  |  8 ++++----
 worktree.c       | 14 +++++++++-----
 worktree.h       |  8 ++++----
 5 files changed, 28 insertions(+), 23 deletions(-)

diff --git a/branch.c b/branch.c
index 0674a99..1f1fbf5 100644
--- a/branch.c
+++ b/branch.c
@@ -336,13 +336,14 @@ void remove_branch_state(void)
 
 void die_if_checked_out(const char *branch)
 {
- char *existing;
+ const struct worktree *wt;
 
- existing = find_shared_symref("HEAD", branch);
- if (existing) {
- skip_prefix(branch, "refs/heads/", &branch);
- die(_("'%s' is already checked out at '%s'"), branch, existing);
- }
+ wt = find_shared_symref("HEAD", branch);
+ if (!wt)
+ return;
+ skip_prefix(branch, "refs/heads/", &branch);
+ die(_("'%s' is already checked out at '%s'"),
+    branch, wt->path);
 }
 
 int replace_each_worktree_head_symref(const char *oldref, const char *newref)
diff --git a/builtin/branch.c b/builtin/branch.c
index 0adba62..bcde87d 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -220,12 +220,12 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
  name = mkpathdup(fmt, bname.buf);
 
  if (kinds == FILTER_REFS_BRANCHES) {
- char *worktree = find_shared_symref("HEAD", name);
- if (worktree) {
+ const struct worktree *wt =
+ find_shared_symref("HEAD", name);
+ if (wt) {
  error(_("Cannot delete branch '%s' "
  "checked out at '%s'"),
-      bname.buf, worktree);
- free(worktree);
+      bname.buf, wt->path);
  ret = 1;
  continue;
  }
diff --git a/builtin/notes.c b/builtin/notes.c
index 6fd058d..c65b59a 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -847,15 +847,15 @@ static int merge(int argc, const char **argv, const char *prefix)
  update_ref(msg.buf, default_notes_ref(), result_sha1, NULL,
    0, UPDATE_REFS_DIE_ON_ERR);
  else { /* Merge has unresolved conflicts */
- char *existing;
+ const struct worktree *wt;
  /* Update .git/NOTES_MERGE_PARTIAL with partial merge result */
  update_ref(msg.buf, "NOTES_MERGE_PARTIAL", result_sha1, NULL,
    0, UPDATE_REFS_DIE_ON_ERR);
  /* Store ref-to-be-updated into .git/NOTES_MERGE_REF */
- existing = find_shared_symref("NOTES_MERGE_REF", default_notes_ref());
- if (existing)
+ wt = find_shared_symref("NOTES_MERGE_REF", default_notes_ref());
+ if (wt)
  die(_("A notes merge into %s is already in-progress at %s"),
-    default_notes_ref(), existing);
+    default_notes_ref(), wt->path);
  if (create_symref("NOTES_MERGE_REF", default_notes_ref(), NULL))
  die("Failed to store link to current notes ref (%s)",
     default_notes_ref());
diff --git a/worktree.c b/worktree.c
index 5ae54f0..360ba41 100644
--- a/worktree.c
+++ b/worktree.c
@@ -191,14 +191,19 @@ const char *get_worktree_git_dir(const struct worktree *wt)
  return git_common_path("worktrees/%s", wt->id);
 }
 
-char *find_shared_symref(const char *symref, const char *target)
+const struct worktree *find_shared_symref(const char *symref,
+  const char *target)
 {
- char *existing = NULL;
+ const struct worktree *existing = NULL;
  struct strbuf path = STRBUF_INIT;
  struct strbuf sb = STRBUF_INIT;
- struct worktree **worktrees = get_worktrees();
+ static struct worktree **worktrees;
  int i = 0;
 
+ if (worktrees)
+ free_worktrees(worktrees);
+ worktrees = get_worktrees();
+
  for (i = 0; worktrees[i]; i++) {
  strbuf_reset(&path);
  strbuf_reset(&sb);
@@ -211,14 +216,13 @@ char *find_shared_symref(const char *symref, const char *target)
  }
 
  if (!strcmp(sb.buf, target)) {
- existing = xstrdup(worktrees[i]->path);
+ existing = worktrees[i];
  break;
  }
  }
 
  strbuf_release(&path);
  strbuf_release(&sb);
- free_worktrees(worktrees);
 
  return existing;
 }
diff --git a/worktree.h b/worktree.h
index 3198c8d..ca50e73 100644
--- a/worktree.h
+++ b/worktree.h
@@ -35,10 +35,10 @@ extern void free_worktrees(struct worktree **);
 
 /*
  * Check if a per-worktree symref points to a ref in the main worktree
- * or any linked worktree, and return the path to the exising worktree
- * if it is.  Returns NULL if there is no existing ref.  The caller is
- * responsible for freeing the returned path.
+ * or any linked worktree, and return the worktree that holds the ref,
+ * or NULL otherwise. The result may be destroyed by the next call.
  */
-extern char *find_shared_symref(const char *symref, const char *target);
+extern const struct worktree *find_shared_symref(const char *symref,
+ const char *target);
 
 #endif
--
2.8.0.rc0.210.gd302cd2

--
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 v3 05/13] worktree.c: mark current worktree

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

diff --git a/worktree.c b/worktree.c
index 360ba41..dc092a7 100644
--- a/worktree.c
+++ b/worktree.c
@@ -2,6 +2,7 @@
 #include "refs.h"
 #include "strbuf.h"
 #include "worktree.h"
+#include "dir.h"
 
 void free_worktrees(struct worktree **worktrees)
 {
@@ -94,6 +95,7 @@ static struct worktree *get_main_worktree(void)
  worktree->is_bare = is_bare;
  worktree->head_ref = NULL;
  worktree->is_detached = is_detached;
+ worktree->is_current = 0;
  add_head_info(&head_ref, worktree);
 
 done:
@@ -138,6 +140,7 @@ static struct worktree *get_linked_worktree(const char *id)
  worktree->is_bare = 0;
  worktree->head_ref = NULL;
  worktree->is_detached = is_detached;
+ worktree->is_current = 0;
  add_head_info(&head_ref, worktree);
 
 done:
@@ -147,6 +150,25 @@ done:
  return worktree;
 }
 
+static void mark_current_worktree(struct worktree **worktrees)
+{
+ struct strbuf git_dir = STRBUF_INIT;
+ struct strbuf path = STRBUF_INIT;
+ 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)
+ break;
+ }
+ strbuf_release(&git_dir);
+ strbuf_release(&path);
+}
+
 struct worktree **get_worktrees(void)
 {
  struct worktree **list = NULL;
@@ -178,6 +200,8 @@ struct worktree **get_worktrees(void)
  }
  ALLOC_GROW(list, counter + 1, alloc);
  list[counter] = NULL;
+
+ mark_current_worktree(list);
  return list;
 }
 
diff --git a/worktree.h b/worktree.h
index ca50e73..ccdf69a 100644
--- a/worktree.h
+++ b/worktree.h
@@ -8,6 +8,7 @@ struct worktree {
  unsigned char head_sha1[20];
  int is_detached;
  int is_bare;
+ int is_current;
 };
 
 /* Functions for acting on the information about worktrees. */
--
2.8.0.rc0.210.gd302cd2

--
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 v3 06/13] path.c: refactor and add worktree_git_path()

Duy Nguyen
In reply to this post by Duy Nguyen
do_git_path(), which is the common code for all git_path* functions, is
modified to take a worktree struct and can produce paths for any
worktree.

worktree_git_path() is the first function that makes use of this. It can
be used to write code that can examine any worktree. For example,
wt_status_get_state() will be converted using this to take
am/rebase/... state of any worktree.

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

diff --git a/path.c b/path.c
index 2ebb23d..8fdd187 100644
--- a/path.c
+++ b/path.c
@@ -5,6 +5,7 @@
 #include "strbuf.h"
 #include "string-list.h"
 #include "dir.h"
+#include "worktree.h"
 
 static int get_st_mode_bits(const char *path, int *mode)
 {
@@ -383,10 +384,11 @@ static void adjust_git_path(struct strbuf *buf, int git_dir_len)
  update_common_dir(buf, git_dir_len, NULL);
 }
 
-static void do_git_path(struct strbuf *buf, const char *fmt, va_list args)
+static void do_git_path(const struct worktree *wt, struct strbuf *buf,
+ const char *fmt, va_list args)
 {
  int gitdir_len;
- strbuf_addstr(buf, get_git_dir());
+ strbuf_addstr(buf, get_worktree_git_dir(wt));
  if (buf->len && !is_dir_sep(buf->buf[buf->len - 1]))
  strbuf_addch(buf, '/');
  gitdir_len = buf->len;
@@ -400,7 +402,7 @@ char *git_path_buf(struct strbuf *buf, const char *fmt, ...)
  va_list args;
  strbuf_reset(buf);
  va_start(args, fmt);
- do_git_path(buf, fmt, args);
+ do_git_path(NULL, buf, fmt, args);
  va_end(args);
  return buf->buf;
 }
@@ -409,7 +411,7 @@ void strbuf_git_path(struct strbuf *sb, const char *fmt, ...)
 {
  va_list args;
  va_start(args, fmt);
- do_git_path(sb, fmt, args);
+ do_git_path(NULL, sb, fmt, args);
  va_end(args);
 }
 
@@ -418,7 +420,7 @@ const char *git_path(const char *fmt, ...)
  struct strbuf *pathname = get_pathname();
  va_list args;
  va_start(args, fmt);
- do_git_path(pathname, fmt, args);
+ do_git_path(NULL, pathname, fmt, args);
  va_end(args);
  return pathname->buf;
 }
@@ -428,7 +430,7 @@ char *git_pathdup(const char *fmt, ...)
  struct strbuf path = STRBUF_INIT;
  va_list args;
  va_start(args, fmt);
- do_git_path(&path, fmt, args);
+ do_git_path(NULL, &path, fmt, args);
  va_end(args);
  return strbuf_detach(&path, NULL);
 }
@@ -454,6 +456,16 @@ const char *mkpath(const char *fmt, ...)
  return cleanup_path(pathname->buf);
 }
 
+const char *worktree_git_path(const struct worktree *wt, const char *fmt, ...)
+{
+ struct strbuf *pathname = get_pathname();
+ va_list args;
+ va_start(args, fmt);
+ do_git_path(wt, pathname, fmt, args);
+ va_end(args);
+ return pathname->buf;
+}
+
 static void do_submodule_path(struct strbuf *buf, const char *path,
       const char *fmt, va_list args)
 {
diff --git a/worktree.h b/worktree.h
index ccdf69a..0da8c1f 100644
--- a/worktree.h
+++ b/worktree.h
@@ -42,4 +42,12 @@ extern void free_worktrees(struct worktree **);
 extern const struct worktree *find_shared_symref(const char *symref,
  const char *target);
 
+/*
+ * Similar to git_path() but can produce paths for a specified
+ * worktree instead of current one
+ */
+extern const char *worktree_git_path(const struct worktree *wt,
+     const char *fmt, ...)
+ __attribute__((format (printf, 2, 3)));
+
 #endif
--
2.8.0.rc0.210.gd302cd2

--
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 v3 07/13] wt-status.c: split rebase detection out of wt_status_get_state()

Duy Nguyen
In reply to this post by Duy Nguyen
worktree.c:find_shared_symref() later needs to know if a branch is being
rebased, and only rebase, no cherry-pick, do detached branch... Split
this code so it can be used independently from other in-progress tests.

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

diff --git a/wt-status.c b/wt-status.c
index 1ea2ebe..ec9240d 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -1360,15 +1360,11 @@ static void wt_status_get_detached_from(struct wt_status_state *state)
  strbuf_release(&cb.buf);
 }
 
-void wt_status_get_state(struct wt_status_state *state,
- int get_detached_from)
+int wt_status_check_rebase(struct wt_status_state *state)
 {
  struct stat st;
- unsigned char sha1[20];
 
- if (!stat(git_path_merge_head(), &st)) {
- state->merge_in_progress = 1;
- } else if (!stat(git_path("rebase-apply"), &st)) {
+ if (!stat(git_path("rebase-apply"), &st)) {
  if (!stat(git_path("rebase-apply/applying"), &st)) {
  state->am_in_progress = 1;
  if (!stat(git_path("rebase-apply/patch"), &st) && !st.st_size)
@@ -1385,6 +1381,21 @@ void wt_status_get_state(struct wt_status_state *state,
  state->rebase_in_progress = 1;
  state->branch = read_and_strip_branch("rebase-merge/head-name");
  state->onto = read_and_strip_branch("rebase-merge/onto");
+ } else
+ return 0;
+ return 1;
+}
+
+void wt_status_get_state(struct wt_status_state *state,
+ int get_detached_from)
+{
+ struct stat st;
+ unsigned char sha1[20];
+
+ if (!stat(git_path_merge_head(), &st)) {
+ state->merge_in_progress = 1;
+ } else if (wt_status_check_rebase(state)) {
+ ; /* all set */
  } else if (!stat(git_path_cherry_pick_head(), &st) &&
  !get_sha1("CHERRY_PICK_HEAD", sha1)) {
  state->cherry_pick_in_progress = 1;
diff --git a/wt-status.h b/wt-status.h
index c9b3b74..b398353 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -100,6 +100,7 @@ void wt_status_prepare(struct wt_status *s);
 void wt_status_print(struct wt_status *s);
 void wt_status_collect(struct wt_status *s);
 void wt_status_get_state(struct wt_status_state *state, int get_detached_from);
+int wt_status_check_rebase(struct wt_status_state *state);
 
 void wt_shortstatus_print(struct wt_status *s);
 void wt_porcelain_print(struct wt_status *s);
--
2.8.0.rc0.210.gd302cd2

--
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 v3 08/13] wt-status.c: make wt_status_check_rebase() work on any worktree

Duy Nguyen
In reply to this post by Duy Nguyen
This is a preparation step for find_shared_symref() to detect if any
worktree is being rebased.

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

diff --git a/wt-status.c b/wt-status.c
index ec9240d..ce5080c 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -15,6 +15,7 @@
 #include "column.h"
 #include "strbuf.h"
 #include "utf8.h"
+#include "worktree.h"
 
 static const char cut_line[] =
 "------------------------ >8 ------------------------\n";
@@ -1262,13 +1263,13 @@ static void show_bisect_in_progress(struct wt_status *s,
 /*
  * Extract branch information from rebase/bisect
  */
-static char *read_and_strip_branch(const char *path)
+static char *get_branch(const struct worktree *wt, const char *path)
 {
  struct strbuf sb = STRBUF_INIT;
  unsigned char sha1[20];
  const char *branch_name;
 
- if (strbuf_read_file(&sb, git_path("%s", path), 0) <= 0)
+ if (strbuf_read_file(&sb, worktree_git_path(wt, "%s", path), 0) <= 0)
  goto got_nothing;
 
  while (sb.len && sb.buf[sb.len - 1] == '\n')
@@ -1295,6 +1296,11 @@ got_nothing:
  return NULL;
 }
 
+static char *read_and_strip_branch(const char *path)
+{
+ return get_branch(NULL, path);
+}
+
 struct grab_1st_switch_cbdata {
  struct strbuf buf;
  unsigned char nsha1[20];
@@ -1360,27 +1366,28 @@ static void wt_status_get_detached_from(struct wt_status_state *state)
  strbuf_release(&cb.buf);
 }
 
-int wt_status_check_rebase(struct wt_status_state *state)
+int wt_status_check_rebase(const struct worktree *wt,
+   struct wt_status_state *state)
 {
  struct stat st;
 
- if (!stat(git_path("rebase-apply"), &st)) {
- if (!stat(git_path("rebase-apply/applying"), &st)) {
+ if (!stat(worktree_git_path(wt, "rebase-apply"), &st)) {
+ if (!stat(worktree_git_path(wt, "rebase-apply/applying"), &st)) {
  state->am_in_progress = 1;
- if (!stat(git_path("rebase-apply/patch"), &st) && !st.st_size)
+ if (!stat(worktree_git_path(wt, "rebase-apply/patch"), &st) && !st.st_size)
  state->am_empty_patch = 1;
  } else {
  state->rebase_in_progress = 1;
- state->branch = read_and_strip_branch("rebase-apply/head-name");
- state->onto = read_and_strip_branch("rebase-apply/onto");
+ state->branch = get_branch(wt, "rebase-apply/head-name");
+ state->onto = get_branch(wt, "rebase-apply/onto");
  }
- } else if (!stat(git_path("rebase-merge"), &st)) {
- if (!stat(git_path("rebase-merge/interactive"), &st))
+ } else if (!stat(worktree_git_path(wt, "rebase-merge"), &st)) {
+ if (!stat(worktree_git_path(wt, "rebase-merge/interactive"), &st))
  state->rebase_interactive_in_progress = 1;
  else
  state->rebase_in_progress = 1;
- state->branch = read_and_strip_branch("rebase-merge/head-name");
- state->onto = read_and_strip_branch("rebase-merge/onto");
+ state->branch = get_branch(wt, "rebase-merge/head-name");
+ state->onto = get_branch(wt, "rebase-merge/onto");
  } else
  return 0;
  return 1;
@@ -1394,7 +1401,7 @@ void wt_status_get_state(struct wt_status_state *state,
 
  if (!stat(git_path_merge_head(), &st)) {
  state->merge_in_progress = 1;
- } else if (wt_status_check_rebase(state)) {
+ } else if (wt_status_check_rebase(NULL, state)) {
  ; /* all set */
  } else if (!stat(git_path_cherry_pick_head(), &st) &&
  !get_sha1("CHERRY_PICK_HEAD", sha1)) {
diff --git a/wt-status.h b/wt-status.h
index b398353..c4ddcad 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -6,6 +6,8 @@
 #include "color.h"
 #include "pathspec.h"
 
+struct worktree;
+
 enum color_wt_status {
  WT_STATUS_HEADER = 0,
  WT_STATUS_UPDATED,
@@ -100,7 +102,8 @@ void wt_status_prepare(struct wt_status *s);
 void wt_status_print(struct wt_status *s);
 void wt_status_collect(struct wt_status *s);
 void wt_status_get_state(struct wt_status_state *state, int get_detached_from);
-int wt_status_check_rebase(struct wt_status_state *state);
+int wt_status_check_rebase(const struct worktree *wt,
+   struct wt_status_state *state);
 
 void wt_shortstatus_print(struct wt_status *s);
 void wt_porcelain_print(struct wt_status *s);
--
2.8.0.rc0.210.gd302cd2

--
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 v3 09/13] worktree.c: avoid referencing to worktrees[i] multiple times

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

diff --git a/worktree.c b/worktree.c
index dc092a7..927905b 100644
--- a/worktree.c
+++ b/worktree.c
@@ -229,10 +229,12 @@ const struct worktree *find_shared_symref(const char *symref,
  worktrees = get_worktrees();
 
  for (i = 0; worktrees[i]; i++) {
+ struct worktree *wt = worktrees[i];
+
  strbuf_reset(&path);
  strbuf_reset(&sb);
  strbuf_addf(&path, "%s/%s",
-    get_worktree_git_dir(worktrees[i]),
+    get_worktree_git_dir(wt),
     symref);
 
  if (parse_ref(path.buf, &sb, NULL)) {
@@ -240,7 +242,7 @@ const struct worktree *find_shared_symref(const char *symref,
  }
 
  if (!strcmp(sb.buf, target)) {
- existing = worktrees[i];
+ existing = wt;
  break;
  }
  }
--
2.8.0.rc0.210.gd302cd2

--
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 v3 10/13] worktree.c: check whether branch is rebased in another worktree

Duy Nguyen
In reply to this post by Duy Nguyen
This function find_shared_symref() is used in a couple places:

1) in builtin/branch.c: it's used to detect if a branch is checked out
   elsewhere and refuse to delete the branch.

2) in builtin/notes.c: it's used to detect if a note is being merged in
   another worktree

3) in branch.c, the function die_if_checked_out() is actually used by
   "git checkout" and "git worktree add" to see if a branch is already
   checked out elsewhere and refuse the operation.

In cases 1 and 3, if a rebase is ongoing, "HEAD" will be in detached
mode, find_shared_symref() fails to detect it and declares "no branch is
checked out here", which is not really what we want.

This patch tightens the test. If the given symref is "HEAD", we try to
detect if rebase is ongoing. If so return the branch being rebased. This
makes checkout and branch delete operations safer because you can't
checkout a branch being rebased in another place, or delete it.

Special case for checkout. If the current branch is being rebased,
git-rebase.sh may use "git checkout" to abort and return back to the
original branch. The updated test in find_shared_symref() will prevent
that and "git rebase --abort" will fail as a result.
find_shared_symref() and die_if_checked_out() have to learn a new
option ignore_current_worktree to loosen the test a bit.

Signed-off-by: Nguyễn Thái Ngọc Duy <[hidden email]>
---
 branch.c                |  4 ++--
 branch.h                |  2 +-
 builtin/checkout.c      |  2 +-
 builtin/worktree.c      |  4 ++--
 t/t2025-worktree-add.sh | 38 ++++++++++++++++++++++++++++++++++++++
 worktree.c              | 32 ++++++++++++++++++++++++++++++++
 6 files changed, 76 insertions(+), 6 deletions(-)

diff --git a/branch.c b/branch.c
index 1f1fbf5..a5a8dcb 100644
--- a/branch.c
+++ b/branch.c
@@ -334,12 +334,12 @@ void remove_branch_state(void)
  unlink(git_path_squash_msg());
 }
 
-void die_if_checked_out(const char *branch)
+void die_if_checked_out(const char *branch, int ignore_current_worktree)
 {
  const struct worktree *wt;
 
  wt = find_shared_symref("HEAD", branch);
- if (!wt)
+ if (!wt || (ignore_current_worktree && wt->is_current))
  return;
  skip_prefix(branch, "refs/heads/", &branch);
  die(_("'%s' is already checked out at '%s'"),
diff --git a/branch.h b/branch.h
index d69163d..b2f9649 100644
--- a/branch.h
+++ b/branch.h
@@ -58,7 +58,7 @@ extern int read_branch_desc(struct strbuf *, const char *branch_name);
  * worktree and die (with a message describing its checkout location) if
  * it is.
  */
-extern void die_if_checked_out(const char *branch);
+extern void die_if_checked_out(const char *branch, int ignore_current_worktree);
 
 /*
  * Update all per-worktree HEADs pointing at the old ref to point the new ref.
diff --git a/builtin/checkout.c b/builtin/checkout.c
index efcbd8f..6041718 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -1111,7 +1111,7 @@ static int checkout_branch(struct checkout_opts *opts,
  char *head_ref = resolve_refdup("HEAD", 0, sha1, &flag);
  if (head_ref &&
     (!(flag & REF_ISSYMREF) || strcmp(head_ref, new->path)))
- die_if_checked_out(new->path);
+ die_if_checked_out(new->path, 1);
  free(head_ref);
  }
 
diff --git a/builtin/worktree.c b/builtin/worktree.c
index d8e3795..12c0af7 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -205,7 +205,7 @@ static int add_worktree(const char *path, const char *refname,
  if (!opts->detach && !strbuf_check_branch_ref(&symref, refname) &&
  ref_exists(symref.buf)) { /* it's a branch */
  if (!opts->force)
- die_if_checked_out(symref.buf);
+ die_if_checked_out(symref.buf, 0);
  } else { /* must be a commit */
  commit = lookup_commit_reference_by_name(refname);
  if (!commit)
@@ -349,7 +349,7 @@ static int add(int ac, const char **av, const char *prefix)
  if (!opts.force &&
     !strbuf_check_branch_ref(&symref, opts.new_branch) &&
     ref_exists(symref.buf))
- die_if_checked_out(symref.buf);
+ die_if_checked_out(symref.buf, 0);
  strbuf_release(&symref);
  }
 
diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh
index 3acb992..da54327 100755
--- a/t/t2025-worktree-add.sh
+++ b/t/t2025-worktree-add.sh
@@ -4,6 +4,8 @@ test_description='test git worktree add'
 
 . ./test-lib.sh
 
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
 test_expect_success 'setup' '
  test_commit init
 '
@@ -225,4 +227,40 @@ test_expect_success '"add" worktree with --checkout' '
  test_cmp init.t swamp2/init.t
 '
 
+test_expect_success 'put a worktree under rebase' '
+ git worktree add under-rebase &&
+ (
+ cd under-rebase &&
+ set_fake_editor &&
+ FAKE_LINES="edit 1" git rebase -i HEAD^ &&
+ git worktree list | grep "under-rebase.*detached HEAD"
+ )
+'
+
+test_expect_success 'add a worktree, checking out a rebased branch' '
+ test_must_fail git worktree add new-rebase under-rebase &&
+ ! test -d new-rebase
+'
+
+test_expect_success 'checking out a rebased branch from another worktree' '
+ git worktree add new-place &&
+ test_must_fail git -C new-place checkout under-rebase
+'
+
+test_expect_success 'not allow to delete a branch under rebase' '
+ (
+ cd under-rebase &&
+ test_must_fail git branch -D under-rebase
+ )
+'
+
+test_expect_success 'check out from current worktree branch ok' '
+ (
+ cd under-rebase &&
+ git checkout under-rebase &&
+ git checkout - &&
+ git rebase --abort
+ )
+'
+
 test_done
diff --git a/worktree.c b/worktree.c
index 927905b..5043756 100644
--- a/worktree.c
+++ b/worktree.c
@@ -3,6 +3,7 @@
 #include "strbuf.h"
 #include "worktree.h"
 #include "dir.h"
+#include "wt-status.h"
 
 void free_worktrees(struct worktree **worktrees)
 {
@@ -215,6 +216,30 @@ const char *get_worktree_git_dir(const struct worktree *wt)
  return git_common_path("worktrees/%s", wt->id);
 }
 
+static int is_worktree_being_rebased(const struct worktree *wt,
+     const char *target)
+{
+ struct wt_status_state state;
+ int found_rebase;
+
+ memset(&state, 0, sizeof(state));
+ found_rebase = wt_status_check_rebase(wt, &state) &&
+ ((state.rebase_in_progress ||
+  state.rebase_interactive_in_progress) &&
+ state.branch &&
+ starts_with(target, "refs/heads/") &&
+ !strcmp(state.branch, target + strlen("refs/heads/")));
+ free(state.branch);
+ free(state.onto);
+ return found_rebase;
+}
+
+/*
+ * note: this function should be able to detect shared symref even if
+ * HEAD is temporarily detached (e.g. in the middle of rebase or
+ * bisect). New commands that do similar things should update this
+ * function as well.
+ */
 const struct worktree *find_shared_symref(const char *symref,
   const char *target)
 {
@@ -231,6 +256,13 @@ const struct worktree *find_shared_symref(const char *symref,
  for (i = 0; worktrees[i]; i++) {
  struct worktree *wt = worktrees[i];
 
+ if (wt->is_detached && !strcmp(symref, "HEAD")) {
+ if (is_worktree_being_rebased(wt, target)) {
+ existing = wt;
+ break;
+ }
+ }
+
  strbuf_reset(&path);
  strbuf_reset(&sb);
  strbuf_addf(&path, "%s/%s",
--
2.8.0.rc0.210.gd302cd2

--
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 v3 11/13] wt-status.c: split bisect detection out of wt_status_get_state()

Duy Nguyen
In reply to this post by Duy Nguyen
And make it work with any given worktree, in preparation for (again)
find_shared_symref(). read_and_strip_branch() is deleted because it's
no longer used.

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

diff --git a/wt-status.c b/wt-status.c
index ce5080c..0032ef5 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -1296,11 +1296,6 @@ got_nothing:
  return NULL;
 }
 
-static char *read_and_strip_branch(const char *path)
-{
- return get_branch(NULL, path);
-}
-
 struct grab_1st_switch_cbdata {
  struct strbuf buf;
  unsigned char nsha1[20];
@@ -1393,6 +1388,19 @@ int wt_status_check_rebase(const struct worktree *wt,
  return 1;
 }
 
+int wt_status_check_bisect(const struct worktree *wt,
+   struct wt_status_state *state)
+{
+ struct stat st;
+
+ if (!stat(worktree_git_path(wt, "BISECT_LOG"), &st)) {
+ state->bisect_in_progress = 1;
+ state->branch = get_branch(wt, "BISECT_START");
+ return 1;
+ }
+ return 0;
+}
+
 void wt_status_get_state(struct wt_status_state *state,
  int get_detached_from)
 {
@@ -1408,10 +1416,7 @@ void wt_status_get_state(struct wt_status_state *state,
  state->cherry_pick_in_progress = 1;
  hashcpy(state->cherry_pick_head_sha1, sha1);
  }
- if (!stat(git_path("BISECT_LOG"), &st)) {
- state->bisect_in_progress = 1;
- state->branch = read_and_strip_branch("BISECT_START");
- }
+ wt_status_check_bisect(NULL, state);
  if (!stat(git_path_revert_head(), &st) &&
     !get_sha1("REVERT_HEAD", sha1)) {
  state->revert_in_progress = 1;
diff --git a/wt-status.h b/wt-status.h
index c4ddcad..2ca93f6 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -104,6 +104,8 @@ void wt_status_collect(struct wt_status *s);
 void wt_status_get_state(struct wt_status_state *state, int get_detached_from);
 int wt_status_check_rebase(const struct worktree *wt,
    struct wt_status_state *state);
+int wt_status_check_bisect(const struct worktree *wt,
+   struct wt_status_state *state);
 
 void wt_shortstatus_print(struct wt_status *s);
 void wt_porcelain_print(struct wt_status *s);
--
2.8.0.rc0.210.gd302cd2

--
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 v3 12/13] worktree.c: check whether branch is bisected in another worktree

Duy Nguyen
In reply to this post by Duy Nguyen
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

Signed-off-by: Nguyễn Thái Ngọc Duy <[hidden email]>
---
 t/t2025-worktree-add.sh | 13 +++++++++++++
 worktree.c              | 19 +++++++++++++++++++
 2 files changed, 32 insertions(+)

diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh
index da54327..8f53944 100755
--- 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 &&
+ ! test -d new-bisect
+ )
+'
+
 test_done
diff --git a/worktree.c b/worktree.c
index 5043756..aab4b95 100644
--- a/worktree.c
+++ b/worktree.c
@@ -234,6 +234,21 @@ static int is_worktree_being_rebased(const struct worktree *wt,
  return found_rebase;
 }
 
+static int is_worktree_being_bisected(const struct worktree *wt,
+      const char *target)
+{
+ struct wt_status_state state;
+ int found_rebase;
+
+ 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;
+}
+
 /*
  * note: this function should be able to detect shared symref even if
  * HEAD is temporarily detached (e.g. in the middle of rebase or
@@ -261,6 +276,10 @@ const struct worktree *find_shared_symref(const char *symref,
  existing = wt;
  break;
  }
+ if (is_worktree_being_bisected(wt, target)) {
+ existing = wt;
+ break;
+ }
  }
 
  strbuf_reset(&path);
--
2.8.0.rc0.210.gd302cd2

--
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 v3 13/13] branch: do not rename a branch under bisect or rebase

Duy Nguyen
In reply to this post by Duy Nguyen
The branch name in that case could be saved in rebase's head_name or
bisect's BISECT_START files. Ideally we should try to update them as
well. But it's trickier (*). Let's play safe and see if the user
complains about inconveniences before doing that.

(*) If we do it, bisect and rebase need to provide an API to rename
branches. We can't do it in worktree.c or builtin/branch.c because
when other people change rebase/bisect code, they may not be aware of
this code and accidentally break it (e.g. rename the branch file, or
refer to the branch in new files). It's a lot more work.

Signed-off-by: Nguyễn Thái Ngọc Duy <[hidden email]>
---
 builtin/branch.c        | 25 +++++++++++++++++++++++++
 t/t2025-worktree-add.sh |  8 ++++++++
 worktree.c              |  8 ++++----
 worktree.h              |  3 +++
 4 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/builtin/branch.c b/builtin/branch.c
index bcde87d..b488c3f 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -524,6 +524,29 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin
  ref_array_clear(&array);
 }
 
+static void reject_rebase_or_bisect_branch(const char *target)
+{
+ struct worktree **worktrees = get_worktrees();
+ int i;
+
+ for (i = 0; worktrees[i]; i++) {
+ struct worktree *wt = worktrees[i];
+
+ if (!wt->is_detached)
+ continue;
+
+ if (is_worktree_being_rebased(wt, target))
+ die(_("Branch %s is being rebased at %s"),
+    target, wt->path);
+
+ if (is_worktree_being_bisected(wt, target))
+ die(_("Branch %s is being bisected at %s"),
+    target, wt->path);
+ }
+
+ free_worktrees(worktrees);
+}
+
 static void rename_branch(const char *oldname, const char *newname, int force)
 {
  struct strbuf oldref = STRBUF_INIT, newref = STRBUF_INIT, logmsg = STRBUF_INIT;
@@ -553,6 +576,8 @@ static void rename_branch(const char *oldname, const char *newname, int force)
 
  validate_new_branchname(newname, &newref, force, clobber_head_ok);
 
+ reject_rebase_or_bisect_branch(oldref.buf);
+
  strbuf_addf(&logmsg, "Branch: renamed %s to %s",
  oldref.buf, newref.buf);
 
diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh
index 8f53944..3a22fc5 100755
--- a/t/t2025-worktree-add.sh
+++ b/t/t2025-worktree-add.sh
@@ -254,6 +254,10 @@ test_expect_success 'not allow to delete a branch under rebase' '
  )
 '
 
+test_expect_success 'rename a branch under rebase not allowed' '
+ test_must_fail git branch -M under-rebase rebase-with-new-name
+'
+
 test_expect_success 'check out from current worktree branch ok' '
  (
  cd under-rebase &&
@@ -276,4 +280,8 @@ test_expect_success 'checkout a branch under bisect' '
  )
 '
 
+test_expect_success 'rename a branch under bisect not allowed' '
+ test_must_fail git branch -M under-bisect bisect-with-new-name
+'
+
 test_done
diff --git a/worktree.c b/worktree.c
index aab4b95..4817d60 100644
--- a/worktree.c
+++ b/worktree.c
@@ -216,8 +216,8 @@ const char *get_worktree_git_dir(const struct worktree *wt)
  return git_common_path("worktrees/%s", wt->id);
 }
 
-static int is_worktree_being_rebased(const struct worktree *wt,
-     const char *target)
+int is_worktree_being_rebased(const struct worktree *wt,
+      const char *target)
 {
  struct wt_status_state state;
  int found_rebase;
@@ -234,8 +234,8 @@ static int is_worktree_being_rebased(const struct worktree *wt,
  return found_rebase;
 }
 
-static int is_worktree_being_bisected(const struct worktree *wt,
-      const char *target)
+int is_worktree_being_bisected(const struct worktree *wt,
+       const char *target)
 {
  struct wt_status_state state;
  int found_rebase;
diff --git a/worktree.h b/worktree.h
index 0da8c1f..1394909 100644
--- a/worktree.h
+++ b/worktree.h
@@ -42,6 +42,9 @@ extern void free_worktrees(struct worktree **);
 extern const struct worktree *find_shared_symref(const char *symref,
  const char *target);
 
+int is_worktree_being_rebased(const struct worktree *wt, const char *target);
+int is_worktree_being_bisected(const struct worktree *wt, const char *target);
+
 /*
  * Similar to git_path() but can produce paths for a specified
  * worktree instead of current one
--
2.8.0.rc0.210.gd302cd2

--
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

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:

> Signed-off-by: Nguyễn Thái Ngọc Duy <[hidden email]>
> ---
> diff --git a/worktree.c b/worktree.c
> @@ -147,6 +150,25 @@ done:
> +static void mark_current_worktree(struct worktree **worktrees)
> +{
> +       struct strbuf git_dir = STRBUF_INIT;
> +       struct strbuf path = STRBUF_INIT;
> +       int i;
> +
> +       strbuf_addstr(&git_dir, absolute_path(get_git_dir()));

This could also just be:

    char *git_dir = xstrdup(absolute_path(...));

with a corresponding 'free(git_dir)' below.

> +       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);

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.

> +               strbuf_reset(&path);
> +               if (wt->is_current)
> +                       break;
> +       }
> +       strbuf_release(&git_dir);
> +       strbuf_release(&path);
> +}
--
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
On Fri, May 6, 2016 at 2:51 PM, Eric Sunshine <[hidden email]> wrote:

> On Fri, Apr 22, 2016 at 9:01 AM, Nguyễn Thái Ngọc Duy <[hidden email]> wrote:
>> Signed-off-by: Nguyễn Thái Ngọc Duy <[hidden email]>
>> ---
>> diff --git a/worktree.c b/worktree.c
>> @@ -147,6 +150,25 @@ done:
>> +static void mark_current_worktree(struct worktree **worktrees)
>> +{
>> +       struct strbuf git_dir = STRBUF_INIT;
>> +       struct strbuf path = STRBUF_INIT;
>> +       int i;
>> +
>> +       strbuf_addstr(&git_dir, absolute_path(get_git_dir()));
>
> This could also just be:
>
>     char *git_dir = xstrdup(absolute_path(...));
>
> with a corresponding 'free(git_dir)' below.
>
>> +       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);
>
> 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.
--
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
123456