Skip to content

Commit b6d323f

Browse files
committed
Merge branch 'dt/refs-backend-preamble'
In preparation for allowing different "backends" to store the refs in a way different from the traditional "one ref per file in $GIT_DIR or in a $GIT_DIR/packed-refs file" filesystem storage, reduce direct filesystem access to ref-like things like CHERRY_PICK_HEAD from scripts and programs. * dt/refs-backend-preamble: git-stash: use update-ref --create-reflog instead of creating files update-ref and tag: add --create-reflog arg refs: add REF_FORCE_CREATE_REFLOG flag git-reflog: add exists command refs: new public ref function: safe_create_reflog refs: break out check for reflog autocreation refs.c: add err arguments to reflog functions
2 parents 8348bf1 + 89dea97 commit b6d323f

File tree

13 files changed

+239
-86
lines changed

13 files changed

+239
-86
lines changed

Documentation/git-reflog.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ depending on the subcommand:
2323
[--dry-run] [--verbose] [--all | <refs>...]
2424
'git reflog delete' [--rewrite] [--updateref]
2525
[--dry-run] [--verbose] ref@\{specifier\}...
26+
'git reflog exists' <ref>
2627

2728
Reference logs, or "reflogs", record when the tips of branches and
2829
other references were updated in the local repository. Reflogs are
@@ -52,6 +53,9 @@ argument must be an _exact_ entry (e.g. "`git reflog delete
5253
master@{2}`"). This subcommand is also typically not used directly by
5354
end users.
5455

56+
The "exists" subcommand checks whether a ref has a reflog. It exits
57+
with zero status if the reflog exists, and non-zero status if it does
58+
not.
5559

5660
OPTIONS
5761
-------

Documentation/git-tag.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ SYNOPSIS
1313
<tagname> [<commit> | <object>]
1414
'git tag' -d <tagname>...
1515
'git tag' [-n[<num>]] -l [--contains <commit>] [--points-at <object>]
16-
[--column[=<options>] | --no-column] [<pattern>...]
16+
[--column[=<options>] | --no-column] [--create-reflog] [<pattern>...]
1717
'git tag' -v <tagname>...
1818

1919
DESCRIPTION
@@ -142,6 +142,9 @@ This option is only applicable when listing tags without annotation lines.
142142
all, 'whitespace' removes just leading/trailing whitespace lines and
143143
'strip' removes both whitespace and commentary.
144144

145+
--create-reflog::
146+
Create a reflog for the tag.
147+
145148
<tagname>::
146149
The name of the tag to create, delete, or describe.
147150
The new tag name must pass all checks defined by

Documentation/git-update-ref.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ git-update-ref - Update the object name stored in a ref safely
88
SYNOPSIS
99
--------
1010
[verse]
11-
'git update-ref' [-m <reason>] (-d <ref> [<oldvalue>] | [--no-deref] <ref> <newvalue> [<oldvalue>] | --stdin [-z])
11+
'git update-ref' [-m <reason>] (-d <ref> [<oldvalue>] | [--no-deref] [--create-reflog] <ref> <newvalue> [<oldvalue>] | --stdin [-z])
1212

1313
DESCRIPTION
1414
-----------
@@ -67,6 +67,9 @@ performs all modifications together. Specify commands of the form:
6767
verify SP <ref> [SP <oldvalue>] LF
6868
option SP <opt> LF
6969

70+
With `--create-reflog`, update-ref will create a reflog for each ref
71+
even if one would not ordinarily be created.
72+
7073
Quote fields containing whitespace as if they were strings in C source
7174
code; i.e., surrounded by double-quotes and with backslash escapes.
7275
Use 40 "0" characters or the empty string to specify a zero value. To

builtin/checkout.c

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -612,22 +612,20 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
612612
if (opts->new_branch) {
613613
if (opts->new_orphan_branch) {
614614
if (opts->new_branch_log && !log_all_ref_updates) {
615-
int temp;
616-
struct strbuf log_file = STRBUF_INIT;
617615
int ret;
618-
const char *ref_name;
619-
620-
ref_name = mkpath("refs/heads/%s", opts->new_orphan_branch);
621-
temp = log_all_ref_updates;
622-
log_all_ref_updates = 1;
623-
ret = log_ref_setup(ref_name, &log_file);
624-
log_all_ref_updates = temp;
625-
strbuf_release(&log_file);
616+
char *refname;
617+
struct strbuf err = STRBUF_INIT;
618+
619+
refname = mkpathdup("refs/heads/%s", opts->new_orphan_branch);
620+
ret = safe_create_reflog(refname, 1, &err);
621+
free(refname);
626622
if (ret) {
627-
fprintf(stderr, _("Can not do reflog for '%s'\n"),
628-
opts->new_orphan_branch);
623+
fprintf(stderr, _("Can not do reflog for '%s': %s\n"),
624+
opts->new_orphan_branch, err.buf);
625+
strbuf_release(&err);
629626
return;
630627
}
628+
strbuf_release(&err);
631629
}
632630
}
633631
else

builtin/reflog.c

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ static const char reflog_expire_usage[] =
1313
"git reflog expire [--expire=<time>] [--expire-unreachable=<time>] [--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] [--verbose] [--all] <refs>...";
1414
static const char reflog_delete_usage[] =
1515
"git reflog delete [--rewrite] [--updateref] [--dry-run | -n] [--verbose] <refs>...";
16+
static const char reflog_exists_usage[] =
17+
"git reflog exists <ref>";
1618

1719
static unsigned long default_reflog_expire;
1820
static unsigned long default_reflog_expire_unreachable;
@@ -699,12 +701,38 @@ static int cmd_reflog_delete(int argc, const char **argv, const char *prefix)
699701
return status;
700702
}
701703

704+
static int cmd_reflog_exists(int argc, const char **argv, const char *prefix)
705+
{
706+
int i, start = 0;
707+
708+
for (i = 1; i < argc; i++) {
709+
const char *arg = argv[i];
710+
if (!strcmp(arg, "--")) {
711+
i++;
712+
break;
713+
}
714+
else if (arg[0] == '-')
715+
usage(reflog_exists_usage);
716+
else
717+
break;
718+
}
719+
720+
start = i;
721+
722+
if (argc - start != 1)
723+
usage(reflog_exists_usage);
724+
725+
if (check_refname_format(argv[start], REFNAME_ALLOW_ONELEVEL))
726+
die("invalid ref format: %s", argv[start]);
727+
return !reflog_exists(argv[start]);
728+
}
729+
702730
/*
703731
* main "reflog"
704732
*/
705733

706734
static const char reflog_usage[] =
707-
"git reflog [ show | expire | delete ]";
735+
"git reflog [ show | expire | delete | exists ]";
708736

709737
int cmd_reflog(int argc, const char **argv, const char *prefix)
710738
{
@@ -724,5 +752,8 @@ int cmd_reflog(int argc, const char **argv, const char *prefix)
724752
if (!strcmp(argv[1], "delete"))
725753
return cmd_reflog_delete(argc - 1, argv + 1, prefix);
726754

755+
if (!strcmp(argv[1], "exists"))
756+
return cmd_reflog_exists(argc - 1, argv + 1, prefix);
757+
727758
return cmd_log_reflog(argc, argv, prefix);
728759
}

builtin/tag.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
579579
struct create_tag_options opt;
580580
char *cleanup_arg = NULL;
581581
int annotate = 0, force = 0, lines = -1;
582+
int create_reflog = 0;
582583
int cmdmode = 0;
583584
const char *msgfile = NULL, *keyid = NULL;
584585
struct msg_arg msg = { 0, STRBUF_INIT };
@@ -605,6 +606,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
605606
OPT_STRING('u', "local-user", &keyid, N_("key-id"),
606607
N_("use another key to sign the tag")),
607608
OPT__FORCE(&force, N_("replace the tag if exists")),
609+
OPT_BOOL(0, "create-reflog", &create_reflog, N_("create_reflog")),
608610

609611
OPT_GROUP(N_("Tag listing options")),
610612
OPT_COLUMN(0, "column", &colopts, N_("show tag list in columns")),
@@ -733,7 +735,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
733735
transaction = ref_transaction_begin(&err);
734736
if (!transaction ||
735737
ref_transaction_update(transaction, ref.buf, object, prev,
736-
0, NULL, &err) ||
738+
create_reflog ? REF_FORCE_CREATE_REFLOG : 0,
739+
NULL, &err) ||
737740
ref_transaction_commit(transaction, &err))
738741
die("%s", err.buf);
739742
ref_transaction_free(transaction);

builtin/update-ref.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ static const char * const git_update_ref_usage[] = {
1414

1515
static char line_termination = '\n';
1616
static int update_flags;
17+
static unsigned create_reflog_flag;
1718
static const char *msg;
1819

1920
/*
@@ -200,7 +201,8 @@ static const char *parse_cmd_update(struct ref_transaction *transaction,
200201

201202
if (ref_transaction_update(transaction, refname,
202203
new_sha1, have_old ? old_sha1 : NULL,
203-
update_flags, msg, &err))
204+
update_flags | create_reflog_flag,
205+
msg, &err))
204206
die("%s", err.buf);
205207

206208
update_flags = 0;
@@ -231,7 +233,8 @@ static const char *parse_cmd_create(struct ref_transaction *transaction,
231233
die("create %s: extra input: %s", refname, next);
232234

233235
if (ref_transaction_create(transaction, refname, new_sha1,
234-
update_flags, msg, &err))
236+
update_flags | create_reflog_flag,
237+
msg, &err))
235238
die("%s", err.buf);
236239

237240
update_flags = 0;
@@ -354,13 +357,15 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
354357
unsigned char sha1[20], oldsha1[20];
355358
int delete = 0, no_deref = 0, read_stdin = 0, end_null = 0;
356359
unsigned int flags = 0;
360+
int create_reflog = 0;
357361
struct option options[] = {
358362
OPT_STRING( 'm', NULL, &msg, N_("reason"), N_("reason of the update")),
359363
OPT_BOOL('d', NULL, &delete, N_("delete the reference")),
360364
OPT_BOOL( 0 , "no-deref", &no_deref,
361365
N_("update <refname> not the one it points to")),
362366
OPT_BOOL('z', NULL, &end_null, N_("stdin has NUL-terminated arguments")),
363367
OPT_BOOL( 0 , "stdin", &read_stdin, N_("read updates from stdin")),
368+
OPT_BOOL( 0 , "create-reflog", &create_reflog, N_("create_reflog")),
364369
OPT_END(),
365370
};
366371

@@ -370,6 +375,8 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
370375
if (msg && !*msg)
371376
die("Refusing to perform update with empty message.");
372377

378+
create_reflog_flag = create_reflog ? REF_FORCE_CREATE_REFLOG : 0;
379+
373380
if (read_stdin) {
374381
struct strbuf err = STRBUF_INIT;
375382
struct ref_transaction *transaction;
@@ -431,5 +438,6 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
431438
flags);
432439
else
433440
return update_ref(msg, refname, sha1, oldval ? oldsha1 : NULL,
434-
flags, UPDATE_REFS_DIE_ON_ERR);
441+
flags | create_reflog_flag,
442+
UPDATE_REFS_DIE_ON_ERR);
435443
}

git-stash.sh

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,7 @@ store_stash () {
183183
stash_msg="Created via \"git stash store\"."
184184
fi
185185

186-
# Make sure the reflog for stash is kept.
187-
: >>"$(git rev-parse --git-path logs/$ref_stash)"
188-
git update-ref -m "$stash_msg" $ref_stash $w_commit
186+
git update-ref --create-reflog -m "$stash_msg" $ref_stash $w_commit
189187
ret=$?
190188
test $ret != 0 && test -z $quiet &&
191189
die "$(eval_gettext "Cannot update \$ref_stash with \$w_commit")"
@@ -262,7 +260,7 @@ save_stash () {
262260
say "$(gettext "No local changes to save")"
263261
exit 0
264262
fi
265-
test -f "$(git rev-parse --git-path logs/$ref_stash)" ||
263+
git reflog exists $ref_stash ||
266264
clear_stash || die "$(gettext "Cannot initialize stash")"
267265

268266
create_stash "$stash_msg" $untracked

0 commit comments

Comments
 (0)