fetch: store FETCH_HEAD We should always save the remote's HEAD as FETCH_HEAD locally. Signed-off-by: Carlos Martín Nieto <carlos@cmartin.tk>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
diff --git a/src/fetch.c b/src/fetch.c
index e8809d0..3c3dbcb 100644
--- a/src/fetch.c
+++ b/src/fetch.c
@@ -24,7 +24,7 @@ static int filter_wants(git_remote *remote)
git_repository *repo = remote->repo;
const git_refspec *spec;
int error;
- unsigned int i;
+ unsigned int i = 0;
error = git_vector_init(&list, 16, NULL);
if (error < GIT_SUCCESS)
@@ -44,7 +44,24 @@ static int filter_wants(git_remote *remote)
*/
spec = git_remote_fetchspec(remote);
- for (i = 0; i < refs.len; ++i) {
+ /*
+ * We need to handle HEAD separately, as we always want it, but it
+ * probably won't matcht he refspec.
+ */
+ head = refs.heads[0];
+ if (refs.len > 0 && !strcmp(head->name, GIT_HEAD_FILE)) {
+ if (git_odb_exists(repo->db, &head->oid))
+ head->local = 1;
+ else
+ remote->need_pack = 1;
+
+ i = 1;
+ error = git_vector_insert(&list, refs.heads[0]);
+ if (error < GIT_SUCCESS)
+ goto cleanup;
+ }
+
+ for (; i < refs.len; ++i) {
git_remote_head *head = refs.heads[i];
/* If it doesn't match the refpec, we don't want it */
diff --git a/src/refs.c b/src/refs.c
index 1135de4..fcf771b 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -1713,7 +1713,8 @@ static int normalize_name(char *buffer_out, size_t out_size, const char *name, i
/* Object id refname have to contain at least one slash, except
* for HEAD in a detached state or MERGE_HEAD if we're in the
* middle of a merge */
- if (is_oid_ref && !contains_a_slash && (strcmp(name, GIT_HEAD_FILE) && strcmp(name, GIT_MERGE_HEAD_FILE)))
+ if (is_oid_ref && !contains_a_slash && (strcmp(name, GIT_HEAD_FILE) && strcmp(name, GIT_MERGE_HEAD_FILE)
+ && strcmp(name, GIT_FETCH_HEAD_FILE)))
return git__throw(GIT_EINVALIDREFNAME, "Failed to normalize name. Reference name contains no slashes");
/* A refname can not end with ".lock" */
diff --git a/src/refs.h b/src/refs.h
index 979af2e..c4b0b0e 100644
--- a/src/refs.h
+++ b/src/refs.h
@@ -24,6 +24,7 @@
#define GIT_PACKEDREFS_HEADER "# pack-refs with: peeled "
#define GIT_HEAD_FILE "HEAD"
+#define GIT_FETCH_HEAD_FILE "FETCH_HEAD"
#define GIT_MERGE_HEAD_FILE "MERGE_HEAD"
#define GIT_REFS_HEADS_MASTER_FILE GIT_REFS_HEADS_DIR "master"
diff --git a/src/remote.c b/src/remote.c
index f581b97..a557a49 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -219,7 +219,7 @@ int git_remote_download(char **filename, git_remote *remote)
int git_remote_update_tips(struct git_remote *remote)
{
int error = GIT_SUCCESS;
- unsigned int i;
+ unsigned int i = 0;
char refname[GIT_PATH_MAX];
git_headarray *refs = &remote->refs;
git_remote_head *head;
@@ -228,8 +228,21 @@ int git_remote_update_tips(struct git_remote *remote)
memset(refname, 0x0, sizeof(refname));
- for (i = 0; i < refs->len; ++i) {
+ if (refs->len == 0)
+ return GIT_SUCCESS;
+
+ /* HEAD is only allowed to be the first in the list */
+ head = refs->heads[0];
+ if (!strcmp(head->name, GIT_HEAD_FILE)) {
+ error = git_reference_create_oid(&ref, remote->repo, GIT_FETCH_HEAD_FILE, &head->oid, 1);
+ i = 1;
+ if (error < GIT_SUCCESS)
+ return git__rethrow(error, "Failed to update FETCH_HEAD");
+ }
+
+ for (; i < refs->len; ++i) {
head = refs->heads[i];
+
error = git_refspec_transform(refname, sizeof(refname), spec, head->name);
if (error < GIT_SUCCESS)
return error;