diff options
-rw-r--r-- | CMakeLists.txt | 15 | ||||
-rw-r--r-- | examples/network/clone.c | 8 | ||||
-rw-r--r-- | include/git2/index.h | 25 | ||||
-rw-r--r-- | include/git2/odb.h | 2 | ||||
-rw-r--r-- | include/git2/odb_backend.h | 4 | ||||
-rw-r--r-- | include/git2/sys/odb_backend.h | 2 | ||||
-rw-r--r-- | src/blob.c | 5 | ||||
-rw-r--r-- | src/odb.c | 22 | ||||
-rw-r--r-- | src/odb.h | 2 | ||||
-rw-r--r-- | src/odb_loose.c | 4 | ||||
-rw-r--r-- | src/pack-objects.c | 28 | ||||
-rw-r--r-- | src/pack-objects.h | 1 | ||||
-rw-r--r-- | src/stash.c | 12 | ||||
-rw-r--r-- | src/transports/local.c | 29 | ||||
-rw-r--r-- | tests/clone/nonetwork.c | 55 | ||||
-rw-r--r-- | tests/stash/apply.c | 2 | ||||
-rw-r--r-- | tests/submodule/modify.c | 1 |
17 files changed, 174 insertions, 43 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index be7d8dfb0..181d30127 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,10 +58,6 @@ IF(MSVC) # are linking statically OPTION( STATIC_CRT "Link the static CRT libraries" ON ) - # If you want to embed a copy of libssh2 into libgit2, pass a - # path to libssh2 - OPTION( EMBED_SSH_PATH "Path to libssh2 to embed (Windows)" OFF ) - ADD_DEFINITIONS(-D_SCL_SECURE_NO_WARNINGS) ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE) ADD_DEFINITIONS(-D_CRT_NONSTDC_NO_DEPRECATE) @@ -163,13 +159,6 @@ IF (COREFOUNDATION_FOUND) ENDIF() -IF (WIN32 AND EMBED_SSH_PATH) - FILE(GLOB SRC_SSH "${EMBED_SSH_PATH}/src/*.c") - INCLUDE_DIRECTORIES("${EMBED_SSH_PATH}/include") - FILE(WRITE "${EMBED_SSH_PATH}/src/libssh2_config.h" "#define HAVE_WINCNG\n#define LIBSSH2_WINCNG\n#include \"../win32/libssh2_config.h\"") - ADD_DEFINITIONS(-DGIT_SSH) -ENDIF() - IF (WIN32 AND WINHTTP) ADD_DEFINITIONS(-DGIT_WINHTTP) INCLUDE_DIRECTORIES(deps/http-parser) @@ -480,7 +469,7 @@ ELSE() ENDIF() # Compile and link libgit2 -ADD_LIBRARY(git2 ${SRC_H} ${SRC_GIT2} ${SRC_OS} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SSH} ${SRC_SHA1} ${WIN_RC}) +ADD_LIBRARY(git2 ${SRC_H} ${SRC_GIT2} ${SRC_OS} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SHA1} ${WIN_RC}) TARGET_LINK_LIBRARIES(git2 ${SECURITY_DIRS}) TARGET_LINK_LIBRARIES(git2 ${COREFOUNDATION_DIRS}) TARGET_LINK_LIBRARIES(git2 ${SSL_LIBRARIES}) @@ -549,7 +538,7 @@ IF (BUILD_CLAR) ${CLAR_PATH}/clar.c PROPERTIES OBJECT_DEPENDS ${CLAR_PATH}/clar.suite) - ADD_EXECUTABLE(libgit2_clar ${SRC_H} ${SRC_GIT2} ${SRC_OS} ${SRC_CLAR} ${SRC_TEST} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SSH} ${SRC_SHA1}) + ADD_EXECUTABLE(libgit2_clar ${SRC_H} ${SRC_GIT2} ${SRC_OS} ${SRC_CLAR} ${SRC_TEST} ${SRC_ZLIB} ${SRC_HTTP} ${SRC_REGEX} ${SRC_SHA1}) TARGET_LINK_LIBRARIES(libgit2_clar ${COREFOUNDATION_DIRS}) TARGET_LINK_LIBRARIES(libgit2_clar ${SECURITY_DIRS}) diff --git a/examples/network/clone.c b/examples/network/clone.c index 37e373d5a..b2d80ed01 100644 --- a/examples/network/clone.c +++ b/examples/network/clone.c @@ -46,6 +46,13 @@ static void print_progress(const progress_data *pd) } } +static int sideband_progress(const char *str, int len, void *payload) +{ + printf("remote: %*s", len, str); + fflush(stdout); + return 0; +} + static int fetch_progress(const git_transfer_progress *stats, void *payload) { progress_data *pd = (progress_data*)payload; @@ -86,6 +93,7 @@ int do_clone(git_repository *repo, int argc, char **argv) checkout_opts.progress_cb = checkout_progress; checkout_opts.progress_payload = &pd; clone_opts.checkout_opts = checkout_opts; + clone_opts.fetch_opts.callbacks.sideband_progress = sideband_progress; clone_opts.fetch_opts.callbacks.transfer_progress = &fetch_progress; clone_opts.fetch_opts.callbacks.credentials = cred_acquire_cb; clone_opts.fetch_opts.callbacks.payload = &pd; diff --git a/include/git2/index.h b/include/git2/index.h index 92636adeb..52032f7fd 100644 --- a/include/git2/index.h +++ b/include/git2/index.h @@ -24,9 +24,9 @@ GIT_BEGIN_DECL /** Time structure used in a git index entry */ typedef struct { - git_time_t seconds; + int32_t seconds; /* nsec should not be stored as time_t compatible */ - unsigned int nanoseconds; + uint32_t nanoseconds; } git_index_time; /** @@ -44,22 +44,27 @@ typedef struct { * accessed via the later `GIT_IDXENTRY_...` bitmasks below. Some of * these flags are read from and written to disk, but some are set aside * for in-memory only reference. + * + * Note that the time and size fields are truncated to 32 bits. This + * is enough to detect changes, which is enough for the index to + * function as a cache, but it should not be taken as an authoritative + * source for that data. */ typedef struct git_index_entry { git_index_time ctime; git_index_time mtime; - unsigned int dev; - unsigned int ino; - unsigned int mode; - unsigned int uid; - unsigned int gid; - git_off_t file_size; + uint32_t dev; + uint32_t ino; + uint32_t mode; + uint32_t uid; + uint32_t gid; + uint32_t file_size; git_oid id; - unsigned short flags; - unsigned short flags_extended; + uint16_t flags; + uint16_t flags_extended; const char *path; } git_index_entry; diff --git a/include/git2/odb.h b/include/git2/odb.h index 114f6b317..4f1e18bc1 100644 --- a/include/git2/odb.h +++ b/include/git2/odb.h @@ -247,7 +247,7 @@ GIT_EXTERN(int) git_odb_write(git_oid *out, git_odb *odb, const void *data, size * @param type type of the object that will be written * @return 0 if the stream was created; error code otherwise */ -GIT_EXTERN(int) git_odb_open_wstream(git_odb_stream **out, git_odb *db, size_t size, git_otype type); +GIT_EXTERN(int) git_odb_open_wstream(git_odb_stream **out, git_odb *db, git_off_t size, git_otype type); /** * Write to an odb stream diff --git a/include/git2/odb_backend.h b/include/git2/odb_backend.h index 4d772cab9..b17cfd8ba 100644 --- a/include/git2/odb_backend.h +++ b/include/git2/odb_backend.h @@ -86,8 +86,8 @@ struct git_odb_stream { unsigned int mode; void *hash_ctx; - size_t declared_size; - size_t received_bytes; + git_off_t declared_size; + git_off_t received_bytes; /** * Write at most `len` bytes into `buffer` and advance the stream. diff --git a/include/git2/sys/odb_backend.h b/include/git2/sys/odb_backend.h index 1fc3c3159..0a51c6dba 100644 --- a/include/git2/sys/odb_backend.h +++ b/include/git2/sys/odb_backend.h @@ -53,7 +53,7 @@ struct git_odb_backend { git_odb_backend *, const git_oid *, const void *, size_t, git_otype); int (* writestream)( - git_odb_stream **, git_odb_backend *, size_t, git_otype); + git_odb_stream **, git_odb_backend *, git_off_t, git_otype); int (* readstream)( git_odb_stream **, git_odb_backend *, const git_oid *); diff --git a/src/blob.c b/src/blob.c index 47216507b..07c4d92c8 100644 --- a/src/blob.c +++ b/src/blob.c @@ -76,10 +76,11 @@ static int write_file_stream( int fd, error; char buffer[FILEIO_BUFSIZE]; git_odb_stream *stream = NULL; - ssize_t read_len = -1, written = 0; + ssize_t read_len = -1; + git_off_t written = 0; if ((error = git_odb_open_wstream( - &stream, odb, (size_t)file_size, GIT_OBJ_BLOB)) < 0) + &stream, odb, file_size, GIT_OBJ_BLOB)) < 0) return error; if ((fd = git_futils_open_ro(path)) < 0) { @@ -21,9 +21,12 @@ #define GIT_ALTERNATES_FILE "info/alternates" -/* TODO: is this correct? */ -#define GIT_LOOSE_PRIORITY 2 -#define GIT_PACKED_PRIORITY 1 +/* + * We work under the assumption that most objects for long-running + * operations will be packed + */ +#define GIT_LOOSE_PRIORITY 1 +#define GIT_PACKED_PRIORITY 2 #define GIT_ALTERNATES_MAX_DEPTH 5 @@ -47,7 +50,7 @@ static git_cache *odb_cache(git_odb *odb) static int load_alternates(git_odb *odb, const char *objects_dir, int alternate_depth); -int git_odb__format_object_header(char *hdr, size_t n, size_t obj_len, git_otype obj_type) +int git_odb__format_object_header(char *hdr, size_t n, git_off_t obj_len, git_otype obj_type) { const char *type_str = git_object_type2string(obj_type); int len = p_snprintf(hdr, n, "%s %"PRIuZ, type_str, obj_len); @@ -327,10 +330,15 @@ static void fake_wstream__free(git_odb_stream *_stream) git__free(stream); } -static int init_fake_wstream(git_odb_stream **stream_p, git_odb_backend *backend, size_t size, git_otype type) +static int init_fake_wstream(git_odb_stream **stream_p, git_odb_backend *backend, git_off_t size, git_otype type) { fake_wstream *stream; + if (!git__is_ssizet(size)) { + giterr_set(GITERR_ODB, "object size too large to keep in memory"); + return -1; + } + stream = git__calloc(1, sizeof(fake_wstream)); GITERR_CHECK_ALLOC(stream); @@ -937,7 +945,7 @@ int git_odb_write( return error; } -static void hash_header(git_hash_ctx *ctx, size_t size, git_otype type) +static void hash_header(git_hash_ctx *ctx, git_off_t size, git_otype type) { char header[64]; int hdrlen; @@ -947,7 +955,7 @@ static void hash_header(git_hash_ctx *ctx, size_t size, git_otype type) } int git_odb_open_wstream( - git_odb_stream **stream, git_odb *db, size_t size, git_otype type) + git_odb_stream **stream, git_odb *db, git_off_t size, git_otype type) { size_t i, writes = 0; int error = GIT_ERROR; @@ -49,7 +49,7 @@ int git_odb__hashobj(git_oid *id, git_rawobj *obj); /* * Format the object header such as it would appear in the on-disk object */ -int git_odb__format_object_header(char *hdr, size_t n, size_t obj_len, git_otype obj_type); +int git_odb__format_object_header(char *hdr, size_t n, git_off_t obj_len, git_otype obj_type); /* * Hash an open file descriptor. * This is a performance call when the contents of a fd need to be hashed, diff --git a/src/odb_loose.c b/src/odb_loose.c index bfd95588b..99b8f7c91 100644 --- a/src/odb_loose.c +++ b/src/odb_loose.c @@ -834,7 +834,7 @@ static void loose_backend__stream_free(git_odb_stream *_stream) git__free(stream); } -static int loose_backend__stream(git_odb_stream **stream_out, git_odb_backend *_backend, size_t length, git_otype type) +static int loose_backend__stream(git_odb_stream **stream_out, git_odb_backend *_backend, git_off_t length, git_otype type) { loose_backend *backend; loose_writestream *stream = NULL; @@ -842,7 +842,7 @@ static int loose_backend__stream(git_odb_stream **stream_out, git_odb_backend *_ git_buf tmp_path = GIT_BUF_INIT; int hdrlen; - assert(_backend); + assert(_backend && length >= 0); backend = (loose_backend *)_backend; *stream_out = NULL; diff --git a/src/pack-objects.c b/src/pack-objects.c index 932764698..e287e3306 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -893,6 +893,29 @@ static unsigned long free_unpacked(struct unpacked *n) return freed_mem; } +static int report_delta_progress(git_packbuilder *pb, uint32_t count, bool force) +{ + int ret; + + if (pb->progress_cb) { + double current_time = git__timer(); + double elapsed = current_time - pb->last_progress_report_time; + + if (force || elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) { + pb->last_progress_report_time = current_time; + + ret = pb->progress_cb( + GIT_PACKBUILDER_DELTAFICATION, + count, pb->nr_objects, pb->progress_cb_payload); + + if (ret) + return giterr_set_after_callback(ret); + } + } + + return 0; +} + static int find_deltas(git_packbuilder *pb, git_pobject **list, unsigned int *list_size, unsigned int window, int depth) @@ -918,6 +941,9 @@ static int find_deltas(git_packbuilder *pb, git_pobject **list, break; } + pb->nr_deltified += 1; + report_delta_progress(pb, pb->nr_deltified, false); + po = *list++; (*list_size)--; git_packbuilder__progress_unlock(pb); @@ -1290,6 +1316,8 @@ static int prepare_pack(git_packbuilder *pb) } } + report_delta_progress(pb, pb->nr_objects, true); + pb->done = true; git__free(delta_list); return 0; diff --git a/src/pack-objects.h b/src/pack-objects.h index 9af5c0b09..82dea81f5 100644 --- a/src/pack-objects.h +++ b/src/pack-objects.h @@ -65,6 +65,7 @@ struct git_packbuilder { git_zstream zstream; uint32_t nr_objects, + nr_deltified, nr_alloc, nr_written, nr_remaining; diff --git a/src/stash.c b/src/stash.c index c79068edf..0c5cd1d2a 100644 --- a/src/stash.c +++ b/src/stash.c @@ -701,10 +701,14 @@ int git_stash_apply_init_options(git_stash_apply_options *opts, unsigned int ver return 0; } -#define NOTIFY_PROGRESS(opts, progress_type) \ - if ((opts).progress_cb && \ - (error = (opts).progress_cb((progress_type), (opts).progress_payload))) \ - return (error < 0) ? error : -1; +#define NOTIFY_PROGRESS(opts, progress_type) \ + do { \ + if ((opts).progress_cb && \ + (error = (opts).progress_cb((progress_type), (opts).progress_payload))) { \ + error = (error < 0) ? error : -1; \ + goto cleanup; \ + } \ + } while(false); int git_stash_apply( git_repository *repo, diff --git a/src/transports/local.c b/src/transports/local.c index bb9719c66..3b031a519 100644 --- a/src/transports/local.c +++ b/src/transports/local.c @@ -468,6 +468,33 @@ static int foreach_cb(void *buf, size_t len, void *payload) } static const char *counting_objects_fmt = "Counting objects %d\r"; +static const char *compressing_objects_fmt = "Compressing objects: %.0f%% (%d/%d)"; + +static int local_counting(int stage, unsigned int current, unsigned int total, void *payload) +{ + git_buf progress_info = GIT_BUF_INIT; + transport_local *t = payload; + + if (!t->progress_cb) + return 0; + + if (stage == GIT_PACKBUILDER_ADDING_OBJECTS) { + git_buf_printf(&progress_info, counting_objects_fmt, current); + } else if (stage == GIT_PACKBUILDER_DELTAFICATION) { + float perc = (((float) current) / total) * 100; + git_buf_printf(&progress_info, compressing_objects_fmt, perc, current, total); + if (current == total) + git_buf_printf(&progress_info, ", done\n"); + else + git_buf_putc(&progress_info, '\r'); + + } + + if (git_buf_oom(&progress_info)) + return -1; + + return t->progress_cb(git_buf_cstr(&progress_info), git_buf_len(&progress_info), t->message_cb_payload); +} static int local_download_pack( git_transport *transport, @@ -493,6 +520,8 @@ static int local_download_pack( if ((error = git_packbuilder_new(&pack, t->repo)) < 0) goto cleanup; + git_packbuilder_set_callbacks(pack, local_counting, t); + stats->total_objects = 0; stats->indexed_objects = 0; stats->received_objects = 0; diff --git a/tests/clone/nonetwork.c b/tests/clone/nonetwork.c index fec6aff2e..44a503818 100644 --- a/tests/clone/nonetwork.c +++ b/tests/clone/nonetwork.c @@ -1,6 +1,8 @@ #include "clar_libgit2.h" #include "git2/clone.h" +#include "git2/sys/commit.h" +#include "../submodule/submodule_helpers.h" #include "remote.h" #include "fileops.h" #include "repository.h" @@ -347,3 +349,56 @@ void test_clone_nonetwork__clone_from_empty_sets_upstream(void) git_repository_free(repo); cl_fixture_cleanup("./repowithunborn"); } + +static int just_return_origin(git_remote **out, git_repository *repo, const char *name, const char *url, void *payload) +{ + GIT_UNUSED(url); GIT_UNUSED(payload); + + return git_remote_lookup(out, repo, name); +} + +static int just_return_repo(git_repository **out, const char *path, int bare, void *payload) +{ + git_submodule *sm = payload; + + GIT_UNUSED(path); GIT_UNUSED(bare); + + return git_submodule_open(out, sm); +} + +void test_clone_nonetwork__clone_submodule(void) +{ + git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; + git_index *index; + git_oid tree_id, commit_id; + git_submodule *sm; + git_signature *sig; + git_repository *sm_repo; + + cl_git_pass(git_repository_init(&g_repo, "willaddsubmodule", false)); + + + /* Create the submodule structure, clone into it and finalize */ + cl_git_pass(git_submodule_add_setup(&sm, g_repo, cl_fixture("testrepo.git"), "testrepo", true)); + + clone_opts.repository_cb = just_return_repo; + clone_opts.repository_cb_payload = sm; + clone_opts.remote_cb = just_return_origin; + clone_opts.remote_cb_payload = sm; + cl_git_pass(git_clone(&sm_repo, cl_fixture("testrepo.git"), "testrepo", &clone_opts)); + cl_git_pass(git_submodule_add_finalize(sm)); + git_repository_free(sm_repo); + git_submodule_free(sm); + + cl_git_pass(git_repository_index(&index, g_repo)); + cl_git_pass(git_index_write_tree(&tree_id, index)); + git_index_free(index); + + cl_git_pass(git_signature_now(&sig, "Submoduler", "submoduler@local")); + cl_git_pass(git_commit_create_from_ids(&commit_id, g_repo, "HEAD", sig, sig, NULL, "A submodule\n", + &tree_id, 0, NULL)); + + git_signature_free(sig); + + assert_submodule_exists(g_repo, "testrepo"); +} diff --git a/tests/stash/apply.c b/tests/stash/apply.c index 213945e9b..42186b6fb 100644 --- a/tests/stash/apply.c +++ b/tests/stash/apply.c @@ -44,6 +44,8 @@ void test_stash_apply__initialize(void) assert_status(repo, "how", GIT_STATUS_CURRENT); assert_status(repo, "who", GIT_STATUS_CURRENT); assert_status(repo, "when", GIT_ENOTFOUND); + + git_index_free(repo_index); } void test_stash_apply__cleanup(void) diff --git a/tests/submodule/modify.c b/tests/submodule/modify.c index 1ede56ec8..bbbb2d56e 100644 --- a/tests/submodule/modify.c +++ b/tests/submodule/modify.c @@ -257,4 +257,5 @@ void test_submodule_modify__save_last(void) cl_git_pass(git_submodule_lookup(&sm, g_repo, "sm_gitmodules_only")); cl_git_pass(git_submodule_save(sm)); + git_submodule_free(sm); } |