summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVicent Martí <vicent@github.com>2012-12-17 03:17:16 -0800
committerVicent Martí <vicent@github.com>2012-12-17 03:17:16 -0800
commit69a402d46c5cee6a09499cf763202dfad2004e95 (patch)
tree29e7256c4ca192952944ccef190f3308a1ab66e5
parent71131b550904824a047d41c7da174686202abd6a (diff)
parentc4e3e797d11bf7d8a9873a193e182d2537b0ee6a (diff)
downloadlibgit2-69a402d46c5cee6a09499cf763202dfad2004e95.tar.gz
Merge pull request #1141 from ben/clone-empty-repo
Allow clone to handle empty repos
-rw-r--r--examples/.gitignore2
-rw-r--r--examples/network/Makefile4
-rw-r--r--src/transports/local.c12
-rw-r--r--tests-clar/clone/empty.c67
-rw-r--r--tests-clar/fetchhead/network.c3
-rw-r--r--tests-clar/network/push.c4
6 files changed, 88 insertions, 4 deletions
diff --git a/examples/.gitignore b/examples/.gitignore
index 4c34e4ab5..e40bfc29f 100644
--- a/examples/.gitignore
+++ b/examples/.gitignore
@@ -1,2 +1,4 @@
general
showindex
+diff
+*.dSYM
diff --git a/examples/network/Makefile b/examples/network/Makefile
index ef3cec659..60969bd87 100644
--- a/examples/network/Makefile
+++ b/examples/network/Makefile
@@ -14,3 +14,7 @@ OBJECTS = \
all: $(OBJECTS)
$(CC) $(CFLAGS) $(LDFLAGS) -o git2 $(OBJECTS)
+
+clean:
+ $(RM) $(OBJECTS)
+ $(RM) git2
diff --git a/src/transports/local.c b/src/transports/local.c
index 53b24947c..c6c95ce75 100644
--- a/src/transports/local.c
+++ b/src/transports/local.c
@@ -42,6 +42,7 @@ static int add_ref(transport_local *t, const char *name)
git_remote_head *head;
git_object *obj = NULL, *target = NULL;
git_buf buf = GIT_BUF_INIT;
+ int error;
head = git__calloc(1, sizeof(git_remote_head));
GITERR_CHECK_ALLOC(head);
@@ -49,10 +50,17 @@ static int add_ref(transport_local *t, const char *name)
head->name = git__strdup(name);
GITERR_CHECK_ALLOC(head->name);
- if (git_reference_name_to_id(&head->oid, t->repo, name) < 0) {
+ error = git_reference_name_to_id(&head->oid, t->repo, name);
+ if (error < 0) {
git__free(head->name);
git__free(head);
- return -1;
+ if (!strcmp(name, GIT_HEAD_FILE) && error == GIT_ENOTFOUND) {
+ /* This is actually okay. Empty repos often have a HEAD that points to
+ * a nonexistent "refs/heads/master". */
+ giterr_clear();
+ return 0;
+ }
+ return error;
}
if (git_vector_insert(&t->refs, head) < 0)
diff --git a/tests-clar/clone/empty.c b/tests-clar/clone/empty.c
new file mode 100644
index 000000000..93fe151bc
--- /dev/null
+++ b/tests-clar/clone/empty.c
@@ -0,0 +1,67 @@
+#include "clar_libgit2.h"
+
+#include "git2/clone.h"
+#include "repository.h"
+
+static git_clone_options g_options;
+static git_remote *g_origin;
+static git_repository *g_repo;
+
+void test_clone_empty__initialize(void)
+{
+ git_repository *sandbox = cl_git_sandbox_init("empty_bare.git");
+ cl_git_remove_placeholders(git_repository_path(sandbox), "dummy-marker.txt");
+
+ g_repo = NULL;
+
+ memset(&g_options, 0, sizeof(git_clone_options));
+ g_options.version = GIT_CLONE_OPTIONS_VERSION;
+ cl_git_pass(git_remote_new(&g_origin, NULL, "origin", cl_git_fixture_url("testrepo.git"), GIT_REMOTE_DEFAULT_FETCH));
+}
+
+void test_clone_empty__cleanup(void)
+{
+ git_remote_free(g_origin);
+ cl_git_sandbox_cleanup();
+}
+
+static void cleanup_repository(void *path)
+{
+ cl_fixture_cleanup((const char *)path);
+}
+
+void test_clone_empty__can_clone_an_empty_local_repo_barely(void)
+{
+ cl_set_cleanup(&cleanup_repository, "./empty");
+
+ git_remote_free(g_origin);
+ cl_git_pass(git_remote_new(&g_origin, NULL, "origin", "./empty_bare.git", GIT_REMOTE_DEFAULT_FETCH));
+
+ g_options.bare = true;
+ cl_git_pass(git_clone(&g_repo, g_origin, "./empty", &g_options));
+}
+
+void test_clone_empty__can_clone_an_empty_local_repo(void)
+{
+ cl_set_cleanup(&cleanup_repository, "./empty");
+
+ git_remote_free(g_origin);
+ cl_git_pass(git_remote_new(&g_origin, NULL, "origin", "./empty_bare.git", GIT_REMOTE_DEFAULT_FETCH));
+
+ cl_git_pass(git_clone(&g_repo, g_origin, "./empty", &g_options));
+}
+
+void test_clone_empty__can_clone_an_empty_standard_repo(void)
+{
+ cl_git_sandbox_cleanup();
+ g_repo = cl_git_sandbox_init("empty_standard_repo");
+ cl_git_remove_placeholders(git_repository_path(g_repo), "dummy-marker.txt");
+ git_repository_free(g_repo);
+
+ git_remote_free(g_origin);
+ cl_git_pass(git_remote_new(&g_origin, NULL, "origin", "./empty_standard_repo", GIT_REMOTE_DEFAULT_FETCH));
+
+ cl_set_cleanup(&cleanup_repository, "./empty");
+
+ cl_git_pass(git_clone(&g_repo, g_origin, "./empty", &g_options));
+}
diff --git a/tests-clar/fetchhead/network.c b/tests-clar/fetchhead/network.c
index d10c891c6..dc223e2aa 100644
--- a/tests-clar/fetchhead/network.c
+++ b/tests-clar/fetchhead/network.c
@@ -63,8 +63,7 @@ static void fetchhead_test_fetch(const char *fetchspec, const char *expected_fet
git_remote_disconnect(remote);
git_remote_free(remote);
- cl_git_pass(git_futils_readbuffer(&fetchhead_buf,
- "./test1/.git/FETCH_HEAD"));
+ cl_git_pass(git_futils_readbuffer(&fetchhead_buf, "./foo/.git/FETCH_HEAD"));
equals = (strcmp(fetchhead_buf.ptr, expected_fetchhead) == 0);
diff --git a/tests-clar/network/push.c b/tests-clar/network/push.c
index f8856091f..788af5267 100644
--- a/tests-clar/network/push.c
+++ b/tests-clar/network/push.c
@@ -211,6 +211,10 @@ void test_network_push__cleanup(void)
{
if (_remote)
git_remote_free(_remote);
+ _remote = NULL;
+
+ /* Freed by cl_git_sandbox_cleanup */
+ _repo = NULL;
record_callbacks_data_clear(&_record_cbs_data);