Unverified Commit 083b1a2e by Edward Thomson Committed by GitHub

Merge pull request #4021 from carlosmn/cmn/refspecs-fetchhead

FETCH_HEAD and multiple refspecs
parents 4110fc84 c081f0d0
...@@ -118,7 +118,7 @@ int git_fetchhead_write(git_repository *repo, git_vector *fetchhead_refs) ...@@ -118,7 +118,7 @@ int git_fetchhead_write(git_repository *repo, git_vector *fetchhead_refs)
if (git_buf_joinpath(&path, repo->gitdir, GIT_FETCH_HEAD_FILE) < 0) if (git_buf_joinpath(&path, repo->gitdir, GIT_FETCH_HEAD_FILE) < 0)
return -1; return -1;
if (git_filebuf_open(&file, path.ptr, GIT_FILEBUF_FORCE, GIT_REFS_FILE_MODE) < 0) { if (git_filebuf_open(&file, path.ptr, GIT_FILEBUF_APPEND, GIT_REFS_FILE_MODE) < 0) {
git_buf_free(&path); git_buf_free(&path);
return -1; return -1;
} }
......
...@@ -102,6 +102,16 @@ int git_futils_open_ro(const char *path) ...@@ -102,6 +102,16 @@ int git_futils_open_ro(const char *path)
return fd; return fd;
} }
int git_futils_truncate(const char *path, int mode)
{
int fd = p_open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode);
if (fd < 0)
return git_path_set_error(errno, path, "open");
close(fd);
return 0;
}
git_off_t git_futils_filesize(git_file fd) git_off_t git_futils_filesize(git_file fd)
{ {
struct stat sb; struct stat sb;
......
...@@ -248,6 +248,11 @@ extern int git_futils_cp_r( ...@@ -248,6 +248,11 @@ extern int git_futils_cp_r(
extern int git_futils_open_ro(const char *path); extern int git_futils_open_ro(const char *path);
/** /**
* Truncate a file, creating it if it doesn't exist.
*/
extern int git_futils_truncate(const char *path, int mode);
/**
* Get the filesize in bytes of a file * Get the filesize in bytes of a file
*/ */
extern git_off_t git_futils_filesize(git_file fd); extern git_off_t git_futils_filesize(git_file fd);
......
...@@ -1541,6 +1541,20 @@ cleanup: ...@@ -1541,6 +1541,20 @@ cleanup:
return error; return error;
} }
static int truncate_fetch_head(const char *gitdir)
{
git_buf path = GIT_BUF_INIT;
int error;
if ((error = git_buf_joinpath(&path, gitdir, GIT_FETCH_HEAD_FILE)) < 0)
return error;
error = git_futils_truncate(path.ptr, GIT_REFS_FILE_MODE);
git_buf_free(&path);
return error;
}
int git_remote_update_tips( int git_remote_update_tips(
git_remote *remote, git_remote *remote,
const git_remote_callbacks *callbacks, const git_remote_callbacks *callbacks,
...@@ -1571,6 +1585,9 @@ int git_remote_update_tips( ...@@ -1571,6 +1585,9 @@ int git_remote_update_tips(
else else
tagopt = download_tags; tagopt = download_tags;
if ((error = truncate_fetch_head(git_repository_path(remote->repo))) < 0)
goto out;
if (tagopt == GIT_REMOTE_DOWNLOAD_TAGS_ALL) { if (tagopt == GIT_REMOTE_DOWNLOAD_TAGS_ALL) {
if ((error = update_tips_for_spec(remote, callbacks, update_fetchhead, tagopt, &tagspec, &refs, reflog_message)) < 0) if ((error = update_tips_for_spec(remote, callbacks, update_fetchhead, tagopt, &tagspec, &refs, reflog_message)) < 0)
goto out; goto out;
......
...@@ -353,20 +353,25 @@ void test_fetchhead_nonetwork__quote_in_branch_name(void) ...@@ -353,20 +353,25 @@ void test_fetchhead_nonetwork__quote_in_branch_name(void)
} }
static bool found_master; static bool found_master;
static bool find_master_called; static bool found_haacked;
static bool find_master_haacked_called;
int find_master(const char *ref_name, const char *remote_url, const git_oid *oid, unsigned int is_merge, void *payload) int find_master_haacked(const char *ref_name, const char *remote_url, const git_oid *oid, unsigned int is_merge, void *payload)
{ {
GIT_UNUSED(remote_url); GIT_UNUSED(remote_url);
GIT_UNUSED(oid); GIT_UNUSED(oid);
GIT_UNUSED(payload); GIT_UNUSED(payload);
find_master_called = true; find_master_haacked_called = true;
if (!strcmp("refs/heads/master", ref_name)) { if (!strcmp("refs/heads/master", ref_name)) {
cl_assert(is_merge); cl_assert(is_merge);
found_master = true; found_master = true;
} }
if (!strcmp("refs/heads/haacked", ref_name)) {
cl_assert(is_merge);
found_haacked = true;
}
return 0; return 0;
} }
...@@ -375,10 +380,12 @@ void test_fetchhead_nonetwork__create_when_refpecs_given(void) ...@@ -375,10 +380,12 @@ void test_fetchhead_nonetwork__create_when_refpecs_given(void)
{ {
git_remote *remote; git_remote *remote;
git_buf path = GIT_BUF_INIT; git_buf path = GIT_BUF_INIT;
char *refspec = "refs/heads/master"; char *refspec1 = "refs/heads/master";
char *refspec2 = "refs/heads/haacked";
char *refspecs[] = { refspec1, refspec2 };
git_strarray specs = { git_strarray specs = {
&refspec, refspecs,
1, 2,
}; };
cl_set_cleanup(&cleanup_repository, "./test1"); cl_set_cleanup(&cleanup_repository, "./test1");
...@@ -391,9 +398,74 @@ void test_fetchhead_nonetwork__create_when_refpecs_given(void) ...@@ -391,9 +398,74 @@ void test_fetchhead_nonetwork__create_when_refpecs_given(void)
cl_git_pass(git_remote_fetch(remote, &specs, NULL, NULL)); cl_git_pass(git_remote_fetch(remote, &specs, NULL, NULL));
cl_assert(git_path_exists(path.ptr)); cl_assert(git_path_exists(path.ptr));
cl_git_pass(git_repository_fetchhead_foreach(g_repo, find_master, NULL)); cl_git_pass(git_repository_fetchhead_foreach(g_repo, find_master_haacked, NULL));
cl_assert(find_master_called); cl_assert(find_master_haacked_called);
cl_assert(found_master); cl_assert(found_master);
cl_assert(found_haacked);
git_remote_free(remote);
git_buf_free(&path);
}
static bool count_refs_called;
struct prefix_count {
const char *prefix;
int count;
int expected;
};
int count_refs(const char *ref_name, const char *remote_url, const git_oid *oid, unsigned int is_merge, void *payload)
{
int i;
struct prefix_count *prefix_counts = (struct prefix_count *) payload;
GIT_UNUSED(remote_url);
GIT_UNUSED(oid);
GIT_UNUSED(is_merge);
count_refs_called = true;
for (i = 0; prefix_counts[i].prefix; i++) {
if (!git__prefixcmp(ref_name, prefix_counts[i].prefix))
prefix_counts[i].count++;
}
return 0;
}
void test_fetchhead_nonetwork__create_with_multiple_refspecs(void)
{
git_remote *remote;
git_buf path = GIT_BUF_INIT;
cl_set_cleanup(&cleanup_repository, "./test1");
cl_git_pass(git_repository_init(&g_repo, "./test1", 0));
cl_git_pass(git_remote_create(&remote, g_repo, "origin", cl_fixture("testrepo.git")));
git_remote_free(remote);
cl_git_pass(git_remote_add_fetch(g_repo, "origin", "+refs/notes/*:refs/origin/notes/*"));
/* Pick up the new refspec */
cl_git_pass(git_remote_lookup(&remote, g_repo, "origin"));
cl_git_pass(git_buf_joinpath(&path, git_repository_path(g_repo), "FETCH_HEAD"));
cl_assert(!git_path_exists(path.ptr));
cl_git_pass(git_remote_fetch(remote, NULL, NULL, NULL));
cl_assert(git_path_exists(path.ptr));
{
int i;
struct prefix_count prefix_counts[] = {
{"refs/notes/", 0, 1},
{"refs/heads/", 0, 12},
{"refs/tags/", 0, 7},
{NULL, 0, 0},
};
cl_git_pass(git_repository_fetchhead_foreach(g_repo, count_refs, &prefix_counts));
cl_assert(count_refs_called);
for (i = 0; prefix_counts[i].prefix; i++)
cl_assert_equal_i(prefix_counts[i].expected, prefix_counts[i].count);
}
git_remote_free(remote); git_remote_free(remote);
git_buf_free(&path); git_buf_free(&path);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment