Skip to content

Commit 0974341

Browse files
hanwengitster
authored andcommitted
Modify pseudo refs through ref backend storage
The previous behavior was introduced in commit 74ec19d ("pseudorefs: create and use pseudoref update and delete functions", Jul 31, 2015), with the justification "alternate ref backends still need to store pseudorefs in GIT_DIR". Refs such as REBASE_HEAD are read through the ref backend. This can only work consistently if they are written through the ref backend as well. Tooling that works directly on files under .git should be updated to use git commands to read refs instead. The following behaviors change: * Updates to pseudorefs (eg. ORIG_HEAD) with core.logAllRefUpdates=always will create reflogs for the pseudoref. * non-HEAD pseudoref symrefs are also dereferenced on deletion. Update t1405 accordingly. Signed-off-by: Han-Wen Nienhuys <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 0b7de6c commit 0974341

File tree

4 files changed

+23
-125
lines changed

4 files changed

+23
-125
lines changed

Documentation/git-update-ref.txt

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -148,12 +148,13 @@ still see a subset of the modifications.
148148

149149
LOGGING UPDATES
150150
---------------
151-
If config parameter "core.logAllRefUpdates" is true and the ref is one under
152-
"refs/heads/", "refs/remotes/", "refs/notes/", or the symbolic ref HEAD; or
153-
the file "$GIT_DIR/logs/<ref>" exists then `git update-ref` will append
154-
a line to the log file "$GIT_DIR/logs/<ref>" (dereferencing all
155-
symbolic refs before creating the log name) describing the change
156-
in ref value. Log lines are formatted as:
151+
If config parameter "core.logAllRefUpdates" is true and the ref is one
152+
under "refs/heads/", "refs/remotes/", "refs/notes/", or a pseudoref
153+
like HEAD or ORIG_HEAD; or the file "$GIT_DIR/logs/<ref>" exists then
154+
`git update-ref` will append a line to the log file
155+
"$GIT_DIR/logs/<ref>" (dereferencing all symbolic refs before creating
156+
the log name) describing the change in ref value. Log lines are
157+
formatted as:
157158

158159
oldsha1 SP newsha1 SP committer LF
159160

refs.c

Lines changed: 7 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -739,102 +739,6 @@ long get_files_ref_lock_timeout_ms(void)
739739
return timeout_ms;
740740
}
741741

