summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md2
-rw-r--r--cmake/Modules/FindIconv.cmake3
-rw-r--r--examples/network/git2.c17
-rw-r--r--include/git2/merge.h3
-rw-r--r--include/git2/push.h30
-rw-r--r--include/git2/remote.h6
-rw-r--r--include/git2/types.h1
-rw-r--r--src/checkout.c2
-rw-r--r--src/config.c5
-rw-r--r--src/filter.c6
-rw-r--r--src/push.c47
-rw-r--r--src/push.h9
-rw-r--r--src/remote.c11
-rw-r--r--tests/online/push_util.h2
-rw-r--r--tests/rebase/merge.c5
15 files changed, 122 insertions, 27 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c97a18b50..4067e48f2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -67,6 +67,8 @@ support for HTTPS connections insead of OpenSSL.
### Breaking API changes
+* `git_smart_subtransport_cb` now has a `param` parameter.
+
* The `git_merge_options` structure member `flags` has been renamed
to `tree_flags`.
diff --git a/cmake/Modules/FindIconv.cmake b/cmake/Modules/FindIconv.cmake
index c5a419011..95414bda6 100644
--- a/cmake/Modules/FindIconv.cmake
+++ b/cmake/Modules/FindIconv.cmake
@@ -11,10 +11,7 @@ IF(ICONV_INCLUDE_DIR AND ICONV_LIBRARIES)
SET(ICONV_FIND_QUIETLY TRUE)
ENDIF()
-FIND_PATH(ICONV_INCLUDE_DIR iconv.h PATHS /opt/local/include NO_DEFAULT_PATH)
FIND_PATH(ICONV_INCLUDE_DIR iconv.h)
-
-FIND_LIBRARY(iconv_lib NAMES iconv libiconv libiconv-2 c NO_DEFAULT_PATH PATHS /opt/local/lib)
FIND_LIBRARY(iconv_lib NAMES iconv libiconv libiconv-2 c)
IF(ICONV_INCLUDE_DIR AND iconv_lib)
diff --git a/examples/network/git2.c b/examples/network/git2.c
index d44334b85..448103c46 100644
--- a/examples/network/git2.c
+++ b/examples/network/git2.c
@@ -23,8 +23,8 @@ static int run_command(git_cb fn, int argc, char **argv)
int error;
git_repository *repo;
-// Before running the actual command, create an instance of the local
-// repository and pass it to the function.
+ // Before running the actual command, create an instance of the local
+ // repository and pass it to the function.
error = git_repository_open(&repo, ".git");
if (error < 0)
@@ -48,6 +48,7 @@ static int run_command(git_cb fn, int argc, char **argv)
int main(int argc, char **argv)
{
int i;
+ int return_code = 1;
if (argc < 2) {
fprintf(stderr, "usage: %s <cmd> [repo]\n", argv[0]);
@@ -57,10 +58,16 @@ int main(int argc, char **argv)
git_libgit2_init();
for (i = 0; commands[i].name != NULL; ++i) {
- if (!strcmp(argv[1], commands[i].name))
- return run_command(commands[i].fn, --argc, ++argv);
+ if (!strcmp(argv[1], commands[i].name)) {
+ return_code = run_command(commands[i].fn, --argc, ++argv);
+ goto shutdown;
+ }
}
fprintf(stderr, "Command not found: %s\n", argv[1]);
- return 1;
+
+shutdown:
+ git_libgit2_shutdown();
+
+ return return_code;
}
diff --git a/include/git2/merge.h b/include/git2/merge.h
index d3360a7e0..5fef452b9 100644
--- a/include/git2/merge.h
+++ b/include/git2/merge.h
@@ -169,7 +169,7 @@ typedef struct {
/** The file to favor in region conflicts. */
git_merge_file_favor_t favor;
- /** Merge file flags. */
+ /** see `git_merge_file_flags_t` above */
unsigned int flags;
} git_merge_file_options;
@@ -246,6 +246,7 @@ typedef struct {
/** Flags for handling conflicting content. */
git_merge_file_favor_t file_favor;
+ /** see `git_merge_file_flags_t` above */
unsigned int file_flags;
} git_merge_options;
diff --git a/include/git2/push.h b/include/git2/push.h
index ecabff397..3f850453d 100644
--- a/include/git2/push.h
+++ b/include/git2/push.h
@@ -59,6 +59,36 @@ typedef int (*git_push_transfer_progress)(
size_t bytes,
void* payload);
+/**
+ * Represents an update which will be performed on the remote during push
+ */
+typedef struct {
+ /**
+ * The source name of the reference
+ */
+ char *src_refname;
+ /**
+ * The name of the reference to update on the server
+ */
+ char *dst_refname;
+ /**
+ * The current target of the reference
+ */
+ git_oid src;
+ /**
+ * The new target for the reference
+ */
+ git_oid dst;
+} git_push_update;
+
+/**
+ * @param updates an array containing the updates which will be sent
+ * as commands to the destination.
+ * @param len number of elements in `updates`
+ * @param payload Payload provided by the caller
+ */
+typedef int (*git_push_negotiation)(const git_push_update **updates, size_t len, void *payload);
+
/** @} */
GIT_END_DECL
#endif
diff --git a/include/git2/remote.h b/include/git2/remote.h
index f85c38429..6e88a4680 100644
--- a/include/git2/remote.h
+++ b/include/git2/remote.h
@@ -521,6 +521,12 @@ struct git_remote_callbacks {
int (*push_update_reference)(const char *refname, const char *status, void *data);
/**
+ * Called once between the negotiation step and the upload. It
+ * provides information about what updates will be performed.
+ */
+ git_push_negotiation push_negotiation;
+
+ /**
* This will be passed to each of the callbacks in this struct
* as the last parameter.
*/
diff --git a/include/git2/types.h b/include/git2/types.h
index c90ac4776..fdb5f2b09 100644
--- a/include/git2/types.h
+++ b/include/git2/types.h
@@ -273,6 +273,7 @@ typedef int (*git_transfer_progress_cb)(const git_transfer_progress *stats, void
*/
typedef int (*git_transport_message_cb)(const char *str, int len, void *payload);
+
/**
* Type of host certificate structure that is passed to the check callback
*/
diff --git a/src/checkout.c b/src/checkout.c
index 0b6e298a0..478130879 100644
--- a/src/checkout.c
+++ b/src/checkout.c
@@ -1457,7 +1457,7 @@ static int blob_content_to_file(
writer.fd = fd;
writer.open = 1;
- error = git_filter_list_stream_blob(fl, blob, (git_writestream *)&writer);
+ error = git_filter_list_stream_blob(fl, blob, &writer.base);
assert(writer.open == 0);
diff --git a/src/config.c b/src/config.c
index 550b22723..1400b9513 100644
--- a/src/config.c
+++ b/src/config.c
@@ -343,7 +343,6 @@ typedef struct {
git_config_iterator *current;
const git_config *cfg;
regex_t regex;
- int has_regex;
size_t i;
} all_iter;
@@ -480,7 +479,6 @@ int git_config_iterator_glob_new(git_config_iterator **out, const git_config *cf
if ((result = regcomp(&iter->regex, regexp, REG_EXTENDED)) != 0) {
giterr_set_regex(&iter->regex, result);
- regfree(&iter->regex);
git__free(iter);
return -1;
}
@@ -983,7 +981,8 @@ void multivar_iter_free(git_config_iterator *_iter)
iter->iter->free(iter->iter);
git__free(iter->name);
- regfree(&iter->regex);
+ if (iter->have_regex)
+ regfree(&iter->regex);
git__free(iter);
}
diff --git a/src/filter.c b/src/filter.c
index 8bd7f4d07..19c793e89 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -671,7 +671,7 @@ int git_filter_list_apply_to_data(
buf_stream_init(&writer, tgt);
if ((error = git_filter_list_stream_data(filters, src,
- (git_writestream *)&writer)) < 0)
+ &writer.parent)) < 0)
return error;
assert(writer.complete);
@@ -690,7 +690,7 @@ int git_filter_list_apply_to_file(
buf_stream_init(&writer, out);
if ((error = git_filter_list_stream_file(
- filters, repo, path, (git_writestream *)&writer)) < 0)
+ filters, repo, path, &writer.parent)) < 0)
return error;
assert(writer.complete);
@@ -721,7 +721,7 @@ int git_filter_list_apply_to_blob(
buf_stream_init(&writer, out);
if ((error = git_filter_list_stream_blob(
- filters, blob, (git_writestream *)&writer)) < 0)
+ filters, blob, &writer.parent)) < 0)
return error;
assert(writer.complete);
diff --git a/src/push.c b/src/push.c
index d4171bbd6..3ac6fbf63 100644
--- a/src/push.c
+++ b/src/push.c
@@ -54,6 +54,13 @@ int git_push_new(git_push **out, git_remote *remote)
return -1;
}
+ if (git_vector_init(&p->updates, 0, NULL) < 0) {
+ git_vector_free(&p->status);
+ git_vector_free(&p->specs);
+ git__free(p);
+ return -1;
+ }
+
*out = p;
return 0;
}
@@ -75,7 +82,9 @@ int git_push_set_callbacks(
git_packbuilder_progress pack_progress_cb,
void *pack_progress_cb_payload,
git_push_transfer_progress transfer_progress_cb,
- void *transfer_progress_cb_payload)
+ void *transfer_progress_cb_payload,
+ git_push_negotiation negotiation_cb,
+ void *negotiation_cb_payload)
{
if (!push)
return -1;
@@ -86,6 +95,9 @@ int git_push_set_callbacks(
push->transfer_progress_cb = transfer_progress_cb;
push->transfer_progress_cb_payload = transfer_progress_cb_payload;
+ push->negotiation_cb = negotiation_cb;
+ push->negotiation_cb_payload = negotiation_cb_payload;
+
return 0;
}
@@ -534,6 +546,22 @@ on_error:
return error;
}
+static int add_update(git_push *push, push_spec *spec)
+{
+ git_push_update *u = git__calloc(1, sizeof(git_push_update));
+ GITERR_CHECK_ALLOC(u);
+
+ u->src_refname = git__strdup(spec->refspec.src);
+ GITERR_CHECK_ALLOC(u->src_refname);
+ u->dst_refname = git__strdup(spec->refspec.src);
+ GITERR_CHECK_ALLOC(u->dst_refname);
+
+ git_oid_cpy(&u->src, &spec->loid);
+ git_oid_cpy(&u->dst, &spec->roid);
+
+ return git_vector_insert(&push->updates, u);
+}
+
static int calculate_work(git_push *push)
{
git_remote_head *head;
@@ -559,6 +587,9 @@ static int calculate_work(git_push *push)
break;
}
}
+
+ if (add_update(push, spec) < 0)
+ return -1;
}
return 0;
@@ -590,9 +621,17 @@ static int do_push(git_push *push)
if ((error = git_packbuilder_set_callbacks(push->pb, push->pack_progress_cb, push->pack_progress_cb_payload)) < 0)
goto on_error;
- if ((error = calculate_work(push)) < 0 ||
- (error = queue_objects(push)) < 0 ||
- (error = transport->push(transport, push)) < 0)
+ if ((error = calculate_work(push)) < 0)
+ goto on_error;
+
+ if (push->negotiation_cb &&
+ (error = push->negotiation_cb((const git_push_update **) push->updates.contents,
+ push->updates.length,
+ push->negotiation_cb_payload)))
+ goto on_error;
+
+ if ((error = queue_objects(push)) < 0 ||
+ (error = transport->push(transport, push)) < 0)
goto on_error;
on_error:
diff --git a/src/push.h b/src/push.h
index b19d40e03..fb5f01480 100644
--- a/src/push.h
+++ b/src/push.h
@@ -29,6 +29,7 @@ struct git_push {
git_packbuilder *pb;
git_remote *remote;
git_vector specs;
+ git_vector updates;
bool report_status;
/* report-status */
@@ -42,6 +43,8 @@ struct git_push {
void *pack_progress_cb_payload;
git_push_transfer_progress transfer_progress_cb;
void *transfer_progress_cb_payload;
+ git_push_negotiation negotiation_cb;
+ void *negotiation_cb_payload;
};
/**
@@ -85,6 +88,8 @@ int git_push_set_options(
* the upload portion of a push. Be aware that this is called inline with
* pack building operations, so performance may be affected.
* @param transfer_progress_cb_payload Payload for the network progress callback.
+ * @param push_negotiation_cb Function to call before sending the commands to the remote.
+ * @param push_negotiation_cb_payload Payload for the negotiation callback
* @return 0 or an error code
*/
int git_push_set_callbacks(
@@ -92,7 +97,9 @@ int git_push_set_callbacks(
git_packbuilder_progress pack_progress_cb,
void *pack_progress_cb_payload,
git_push_transfer_progress transfer_progress_cb,
- void *transfer_progress_cb_payload);
+ void *transfer_progress_cb_payload,
+ git_push_negotiation negotiation_cb,
+ void *negotiation_cb_payload);
/**
* Add a refspec to be pushed
diff --git a/src/remote.c b/src/remote.c
index ac7c43c78..5257e85f3 100644
--- a/src/remote.c
+++ b/src/remote.c
@@ -171,11 +171,11 @@ static int create_internal(git_remote **out, git_repository *repo, const char *n
if ((error = git_repository_config_snapshot(&config, repo)) < 0)
goto on_error;
- if (lookup_remote_prune_config(remote, config, name) < 0)
+ if ((error = lookup_remote_prune_config(remote, config, name)) < 0)
goto on_error;
/* Move the data over to where the matching functions can find them */
- if (dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &remote->refs) < 0)
+ if ((error = dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &remote->refs)) < 0)
goto on_error;
}
@@ -457,7 +457,7 @@ int git_remote_lookup(git_remote **out, git_repository *repo, const char *name)
goto cleanup;
/* Move the data over to where the matching functions can find them */
- if (dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &remote->refs) < 0)
+ if ((error = dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &remote->refs)) < 0)
goto cleanup;
*out = remote;
@@ -2330,7 +2330,7 @@ int git_remote_upload(git_remote *remote, const git_strarray *refspecs, const gi
goto cleanup;
free_refspecs(&remote->active_refspecs);
- if (dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &remote->refs) < 0)
+ if ((error = dwim_refspecs(&remote->active_refspecs, &remote->refspecs, &remote->refs)) < 0)
goto cleanup;
if (remote->push) {
@@ -2363,7 +2363,8 @@ int git_remote_upload(git_remote *remote, const git_strarray *refspecs, const gi
cbs = &remote->callbacks;
if ((error = git_push_set_callbacks(push,
cbs->pack_progress, cbs->payload,
- cbs->push_transfer_progress, cbs->payload)) < 0)
+ cbs->push_transfer_progress, cbs->payload,
+ cbs->push_negotiation, cbs->payload)) < 0)
goto cleanup;
if ((error = git_push_finish(push)) < 0)
diff --git a/tests/online/push_util.h b/tests/online/push_util.h
index 2e05c4ed7..83d46b506 100644
--- a/tests/online/push_util.h
+++ b/tests/online/push_util.h
@@ -12,7 +12,7 @@ extern const git_oid OID_ZERO;
* @param data pointer to a record_callbacks_data instance
*/
#define RECORD_CALLBACKS_INIT(data) \
- { GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, cred_acquire_cb, NULL, NULL, record_update_tips_cb, NULL, NULL, NULL, data }
+ { GIT_REMOTE_CALLBACKS_VERSION, NULL, NULL, cred_acquire_cb, NULL, NULL, record_update_tips_cb, NULL, NULL, NULL, NULL, data }
typedef struct {
char *name;
diff --git a/tests/rebase/merge.c b/tests/rebase/merge.c
index 12f0de5a0..33eadb7ed 100644
--- a/tests/rebase/merge.c
+++ b/tests/rebase/merge.c
@@ -517,6 +517,11 @@ void rebase_checkout_progress_cb(
void *payload)
{
int *called = payload;
+
+ GIT_UNUSED(path);
+ GIT_UNUSED(completed_steps);
+ GIT_UNUSED(total_steps);
+
*called = 1;
}