summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Myhre <hash@exultant.us>2016-07-08 01:37:22 -0500
committerPatrick Steinhardt <ps@pks.im>2017-05-05 10:41:45 +0200
commit4bc16c376bde9dca63393e57d0f583cb239a29a2 (patch)
treee5e897a26b13b5ac75365cfee666477b70db883c
parent8897f8fe687f11d327be30873480c5d02a6a00a6 (diff)
downloadlibgit2-4bc16c376bde9dca63393e57d0f583cb239a29a2.tar.gz
remote: add function to create detached remotes
Right now it is only possible to create remotes from a repository. While this is probably the most common use-case, there are commands which make sense even without a repository, e.g. the equivalence of `git ls-remote`. Add a new function `git_remote_create_detached`, which simply accepts a URL.
-rw-r--r--AUTHORS1
-rw-r--r--CHANGELOG.md4
-rw-r--r--include/git2/remote.h18
-rw-r--r--src/remote.c24
4 files changed, 40 insertions, 7 deletions
diff --git a/AUTHORS b/AUTHORS
index 61e2113ec..458ff06c3 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -22,6 +22,7 @@ Dmitry Kakurin
Dmitry Kovega
Emeric Fermas
Emmanuel Rodriguez
+Eric Myhre
Florian Forster
Holger Weiss
Ingmar Vanhassel
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bcf8160c1..64fafc226 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -138,6 +138,10 @@ v0.25
`git_merge_driver_source_file_options()` added as accessors to
`git_merge_driver_source`.
+* `git_remote_create_unattached()` creates a remote that is not associated
+ to any repository (and does not apply configuration like 'insteadof' rules).
+ This is mostly useful for e.g. emulating `git ls-remote` behavior.
+
### API removals
* `git_blob_create_fromchunks()` has been removed in favour of
diff --git a/include/git2/remote.h b/include/git2/remote.h
index e9e4e5b65..b1e04d557 100644
--- a/include/git2/remote.h
+++ b/include/git2/remote.h
@@ -76,6 +76,24 @@ GIT_EXTERN(int) git_remote_create_anonymous(
const char *url);
/**
+ * Create a remote without a connected local repo
+ *
+ * Create a remote with the given url in-memory. You can use this when
+ * you have a URL instead of a remote's name.
+ *
+ * Contrasted with git_remote_create_anonymous, a detached remote
+ * will not consider any repo configuration values (such as insteadof url
+ * substitutions).
+ *
+ * @param out pointer to the new remote objects
+ * @param url the remote repository's URL
+ * @return 0 or an error code
+ */
+GIT_EXTERN(int) git_remote_create_detached(
+ git_remote **out,
+ const char *url);
+
+/**
* Get the information for a particular remote
*
* The name will be checked for validity.
diff --git a/src/remote.c b/src/remote.c
index 86fda5ff1..87fc17dda 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -197,10 +197,10 @@ static int create_internal(git_remote **out, git_repository *repo, const char *n
git_buf var = GIT_BUF_INIT;
int error = -1;
- /* name is optional */
- assert(out && repo && url);
+ /* repo, name, and fetch are optional */
+ assert(out && url);
- if ((error = git_repository_config_snapshot(&config_ro, repo)) < 0)
+ if (repo && (error = git_repository_config_snapshot(&config_ro, repo)) < 0)
return error;
remote = git__calloc(1, sizeof(git_remote));
@@ -212,7 +212,11 @@ static int create_internal(git_remote **out, git_repository *repo, const char *n
(error = canonicalize_url(&canonical_url, url)) < 0)
goto on_error;
- remote->url = apply_insteadof(config_ro, canonical_url.ptr, GIT_DIRECTION_FETCH);
+ if (repo) {
+ remote->url = apply_insteadof(config_ro, canonical_url.ptr, GIT_DIRECTION_FETCH);
+ } else {
+ remote->url = git__strdup(canonical_url.ptr);
+ }
GITERR_CHECK_ALLOC(remote->url);
if (name != NULL) {
@@ -222,8 +226,9 @@ static int create_internal(git_remote **out, git_repository *repo, const char *n
if ((error = git_buf_printf(&var, CONFIG_URL_FMT, name)) < 0)
goto on_error;
- if ((error = git_repository_config__weakptr(&config_rw, repo)) < 0 ||
- (error = git_config_set_string(config_rw, var.ptr, canonical_url.ptr)) < 0)
+ if (repo &&
+ ((error = git_repository_config__weakptr(&config_rw, repo)) < 0 ||
+ (error = git_config_set_string(config_rw, var.ptr, canonical_url.ptr)) < 0))
goto on_error;
}
@@ -235,7 +240,7 @@ static int create_internal(git_remote **out, git_repository *repo, const char *n
if (name && (error = write_add_refspec(repo, name, fetch, true)) < 0)
goto on_error;
- if ((error = lookup_remote_prune_config(remote, config_ro, name)) < 0)
+ if (repo && (error = lookup_remote_prune_config(remote, config_ro, name)) < 0)
goto on_error;
/* Move the data over to where the matching functions can find them */
@@ -330,6 +335,11 @@ int git_remote_create_anonymous(git_remote **out, git_repository *repo, const ch
return create_internal(out, repo, NULL, url, NULL);
}
+int git_remote_create_detached(git_remote **out, const char *url)
+{
+ return create_internal(out, NULL, NULL, url, NULL);
+}
+
int git_remote_dup(git_remote **dest, git_remote *source)
{
size_t i;