Skip to content

Commit 98df75b

Browse files
committed
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
2 parents bd3ae9f + e811530 commit 98df75b

File tree

4 files changed

+63
-26
lines changed

4 files changed

+63
-26
lines changed

refs.c

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1527,11 +1527,37 @@ int for_each_rawref(each_ref_fn fn, void *cb_data)
15271527
return refs_for_each_rawref(get_main_ref_store(the_repository), fn, cb_data);
15281528
}
15291529

1530+
static int refs_read_special_head(struct ref_store *ref_store,
1531+
const char *refname, struct object_id *oid,
1532+
struct strbuf *referent, unsigned int *type)
1533+
{
1534+
struct strbuf full_path = STRBUF_INIT;
1535+
struct strbuf content = STRBUF_INIT;
1536+
int result = -1;
1537+
strbuf_addf(&full_path, "%s/%s", ref_store->gitdir, refname);
1538+
1539+
if (strbuf_read_file(&content, full_path.buf, 0) < 0)
1540+
goto done;
1541+
1542+
result = parse_loose_ref_contents(content.buf, oid, referent, type);
1543+
1544+
done:
1545+
strbuf_release(&full_path);
1546+
strbuf_release(&content);
1547+
return result;
1548+
}
1549+
15301550
int refs_read_raw_ref(struct ref_store *ref_store,
15311551
const char *refname, struct object_id *oid,
15321552
struct strbuf *referent, unsigned int *type)
15331553
{
1534-
return ref_store->be->read_raw_ref(ref_store, refname, oid, referent, type);
1554+
if (!strcmp(refname, "FETCH_HEAD") || !strcmp(refname, "MERGE_HEAD")) {
1555+
return refs_read_special_head(ref_store, refname, oid, referent,
1556+
type);
1557+
}
1558+
1559+
return ref_store->be->read_raw_ref(ref_store, refname, oid, referent,
1560+
type);
15351561
}
15361562

15371563
/* This function needs to return a meaningful errno on failure */

