From: Jonathan Tan <jonathantanmy@google.com>
To: git@vger.kernel.org
Cc: Jonathan Tan <jonathantanmy@google.com>,
gitster@pobox.com, jrnieder@gmail.com
Subject: [PATCH v2 2/2] wt-status: tolerate dangling marks
Date: Fri, 28 Aug 2020 18:02:27 -0700 [thread overview]
Message-ID: <59b91a206d9d7bf64825cb48c747730e28b10a79.1598662525.git.jonathantanmy@google.com> (raw)
In-Reply-To: <cover.1598662525.git.jonathantanmy@google.com>
When a user checks out the upstream branch of HEAD, the upstream branch
not being a local branch, and then runs "git status", like this:
git clone $URL client
cd client
git checkout @{u}
git status
no status is printed, but instead an error message:
fatal: HEAD does not point to a branch
(This error message when running "git branch" persists even after
checking out other things - it only stops after checking out a branch.)
This is because "git status" reads the reflog when determining the "HEAD
detached" message, and thus attempts to DWIM "@{u}", but that doesn't
work because HEAD no longer points to a branch.
Therefore, when calculating the status of a worktree, tolerate dangling
marks. This is done by adding an additional parameter to
repo_dwim_ref().
Signed-off-by: Jonathan Tan <jonathantanmy@google.com>
---
cache.h | 7 +++++++
refs.c | 16 ++++++++++------
refs.h | 3 ++-
sha1-name.c | 16 +++++++++++-----
t/t7508-status.sh | 12 ++++++++++++
wt-status.c | 2 +-
6 files changed, 43 insertions(+), 13 deletions(-)
diff --git a/cache.h b/cache.h
index 4f16a57ba4..cee8aa5dc3 100644
--- a/cache.h
+++ b/cache.h
@@ -1569,6 +1569,13 @@ struct interpret_branch_name_options {
* allowed, even ones to refs outside of those namespaces.
*/
unsigned allowed;
+
+ /*
+ * If ^{upstream} or ^{push} (or equivalent) is requested, and the
+ * branch in question does not have such a reference, return -1 instead
+ * of die()-ing.
+ */
+ unsigned nonfatal_dangling_mark : 1;
};
int repo_interpret_branch_name(struct repository *r,
const char *str, int len,
diff --git a/refs.c b/refs.c
index cf09cd039f..b6f1a2f452 100644
--- a/refs.c
+++ b/refs.c
@@ -598,10 +598,13 @@ const char *git_default_branch_name(void)
* to name a branch.
*/
static char *substitute_branch_name(struct repository *r,
- const char **string, int *len)
+ const char **string, int *len,
+ int nonfatal_dangling_mark)
{
struct strbuf buf = STRBUF_INIT;
- struct interpret_branch_name_options options = { 0 } ;
+ struct interpret_branch_name_options options = {
+ .nonfatal_dangling_mark = nonfatal_dangling_mark
+ };
int ret = repo_interpret_branch_name(r, *string, *len, &buf, &options);
if (ret == *len) {
@@ -615,9 +618,10 @@ static char *substitute_branch_name(struct repository *r,
}
int repo_dwim_ref(struct repository *r, const char *str, int len,
- struct object_id *oid, char **ref)
+ struct object_id *oid, char **ref, int nonfatal_dangling_mark)
{
- char *last_branch = substitute_branch_name(r, &str, &len);
+ char *last_branch = substitute_branch_name(r, &str, &len,
+ nonfatal_dangling_mark);
int refs_found = expand_ref(r, str, len, oid, ref);
free(last_branch);
return refs_found;
@@ -625,7 +629,7 @@ int repo_dwim_ref(struct repository *r, const char *str, int len,
int dwim_ref(const char *str, int len, struct object_id *oid, char **ref)
{
- return repo_dwim_ref(the_repository, str, len, oid, ref);
+ return repo_dwim_ref(the_repository, str, len, oid, ref, 0);
}
int expand_ref(struct repository *repo, const char *str, int len,
@@ -666,7 +670,7 @@ int repo_dwim_log(struct repository *r, const char *str, int len,
struct object_id *oid, char **log)
{
struct ref_store *refs = get_main_ref_store(r);
- char *last_branch = substitute_branch_name(r, &str, &len);
+ char *last_branch = substitute_branch_name(r, &str, &len, 0);
const char **p;
int logs_found = 0;
struct strbuf path = STRBUF_INIT;
diff --git a/refs.h b/refs.h
index 29e28124cd..b94a7fd4f7 100644
--- a/refs.h
+++ b/refs.h
@@ -149,7 +149,8 @@ struct strvec;
void expand_ref_prefix(struct strvec *prefixes, const char *prefix);
int expand_ref(struct repository *r, const char *str, int len, struct object_id *oid, char **ref);
-int repo_dwim_ref(struct repository *r, const char *str, int len, struct object_id *oid, char **ref);
+int repo_dwim_ref(struct repository *r, const char *str, int len,
+ struct object_id *oid, char **ref, int nonfatal_dangling_mark);
int repo_dwim_log(struct repository *r, const char *str, int len, struct object_id *oid, char **ref);
int dwim_ref(const char *str, int len, struct object_id *oid, char **ref);
int dwim_log(const char *str, int len, struct object_id *oid, char **ref);
diff --git a/sha1-name.c b/sha1-name.c
index a7a9de66c4..0b23b86ceb 100644
--- a/sha1-name.c
+++ b/sha1-name.c
@@ -809,7 +809,7 @@ static int get_oid_basic(struct repository *r, const char *str, int len,
if (len == r->hash_algo->hexsz && !get_oid_hex(str, oid)) {
if (warn_ambiguous_refs && warn_on_object_refname_ambiguity) {
- refs_found = repo_dwim_ref(r, str, len, &tmp_oid, &real_ref);
+ refs_found = repo_dwim_ref(r, str, len, &tmp_oid, &real_ref, 0);
if (refs_found > 0) {
warning(warn_msg, len, str);
if (advice_object_name_warning)
@@ -860,11 +860,11 @@ static int get_oid_basic(struct repository *r, const char *str, int len,
if (!len && reflog_len)
/* allow "@{...}" to mean the current branch reflog */
- refs_found = repo_dwim_ref(r, "HEAD", 4, oid, &real_ref);
+ refs_found = repo_dwim_ref(r, "HEAD", 4, oid, &real_ref, 0);
else if (reflog_len)
refs_found = repo_dwim_log(r, str, len, oid, &real_ref);
else
- refs_found = repo_dwim_ref(r, str, len, oid, &real_ref);
+ refs_found = repo_dwim_ref(r, str, len, oid, &real_ref, 0);
if (!refs_found)
return -1;
@@ -1496,8 +1496,14 @@ static int interpret_branch_mark(struct repository *r,
branch = branch_get(NULL);
value = get_data(branch, &err);
- if (!value)
- die("%s", err.buf);
+ if (!value) {
+ if (options->nonfatal_dangling_mark) {
+ strbuf_release(&err);
+ return -1;
+ } else {
+ die("%s", err.buf);
+ }
+ }
if (!branch_interpret_allowed(value, options->allowed))
return -1;
diff --git a/t/t7508-status.sh b/t/t7508-status.sh
index e81759319f..45e1f6ff68 100755
--- a/t/t7508-status.sh
+++ b/t/t7508-status.sh
@@ -846,6 +846,18 @@ test_expect_success 'status refreshes the index' '
test_cmp expect output
'
+test_expect_success 'status shows detached HEAD properly after checking out non-local upstream branch' '
+ test_when_finished rm -rf upstream downstream actual &&
+
+ test_create_repo upstream &&
+ test_commit -C upstream foo &&
+
+ git clone upstream downstream &&
+ git -C downstream checkout @{u} &&
+ git -C downstream status >actual &&
+ test_i18ngrep "HEAD detached at [0-9a-f]\\+" actual
+'
+
test_expect_success 'setup status submodule summary' '
test_create_repo sm && (
cd sm &&
diff --git a/wt-status.c b/wt-status.c
index 7ce58b8aae..ae16faf40d 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -1569,7 +1569,7 @@ static void wt_status_get_detached_from(struct repository *r,
return;
}
- if (dwim_ref(cb.buf.buf, cb.buf.len, &oid, &ref) == 1 &&
+ if (repo_dwim_ref(the_repository, cb.buf.buf, cb.buf.len, &oid, &ref, 1) == 1 &&
/* sha1 is a commit? match without further lookup */
(oideq(&cb.noid, &oid) ||
/* perhaps sha1 is a tag, try to dereference to a commit */
--
2.28.0.402.g5ffc5be6b7-goog
next prev parent reply other threads:[~2020-08-29 1:02 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-05-13 0:40 [PATCH] wt-status: expand, not dwim, a "detached from" ref Jonathan Tan
2020-05-13 5:33 ` Junio C Hamano
2020-05-13 14:59 ` Junio C Hamano
2020-05-18 22:24 ` Jonathan Tan
2020-08-27 1:47 ` Jonathan Nieder
2020-08-27 2:10 ` Junio C Hamano
2020-08-29 1:02 ` [PATCH v2 0/2] Fix for git checkout @{u} (non-local) then git status Jonathan Tan
2020-08-29 1:02 ` [PATCH v2 1/2] sha1-name: replace unsigned int with option struct Jonathan Tan
2020-08-29 18:44 ` Junio C Hamano
2020-08-29 1:02 ` Jonathan Tan [this message]
2020-08-29 18:55 ` [PATCH v2 2/2] wt-status: tolerate dangling marks Junio C Hamano
2020-08-31 17:17 ` Jonathan Tan
2020-08-31 17:37 ` Junio C Hamano
2020-09-01 22:28 ` [PATCH v3 0/3] Fix for git checkout @{u} (non-local) then git status Jonathan Tan
2020-09-01 22:28 ` [PATCH v3 1/3] sha1-name: replace unsigned int with option struct Jonathan Tan
2020-09-01 22:28 ` [PATCH v3 2/3] refs: move dwim_ref() to header file Jonathan Tan
2020-09-01 22:28 ` [PATCH v3 3/3] wt-status: tolerate dangling marks Jonathan Tan
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=59b91a206d9d7bf64825cb48c747730e28b10a79.1598662525.git.jonathantanmy@google.com \
--to=jonathantanmy@google.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=jrnieder@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).