зеркало из https://github.com/microsoft/git.git
Merge branch 'hn/reftable-prep-part-2'
Further preliminary change to refs API. * hn/reftable-prep-part-2: Make HEAD a PSEUDOREF rather than PER_WORKTREE. Modify pseudo refs through ref backend storage t1400: use git rev-parse for testing PSEUDOREF existence
This commit is contained in:
Коммит
95c687bf85
|
@ -148,12 +148,13 @@ still see a subset of the modifications.
|
|||
|
||||
LOGGING UPDATES
|
||||
---------------
|
||||
If config parameter "core.logAllRefUpdates" is true and the ref is one under
|
||||
"refs/heads/", "refs/remotes/", "refs/notes/", or the symbolic ref HEAD; or
|
||||
the file "$GIT_DIR/logs/<ref>" exists then `git update-ref` will append
|
||||
a line to the log file "$GIT_DIR/logs/<ref>" (dereferencing all
|
||||
symbolic refs before creating the log name) describing the change
|
||||
in ref value. Log lines are formatted as:
|
||||
If config parameter "core.logAllRefUpdates" is true and the ref is one
|
||||
under "refs/heads/", "refs/remotes/", "refs/notes/", or a pseudoref
|
||||
like HEAD or ORIG_HEAD; or the file "$GIT_DIR/logs/<ref>" exists then
|
||||
`git update-ref` will append a line to the log file
|
||||
"$GIT_DIR/logs/<ref>" (dereferencing all symbolic refs before creating
|
||||
the log name) describing the change in ref value. Log lines are
|
||||
formatted as:
|
||||
|
||||
oldsha1 SP newsha1 SP committer LF
|
||||
|
||||
|
|
127
refs.c
127
refs.c
|
@ -708,10 +708,9 @@ int dwim_log(const char *str, int len, struct object_id *oid, char **log)
|
|||
|
||||
static int is_per_worktree_ref(const char *refname)
|
||||
{
|
||||
return !strcmp(refname, "HEAD") ||
|
||||
starts_with(refname, "refs/worktree/") ||
|
||||
starts_with(refname, "refs/bisect/") ||
|
||||
starts_with(refname, "refs/rewritten/");
|
||||
return starts_with(refname, "refs/worktree/") ||
|
||||
starts_with(refname, "refs/bisect/") ||
|
||||
starts_with(refname, "refs/rewritten/");
|
||||
}
|
||||
|
||||
static int is_pseudoref_syntax(const char *refname)
|
||||
|
@ -771,102 +770,6 @@ long get_files_ref_lock_timeout_ms(void)
|
|||
return timeout_ms;
|
||||
}
|
||||
|
||||
static int write_pseudoref(const char *pseudoref, const struct object_id *oid,
|
||||
const struct object_id *old_oid, struct strbuf *err)
|
||||
{
|
||||
const char *filename;
|
||||
int fd;
|
||||
struct lock_file lock = LOCK_INIT;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
int ret = -1;
|
||||
|
||||
if (!oid)
|
||||
return 0;
|
||||
|
||||
strbuf_addf(&buf, "%s\n", oid_to_hex(oid));
|
||||
|
||||
filename = git_path("%s", pseudoref);
|
||||
fd = hold_lock_file_for_update_timeout(&lock, filename, 0,
|
||||
get_files_ref_lock_timeout_ms());
|
||||
if (fd < 0) {
|
||||
strbuf_addf(err, _("could not open '%s' for writing: %s"),
|
||||
filename, strerror(errno));
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (old_oid) {
|
||||
struct object_id actual_old_oid;
|
||||
|
||||
if (read_ref(pseudoref, &actual_old_oid)) {
|
||||
if (!is_null_oid(old_oid)) {
|
||||
strbuf_addf(err, _("could not read ref '%s'"),
|
||||
pseudoref);
|
||||
rollback_lock_file(&lock);
|
||||
goto done;
|
||||
}
|
||||
} else if (is_null_oid(old_oid)) {
|
||||
strbuf_addf(err, _("ref '%s' already exists"),
|
||||
pseudoref);
|
||||
rollback_lock_file(&lock);
|
||||
goto done;
|
||||
} else if (!oideq(&actual_old_oid, old_oid)) {
|
||||
strbuf_addf(err, _("unexpected object ID when writing '%s'"),
|
||||
pseudoref);
|
||||
rollback_lock_file(&lock);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (write_in_full(fd, buf.buf, buf.len) < 0) {
|
||||
strbuf_addf(err, _("could not write to '%s'"), filename);
|
||||
rollback_lock_file(&lock);
|
||||
goto done;
|
||||
}
|
||||
|
||||
commit_lock_file(&lock);
|
||||
ret = 0;
|
||||
done:
|
||||
strbuf_release(&buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int delete_pseudoref(const char *pseudoref, const struct object_id *old_oid)
|
||||
{
|
||||
const char *filename;
|
||||
|
||||
filename = git_path("%s", pseudoref);
|
||||
|
||||
if (old_oid && !is_null_oid(old_oid)) {
|
||||
struct lock_file lock = LOCK_INIT;
|
||||
int fd;
|
||||
struct object_id actual_old_oid;
|
||||
|
||||
fd = hold_lock_file_for_update_timeout(
|
||||
&lock, filename, 0,
|
||||
get_files_ref_lock_timeout_ms());
|
||||
if (fd < 0) {
|
||||
error_errno(_("could not open '%s' for writing"),
|
||||
filename);
|
||||
return -1;
|
||||
}
|
||||
if (read_ref(pseudoref, &actual_old_oid))
|
||||
die(_("could not read ref '%s'"), pseudoref);
|
||||
if (!oideq(&actual_old_oid, old_oid)) {
|
||||
error(_("unexpected object ID when deleting '%s'"),
|
||||
pseudoref);
|
||||
rollback_lock_file(&lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
unlink(filename);
|
||||
rollback_lock_file(&lock);
|
||||
} else {
|
||||
unlink(filename);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int refs_delete_ref(struct ref_store *refs, const char *msg,
|
||||
const char *refname,
|
||||
const struct object_id *old_oid,
|
||||
|
@ -875,11 +778,6 @@ int refs_delete_ref(struct ref_store *refs, const char *msg,
|
|||
struct ref_transaction *transaction;
|
||||
struct strbuf err = STRBUF_INIT;
|
||||
|
||||
if (ref_type(refname) == REF_TYPE_PSEUDOREF) {
|
||||
assert(refs == get_main_ref_store(the_repository));
|
||||
return delete_pseudoref(refname, old_oid);
|
||||
}
|
||||
|
||||
transaction = ref_store_transaction_begin(refs, &err);
|
||||
if (!transaction ||
|
||||
ref_transaction_delete(transaction, refname, old_oid,
|
||||
|
@ -1210,18 +1108,13 @@ int refs_update_ref(struct ref_store *refs, const char *msg,
|
|||
struct strbuf err = STRBUF_INIT;
|
||||
int ret = 0;
|
||||
|
||||
if (ref_type(refname) == REF_TYPE_PSEUDOREF) {
|
||||
assert(refs == get_main_ref_store(the_repository));
|
||||
ret = write_pseudoref(refname, new_oid, old_oid, &err);
|
||||
} else {
|
||||
t = ref_store_transaction_begin(refs, &err);
|
||||
if (!t ||
|
||||
ref_transaction_update(t, refname, new_oid, old_oid,
|
||||
flags, msg, &err) ||
|
||||
ref_transaction_commit(t, &err)) {
|
||||
ret = 1;
|
||||
ref_transaction_free(t);
|
||||
}
|
||||
t = ref_store_transaction_begin(refs, &err);
|
||||
if (!t ||
|
||||
ref_transaction_update(t, refname, new_oid, old_oid, flags, msg,
|
||||
&err) ||
|
||||
ref_transaction_commit(t, &err)) {
|
||||
ret = 1;
|
||||
ref_transaction_free(t);
|
||||
}
|
||||
if (ret) {
|
||||
const char *str = _("update_ref failed for ref '%s': %s");
|
||||
|
|
|
@ -160,10 +160,10 @@ test_expect_success 'core.logAllRefUpdates=always creates reflog by default' '
|
|||
git reflog exists $outside
|
||||
'
|
||||
|
||||
test_expect_success 'core.logAllRefUpdates=always creates no reflog for ORIG_HEAD' '
|
||||
test_expect_success 'core.logAllRefUpdates=always creates reflog for ORIG_HEAD' '
|
||||
test_config core.logAllRefUpdates always &&
|
||||
git update-ref ORIG_HEAD $A &&
|
||||
test_must_fail git reflog exists ORIG_HEAD
|
||||
git reflog exists ORIG_HEAD
|
||||
'
|
||||
|
||||
test_expect_success '--no-create-reflog overrides core.logAllRefUpdates=always' '
|
||||
|
@ -475,57 +475,57 @@ test_expect_success 'git cat-file blob master@{2005-05-26 23:42}:F (expect OTHER
|
|||
|
||||
test_expect_success 'given old value for missing pseudoref, do not create' '
|
||||
test_must_fail git update-ref PSEUDOREF $A $B 2>err &&
|
||||
test_path_is_missing .git/PSEUDOREF &&
|
||||
test_i18ngrep "could not read ref" err
|
||||
test_must_fail git rev-parse PSEUDOREF &&
|
||||
test_i18ngrep "unable to resolve reference" err
|
||||
'
|
||||
|
||||
test_expect_success 'create pseudoref' '
|
||||
git update-ref PSEUDOREF $A &&
|
||||
test $A = $(cat .git/PSEUDOREF)
|
||||
test $A = $(git rev-parse PSEUDOREF)
|
||||
'
|
||||
|
||||
test_expect_success 'overwrite pseudoref with no old value given' '
|
||||
git update-ref PSEUDOREF $B &&
|
||||
test $B = $(cat .git/PSEUDOREF)
|
||||
test $B = $(git rev-parse PSEUDOREF)
|
||||
'
|
||||
|
||||
test_expect_success 'overwrite pseudoref with correct old value' '
|
||||
git update-ref PSEUDOREF $C $B &&
|
||||
test $C = $(cat .git/PSEUDOREF)
|
||||
test $C = $(git rev-parse PSEUDOREF)
|
||||
'
|
||||
|
||||
test_expect_success 'do not overwrite pseudoref with wrong old value' '
|
||||
test_must_fail git update-ref PSEUDOREF $D $E 2>err &&
|
||||
test $C = $(cat .git/PSEUDOREF) &&
|
||||
test_i18ngrep "unexpected object ID" err
|
||||
test $C = $(git rev-parse PSEUDOREF) &&
|
||||
test_i18ngrep "cannot lock ref.*expected" err
|
||||
'
|
||||
|
||||
test_expect_success 'delete pseudoref' '
|
||||
git update-ref -d PSEUDOREF &&
|
||||
test_path_is_missing .git/PSEUDOREF
|
||||
test_must_fail git rev-parse PSEUDOREF
|
||||
'
|
||||
|
||||
test_expect_success 'do not delete pseudoref with wrong old value' '
|
||||
git update-ref PSEUDOREF $A &&
|
||||
test_must_fail git update-ref -d PSEUDOREF $B 2>err &&
|
||||
test $A = $(cat .git/PSEUDOREF) &&
|
||||
test_i18ngrep "unexpected object ID" err
|
||||
test $A = $(git rev-parse PSEUDOREF) &&
|
||||
test_i18ngrep "cannot lock ref.*expected" err
|
||||
'
|
||||
|
||||
test_expect_success 'delete pseudoref with correct old value' '
|
||||
git update-ref -d PSEUDOREF $A &&
|
||||
test_path_is_missing .git/PSEUDOREF
|
||||
test_must_fail git rev-parse PSEUDOREF
|
||||
'
|
||||
|
||||
test_expect_success 'create pseudoref with old OID zero' '
|
||||
git update-ref PSEUDOREF $A $Z &&
|
||||
test $A = $(cat .git/PSEUDOREF)
|
||||
test $A = $(git rev-parse PSEUDOREF)
|
||||
'
|
||||
|
||||
test_expect_success 'do not overwrite pseudoref with old OID zero' '
|
||||
test_when_finished git update-ref -d PSEUDOREF &&
|
||||
test_must_fail git update-ref PSEUDOREF $B $Z 2>err &&
|
||||
test $A = $(cat .git/PSEUDOREF) &&
|
||||
test $A = $(git rev-parse PSEUDOREF) &&
|
||||
test_i18ngrep "already exists" err
|
||||
'
|
||||
|
||||
|
|
|
@ -31,7 +31,10 @@ test_expect_success 'create_symref(FOO, refs/heads/master)' '
|
|||
test_expect_success 'delete_refs(FOO, refs/tags/new-tag)' '
|
||||
git rev-parse FOO -- &&
|
||||
git rev-parse refs/tags/new-tag -- &&
|
||||
$RUN delete-refs 0 nothing FOO refs/tags/new-tag &&
|
||||
m=$(git rev-parse master) &&
|
||||
REF_NO_DEREF=1 &&
|
||||
$RUN delete-refs $REF_NO_DEREF nothing FOO refs/tags/new-tag &&
|
||||
test_must_fail git rev-parse --symbolic-full-name FOO &&
|
||||
test_must_fail git rev-parse FOO -- &&
|
||||
test_must_fail git rev-parse refs/tags/new-tag --
|
||||
'
|
||||
|
|
Загрузка…
Ссылка в новой задаче