mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-21 14:39:10 +00:00
Merge pull request #1412 from jamill/push_progress
Initial Implementation of progress reports during push
This commit is contained in:
commit
a6884b6fc7
@ -56,6 +56,8 @@ FUNCTION(TARGET_OS_LIBRARIES target)
|
|||||||
TARGET_LINK_LIBRARIES(${target} ws2_32)
|
TARGET_LINK_LIBRARIES(${target} ws2_32)
|
||||||
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
|
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
|
||||||
TARGET_LINK_LIBRARIES(${target} socket nsl)
|
TARGET_LINK_LIBRARIES(${target} socket nsl)
|
||||||
|
ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||||
|
TARGET_LINK_LIBRARIES(${target} rt)
|
||||||
ENDIF ()
|
ENDIF ()
|
||||||
IF(THREADSAFE)
|
IF(THREADSAFE)
|
||||||
TARGET_LINK_LIBRARIES(${target} ${CMAKE_THREAD_LIBS_INIT})
|
TARGET_LINK_LIBRARIES(${target} ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
@ -45,6 +45,14 @@
|
|||||||
*/
|
*/
|
||||||
GIT_BEGIN_DECL
|
GIT_BEGIN_DECL
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stages that are reported by the packbuilder progress callback.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
GIT_PACKBUILDER_ADDING_OBJECTS = 0,
|
||||||
|
GIT_PACKBUILDER_DELTAFICATION = 1,
|
||||||
|
} git_packbuilder_stage_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize a new packbuilder
|
* Initialize a new packbuilder
|
||||||
*
|
*
|
||||||
@ -149,6 +157,28 @@ GIT_EXTERN(uint32_t) git_packbuilder_object_count(git_packbuilder *pb);
|
|||||||
*/
|
*/
|
||||||
GIT_EXTERN(uint32_t) git_packbuilder_written(git_packbuilder *pb);
|
GIT_EXTERN(uint32_t) git_packbuilder_written(git_packbuilder *pb);
|
||||||
|
|
||||||
|
/** Packbuilder progress notification function */
|
||||||
|
typedef void (*git_packbuilder_progress)(
|
||||||
|
int stage,
|
||||||
|
unsigned int current,
|
||||||
|
unsigned int total,
|
||||||
|
void *payload);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the callbacks for a packbuilder
|
||||||
|
*
|
||||||
|
* @param pb The packbuilder object
|
||||||
|
* @param progress_cb Function to call with progress information during
|
||||||
|
* pack building. Be aware that this is called inline with pack building
|
||||||
|
* operations, so performance may be affected.
|
||||||
|
* @param progress_cb_payload Payload for progress callback.
|
||||||
|
* @return 0 or an error code
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_packbuilder_set_callbacks(
|
||||||
|
git_packbuilder *pb,
|
||||||
|
git_packbuilder_progress progress_cb,
|
||||||
|
void *progress_cb_payload);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Free the packbuilder and all associated data
|
* Free the packbuilder and all associated data
|
||||||
*
|
*
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#define INCLUDE_git_push_h__
|
#define INCLUDE_git_push_h__
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "pack.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file git2/push.h
|
* @file git2/push.h
|
||||||
@ -38,6 +39,13 @@ typedef struct {
|
|||||||
#define GIT_PUSH_OPTIONS_VERSION 1
|
#define GIT_PUSH_OPTIONS_VERSION 1
|
||||||
#define GIT_PUSH_OPTIONS_INIT { GIT_PUSH_OPTIONS_VERSION }
|
#define GIT_PUSH_OPTIONS_INIT { GIT_PUSH_OPTIONS_VERSION }
|
||||||
|
|
||||||
|
/** Push network progress notification function */
|
||||||
|
typedef void (*git_push_transfer_progress)(
|
||||||
|
unsigned int current,
|
||||||
|
unsigned int total,
|
||||||
|
size_t bytes,
|
||||||
|
void* payload);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new push object
|
* Create a new push object
|
||||||
*
|
*
|
||||||
@ -60,6 +68,27 @@ GIT_EXTERN(int) git_push_set_options(
|
|||||||
git_push *push,
|
git_push *push,
|
||||||
const git_push_options *opts);
|
const git_push_options *opts);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the callbacks for a push
|
||||||
|
*
|
||||||
|
* @param push The push object
|
||||||
|
* @param pack_progress_cb Function to call with progress information during
|
||||||
|
* pack building. Be aware that this is called inline with pack building
|
||||||
|
* operations, so performance may be affected.
|
||||||
|
* @param pack_progress_cb_payload Payload for the pack progress callback.
|
||||||
|
* @param transfer_progress_cb Function to call with progress information during
|
||||||
|
* 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.
|
||||||
|
* @return 0 or an error code
|
||||||
|
*/
|
||||||
|
GIT_EXTERN(int) git_push_set_callbacks(
|
||||||
|
git_push *push,
|
||||||
|
git_packbuilder_progress pack_progress_cb,
|
||||||
|
void *pack_progress_cb_payload,
|
||||||
|
git_push_transfer_progress transfer_progress_cb,
|
||||||
|
void *transfer_progress_cb_payload);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a refspec to be pushed
|
* Add a refspec to be pushed
|
||||||
*
|
*
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "pack.h"
|
#include "pack.h"
|
||||||
#include "thread-utils.h"
|
#include "thread-utils.h"
|
||||||
#include "tree.h"
|
#include "tree.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
#include "git2/pack.h"
|
#include "git2/pack.h"
|
||||||
#include "git2/commit.h"
|
#include "git2/commit.h"
|
||||||
@ -57,6 +58,9 @@ struct pack_write_context {
|
|||||||
#define git_packbuilder__progress_lock(pb) GIT_PACKBUILDER__MUTEX_OP(pb, progress_mutex, lock)
|
#define git_packbuilder__progress_lock(pb) GIT_PACKBUILDER__MUTEX_OP(pb, progress_mutex, lock)
|
||||||
#define git_packbuilder__progress_unlock(pb) GIT_PACKBUILDER__MUTEX_OP(pb, progress_mutex, unlock)
|
#define git_packbuilder__progress_unlock(pb) GIT_PACKBUILDER__MUTEX_OP(pb, progress_mutex, unlock)
|
||||||
|
|
||||||
|
/* The minimal interval between progress updates (in seconds). */
|
||||||
|
#define MIN_PROGRESS_UPDATE_INTERVAL 0.5
|
||||||
|
|
||||||
static unsigned name_hash(const char *name)
|
static unsigned name_hash(const char *name)
|
||||||
{
|
{
|
||||||
unsigned c, hash = 0;
|
unsigned c, hash = 0;
|
||||||
@ -212,6 +216,14 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid,
|
|||||||
assert(ret != 0);
|
assert(ret != 0);
|
||||||
kh_value(pb->object_ix, pos) = po;
|
kh_value(pb->object_ix, pos) = po;
|
||||||
|
|
||||||
|
if (pb->progress_cb) {
|
||||||
|
double current_time = git__timer();
|
||||||
|
if ((current_time - pb->last_progress_report_time) >= MIN_PROGRESS_UPDATE_INTERVAL) {
|
||||||
|
pb->last_progress_report_time = current_time;
|
||||||
|
pb->progress_cb(GIT_PACKBUILDER_ADDING_OBJECTS, pb->nr_objects, 0, pb->progress_cb_payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pb->done = false;
|
pb->done = false;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1207,6 +1219,13 @@ static int prepare_pack(git_packbuilder *pb)
|
|||||||
if (pb->nr_objects == 0 || pb->done)
|
if (pb->nr_objects == 0 || pb->done)
|
||||||
return 0; /* nothing to do */
|
return 0; /* nothing to do */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Although we do not report progress during deltafication, we
|
||||||
|
* at least report that we are in the deltafication stage
|
||||||
|
*/
|
||||||
|
if (pb->progress_cb)
|
||||||
|
pb->progress_cb(GIT_PACKBUILDER_DELTAFICATION, 0, pb->nr_objects, pb->progress_cb_payload);
|
||||||
|
|
||||||
delta_list = git__malloc(pb->nr_objects * sizeof(*delta_list));
|
delta_list = git__malloc(pb->nr_objects * sizeof(*delta_list));
|
||||||
GITERR_CHECK_ALLOC(delta_list);
|
GITERR_CHECK_ALLOC(delta_list);
|
||||||
|
|
||||||
@ -1348,6 +1367,17 @@ uint32_t git_packbuilder_written(git_packbuilder *pb)
|
|||||||
return pb->nr_written;
|
return pb->nr_written;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int git_packbuilder_set_callbacks(git_packbuilder *pb, git_packbuilder_progress progress_cb, void *progress_cb_payload)
|
||||||
|
{
|
||||||
|
if (!pb)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
pb->progress_cb = progress_cb;
|
||||||
|
pb->progress_cb_payload = progress_cb_payload;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void git_packbuilder_free(git_packbuilder *pb)
|
void git_packbuilder_free(git_packbuilder *pb)
|
||||||
{
|
{
|
||||||
if (pb == NULL)
|
if (pb == NULL)
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "netops.h"
|
#include "netops.h"
|
||||||
|
|
||||||
#include "git2/oid.h"
|
#include "git2/oid.h"
|
||||||
|
#include "git2/pack.h"
|
||||||
|
|
||||||
#define GIT_PACK_WINDOW 10 /* number of objects to possibly delta against */
|
#define GIT_PACK_WINDOW 10 /* number of objects to possibly delta against */
|
||||||
#define GIT_PACK_DEPTH 50 /* max delta depth */
|
#define GIT_PACK_DEPTH 50 /* max delta depth */
|
||||||
@ -79,6 +80,10 @@ struct git_packbuilder {
|
|||||||
|
|
||||||
int nr_threads; /* nr of threads to use */
|
int nr_threads; /* nr of threads to use */
|
||||||
|
|
||||||
|
git_packbuilder_progress progress_cb;
|
||||||
|
void *progress_cb_payload;
|
||||||
|
double last_progress_report_time; /* the time progress was last reported */
|
||||||
|
|
||||||
bool done;
|
bool done;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
23
src/push.c
23
src/push.c
@ -70,6 +70,25 @@ int git_push_set_options(git_push *push, const git_push_options *opts)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int git_push_set_callbacks(
|
||||||
|
git_push *push,
|
||||||
|
git_packbuilder_progress pack_progress_cb,
|
||||||
|
void *pack_progress_cb_payload,
|
||||||
|
git_push_transfer_progress transfer_progress_cb,
|
||||||
|
void *transfer_progress_cb_payload)
|
||||||
|
{
|
||||||
|
if (!push)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
push->pack_progress_cb = pack_progress_cb;
|
||||||
|
push->pack_progress_cb_payload = pack_progress_cb_payload;
|
||||||
|
|
||||||
|
push->transfer_progress_cb = transfer_progress_cb;
|
||||||
|
push->transfer_progress_cb_payload = transfer_progress_cb_payload;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void free_refspec(push_spec *spec)
|
static void free_refspec(push_spec *spec)
|
||||||
{
|
{
|
||||||
if (spec == NULL)
|
if (spec == NULL)
|
||||||
@ -583,6 +602,10 @@ static int do_push(git_push *push)
|
|||||||
|
|
||||||
git_packbuilder_set_threads(push->pb, push->pb_parallelism);
|
git_packbuilder_set_threads(push->pb, push->pb_parallelism);
|
||||||
|
|
||||||
|
if (push->pack_progress_cb)
|
||||||
|
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 ||
|
if ((error = calculate_work(push)) < 0 ||
|
||||||
(error = queue_objects(push)) < 0 ||
|
(error = queue_objects(push)) < 0 ||
|
||||||
(error = transport->push(transport, push)) < 0)
|
(error = transport->push(transport, push)) < 0)
|
||||||
|
@ -39,6 +39,11 @@ struct git_push {
|
|||||||
|
|
||||||
/* options */
|
/* options */
|
||||||
unsigned pb_parallelism;
|
unsigned pb_parallelism;
|
||||||
|
|
||||||
|
git_packbuilder_progress pack_progress_cb;
|
||||||
|
void *pack_progress_cb_payload;
|
||||||
|
git_push_transfer_progress transfer_progress_cb;
|
||||||
|
void *transfer_progress_cb_payload;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,8 +13,11 @@
|
|||||||
#include "push.h"
|
#include "push.h"
|
||||||
#include "pack-objects.h"
|
#include "pack-objects.h"
|
||||||
#include "remote.h"
|
#include "remote.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
#define NETWORK_XFER_THRESHOLD (100*1024)
|
#define NETWORK_XFER_THRESHOLD (100*1024)
|
||||||
|
/* The minimal interval between progress updates (in seconds). */
|
||||||
|
#define MIN_PROGRESS_UPDATE_INTERVAL 0.5
|
||||||
|
|
||||||
int git_smart__store_refs(transport_smart *t, int flushes)
|
int git_smart__store_refs(transport_smart *t, int flushes)
|
||||||
{
|
{
|
||||||
@ -801,22 +804,53 @@ static int update_refs_from_report(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct push_packbuilder_payload
|
||||||
|
{
|
||||||
|
git_smart_subtransport_stream *stream;
|
||||||
|
git_packbuilder *pb;
|
||||||
|
git_push_transfer_progress cb;
|
||||||
|
void *cb_payload;
|
||||||
|
size_t last_bytes;
|
||||||
|
double last_progress_report_time;
|
||||||
|
};
|
||||||
|
|
||||||
static int stream_thunk(void *buf, size_t size, void *data)
|
static int stream_thunk(void *buf, size_t size, void *data)
|
||||||
{
|
{
|
||||||
git_smart_subtransport_stream *s = (git_smart_subtransport_stream *)data;
|
int error = 0;
|
||||||
|
struct push_packbuilder_payload *payload = data;
|
||||||
|
|
||||||
return s->write(s, (const char *)buf, size);
|
if ((error = payload->stream->write(payload->stream, (const char *)buf, size)) < 0)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
if (payload->cb) {
|
||||||
|
double current_time = git__timer();
|
||||||
|
payload->last_bytes += size;
|
||||||
|
|
||||||
|
if ((current_time - payload->last_progress_report_time) >= MIN_PROGRESS_UPDATE_INTERVAL) {
|
||||||
|
payload->last_progress_report_time = current_time;
|
||||||
|
payload->cb(payload->pb->nr_written, payload->pb->nr_objects, payload->last_bytes, payload->cb_payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_smart__push(git_transport *transport, git_push *push)
|
int git_smart__push(git_transport *transport, git_push *push)
|
||||||
{
|
{
|
||||||
transport_smart *t = (transport_smart *)transport;
|
transport_smart *t = (transport_smart *)transport;
|
||||||
git_smart_subtransport_stream *s;
|
struct push_packbuilder_payload packbuilder_payload = {0};
|
||||||
git_buf pktline = GIT_BUF_INIT;
|
git_buf pktline = GIT_BUF_INIT;
|
||||||
int error = -1, need_pack = 0;
|
int error = -1, need_pack = 0;
|
||||||
push_spec *spec;
|
push_spec *spec;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
|
packbuilder_payload.pb = push->pb;
|
||||||
|
|
||||||
|
if (push->transfer_progress_cb) {
|
||||||
|
packbuilder_payload.cb = push->transfer_progress_cb;
|
||||||
|
packbuilder_payload.cb_payload = push->transfer_progress_cb_payload;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef PUSH_DEBUG
|
#ifdef PUSH_DEBUG
|
||||||
{
|
{
|
||||||
git_remote_head *head;
|
git_remote_head *head;
|
||||||
@ -848,12 +882,12 @@ int git_smart__push(git_transport *transport, git_push *push)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (git_smart__get_push_stream(t, &s) < 0 ||
|
if (git_smart__get_push_stream(t, &packbuilder_payload.stream) < 0 ||
|
||||||
gen_pktline(&pktline, push) < 0 ||
|
gen_pktline(&pktline, push) < 0 ||
|
||||||
s->write(s, git_buf_cstr(&pktline), git_buf_len(&pktline)) < 0)
|
packbuilder_payload.stream->write(packbuilder_payload.stream, git_buf_cstr(&pktline), git_buf_len(&pktline)) < 0)
|
||||||
goto on_error;
|
goto on_error;
|
||||||
|
|
||||||
if (need_pack && git_packbuilder_foreach(push->pb, &stream_thunk, s) < 0)
|
if (need_pack && git_packbuilder_foreach(push->pb, &stream_thunk, &packbuilder_payload) < 0)
|
||||||
goto on_error;
|
goto on_error;
|
||||||
|
|
||||||
/* If we sent nothing or the server doesn't support report-status, then
|
/* If we sent nothing or the server doesn't support report-status, then
|
||||||
@ -863,6 +897,11 @@ int git_smart__push(git_transport *transport, git_push *push)
|
|||||||
else if (parse_report(&t->buffer, push) < 0)
|
else if (parse_report(&t->buffer, push) < 0)
|
||||||
goto on_error;
|
goto on_error;
|
||||||
|
|
||||||
|
/* If progress is being reported write the final report */
|
||||||
|
if (push->transfer_progress_cb) {
|
||||||
|
push->transfer_progress_cb(push->pb->nr_written, push->pb->nr_objects, packbuilder_payload.last_bytes, push->transfer_progress_cb_payload);
|
||||||
|
}
|
||||||
|
|
||||||
if (push->status.length &&
|
if (push->status.length &&
|
||||||
update_refs_from_report(&t->refs, &push->specs, &push->status) < 0)
|
update_refs_from_report(&t->refs, &push->specs, &push->status) < 0)
|
||||||
goto on_error;
|
goto on_error;
|
||||||
|
61
src/util.h
61
src/util.h
@ -353,4 +353,65 @@ GIT_INLINE(void) git__memzero(void *data, size_t size)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef GIT_WIN32
|
||||||
|
|
||||||
|
GIT_INLINE(double) git__timer(void)
|
||||||
|
{
|
||||||
|
/* We need the initial tick count to detect if the tick
|
||||||
|
* count has rolled over. */
|
||||||
|
static DWORD initial_tick_count = 0;
|
||||||
|
|
||||||
|
/* GetTickCount returns the number of milliseconds that have
|
||||||
|
* elapsed since the system was started. */
|
||||||
|
DWORD count = GetTickCount();
|
||||||
|
|
||||||
|
if(initial_tick_count == 0) {
|
||||||
|
initial_tick_count = count;
|
||||||
|
} else if (count < initial_tick_count) {
|
||||||
|
/* The tick count has rolled over - adjust for it. */
|
||||||
|
count = (0xFFFFFFFF - initial_tick_count) + count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (double) count / (double) 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif __APPLE__
|
||||||
|
|
||||||
|
#include <mach/mach_time.h>
|
||||||
|
|
||||||
|
double git__timer(void)
|
||||||
|
{
|
||||||
|
uint64_t time = mach_absolute_time();
|
||||||
|
static double scaling_factor = 0;
|
||||||
|
|
||||||
|
if (scaling_factor == 0) {
|
||||||
|
mach_timebase_info_data_t info;
|
||||||
|
(void)mach_timebase_info(&info);
|
||||||
|
scaling_factor = (double)info.numer / (double)info.denom;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (double)time * scaling_factor / 1.0E-9;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
GIT_INLINE(double) git__timer(void)
|
||||||
|
{
|
||||||
|
struct timespec tp;
|
||||||
|
|
||||||
|
if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) {
|
||||||
|
return (double) tp.tv_sec + (double) tp.tv_nsec / 1E-9;
|
||||||
|
} else {
|
||||||
|
/* Fall back to using gettimeofday */
|
||||||
|
struct timeval tv;
|
||||||
|
struct timezone tz;
|
||||||
|
gettimeofday(&tv, &tz);
|
||||||
|
return (double)tv.tv_sec + (double)tv.tv_usec / 1E-6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* INCLUDE_util_h__ */
|
#endif /* INCLUDE_util_h__ */
|
||||||
|
@ -348,6 +348,18 @@ void test_online_push__cleanup(void)
|
|||||||
cl_git_sandbox_cleanup();
|
cl_git_sandbox_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void push_pack_progress_cb(int stage, unsigned int current, unsigned int total, void* payload)
|
||||||
|
{
|
||||||
|
int *was_called = (int *) payload;
|
||||||
|
*was_called = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void push_transfer_progress_cb(unsigned int current, unsigned int total, size_t bytes, void* payload)
|
||||||
|
{
|
||||||
|
int *was_called = (int *) payload;
|
||||||
|
*was_called = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calls push and relists refs on remote to verify success.
|
* Calls push and relists refs on remote to verify success.
|
||||||
*
|
*
|
||||||
@ -356,15 +368,17 @@ void test_online_push__cleanup(void)
|
|||||||
* @param expected_refs expected remote refs after push
|
* @param expected_refs expected remote refs after push
|
||||||
* @param expected_refs_len length of expected_refs
|
* @param expected_refs_len length of expected_refs
|
||||||
* @param expected_ret expected return value from git_push_finish()
|
* @param expected_ret expected return value from git_push_finish()
|
||||||
|
* @param check_progress_cb Check that the push progress callbacks are called
|
||||||
*/
|
*/
|
||||||
static void do_push(const char *refspecs[], size_t refspecs_len,
|
static void do_push(const char *refspecs[], size_t refspecs_len,
|
||||||
push_status expected_statuses[], size_t expected_statuses_len,
|
push_status expected_statuses[], size_t expected_statuses_len,
|
||||||
expected_ref expected_refs[], size_t expected_refs_len, int expected_ret)
|
expected_ref expected_refs[], size_t expected_refs_len, int expected_ret, int check_progress_cb)
|
||||||
{
|
{
|
||||||
git_push *push;
|
git_push *push;
|
||||||
git_push_options opts = GIT_PUSH_OPTIONS_INIT;
|
git_push_options opts = GIT_PUSH_OPTIONS_INIT;
|
||||||
size_t i;
|
size_t i;
|
||||||
int ret;
|
int ret;
|
||||||
|
int pack_progress_called = 0, transfer_progress_called = 0;
|
||||||
|
|
||||||
if (_remote) {
|
if (_remote) {
|
||||||
/* Auto-detect the number of threads to use */
|
/* Auto-detect the number of threads to use */
|
||||||
@ -375,6 +389,9 @@ static void do_push(const char *refspecs[], size_t refspecs_len,
|
|||||||
cl_git_pass(git_push_new(&push, _remote));
|
cl_git_pass(git_push_new(&push, _remote));
|
||||||
cl_git_pass(git_push_set_options(push, &opts));
|
cl_git_pass(git_push_set_options(push, &opts));
|
||||||
|
|
||||||
|
if (check_progress_cb)
|
||||||
|
cl_git_pass(git_push_set_callbacks(push, push_pack_progress_cb, &pack_progress_called, push_transfer_progress_cb, &transfer_progress_called));
|
||||||
|
|
||||||
for (i = 0; i < refspecs_len; i++)
|
for (i = 0; i < refspecs_len; i++)
|
||||||
cl_git_pass(git_push_add_refspec(push, refspecs[i]));
|
cl_git_pass(git_push_add_refspec(push, refspecs[i]));
|
||||||
|
|
||||||
@ -387,6 +404,11 @@ static void do_push(const char *refspecs[], size_t refspecs_len,
|
|||||||
cl_assert_equal_i(1, git_push_unpack_ok(push));
|
cl_assert_equal_i(1, git_push_unpack_ok(push));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (check_progress_cb) {
|
||||||
|
cl_assert_equal_i(1, pack_progress_called);
|
||||||
|
cl_assert_equal_i(1, transfer_progress_called);
|
||||||
|
}
|
||||||
|
|
||||||
do_verify_push_status(push, expected_statuses, expected_statuses_len);
|
do_verify_push_status(push, expected_statuses, expected_statuses_len);
|
||||||
|
|
||||||
cl_assert_equal_i(expected_ret, ret);
|
cl_assert_equal_i(expected_ret, ret);
|
||||||
@ -405,7 +427,7 @@ static void do_push(const char *refspecs[], size_t refspecs_len,
|
|||||||
/* Call push_finish() without ever calling git_push_add_refspec() */
|
/* Call push_finish() without ever calling git_push_add_refspec() */
|
||||||
void test_online_push__noop(void)
|
void test_online_push__noop(void)
|
||||||
{
|
{
|
||||||
do_push(NULL, 0, NULL, 0, NULL, 0, 0);
|
do_push(NULL, 0, NULL, 0, NULL, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_online_push__b1(void)
|
void test_online_push__b1(void)
|
||||||
@ -415,7 +437,7 @@ void test_online_push__b1(void)
|
|||||||
expected_ref exp_refs[] = { { "refs/heads/b1", &_oid_b1 } };
|
expected_ref exp_refs[] = { { "refs/heads/b1", &_oid_b1 } };
|
||||||
do_push(specs, ARRAY_SIZE(specs),
|
do_push(specs, ARRAY_SIZE(specs),
|
||||||
exp_stats, ARRAY_SIZE(exp_stats),
|
exp_stats, ARRAY_SIZE(exp_stats),
|
||||||
exp_refs, ARRAY_SIZE(exp_refs), 0);
|
exp_refs, ARRAY_SIZE(exp_refs), 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_online_push__b2(void)
|
void test_online_push__b2(void)
|
||||||
@ -425,7 +447,7 @@ void test_online_push__b2(void)
|
|||||||
expected_ref exp_refs[] = { { "refs/heads/b2", &_oid_b2 } };
|
expected_ref exp_refs[] = { { "refs/heads/b2", &_oid_b2 } };
|
||||||
do_push(specs, ARRAY_SIZE(specs),
|
do_push(specs, ARRAY_SIZE(specs),
|
||||||
exp_stats, ARRAY_SIZE(exp_stats),
|
exp_stats, ARRAY_SIZE(exp_stats),
|
||||||
exp_refs, ARRAY_SIZE(exp_refs), 0);
|
exp_refs, ARRAY_SIZE(exp_refs), 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_online_push__b3(void)
|
void test_online_push__b3(void)
|
||||||
@ -435,7 +457,7 @@ void test_online_push__b3(void)
|
|||||||
expected_ref exp_refs[] = { { "refs/heads/b3", &_oid_b3 } };
|
expected_ref exp_refs[] = { { "refs/heads/b3", &_oid_b3 } };
|
||||||
do_push(specs, ARRAY_SIZE(specs),
|
do_push(specs, ARRAY_SIZE(specs),
|
||||||
exp_stats, ARRAY_SIZE(exp_stats),
|
exp_stats, ARRAY_SIZE(exp_stats),
|
||||||
exp_refs, ARRAY_SIZE(exp_refs), 0);
|
exp_refs, ARRAY_SIZE(exp_refs), 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_online_push__b4(void)
|
void test_online_push__b4(void)
|
||||||
@ -445,7 +467,7 @@ void test_online_push__b4(void)
|
|||||||
expected_ref exp_refs[] = { { "refs/heads/b4", &_oid_b4 } };
|
expected_ref exp_refs[] = { { "refs/heads/b4", &_oid_b4 } };
|
||||||
do_push(specs, ARRAY_SIZE(specs),
|
do_push(specs, ARRAY_SIZE(specs),
|
||||||
exp_stats, ARRAY_SIZE(exp_stats),
|
exp_stats, ARRAY_SIZE(exp_stats),
|
||||||
exp_refs, ARRAY_SIZE(exp_refs), 0);
|
exp_refs, ARRAY_SIZE(exp_refs), 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_online_push__b5(void)
|
void test_online_push__b5(void)
|
||||||
@ -455,7 +477,7 @@ void test_online_push__b5(void)
|
|||||||
expected_ref exp_refs[] = { { "refs/heads/b5", &_oid_b5 } };
|
expected_ref exp_refs[] = { { "refs/heads/b5", &_oid_b5 } };
|
||||||
do_push(specs, ARRAY_SIZE(specs),
|
do_push(specs, ARRAY_SIZE(specs),
|
||||||
exp_stats, ARRAY_SIZE(exp_stats),
|
exp_stats, ARRAY_SIZE(exp_stats),
|
||||||
exp_refs, ARRAY_SIZE(exp_refs), 0);
|
exp_refs, ARRAY_SIZE(exp_refs), 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_online_push__multi(void)
|
void test_online_push__multi(void)
|
||||||
@ -483,7 +505,7 @@ void test_online_push__multi(void)
|
|||||||
};
|
};
|
||||||
do_push(specs, ARRAY_SIZE(specs),
|
do_push(specs, ARRAY_SIZE(specs),
|
||||||
exp_stats, ARRAY_SIZE(exp_stats),
|
exp_stats, ARRAY_SIZE(exp_stats),
|
||||||
exp_refs, ARRAY_SIZE(exp_refs), 0);
|
exp_refs, ARRAY_SIZE(exp_refs), 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_online_push__implicit_tgt(void)
|
void test_online_push__implicit_tgt(void)
|
||||||
@ -501,10 +523,10 @@ void test_online_push__implicit_tgt(void)
|
|||||||
|
|
||||||
do_push(specs1, ARRAY_SIZE(specs1),
|
do_push(specs1, ARRAY_SIZE(specs1),
|
||||||
exp_stats1, ARRAY_SIZE(exp_stats1),
|
exp_stats1, ARRAY_SIZE(exp_stats1),
|
||||||
exp_refs1, ARRAY_SIZE(exp_refs1), 0);
|
exp_refs1, ARRAY_SIZE(exp_refs1), 0, 1);
|
||||||
do_push(specs2, ARRAY_SIZE(specs2),
|
do_push(specs2, ARRAY_SIZE(specs2),
|
||||||
exp_stats2, ARRAY_SIZE(exp_stats2),
|
exp_stats2, ARRAY_SIZE(exp_stats2),
|
||||||
exp_refs2, ARRAY_SIZE(exp_refs2), 0);
|
exp_refs2, ARRAY_SIZE(exp_refs2), 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_online_push__fast_fwd(void)
|
void test_online_push__fast_fwd(void)
|
||||||
@ -526,19 +548,19 @@ void test_online_push__fast_fwd(void)
|
|||||||
|
|
||||||
do_push(specs_init, ARRAY_SIZE(specs_init),
|
do_push(specs_init, ARRAY_SIZE(specs_init),
|
||||||
exp_stats_init, ARRAY_SIZE(exp_stats_init),
|
exp_stats_init, ARRAY_SIZE(exp_stats_init),
|
||||||
exp_refs_init, ARRAY_SIZE(exp_refs_init), 0);
|
exp_refs_init, ARRAY_SIZE(exp_refs_init), 0, 1);
|
||||||
|
|
||||||
do_push(specs_ff, ARRAY_SIZE(specs_ff),
|
do_push(specs_ff, ARRAY_SIZE(specs_ff),
|
||||||
exp_stats_ff, ARRAY_SIZE(exp_stats_ff),
|
exp_stats_ff, ARRAY_SIZE(exp_stats_ff),
|
||||||
exp_refs_ff, ARRAY_SIZE(exp_refs_ff), 0);
|
exp_refs_ff, ARRAY_SIZE(exp_refs_ff), 0, 0);
|
||||||
|
|
||||||
do_push(specs_reset, ARRAY_SIZE(specs_reset),
|
do_push(specs_reset, ARRAY_SIZE(specs_reset),
|
||||||
exp_stats_init, ARRAY_SIZE(exp_stats_init),
|
exp_stats_init, ARRAY_SIZE(exp_stats_init),
|
||||||
exp_refs_init, ARRAY_SIZE(exp_refs_init), 0);
|
exp_refs_init, ARRAY_SIZE(exp_refs_init), 0, 0);
|
||||||
|
|
||||||
do_push(specs_ff_force, ARRAY_SIZE(specs_ff_force),
|
do_push(specs_ff_force, ARRAY_SIZE(specs_ff_force),
|
||||||
exp_stats_ff, ARRAY_SIZE(exp_stats_ff),
|
exp_stats_ff, ARRAY_SIZE(exp_stats_ff),
|
||||||
exp_refs_ff, ARRAY_SIZE(exp_refs_ff), 0);
|
exp_refs_ff, ARRAY_SIZE(exp_refs_ff), 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_online_push__tag_commit(void)
|
void test_online_push__tag_commit(void)
|
||||||
@ -548,7 +570,7 @@ void test_online_push__tag_commit(void)
|
|||||||
expected_ref exp_refs[] = { { "refs/tags/tag-commit", &_tag_commit } };
|
expected_ref exp_refs[] = { { "refs/tags/tag-commit", &_tag_commit } };
|
||||||
do_push(specs, ARRAY_SIZE(specs),
|
do_push(specs, ARRAY_SIZE(specs),
|
||||||
exp_stats, ARRAY_SIZE(exp_stats),
|
exp_stats, ARRAY_SIZE(exp_stats),
|
||||||
exp_refs, ARRAY_SIZE(exp_refs), 0);
|
exp_refs, ARRAY_SIZE(exp_refs), 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_online_push__tag_tree(void)
|
void test_online_push__tag_tree(void)
|
||||||
@ -558,7 +580,7 @@ void test_online_push__tag_tree(void)
|
|||||||
expected_ref exp_refs[] = { { "refs/tags/tag-tree", &_tag_tree } };
|
expected_ref exp_refs[] = { { "refs/tags/tag-tree", &_tag_tree } };
|
||||||
do_push(specs, ARRAY_SIZE(specs),
|
do_push(specs, ARRAY_SIZE(specs),
|
||||||
exp_stats, ARRAY_SIZE(exp_stats),
|
exp_stats, ARRAY_SIZE(exp_stats),
|
||||||
exp_refs, ARRAY_SIZE(exp_refs), 0);
|
exp_refs, ARRAY_SIZE(exp_refs), 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_online_push__tag_blob(void)
|
void test_online_push__tag_blob(void)
|
||||||
@ -568,7 +590,7 @@ void test_online_push__tag_blob(void)
|
|||||||
expected_ref exp_refs[] = { { "refs/tags/tag-blob", &_tag_blob } };
|
expected_ref exp_refs[] = { { "refs/tags/tag-blob", &_tag_blob } };
|
||||||
do_push(specs, ARRAY_SIZE(specs),
|
do_push(specs, ARRAY_SIZE(specs),
|
||||||
exp_stats, ARRAY_SIZE(exp_stats),
|
exp_stats, ARRAY_SIZE(exp_stats),
|
||||||
exp_refs, ARRAY_SIZE(exp_refs), 0);
|
exp_refs, ARRAY_SIZE(exp_refs), 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_online_push__tag_lightweight(void)
|
void test_online_push__tag_lightweight(void)
|
||||||
@ -578,7 +600,7 @@ void test_online_push__tag_lightweight(void)
|
|||||||
expected_ref exp_refs[] = { { "refs/tags/tag-lightweight", &_tag_lightweight } };
|
expected_ref exp_refs[] = { { "refs/tags/tag-lightweight", &_tag_lightweight } };
|
||||||
do_push(specs, ARRAY_SIZE(specs),
|
do_push(specs, ARRAY_SIZE(specs),
|
||||||
exp_stats, ARRAY_SIZE(exp_stats),
|
exp_stats, ARRAY_SIZE(exp_stats),
|
||||||
exp_refs, ARRAY_SIZE(exp_refs), 0);
|
exp_refs, ARRAY_SIZE(exp_refs), 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_online_push__tag_to_tag(void)
|
void test_online_push__tag_to_tag(void)
|
||||||
@ -588,7 +610,7 @@ void test_online_push__tag_to_tag(void)
|
|||||||
expected_ref exp_refs[] = { { "refs/tags/tag-tag", &_tag_tag } };
|
expected_ref exp_refs[] = { { "refs/tags/tag-tag", &_tag_tag } };
|
||||||
do_push(specs, ARRAY_SIZE(specs),
|
do_push(specs, ARRAY_SIZE(specs),
|
||||||
exp_stats, ARRAY_SIZE(exp_stats),
|
exp_stats, ARRAY_SIZE(exp_stats),
|
||||||
exp_refs, ARRAY_SIZE(exp_refs), 0);
|
exp_refs, ARRAY_SIZE(exp_refs), 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_online_push__force(void)
|
void test_online_push__force(void)
|
||||||
@ -605,16 +627,16 @@ void test_online_push__force(void)
|
|||||||
|
|
||||||
do_push(specs1, ARRAY_SIZE(specs1),
|
do_push(specs1, ARRAY_SIZE(specs1),
|
||||||
exp_stats1, ARRAY_SIZE(exp_stats1),
|
exp_stats1, ARRAY_SIZE(exp_stats1),
|
||||||
exp_refs1, ARRAY_SIZE(exp_refs1), 0);
|
exp_refs1, ARRAY_SIZE(exp_refs1), 0, 1);
|
||||||
|
|
||||||
do_push(specs2, ARRAY_SIZE(specs2),
|
do_push(specs2, ARRAY_SIZE(specs2),
|
||||||
NULL, 0,
|
NULL, 0,
|
||||||
exp_refs1, ARRAY_SIZE(exp_refs1), GIT_ENONFASTFORWARD);
|
exp_refs1, ARRAY_SIZE(exp_refs1), GIT_ENONFASTFORWARD, 0);
|
||||||
|
|
||||||
/* Non-fast-forward update with force should pass. */
|
/* Non-fast-forward update with force should pass. */
|
||||||
do_push(specs2_force, ARRAY_SIZE(specs2_force),
|
do_push(specs2_force, ARRAY_SIZE(specs2_force),
|
||||||
exp_stats2_force, ARRAY_SIZE(exp_stats2_force),
|
exp_stats2_force, ARRAY_SIZE(exp_stats2_force),
|
||||||
exp_refs2_force, ARRAY_SIZE(exp_refs2_force), 0);
|
exp_refs2_force, ARRAY_SIZE(exp_refs2_force), 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_online_push__delete(void)
|
void test_online_push__delete(void)
|
||||||
@ -645,7 +667,7 @@ void test_online_push__delete(void)
|
|||||||
|
|
||||||
do_push(specs1, ARRAY_SIZE(specs1),
|
do_push(specs1, ARRAY_SIZE(specs1),
|
||||||
exp_stats1, ARRAY_SIZE(exp_stats1),
|
exp_stats1, ARRAY_SIZE(exp_stats1),
|
||||||
exp_refs1, ARRAY_SIZE(exp_refs1), 0);
|
exp_refs1, ARRAY_SIZE(exp_refs1), 0, 1);
|
||||||
|
|
||||||
/* When deleting a non-existent branch, the git client sends zero for both
|
/* When deleting a non-existent branch, the git client sends zero for both
|
||||||
* the old and new commit id. This should succeed on the server with the
|
* the old and new commit id. This should succeed on the server with the
|
||||||
@ -655,23 +677,23 @@ void test_online_push__delete(void)
|
|||||||
*/
|
*/
|
||||||
do_push(specs_del_fake, ARRAY_SIZE(specs_del_fake),
|
do_push(specs_del_fake, ARRAY_SIZE(specs_del_fake),
|
||||||
exp_stats_fake, 1,
|
exp_stats_fake, 1,
|
||||||
exp_refs1, ARRAY_SIZE(exp_refs1), 0);
|
exp_refs1, ARRAY_SIZE(exp_refs1), 0, 0);
|
||||||
do_push(specs_del_fake_force, ARRAY_SIZE(specs_del_fake_force),
|
do_push(specs_del_fake_force, ARRAY_SIZE(specs_del_fake_force),
|
||||||
exp_stats_fake, 1,
|
exp_stats_fake, 1,
|
||||||
exp_refs1, ARRAY_SIZE(exp_refs1), 0);
|
exp_refs1, ARRAY_SIZE(exp_refs1), 0, 0);
|
||||||
|
|
||||||
/* Delete one of the pushed branches. */
|
/* Delete one of the pushed branches. */
|
||||||
do_push(specs_delete, ARRAY_SIZE(specs_delete),
|
do_push(specs_delete, ARRAY_SIZE(specs_delete),
|
||||||
exp_stats_delete, ARRAY_SIZE(exp_stats_delete),
|
exp_stats_delete, ARRAY_SIZE(exp_stats_delete),
|
||||||
exp_refs_delete, ARRAY_SIZE(exp_refs_delete), 0);
|
exp_refs_delete, ARRAY_SIZE(exp_refs_delete), 0, 0);
|
||||||
|
|
||||||
/* Re-push branches and retry delete with force. */
|
/* Re-push branches and retry delete with force. */
|
||||||
do_push(specs1, ARRAY_SIZE(specs1),
|
do_push(specs1, ARRAY_SIZE(specs1),
|
||||||
exp_stats1, ARRAY_SIZE(exp_stats1),
|
exp_stats1, ARRAY_SIZE(exp_stats1),
|
||||||
exp_refs1, ARRAY_SIZE(exp_refs1), 0);
|
exp_refs1, ARRAY_SIZE(exp_refs1), 0, 0);
|
||||||
do_push(specs_delete_force, ARRAY_SIZE(specs_delete_force),
|
do_push(specs_delete_force, ARRAY_SIZE(specs_delete_force),
|
||||||
exp_stats_delete, ARRAY_SIZE(exp_stats_delete),
|
exp_stats_delete, ARRAY_SIZE(exp_stats_delete),
|
||||||
exp_refs_delete, ARRAY_SIZE(exp_refs_delete), 0);
|
exp_refs_delete, ARRAY_SIZE(exp_refs_delete), 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_online_push__bad_refspecs(void)
|
void test_online_push__bad_refspecs(void)
|
||||||
@ -703,11 +725,11 @@ void test_online_push__expressions(void)
|
|||||||
/* TODO: Find a more precise way of checking errors than a exit code of -1. */
|
/* TODO: Find a more precise way of checking errors than a exit code of -1. */
|
||||||
do_push(specs_left_expr, ARRAY_SIZE(specs_left_expr),
|
do_push(specs_left_expr, ARRAY_SIZE(specs_left_expr),
|
||||||
NULL, 0,
|
NULL, 0,
|
||||||
NULL, 0, -1);
|
NULL, 0, -1, 0);
|
||||||
|
|
||||||
do_push(specs_right_expr, ARRAY_SIZE(specs_right_expr),
|
do_push(specs_right_expr, ARRAY_SIZE(specs_right_expr),
|
||||||
exp_stats_right_expr, ARRAY_SIZE(exp_stats_right_expr),
|
exp_stats_right_expr, ARRAY_SIZE(exp_stats_right_expr),
|
||||||
NULL, 0, 0);
|
NULL, 0, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_online_push__notes(void)
|
void test_online_push__notes(void)
|
||||||
@ -727,7 +749,7 @@ void test_online_push__notes(void)
|
|||||||
|
|
||||||
do_push(specs, ARRAY_SIZE(specs),
|
do_push(specs, ARRAY_SIZE(specs),
|
||||||
exp_stats, ARRAY_SIZE(exp_stats),
|
exp_stats, ARRAY_SIZE(exp_stats),
|
||||||
exp_refs, ARRAY_SIZE(exp_refs), 0);
|
exp_refs, ARRAY_SIZE(exp_refs), 0, 1);
|
||||||
|
|
||||||
git_signature_free(signature);
|
git_signature_free(signature);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user