Browse Source

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
maint
Junio C Hamano 5 years ago
parent
commit
98df75b286
  1. 28
      refs.c
  2. 49
      refs/files-backend.c
  3. 1
      refs/packed-backend.c
  4. 11
      refs/refs-internal.h

28
refs.c

@ -1527,11 +1527,37 @@ int for_each_rawref(each_ref_fn fn, void *cb_data) @@ -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 */

49
refs/files-backend.c

@ -67,7 +67,6 @@ struct files_ref_store { @@ -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, @@ -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, @@ -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, @@ -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, @@ -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,6 +462,21 @@ stat_ref: @@ -465,6 +462,21 @@ stat_ref:
close(fd);
strbuf_rtrim(&sb_contents);
buf = sb_contents.buf;

ret = parse_loose_ref_contents(buf, oid, referent, type);

out:
save_errno = errno;
strbuf_release(&sb_path);
strbuf_release(&sb_contents);
errno = save_errno;
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++;
@ -472,29 +484,19 @@ stat_ref: @@ -472,29 +484,19 @@ stat_ref:
strbuf_reset(referent);
strbuf_addstr(referent, buf);
*type |= REF_ISSYMREF;
ret = 0;
goto out;
return 0;
}

/*
* Please note that FETCH_HEAD has additional
* data after the sha.
* 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;
return -1;
}

ret = 0;

out:
save_errno = errno;
strbuf_release(&sb_path);
strbuf_release(&sb_contents);
errno = save_errno;
return ret;
return 0;
}

static void unlock_ref(struct ref_lock *lock)
@ -2199,12 +2201,11 @@ static struct ref_iterator *files_reflog_iterator_begin(struct ref_store *ref_st @@ -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);
}

1
refs/packed-backend.c

@ -200,6 +200,7 @@ struct ref_store *packed_ref_store_create(const char *path, @@ -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);

11
refs/refs-internal.h

@ -667,13 +667,22 @@ extern struct ref_storage_be refs_be_packed; @@ -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.

Loading…
Cancel
Save