From: Jay Soffian <jaysoffian@gmail.com>
To: git@vger.kernel.org
Cc: Jay Soffian <jaysoffian@gmail.com>,
Nguyen Thai Ngoc Duy <pclouds@gmail.com>,
Junio C Hamano <gitster@pobox.com>
Subject: Re: [RFC/PATCH] Add multiple workdir support to branch/checkout
Date: Wed, 5 Oct 2011 12:01:09 -0400 [thread overview]
Message-ID: <1317830469-72878-1-git-send-email-jaysoffian@gmail.com> (raw)
In-Reply-To: <1317828285-66581-1-git-send-email-jaysoffian@gmail.com>
> I was more looking for feedback on the idea than the implementation, but
> here's a better implementation. Still an RFC so no tests yet.
Oops. Let's try that again. Sent the wrong thing.
-- >8 --
Subject: [RFC/PATCH] Teach branch/checkout about workdirs
When using 'git new-workdir', there is no safety mechanism to prevent the
same branch from being checked out twice, nor to prevent a checked out
branch from being deleted.
Teach 'checkout' to record the workdir path using 'branch.<name>.checkout'
when switching branches. We can then easily check if a branch is already
checked out in another workdir before switching to that branch. Add a
similar check before deleting a branch.
Allow 'checkout -f' to force the checkout and issue a warning instead of
an error.
Guard this behavior behind 'core.recordCheckouts', which we will teach
'git new-workdir' to set in a followup commit.
Note: when switching away from a branch, we set 'branch.<name>.checkout'
to the empty string, instead of deleting it entirely, since git_config()
otherwise leaves behind an empty section which it does not re-use.
Signed-off-by: Jay Soffian <jaysoffian@gmail.com>
---
builtin/branch.c | 10 ++++++++++
builtin/checkout.c | 43 +++++++++++++++++++++++++++++++++++++++++++
remote.c | 4 ++++
remote.h | 1 +
4 files changed, 58 insertions(+), 0 deletions(-)
diff --git a/builtin/branch.c b/builtin/branch.c
index f49596f826..6ce1a5b133 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -182,6 +182,16 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)
ret = 1;
continue;
}
+ if (kinds == REF_LOCAL_BRANCH) {
+ struct branch *branch = branch_get(bname.buf);
+ if (branch->work_tree && strlen(branch->work_tree)) {
+ error(_("Cannot delete the branch '%s' "
+ "which is currently checked out in '%s'"),
+ bname.buf, branch->work_tree);
+ ret = 1;
+ continue;
+ }
+ }
free(name);
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 5e356a6c61..75510befde 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -33,6 +33,7 @@ struct checkout_opts {
int force_detach;
int writeout_stage;
int writeout_error;
+ int record_checkouts;
/* not set by parse_options */
int branch_exists;
@@ -508,6 +509,21 @@ static void detach_advice(const char *old_path, const char *new_name)
fprintf(stderr, fmt, new_name);
}
+static void record_checkout(const char *name, const char *new_work_tree)
+{
+ struct strbuf key = STRBUF_INIT;
+ strbuf_addf(&key, "branch.%s.checkout", name);
+ if (new_work_tree) { /* reserve name */
+ git_config_set(key.buf, new_work_tree);
+ } else { /* release name if we reserved it */
+ struct branch *branch = branch_get(name);
+ if (branch->work_tree &&
+ !strcmp(branch->work_tree, get_git_work_tree()))
+ git_config_set(key.buf, "");
+ }
+ strbuf_release(&key);
+}
+
static void update_refs_for_switch(struct checkout_opts *opts,
struct branch_info *old,
struct branch_info *new)
@@ -556,6 +572,8 @@ static void update_refs_for_switch(struct checkout_opts *opts,
detach_advice(old->path, new->name);
describe_detached_head(_("HEAD is now at"), new->commit);
}
+ if (opts->record_checkouts && old->name)
+ record_checkout(old->name, NULL);
} else if (new->path) { /* Switch branches. */
create_symref("HEAD", new->path, msg.buf);
if (!opts->quiet) {
@@ -580,6 +598,11 @@ static void update_refs_for_switch(struct checkout_opts *opts,
if (!file_exists(ref_file) && file_exists(log_file))
remove_path(log_file);
}
+ if (opts->record_checkouts) {
+ if (old->name)
+ record_checkout(old->name, NULL);
+ record_checkout(new->name, get_git_work_tree());
+ }
}
remove_branch_state();
strbuf_release(&msg);
@@ -709,6 +732,20 @@ static void orphaned_commit_warning(struct commit *commit)
for_each_ref(clear_commit_marks_from_one_ref, NULL);
}
+static void check_if_checked_out(struct checkout_opts *opts, const char *name)
+{
+ struct branch *branch = branch_get(name);
+ if (branch->work_tree && strlen(branch->work_tree) &&
+ strcmp(branch->work_tree, get_git_work_tree())) {
+ if (opts->force)
+ warning(_("branch '%s' is currently checked out"
+ " in '%s'"), name, branch->work_tree);
+ else
+ die(_("branch '%s' is currently checked out"
+ " in '%s'"), name, branch->work_tree);
+ }
+}
+
static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
{
int ret = 0;
@@ -732,6 +769,8 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
if (!new->commit)
die(_("You are on a branch yet to be born"));
parse_commit(new->commit);
+ } else if (opts->record_checkouts) {
+ check_if_checked_out(opts, new->name);
}
ret = merge_working_tree(opts, &old, new);
@@ -756,6 +795,10 @@ static int git_checkout_config(const char *var, const char *value, void *cb)
return 0;
}
+ if (!strcmp(var, "core.recordcheckouts")) {
+ struct checkout_opts *opts = cb;
+ opts->record_checkouts = git_config_bool(var, value);
+ }
if (!prefixcmp(var, "submodule."))
return parse_submodule_config_option(var, value);
diff --git a/remote.c b/remote.c
index b8ecfa5d95..2bc063dae8 100644
--- a/remote.c
+++ b/remote.c
@@ -364,6 +364,10 @@ static int handle_config(const char *key, const char *value, void *cb)
if (!value)
return config_error_nonbool(key);
add_merge(branch, xstrdup(value));
+ } else if (!strcmp(subkey, ".checkout")) {
+ if (!value)
+ return config_error_nonbool(key);
+ branch->work_tree = xstrdup(value);
}
return 0;
}
diff --git a/remote.h b/remote.h
index 9a30a9dba6..4103ec7e31 100644
--- a/remote.h
+++ b/remote.h
@@ -126,6 +126,7 @@ int remote_find_tracking(struct remote *remote, struct refspec *refspec);
struct branch {
const char *name;
const char *refname;
+ const char *work_tree;
const char *remote_name;
struct remote *remote;
--
1.7.7.5.gd207e.dirty
next prev parent reply other threads:[~2011-10-05 16:01 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-10-05 3:43 [RFC/PATCH] Add multiple workdir support to branch/checkout Jay Soffian
2011-10-05 3:48 ` Jay Soffian
2011-10-05 4:02 ` Nguyen Thai Ngoc Duy
2011-10-05 13:11 ` Jay Soffian
2011-10-05 16:46 ` Junio C Hamano
2011-10-05 17:17 ` Jay Soffian
2011-10-05 18:19 ` Junio C Hamano
2011-10-05 19:11 ` Jay Soffian
2011-10-05 20:00 ` Andreas Krey
2011-10-05 20:50 ` Jay Soffian
2011-10-05 21:30 ` Jonathan Nieder
2011-10-05 21:52 ` Jay Soffian
2011-10-05 21:57 ` Jonathan Nieder
2011-10-05 21:29 ` Junio C Hamano
2011-10-05 21:49 ` Jay Soffian
2011-10-05 19:14 ` Jay Soffian
2011-10-05 22:47 ` Nguyen Thai Ngoc Duy
2011-10-05 22:56 ` Junio C Hamano
2011-10-05 23:11 ` Nguyen Thai Ngoc Duy
2011-10-05 23:49 ` Junio C Hamano
2011-10-06 0:33 ` Jay Soffian
2011-10-06 0:43 ` Junio C Hamano
2011-10-06 0:57 ` Jay Soffian
2011-10-06 1:15 ` Junio C Hamano
2011-10-06 1:38 ` Jay Soffian
2011-10-06 1:57 ` Junio C Hamano
2011-10-06 4:02 ` Jay Soffian
2011-10-06 2:06 ` Nguyen Thai Ngoc Duy
2011-10-06 11:25 ` Bernhard R. Link
2011-10-06 14:42 ` Jeff King
2011-10-05 22:38 ` Nguyen Thai Ngoc Duy
2011-10-05 4:07 ` Junio C Hamano
2011-10-05 15:24 ` Jay Soffian
2011-10-05 16:01 ` Jay Soffian [this message]
2011-10-08 22:55 ` Julián Landerreche
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1317830469-72878-1-git-send-email-jaysoffian@gmail.com \
--to=jaysoffian@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=pclouds@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).