summaryrefslogtreecommitdiff
path: root/builtin/reflog.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2018-11-13 13:37:26 (GMT)
committerJunio C Hamano <gitster@pobox.com>2018-11-13 13:37:26 (GMT)
commite146cc97be4c054c60d38e9f4edcdc33205bf563 (patch)
treeb36de8c572922ac1c0fda47c028cd7ccd8fd7a35 /builtin/reflog.c
parent11aa560de964e800aabce446d600ab0fb4c90c20 (diff)
parent14f74d59072c7bf0586b15165538373bed898f18 (diff)
downloadgit-e146cc97be4c054c60d38e9f4edcdc33205bf563.zip
git-e146cc97be4c054c60d38e9f4edcdc33205bf563.tar.gz
git-e146cc97be4c054c60d38e9f4edcdc33205bf563.tar.bz2
Merge branch 'nd/per-worktree-ref-iteration'
The code to traverse objects for reachability, used to decide what objects are unreferenced and expendable, have been taught to also consider per-worktree refs of other worktrees as starting points to prevent data loss. * nd/per-worktree-ref-iteration: git-worktree.txt: correct linkgit command name reflog expire: cover reflog from all worktrees fsck: check HEAD and reflog from other worktrees fsck: move fsck_head_link() to get_default_heads() to avoid some globals revision.c: better error reporting on ref from different worktrees revision.c: correct a parameter name refs: new ref types to make per-worktree refs visible to all worktrees Add a place for (not) sharing stuff between worktrees refs.c: indent with tabs, not spaces
Diffstat (limited to 'builtin/reflog.c')
-rw-r--r--builtin/reflog.c46
1 files changed, 42 insertions, 4 deletions
diff --git a/builtin/reflog.c b/builtin/reflog.c
index b5941c1..7a85e4b 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -10,6 +10,7 @@
#include "diff.h"
#include "revision.h"
#include "reachable.h"
+#include "worktree.h"
/* NEEDSWORK: switch to using parse_options */
static const char reflog_expire_usage[] =
@@ -52,6 +53,7 @@ struct collect_reflog_cb {
struct collected_reflog **e;
int alloc;
int nr;
+ struct worktree *wt;
};
/* Remember to update object flag allocation in object.h */
@@ -330,13 +332,27 @@ static int push_tip_to_list(const char *refname, const struct object_id *oid,
return 0;
}
+static int is_head(const char *refname)
+{
+ switch (ref_type(refname)) {
+ case REF_TYPE_OTHER_PSEUDOREF:
+ case REF_TYPE_MAIN_PSEUDOREF:
+ if (parse_worktree_ref(refname, NULL, NULL, &refname))
+ BUG("not a worktree ref: %s", refname);
+ break;
+ default:
+ break;
+ }
+ return !strcmp(refname, "HEAD");
+}
+
static void reflog_expiry_prepare(const char *refname,
const struct object_id *oid,
void *cb_data)
{
struct expire_reflog_policy_cb *cb = cb_data;
- if (!cb->cmd.expire_unreachable || !strcmp(refname, "HEAD")) {
+ if (!cb->cmd.expire_unreachable || is_head(refname)) {
cb->tip_commit = NULL;
cb->unreachable_expire_kind = UE_HEAD;
} else {
@@ -388,8 +404,19 @@ static int collect_reflog(const char *ref, const struct object_id *oid, int unus
{
struct collected_reflog *e;
struct collect_reflog_cb *cb = cb_data;
+ struct strbuf newref = STRBUF_INIT;
+
+ /*
+ * Avoid collecting the same shared ref multiple times because
+ * they are available via all worktrees.
+ */
+ if (!cb->wt->is_current && ref_type(ref) == REF_TYPE_NORMAL)
+ return 0;
+
+ strbuf_worktree_ref(cb->wt, &newref, ref);
+ FLEX_ALLOC_STR(e, reflog, newref.buf);
+ strbuf_release(&newref);
- FLEX_ALLOC_STR(e, reflog, ref);
oidcpy(&e->oid, oid);
ALLOC_GROW(cb->e, cb->nr + 1, cb->alloc);
cb->e[cb->nr++] = e;
@@ -512,7 +539,7 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
{
struct expire_reflog_policy_cb cb;
timestamp_t now = time(NULL);
- int i, status, do_all;
+ int i, status, do_all, all_worktrees = 1;
int explicit_expiry = 0;
unsigned int flags = 0;
@@ -549,6 +576,8 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
flags |= EXPIRE_REFLOGS_UPDATE_REF;
else if (!strcmp(arg, "--all"))
do_all = 1;
+ else if (!strcmp(arg, "--single-worktree"))
+ all_worktrees = 0;
else if (!strcmp(arg, "--verbose"))
flags |= EXPIRE_REFLOGS_VERBOSE;
else if (!strcmp(arg, "--")) {
@@ -577,10 +606,19 @@ static int cmd_reflog_expire(int argc, const char **argv, const char *prefix)
if (do_all) {
struct collect_reflog_cb collected;
+ struct worktree **worktrees, **p;
int i;
memset(&collected, 0, sizeof(collected));
- for_each_reflog(collect_reflog, &collected);
+ worktrees = get_worktrees(0);
+ for (p = worktrees; *p; p++) {
+ if (!all_worktrees && !(*p)->is_current)
+ continue;
+ collected.wt = *p;
+ refs_for_each_reflog(get_worktree_ref_store(*p),
+ collect_reflog, &collected);
+ }
+ free_worktrees(worktrees);
for (i = 0; i < collected.nr; i++) {
struct collected_reflog *e = collected.e[i];
set_reflog_expiry_param(&cb.cmd, explicit_expiry, e->reflog);