refs/files-backend.c

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ struct files_ref_store {
6767
struct ref_store base;
6868
unsigned int store_flags;
6969

70-
char *gitdir;
7170
char *gitcommondir;
7271

7372
struct ref_cache *loose;
@@ -94,18 +93,17 @@ static struct ref_store *files_ref_store_create(const char *gitdir,
9493
struct ref_store *ref_store = (struct ref_store *)refs;
9594
struct strbuf sb = STRBUF_INIT;
9695

96+
ref_store->gitdir = xstrdup(gitdir);
9797
base_ref_store_init(ref_store, &refs_be_files);
9898
refs->store_flags = flags;
9999

100-
refs->gitdir = xstrdup(gitdir);
101100
get_common_dir_noenv(&sb, gitdir);
102101
refs->gitcommondir = strbuf_detach(&sb, NULL);
103102
strbuf_addf(&sb, "%s/packed-refs", refs->gitcommondir);
104103
refs->packed_ref_store = packed_ref_store_create(sb.buf, flags);
105104
strbuf_release(&sb);
106105

107-
chdir_notify_reparent("files-backend $GIT_DIR",
108-
&refs->gitdir);
106+
chdir_notify_reparent("files-backend $GIT_DIR", &refs->base.gitdir);
109107
chdir_notify_reparent("files-backend $GIT_COMMONDIR",
110108
&refs->gitcommondir);
111109

@@ -176,7 +174,7 @@ static void files_reflog_path(struct files_ref_store *refs,
176174
switch (ref_type(refname)) {
177175
case REF_TYPE_PER_WORKTREE:
178176
case REF_TYPE_PSEUDOREF:
179-
strbuf_addf(sb, "%s/logs/%s", refs->gitdir, refname);
177+
strbuf_addf(sb, "%s/logs/%s", refs->base.gitdir, refname);
180178
break;
181179
case REF_TYPE_OTHER_PSEUDOREF:
182180
case REF_TYPE_MAIN_PSEUDOREF:
@@ -198,7 +196,7 @@ static void files_ref_path(struct files_ref_store *refs,
198196
switch (ref_type(refname)) {
199197
case REF_TYPE_PER_WORKTREE:
200198
case REF_TYPE_PSEUDOREF:
201-
strbuf_addf(sb, "%s/%s", refs->gitdir, refname);
199+
strbuf_addf(sb, "%s/%s", refs->base.gitdir, refname);
202200
break;
203201
case REF_TYPE_MAIN_PSEUDOREF:
204202
if (!skip_prefix(refname, "main-worktree/", &refname))
@@ -360,7 +358,6 @@ static int files_read_raw_ref(struct ref_store *ref_store,
360358
struct strbuf sb_path = STRBUF_INIT;
361359
const char *path;
362360
const char *buf;
363-
const char *p;
364361
struct stat st;
365362
int fd;
366363
int ret = -1;
@@ -465,36 +462,41 @@ static int files_read_raw_ref(struct ref_store *ref_store,
465462
close(fd);
466463
strbuf_rtrim(&sb_contents);
467464
buf = sb_contents.buf;
465+
466+
ret = parse_loose_ref_contents(buf, oid, referent, type);
467+
468+
out:
469+
save_errno = errno;
470+
strbuf_release(&sb_path);
471+
strbuf_release(&sb_contents);
472+
errno = save_errno;
473+
return ret;
474+
}
475+
476+
int parse_loose_ref_contents(const char *buf, struct object_id *oid,
477+
struct strbuf *referent, unsigned int *type)
478+
{
479+
const char *p;
468480
if (skip_prefix(buf, "ref:", &buf)) {
469481
while (isspace(*buf))
470482
buf++;
471483

472484
strbuf_reset(referent);
473485
strbuf_addstr(referent, buf);
474486
*type |= REF_ISSYMREF;
475-
ret = 0;
476-
goto out;
487+
return 0;
477488
}
478489

479490
/*
480-
* Please note that FETCH_HEAD has additional
481-
* data after the sha.
491+
* FETCH_HEAD has additional data after the sha.
482492
*/
483493
if (parse_oid_hex(buf, oid, &p) ||
484494
(*p != '\0' && !isspace(*p))) {
485495
*type |= REF_ISBROKEN;
486496
errno = EINVAL;
487-
goto out;
497+
return -1;
488498
}
489-
490-
ret = 0;
491-
492-
out:
493-
save_errno = errno;
494-
strbuf_release(&sb_path);
495-
strbuf_release(&sb_contents);
496-
errno = save_errno;
497-
return ret;
499+
return 0;
498500
}
499501

500502
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
21992201
files_downcast(ref_store, REF_STORE_READ,
22002202
"reflog_iterator_begin");
22012203

2202-
if (!strcmp(refs->gitdir, refs->gitcommondir)) {
2204+
if (!strcmp(refs->base.gitdir, refs->gitcommondir)) {
22032205
return reflog_iterator_begin(ref_store, refs->gitcommondir);
22042206
} else {
22052207
return merge_ref_iterator_begin(
2206-
0,
2207-
reflog_iterator_begin(ref_store, refs->gitdir),
2208+
0, reflog_iterator_begin(ref_store, refs->base.gitdir),
22082209
reflog_iterator_begin(ref_store, refs->gitcommondir),
22092210
reflog_iterator_select, refs);
22102211
}

refs/packed-backend.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ struct ref_store *packed_ref_store_create(const char *path,
200200
struct ref_store *ref_store = (struct ref_store *)refs;
201201

202202
base_ref_store_init(ref_store, &refs_be_packed);
203+
ref_store->gitdir = xstrdup(path);
203204
refs->store_flags = store_flags;
204205

205206
refs->path = xstrdup(path);

refs/refs-internal.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -667,13 +667,22 @@ extern struct ref_storage_be refs_be_packed;
667667
/*
668668
* A representation of the reference store for the main repository or
669669
* a submodule. The ref_store instances for submodules are kept in a
670-
* linked list.
670+
* hash map; see get_submodule_ref_store() for more info.
671671
*/
672672
struct ref_store {
673673
/* The backend describing this ref_store's storage scheme: */
674674
const struct ref_storage_be *be;
675+
676+
/* The gitdir that this ref_store applies to: */
677+
char *gitdir;
675678
};
676679

680+
/*
681+
* Parse contents of a loose ref file.
682+
*/
683+
int parse_loose_ref_contents(const char *buf, struct object_id *oid,
684+
struct strbuf *referent, unsigned int *type);
685+
677686
/*
678687
* Fill in the generic part of refs and add it to our collection of
679688
* reference stores.

0 commit comments

Comments
 (0)