@matheusbsbs / matheus-bagliano / commits / 09743417a2
Fork 0

Modify pseudo refs through ref backend storage

The previous behavior was introduced in commit 74ec19d4be ("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 <hanwen@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Han-Wen Nienhuys committed Jul 27, 2020 at 16:25 UTC 09743417a201511888aee42480e468ebf47fcecb
4 files changed +23 -125
Documentation/git-update-ref.txt
+7 -6
@@ -148,12 +148,13 @@ still see a subset of the modifications.
148
149 LOGGING UPDATES
150 ---------------
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:
158
159 oldsha1 SP newsha1 SP committer LF
160
refs.c
+7 -113
@@ -739,102 +739,6 @@ long get_files_ref_lock_timeout_ms(void)
739 return timeout_ms;
740 }
741
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 -
742 int refs_delete_ref(struct ref_store *refs, const char *msg,
743 const char *refname,
744 const struct object_id *old_oid,
@@ -843,11 +747,6 @@ int refs_delete_ref(struct ref_store *refs, const char *msg,
747 struct ref_transaction *transaction;
748 struct strbuf err = STRBUF_INIT;
749
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 -
750 transaction = ref_store_transaction_begin(refs, &err);
751 if (!transaction ||
752 ref_transaction_delete(transaction, refname, old_oid,
@@ -1179,18 +1078,13 @@ int refs_update_ref(struct ref_store *refs, const char *msg,
1078 struct strbuf err = STRBUF_INIT;
1079 int ret = 0;
1080
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);
1088 }
1089 if (ret) {
1090 const char *str = _("update_ref failed for ref '%s': %s");
t/t1400-update-ref.sh
+5 -5
@@ -160,10 +160,10 @@ test_expect_success 'core.logAllRefUpdates=always creates reflog by default' '
160 git reflog exists $outside
161 '
162
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' '
164 test_config core.logAllRefUpdates always &&
165 git update-ref ORIG_HEAD $A &&
166 - test_must_fail git reflog exists ORIG_HEAD
166 + git reflog exists ORIG_HEAD
167 '
168
169 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
476 test_expect_success 'given old value for missing pseudoref, do not create' '
477 test_must_fail git update-ref PSEUDOREF $A $B 2>err &&
478 test_must_fail git rev-parse PSEUDOREF &&
479 - test_i18ngrep "could not read ref" err
479 + test_i18ngrep "unable to resolve reference" err
480 '
481
482 test_expect_success 'create pseudoref' '
@@ -497,7 +497,7 @@ test_expect_success 'overwrite pseudoref with correct old value' '
497 test_expect_success 'do not overwrite pseudoref with wrong old value' '
498 test_must_fail git update-ref PSEUDOREF $D $E 2>err &&
499 test $C = $(git rev-parse PSEUDOREF) &&
500 - test_i18ngrep "unexpected object ID" err
500 + test_i18ngrep "cannot lock ref.*expected" err
501 '
502
503 test_expect_success 'delete pseudoref' '
@@ -509,7 +509,7 @@ test_expect_success 'do not delete pseudoref with wrong old value' '
509 git update-ref PSEUDOREF $A &&
510 test_must_fail git update-ref -d PSEUDOREF $B 2>err &&
511 test $A = $(git rev-parse PSEUDOREF) &&
512 - test_i18ngrep "unexpected object ID" err
512 + test_i18ngrep "cannot lock ref.*expected" err
513 '
514
515 test_expect_success 'delete pseudoref with correct old value' '
t/t1405-main-ref-store.sh
+4 -1
@@ -31,7 +31,10 @@ test_expect_success 'create_symref(FOO, refs/heads/master)' '
31 test_expect_success 'delete_refs(FOO, refs/tags/new-tag)' '
32 git rev-parse FOO -- &&
33 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 &&
38 test_must_fail git rev-parse FOO -- &&
39 test_must_fail git rev-parse refs/tags/new-tag --
40 '