summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVicent Marti <tanoku@gmail.com>2013-01-03 04:24:12 +0100
committerVicent Marti <tanoku@gmail.com>2013-01-03 04:24:12 +0100
commit7761ce21625564b6526b89326c14a9843a1403d4 (patch)
tree7982836b366da36a70017d8ce15856e08d7d27a2 /src
parent4236164a77b57c42641530a523590a913ba299f9 (diff)
parent922dd9788cfec2ec4727e1b264a2ad6a7f4849ba (diff)
downloadlibgit2-7761ce21625564b6526b89326c14a9843a1403d4.tar.gz
Merge branch 'development' into clar2
Conflicts: tests-clar/clone/nonetwork.c tests-clar/online/clone.c tests-clar/online/fetchhead.c
Diffstat (limited to 'src')
-rw-r--r--src/clone.c131
-rw-r--r--src/path.c2
-rw-r--r--src/remote.c166
-rw-r--r--src/repository.c3
4 files changed, 172 insertions, 130 deletions
diff --git a/src/clone.c b/src/clone.c
index 865521bce..39c0ba26c 100644
--- a/src/clone.c
+++ b/src/clone.c
@@ -258,27 +258,71 @@ cleanup:
* submodules?
*/
+static int create_and_configure_origin(
+ git_remote **out,
+ git_repository *repo,
+ const char *url,
+ const git_clone_options *options)
+{
+ int error;
+ git_remote *origin = NULL;
+
+ if ((error = git_remote_create(&origin, repo, options->remote_name, url)) < 0)
+ goto on_error;
+
+ git_remote_set_cred_acquire_cb(origin, options->cred_acquire_cb,
+ options->cred_acquire_payload);
+ git_remote_set_autotag(origin, options->remote_autotag);
+ /*
+ * Don't write FETCH_HEAD, we'll check out the remote tracking
+ * branch ourselves based on the server's default.
+ */
+ git_remote_set_update_fetchhead(origin, 0);
+
+ if (options->remote_callbacks &&
+ (error = git_remote_set_callbacks(origin, options->remote_callbacks)) < 0)
+ goto on_error;
+
+ if (options->fetch_spec &&
+ (error = git_remote_set_fetchspec(origin, options->fetch_spec)) < 0)
+ goto on_error;
+
+ if (options->push_spec &&
+ (error = git_remote_set_pushspec(origin, options->push_spec)) < 0)
+ goto on_error;
+
+ if (options->pushurl &&
+ (error = git_remote_set_pushurl(origin, options->pushurl)) < 0)
+ goto on_error;
+
+ if ((error = git_remote_save(origin)) < 0)
+ goto on_error;
+
+ *out = origin;
+ return 0;
+
+on_error:
+ git_remote_free(origin);
+ return error;
+}
static int setup_remotes_and_fetch(
git_repository *repo,
- git_remote *origin,
- git_transfer_progress_callback progress_cb,
- void *progress_payload)
+ const char *url,
+ const git_clone_options *options)
{
int retcode = GIT_ERROR;
+ git_remote *origin;
- /* Add the origin remote */
- if (!git_remote_set_repository(origin, repo) && !git_remote_save(origin)) {
- /*
- * Don't write FETCH_HEAD, we'll check out the remote tracking
- * branch ourselves based on the server's default.
- */
+ /* Construct an origin remote */
+ if (!create_and_configure_origin(&origin, repo, url, options)) {
git_remote_set_update_fetchhead(origin, 0);
/* Connect and download everything */
if (!git_remote_connect(origin, GIT_DIRECTION_FETCH)) {
- if (!git_remote_download(origin, progress_cb, progress_payload)) {
+ if (!git_remote_download(origin, options->fetch_progress_cb,
+ options->fetch_progress_payload)) {
/* Create "origin/foo" branches for all remote branches */
if (!git_remote_update_tips(origin)) {
/* Point HEAD to the same ref as the remote's head */
@@ -318,62 +362,55 @@ static bool should_checkout(
if (!opts)
return false;
+ if (opts->checkout_strategy == GIT_CHECKOUT_DEFAULT)
+ return false;
+
return !git_repository_head_orphan(repo);
}
-static int clone_internal(
+static void normalize_options(git_clone_options *dst, const git_clone_options *src)
+{
+ git_clone_options default_options = GIT_CLONE_OPTIONS_INIT;
+ if (!src) src = &default_options;
+
+ *dst = *src;
+
+ /* Provide defaults for null pointers */
+ if (!dst->remote_name) dst->remote_name = "origin";
+}
+
+int git_clone(
git_repository **out,
- git_remote *origin_remote,
- const char *path,
- git_transfer_progress_callback fetch_progress_cb,
- void *fetch_progress_payload,
- git_checkout_opts *checkout_opts,
- bool is_bare)
+ const char *url,
+ const char *local_path,
+ const git_clone_options *options)
{
int retcode = GIT_ERROR;
git_repository *repo = NULL;
+ git_clone_options normOptions;
+
+ assert(out && url && local_path);
- if (!path_is_okay(path)) {
+ normalize_options(&normOptions, options);
+ GITERR_CHECK_VERSION(&normOptions, GIT_CLONE_OPTIONS_VERSION, "git_clone_options");
+
+ if (!path_is_okay(local_path)) {
return GIT_ERROR;
}
- if (!(retcode = git_repository_init(&repo, path, is_bare))) {
- if ((retcode = setup_remotes_and_fetch(repo, origin_remote,
- fetch_progress_cb, fetch_progress_payload)) < 0) {
+ if (!(retcode = git_repository_init(&repo, local_path, normOptions.bare))) {
+ if ((retcode = setup_remotes_and_fetch(repo, url, &normOptions)) < 0) {
/* Failed to fetch; clean up */
git_repository_free(repo);
- git_futils_rmdir_r(path, NULL, GIT_RMDIR_REMOVE_FILES);
+ git_futils_rmdir_r(local_path, NULL, GIT_RMDIR_REMOVE_FILES);
} else {
*out = repo;
retcode = 0;
}
}
- if (!retcode && should_checkout(repo, is_bare, checkout_opts))
- retcode = git_checkout_head(*out, checkout_opts);
+ if (!retcode && should_checkout(repo, normOptions.bare, &normOptions.checkout_opts))
+ retcode = git_checkout_head(*out, &normOptions.checkout_opts);
return retcode;
}
-
-int git_clone(
- git_repository **out,
- git_remote *origin,
- const char *local_path,
- const git_clone_options *options)
-{
- git_clone_options dummy_options = GIT_CLONE_OPTIONS_INIT;
-
- assert(out && origin && local_path);
- if (!options) options = &dummy_options;
-
- GITERR_CHECK_VERSION(options, GIT_CLONE_OPTIONS_VERSION, "git_clone_options");
-
- return clone_internal(
- out,
- origin,
- local_path,
- options->fetch_progress_cb,
- options->fetch_progress_payload,
- options->checkout_opts,
- options->bare ? 1 : 0);
-}
diff --git a/src/path.c b/src/path.c
index dd6bb70ad..1b1f554c7 100644
--- a/src/path.c
+++ b/src/path.c
@@ -19,6 +19,7 @@
#define LOOKS_LIKE_DRIVE_PREFIX(S) (git__isalpha((S)[0]) && (S)[1] == ':')
+#ifdef GIT_WIN32
static bool looks_like_network_computer_name(const char *path, int pos)
{
if (pos < 3)
@@ -34,6 +35,7 @@ static bool looks_like_network_computer_name(const char *path, int pos)
return true;
}
+#endif
/*
* Based on the Android implementation, BSD licensed.
diff --git a/src/remote.c b/src/remote.c
index 28ce88a93..29734cc1a 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -83,14 +83,14 @@ cleanup:
return error;
}
-int git_remote_new(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch)
+static int create_internal(git_remote **out, git_repository *repo, const char *name, const char *url, const char *fetch)
{
git_remote *remote;
git_buf fetchbuf = GIT_BUF_INIT;
int error = -1;
/* name is optional */
- assert(out && url);
+ assert(out && repo && url);
remote = git__calloc(1, sizeof(git_remote));
GITERR_CHECK_ALLOC(remote);
@@ -106,20 +106,8 @@ int git_remote_new(git_remote **out, git_repository *repo, const char *name, con
GITERR_CHECK_ALLOC(remote->url);
if (name != NULL) {
- if ((error = ensure_remote_name_is_valid(name)) < 0) {
- error = GIT_EINVALIDSPEC;
- goto on_error;
- }
-
remote->name = git__strdup(name);
GITERR_CHECK_ALLOC(remote->name);
-
- /* An empty name indicates to use a sensible default for the fetchspec. */
- if (fetch && !(*fetch)) {
- if (git_buf_printf(&fetchbuf, "+refs/heads/*:refs/remotes/%s/*", remote->name) < 0)
- goto on_error;
- fetch = git_buf_cstr(&fetchbuf);
- }
}
if (fetch != NULL) {
@@ -142,6 +130,71 @@ on_error:
return error;
}
+static int ensure_remote_doesnot_exist(git_repository *repo, const char *name)
+{
+ int error;
+ git_remote *remote;
+
+ error = git_remote_load(&remote, repo, name);
+
+ if (error == GIT_ENOTFOUND)
+ return 0;
+
+ if (error < 0)
+ return error;
+
+ git_remote_free(remote);
+
+ giterr_set(
+ GITERR_CONFIG,
+ "Remote '%s' already exists.", name);
+
+ return GIT_EEXISTS;
+}
+
+
+int git_remote_create(git_remote **out, git_repository *repo, const char *name, const char *url)
+{
+ git_buf buf = GIT_BUF_INIT;
+ int error;
+
+ if ((error = ensure_remote_name_is_valid(name)) < 0)
+ return error;
+
+ if ((error = ensure_remote_doesnot_exist(repo, name)) < 0)
+ return error;
+
+ if (git_buf_printf(&buf, "+refs/heads/*:refs/remotes/%s/*", name) < 0)
+ return -1;
+
+ if (create_internal(out, repo, name, url, git_buf_cstr(&buf)) < 0)
+ goto on_error;
+
+ git_buf_free(&buf);
+
+ if (git_remote_save(*out) < 0)
+ goto on_error;
+
+ return 0;
+
+on_error:
+ git_buf_free(&buf);
+ git_remote_free(*out);
+ return -1;
+}
+
+int git_remote_create_inmemory(git_remote **out, git_repository *repo, const char *fetch, const char *url)
+{
+ int error;
+ git_remote *remote;
+
+ if ((error = create_internal(&remote, repo, NULL, url, fetch)) < 0)
+ return error;
+
+ *out = remote;
+ return 0;
+}
+
int git_remote_set_repository(git_remote *remote, git_repository *repo)
{
assert(repo);
@@ -312,9 +365,9 @@ int git_remote_save(const git_remote *remote)
assert(remote);
- if (!remote->repo) {
- giterr_set(GITERR_INVALID, "Can't save a dangling remote.");
- return GIT_ERROR;
+ if (!remote->name) {
+ giterr_set(GITERR_INVALID, "Can't save an in-memory remote.");
+ return GIT_EINVALIDSPEC;
}
if ((error = ensure_remote_name_is_valid(remote->name)) < 0)
@@ -461,8 +514,7 @@ int git_remote_set_fetchspec(git_remote *remote, const char *spec)
return -1;
git_refspec__free(&remote->fetch);
- remote->fetch.src = refspec.src;
- remote->fetch.dst = refspec.dst;
+ memcpy(&remote->fetch, &refspec, sizeof(git_refspec));
return 0;
}
@@ -641,7 +693,7 @@ static int update_tips_callback(git_remote_head *head, void *payload)
git_vector *refs = (git_vector *)payload;
git_vector_insert(refs, head);
- return 0;
+ return 0;
}
static int remote_head_for_fetchspec_src(git_remote_head **out, git_vector *update_heads, const char *fetchspec_src)
@@ -652,11 +704,11 @@ static int remote_head_for_fetchspec_src(git_remote_head **out, git_vector *upda
assert(update_heads && fetchspec_src);
*out = NULL;
-
- git_vector_foreach(update_heads, i, remote_ref) {
- if (strcmp(remote_ref->name, fetchspec_src) == 0) {
- *out = remote_ref;
- break;
+
+ git_vector_foreach(update_heads, i, remote_ref) {
+ if (strcmp(remote_ref->name, fetchspec_src) == 0) {
+ *out = remote_ref;
+ break;
}
}
@@ -727,7 +779,7 @@ static int git_remote_write_fetchhead(git_remote *remote, git_vector *update_hea
}
/* Create the FETCH_HEAD file */
- git_vector_foreach(update_heads, i, remote_ref) {
+ git_vector_foreach(update_heads, i, remote_ref) {
int merge_this_fetchhead = (merge_remote_ref == remote_ref);
if (!include_all_fetchheads &&
@@ -773,11 +825,6 @@ int git_remote_update_tips(git_remote *remote)
assert(remote);
- if (!remote->repo) {
- giterr_set(GITERR_INVALID, "Can't update tips on a dangling remote.");
- return GIT_ERROR;
- }
-
spec = &remote->fetch;
if (git_repository_odb__weakptr(&odb, remote->repo) < 0)
@@ -788,7 +835,7 @@ int git_remote_update_tips(git_remote *remote)
/* Make a copy of the transport's refs */
if (git_vector_init(&refs, 16, NULL) < 0 ||
- git_vector_init(&update_heads, 16, NULL) < 0)
+ git_vector_init(&update_heads, 16, NULL) < 0)
return -1;
if (git_remote_ls(remote, update_tips_callback, &refs) < 0)
@@ -998,33 +1045,6 @@ int git_remote_list(git_strarray *remotes_list, git_repository *repo)
return 0;
}
-int git_remote_add(git_remote **out, git_repository *repo, const char *name, const char *url)
-{
- git_buf buf = GIT_BUF_INIT;
- int error;
-
- if ((error = ensure_remote_name_is_valid(name)) < 0)
- return error;
-
- if (git_buf_printf(&buf, "+refs/heads/*:refs/remotes/%s/*", name) < 0)
- return -1;
-
- if (git_remote_new(out, repo, name, url, git_buf_cstr(&buf)) < 0)
- goto on_error;
-
- git_buf_free(&buf);
-
- if (git_remote_save(*out) < 0)
- goto on_error;
-
- return 0;
-
-on_error:
- git_buf_free(&buf);
- git_remote_free(*out);
- return -1;
-}
-
void git_remote_check_cert(git_remote *remote, int check)
{
assert(remote);
@@ -1091,28 +1111,6 @@ void git_remote_set_autotag(git_remote *remote, git_remote_autotag_option_t valu
remote->download_tags = value;
}
-static int ensure_remote_doesnot_exist(git_repository *repo, const char *name)
-{
- int error;
- git_remote *remote;
-
- error = git_remote_load(&remote, repo, name);
-
- if (error == GIT_ENOTFOUND)
- return 0;
-
- if (error < 0)
- return error;
-
- git_remote_free(remote);
-
- giterr_set(
- GITERR_CONFIG,
- "Remote '%s' already exists.", name);
-
- return GIT_EEXISTS;
-}
-
static int rename_remote_config_section(
git_repository *repo,
const char *old_name,
@@ -1326,6 +1324,11 @@ int git_remote_rename(
assert(remote && new_name);
+ if (!remote->name) {
+ giterr_set(GITERR_INVALID, "Can't rename an in-memory remote.");
+ return GIT_EINVALIDSPEC;
+ }
+
if ((error = ensure_remote_name_is_valid(new_name)) < 0)
return error;
@@ -1343,6 +1346,7 @@ int git_remote_rename(
remote->name = git__strdup(new_name);
+ if (!remote->name) return 0;
return git_remote_save(remote);
}
diff --git a/src/repository.c b/src/repository.c
index 10ed12b64..33aaee841 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -1140,8 +1140,7 @@ static int repo_init_create_origin(git_repository *repo, const char *url)
int error;
git_remote *remote;
- if (!(error = git_remote_add(&remote, repo, GIT_REMOTE_ORIGIN, url))) {
- error = git_remote_save(remote);
+ if (!(error = git_remote_create(&remote, repo, GIT_REMOTE_ORIGIN, url))) {
git_remote_free(remote);
}