1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-06-02 14:06:12 +02:00

Merge branch 'hn/refs-fetch-head-is-special'

The FETCH_HEAD is now always read from the filesystem regardless of
the ref backend in use, as its format is much richer than the
normal refs, and written directly by "git fetch" as a plain file..

* hn/refs-fetch-head-is-special:
  refs: read FETCH_HEAD and MERGE_HEAD generically
  refs: move gitdir into base ref_store
  refs: fix comment about submodule ref_stores
  refs: split off reading loose ref data in separate function
This commit is contained in:
Junio C Hamano 2020-08-27 14:04:49 -07:00
commit 98df75b286
4 changed files with 71 additions and 34 deletions

28
refs.c
View File

@ -1527,11 +1527,37 @@ int for_each_rawref(each_ref_fn fn, void *cb_data)
return refs_for_each_rawref(get_main_ref_store(the_repository), fn, cb_data);
}
static int refs_read_special_head(struct ref_store *ref_store,
const char *refname, struct object_id *oid,
struct strbuf *referent, unsigned int *type)
{
struct strbuf full_path = STRBUF_INIT;
struct strbuf content = STRBUF_INIT;
int result = -1;
strbuf_addf(&full_path, "%s/%s", ref_store->gitdir, refname);
if (strbuf_read_file(&content, full_path.buf, 0) < 0)
goto done;
result = parse_loose_ref_contents(content.buf, oid, referent, type);
done:
strbuf_release(&full_path);
strbuf_release(&content);
return result;
}
int refs_read_raw_ref(struct ref_store *ref_store,
const char *refname, struct object_id *oid,
struct strbuf *referent, unsigned int *type)
{
return ref_store->be->read_raw_ref(ref_store, refname, oid, referent, type);
if (!strcmp(refname, "FETCH_HEAD") || !strcmp(refname, "MERGE_HEAD")) {
return refs_read_special_head(ref_store, refname, oid, referent,
type);
}
return ref_store->be->read_raw_ref(ref_store, refname, oid, referent,
type);
}
/* This function needs to return a meaningful errno on failure */

View File