742-
static int write_pseudoref(const char *pseudoref, const struct object_id *oid,
743-
const struct object_id *old_oid, struct strbuf *err)
744-
{
745-
const char *filename;
746-
int fd;
747-
struct lock_file lock = LOCK_INIT;
748-
struct strbuf buf = STRBUF_INIT;
749-
int ret = -1;
750-
751-
if (!oid)
752-
return 0;
753-
754-
strbuf_addf(&buf, "%s\n", oid_to_hex(oid));
755-
756-
filename = git_path("%s", pseudoref);
757-
fd = hold_lock_file_for_update_timeout(&lock, filename, 0,
758-
get_files_ref_lock_timeout_ms());
759-
if (fd < 0) {
760-
strbuf_addf(err, _("could not open '%s' for writing: %s"),
761-
filename, strerror(errno));
762-
goto done;
763-
}
764-
765-
if (old_oid) {
766-
struct object_id actual_old_oid;
767-
768-
if (read_ref(pseudoref, &actual_old_oid)) {
769-
if (!is_null_oid(old_oid)) {
770-
strbuf_addf(err, _("could not read ref '%s'"),
771-
pseudoref);
772-
rollback_lock_file(&lock);
773-
goto done;
774-
}
775-
} else if (is_null_oid(old_oid)) {
776-
strbuf_addf(err, _("ref '%s' already exists"),
777-
pseudoref);
778-
rollback_lock_file(&lock);
779-
goto done;
780-
} else if (!oideq(&actual_old_oid, old_oid)) {
781-
strbuf_addf(err, _("unexpected object ID when writing '%s'"),
782-
pseudoref);
783-
rollback_lock_file(&lock);
784-
goto done;
785-
}
786-
}
787-
788-
if (write_in_full(fd, buf.buf, buf.len) < 0) {
789-
strbuf_addf(err, _("could not write to '%s'"), filename);
790-
rollback_lock_file(&lock);
791-
goto done;
792-
}
793-
794-
commit_lock_file(&lock);
795-
ret = 0;
796-
done:
797-
strbuf_release(&buf);
798-
return ret;
799-
}
800-
801-
static int delete_pseudoref(const char *pseudoref, const struct object_id *old_oid)
802-
{
803-
const char *filename;
804-
805-
filename = git_path("%s", pseudoref);
806-
807-
if (old_oid && !is_null_oid(old_oid)) {
808-
struct lock_file lock = LOCK_INIT;
809-
int fd;
810-
struct object_id actual_old_oid;
811-
812-
fd = hold_lock_file_for_update_timeout(
813-
&lock, filename, 0,
814-
get_files_ref_lock_timeout_ms());
815-
if (fd < 0) {
816-
error_errno(_("could not open '%s' for writing"),
817-
filename);
818-
return -1;
819-
}
820-
if (read_ref(pseudoref, &actual_old_oid))
821-
die(_("could not read ref '%s'"), pseudoref);
822-
if (!oideq(&actual_old_oid, old_oid)) {
823-
error(_("unexpected object ID when deleting '%s'"),
824-
pseudoref);
825-
rollback_lock_file(&lock);
826-
return -1;
827-
}
828-
829-
unlink(filename);
830-
rollback_lock_file(&lock);
831-
} else {
832-
unlink(filename);
833-
}
834-
835-
return 0;
836-
}
837-
838742
int refs_delete_ref(struct ref_store *refs, const char *msg,
839743
const char *refname,
840744
const struct object_id *old_oid,
@@ -843,11 +747,6 @@ int refs_delete_ref(struct ref_store *refs, const char *msg,
843747
struct ref_transaction *transaction;
844748
struct strbuf err = STRBUF_INIT;
845749

846-
if (ref_type(refname) == REF_TYPE_PSEUDOREF) {
847-
assert(refs == get_main_ref_store(the_repository));
848-
return delete_pseudoref(refname, old_oid);
849-
}
850-
851750
transaction = ref_store_transaction_begin(refs, &err);
852751
if (!transaction ||
853752
ref_transaction_delete(transaction, refname, old_oid,
@@ -1179,18 +1078,13 @@ int refs_update_ref(struct ref_store *refs, const char *msg,
11791078
struct strbuf err = STRBUF_INIT;
11801079
int ret = 0;
11811080

1182-
if (ref_type(refname) == REF_TYPE_PSEUDOREF) {
1183-
assert(refs == get_main_ref_store(the_repository));
1184-
ret = write_pseudoref(refname, new_oid, old_oid, &err);
1185-
} else {
1186-
t = ref_store_transaction_begin(refs, &err);
1187-
if (!t ||
1188-
ref_transaction_update(t, refname, new_oid, old_oid,
1189-
flags, msg, &err) ||
1190-
ref_transaction_commit(t, &err)) {
1191-
ret = 1;
1192-
ref_transaction_free(t);
1193-
}
1081+
t = ref_store_transaction_begin(refs, &err);
1082+
if (!t ||
1083+
ref_transaction_update(t, refname, new_oid, old_oid, flags, msg,
1084+
&err) ||
1085+
ref_transaction_commit(t, &err)) {
1086+
ret = 1;
1087+
ref_transaction_free(t);
11941088
}
11951089
if (ret) {
11961090
const char *str = _("update_ref failed for ref '%s': %s");

t/t1400-update-ref.sh

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -160,10 +160,10 @@ test_expect_success 'core.logAllRefUpdates=always creates reflog by default' '
160160
git reflog exists $outside
161161
'
162162

163-
test_expect_success 'core.logAllRefUpdates=always creates no reflog for ORIG_HEAD' '
163+
test_expect_success 'core.logAllRefUpdates=always creates reflog for ORIG_HEAD' '
164164
test_config core.logAllRefUpdates always &&
165165
git update-ref ORIG_HEAD $A &&
166-
test_must_fail git reflog exists ORIG_HEAD
166+
git reflog exists ORIG_HEAD
167167
'
168168

169169
test_expect_success '--no-create-reflog overrides core.logAllRefUpdates=always' '
@@ -476,7 +476,7 @@ test_expect_success 'git cat-file blob master@{2005-05-26 23:42}:F (expect OTHER
476476
test_expect_success 'given old value for missing pseudoref, do not create' '
477477
test_must_fail git update-ref PSEUDOREF $A $B 2>err &&
478478
test_must_fail git rev-parse PSEUDOREF &&
479-
test_i18ngrep "could not read ref" err
479+
test_i18ngrep "unable to resolve reference" err
480480
'
481481

482482
test_expect_success 'create pseudoref' '
@@ -497,7 +497,7 @@ test_expect_success 'overwrite pseudoref with correct old value' '
497497
test_expect_success 'do not overwrite pseudoref with wrong old value' '
498498
test_must_fail git update-ref PSEUDOREF $D $E 2>err &&
499499
test $C = $(git rev-parse PSEUDOREF) &&
500-
test_i18ngrep "unexpected object ID" err
500+
test_i18ngrep "cannot lock ref.*expected" err
501501
'
502502

503503
test_expect_success 'delete pseudoref' '
@@ -509,7 +509,7 @@ test_expect_success 'do not delete pseudoref with wrong old value' '
509509
git update-ref PSEUDOREF $A &&
510510
test_must_fail git update-ref -d PSEUDOREF $B 2>err &&
511511
test $A = $(git rev-parse PSEUDOREF) &&
512-
test_i18ngrep "unexpected object ID" err
512+
test_i18ngrep "cannot lock ref.*expected" err
513513
'
514514

515515
test_expect_success 'delete pseudoref with correct old value' '

t/t1405-main-ref-store.sh

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ test_expect_success 'create_symref(FOO, refs/heads/master)' '
3131
test_expect_success 'delete_refs(FOO, refs/tags/new-tag)' '
3232
git rev-parse FOO -- &&
3333
git rev-parse refs/tags/new-tag -- &&
34-
$RUN delete-refs 0 nothing FOO refs/tags/new-tag &&
34+
m=$(git rev-parse master) &&
35+
REF_NO_DEREF=1 &&
36+
$RUN delete-refs $REF_NO_DEREF nothing FOO refs/tags/new-tag &&
37+
test_must_fail git rev-parse --symbolic-full-name FOO &&
3538
test_must_fail git rev-parse FOO -- &&
3639
test_must_fail git rev-parse refs/tags/new-tag --
3740
'

0 commit comments

Comments
 (0)