summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt15
-rw-r--r--examples/network/clone.c8
-rw-r--r--include/git2/index.h25
-rw-r--r--include/git2/odb.h2
-rw-r--r--include/git2/odb_backend.h4
-rw-r--r--include/git2/sys/odb_backend.h2
-rw-r--r--src/blob.c5
-rw-r--r--src/odb.c22
-rw-r--r--src/odb.h2
-rw-r--r--src/odb_loose.c4
-rw-r--r--src/pack-objects.c28
-rw-r--r--src/pack-objects.h1
-rw-r--r--src/stash.c12
-rw-r--r--src/transports/local.c29
-rw-r--r--tests/clone/nonetwork.c55
-rw-r--r--tests/stash/apply.c2
-rw-r--r--tests/submodule/modify.c1
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) {
diff --git a/src/odb.c b/src/odb.c
index c3ae15a6a..deb9d5c82 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -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;
diff --git a/src/odb.h b/src/odb.h
index 61dd9a7fd..281bd3a4d 100644
--- a/src/odb.h
+++ b/src/odb.h
@@ -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);
}