@ -67,7 +67,6 @@ struct files_ref_store {
struct ref_store base;
unsigned int store_flags;
char *gitdir;
char *gitcommondir;
struct ref_cache *loose;
@ -94,18 +93,17 @@ static struct ref_store *files_ref_store_create(const char *gitdir,
struct ref_store *ref_store = (struct ref_store *)refs;
struct strbuf sb = STRBUF_INIT;
ref_store->gitdir = xstrdup(gitdir);
base_ref_store_init(ref_store, &refs_be_files);
refs->store_flags = flags;
refs->gitdir = xstrdup(gitdir);
get_common_dir_noenv(&sb, gitdir);
refs->gitcommondir = strbuf_detach(&sb, NULL);
strbuf_addf(&sb, "%s/packed-refs", refs->gitcommondir);
refs->packed_ref_store = packed_ref_store_create(sb.buf, flags);
strbuf_release(&sb);
chdir_notify_reparent("files-backend $GIT_DIR",
&refs->gitdir);
chdir_notify_reparent("files-backend $GIT_DIR", &refs->base.gitdir);
chdir_notify_reparent("files-backend $GIT_COMMONDIR",
&refs->gitcommondir);
@ -176,7 +174,7 @@ static void files_reflog_path(struct files_ref_store *refs,
switch (ref_type(refname)) {
case REF_TYPE_PER_WORKTREE:
case REF_TYPE_PSEUDOREF:
strbuf_addf(sb, "%s/logs/%s", refs->gitdir, refname);
strbuf_addf(sb, "%s/logs/%s", refs->base.gitdir, refname);
break;
case REF_TYPE_OTHER_PSEUDOREF:
case REF_TYPE_MAIN_PSEUDOREF:
@ -198,7 +196,7 @@ static void files_ref_path(struct files_ref_store *refs,
switch (ref_type(refname)) {
case REF_TYPE_PER_WORKTREE:
case REF_TYPE_PSEUDOREF:
strbuf_addf(sb, "%s/%s", refs->gitdir, refname);
strbuf_addf(sb, "%s/%s", refs->base.gitdir, refname);
break;
case REF_TYPE_MAIN_PSEUDOREF:
if (!skip_prefix(refname, "main-worktree/", &refname))
@ -360,7 +358,6 @@ static int files_read_raw_ref(struct ref_store *ref_store,
struct strbuf sb_path = STRBUF_INIT;
const char *path;
const char *buf;
const char *p;
struct stat st;
int fd;
int ret = -1;
@ -465,29 +462,8 @@ static int files_read_raw_ref(struct ref_store *ref_store,
close(fd);
strbuf_rtrim(&sb_contents);
buf = sb_contents.buf;
if (skip_prefix(buf, "ref:", &buf)) {
while (isspace(*buf))
buf++;
strbuf_reset(referent);
strbuf_addstr(referent, buf);
*type |= REF_ISSYMREF;
ret = 0;
goto out;
}
/*
* Please note that FETCH_HEAD has additional
* data after the sha.
*/
if (parse_oid_hex(buf, oid, &p) ||
(*p != '\0' && !isspace(*p))) {
*type |= REF_ISBROKEN;
errno = EINVAL;
goto out;
}
ret = 0;
ret = parse_loose_ref_contents(buf, oid, referent, type);
out:
save_errno = errno;
@ -497,6 +473,32 @@ static int files_read_raw_ref(struct ref_store *ref_store,
return ret;
}
int parse_loose_ref_contents(const char *buf, struct object_id *oid,
struct strbuf *referent, unsigned int *type)
{
const char *p;
if (skip_prefix(buf, "ref:", &buf)) {
while (isspace(*buf))
buf++;
strbuf_reset(referent);
strbuf_addstr(referent, buf);
*type |= REF_ISSYMREF;
return 0;
}
/*
* FETCH_HEAD has additional data after the sha.
*/
if (parse_oid_hex(buf, oid, &p) ||
(*p != '\0' && !isspace(*p))) {
*type |= REF_ISBROKEN;
errno = EINVAL;
return -1;
}
return 0;
}
static void unlock_ref(struct ref_lock *lock)
{
rollback_lock_file(&lock->lk);
@ -2199,12 +2201,11 @@ static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_st
files_downcast(ref_store, REF_STORE_READ,
"reflog_iterator_begin");
if (!strcmp(refs->gitdir, refs->gitcommondir)) {
if (!strcmp(refs->base.gitdir, refs->gitcommondir)) {
return reflog_iterator_begin(ref_store, refs->gitcommondir);
} else {
return merge_ref_iterator_begin(
0,
reflog_iterator_begin(ref_store, refs->gitdir),
0, reflog_iterator_begin(ref_store, refs->base.gitdir),
reflog_iterator_begin(ref_store, refs->gitcommondir),
reflog_iterator_select, refs);
}

View File

@ -200,6 +200,7 @@ struct ref_store *packed_ref_store_create(const char *path,
struct ref_store *ref_store = (struct ref_store *)refs;
base_ref_store_init(ref_store, &refs_be_packed);
ref_store->gitdir = xstrdup(path);
refs->store_flags = store_flags;
refs->path = xstrdup(path);

View File

@ -667,13 +667,22 @@ extern struct ref_storage_be refs_be_packed;
/*
* A representation of the reference store for the main repository or
* a submodule. The ref_store instances for submodules are kept in a
* linked list.
* hash map; see get_submodule_ref_store() for more info.
*/
struct ref_store {
/* The backend describing this ref_store's storage scheme: */
const struct ref_storage_be *be;
/* The gitdir that this ref_store applies to: */
char *gitdir;
};
/*
* Parse contents of a loose ref file.
*/
int parse_loose_ref_contents(const char *buf, struct object_id *oid,
struct strbuf *referent, unsigned int *type);
/*
* Fill in the generic part of refs and add it to our collection of
* reference stores.