Merge pull request #3739 from ethomson/0.24.1
Backport bug fixes to 0.24
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f4e56e6..c79b263 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -412,7 +412,7 @@
# /MTd - Statically link the multithreaded debug version of the CRT
# /MDd - Dynamically link the multithreaded debug version of the CRT
# /RTC1 - Run time checks
- SET(CMAKE_C_FLAGS_DEBUG "/Zi /Od /D_DEBUG /RTC1 ${CRT_FLAG_DEBUG}")
+ SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Zi /Od /D_DEBUG /RTC1 ${CRT_FLAG_DEBUG}")
# /DNDEBUG - Disables asserts
# /MT - Statically link the multithreaded release version of the CRT
@@ -464,7 +464,7 @@
ENDIF()
IF (WIN32 AND NOT CYGWIN)
- SET(CMAKE_C_FLAGS_DEBUG "-D_DEBUG")
+ SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
ENDIF ()
IF (MINGW) # MinGW always does PIC and complains if we tell it to
@@ -608,6 +608,8 @@
IF (LIBGIT2_FILENAME)
ADD_DEFINITIONS(-DLIBGIT2_FILENAME=\"${LIBGIT2_FILENAME}\")
SET_TARGET_PROPERTIES(git2 PROPERTIES OUTPUT_NAME ${LIBGIT2_FILENAME})
+ ELSEIF (DEFINED LIBGIT2_PREFIX)
+ SET_TARGET_PROPERTIES(git2 PROPERTIES PREFIX "${LIBGIT2_PREFIX}")
ENDIF()
ENDIF()
STRING(REPLACE ";" " " LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS}")
diff --git a/deps/http-parser/http_parser.c b/deps/http-parser/http_parser.c
index 2035302..27bdd20 100644
--- a/deps/http-parser/http_parser.c
+++ b/deps/http-parser/http_parser.c
@@ -99,7 +99,7 @@
FOR##_mark = NULL; \
} \
} while (0)
-
+
/* Run the data callback FOR and consume the current byte */
#define CALLBACK_DATA(FOR) \
CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1)
@@ -444,6 +444,9 @@
return s_req_path;
}
+ /* The schema must start with an alpha character. After that, it may
+ * consist of digits, '+', '-' or '.', followed by a ':'.
+ */
if (IS_ALPHA(ch)) {
return s_req_schema;
}
@@ -451,7 +454,7 @@
break;
case s_req_schema:
- if (IS_ALPHA(ch)) {
+ if (IS_ALPHANUM(ch) || ch == '+' || ch == '-' || ch == '.') {
return s;
}
diff --git a/include/git2/common.h b/include/git2/common.h
index 4f43185..d7428d8 100644
--- a/include/git2/common.h
+++ b/include/git2/common.h
@@ -24,10 +24,19 @@
GIT_BEGIN_DECL
# include "inttypes.h"
GIT_END_DECL
-#else
+/** This check is needed for importing this file in an iOS/OS X framework throws an error in Xcode otherwise.*/
+#elif !defined(__CLANG_INTTYPES_H)
# include <inttypes.h>
#endif
+#ifdef DOCURIUM
+/*
+ * This is so clang's doc parser acknowledges comments on functions
+ * with size_t parameters.
+ */
+typedef size_t size_t;
+#endif
+
/** Declare a public function exported for application use. */
#if __GNUC__ >= 4
# define GIT_EXTERN(type) extern \
@@ -148,6 +157,7 @@
GIT_OPT_SET_SSL_CERT_LOCATIONS,
GIT_OPT_SET_USER_AGENT,
GIT_OPT_ENABLE_STRICT_OBJECT_CREATION,
+ GIT_OPT_SET_SSL_CIPHERS,
} git_libgit2_opt_t;
/**
@@ -259,6 +269,11 @@
* > example, when this is enabled, the parent(s) and tree inputs
* > will be validated when creating a new commit. This defaults
* > to disabled.
+ * * opts(GIT_OPT_SET_SSL_CIPHERS, const char *ciphers)
+ *
+ * > Set the SSL ciphers use for HTTPS connections.
+ * >
+ * > - `ciphers` is the list of ciphers that are eanbled.
*
* @param option Option key
* @param ... value to set the option
diff --git a/script/coverity.sh b/script/coverity.sh
index 8c82689..7fe9eb4 100755
--- a/script/coverity.sh
+++ b/script/coverity.sh
@@ -49,10 +49,24 @@
# Upload results
tar czf libgit2.tgz cov-int
SHA=$(git rev-parse --short HEAD)
-curl \
+
+HTML="$(curl \
+ --silent \
+ --write-out "\n%{http_code}" \
--form token="$COVERITY_TOKEN" \
--form email=bs@github.com \
--form file=@libgit2.tgz \
--form version="$SHA" \
--form description="Travis build" \
- https://scan.coverity.com/builds?project=libgit2
+ https://scan.coverity.com/builds?project=libgit2)"
+# Body is everything up to the last line
+BODY="$(echo "$HTML" | head -n-1)"
+# Status code is the last line
+STATUS_CODE="$(echo "$HTML" | tail -n1)"
+
+echo "${BODY}"
+
+if [ "${STATUS_CODE}" != "201" ]; then
+ echo "Received error code ${STATUS_CODE} from Coverity"
+ exit 1
+fi
diff --git a/src/array.h b/src/array.h
index 7cd9b71..490e6be 100644
--- a/src/array.h
+++ b/src/array.h
@@ -82,4 +82,44 @@
#define git_array_valid_index(a, i) ((i) < (a).size)
+#define git_array_foreach(a, i, element) \
+ for ((i) = 0; (i) < (a).size && ((element) = &(a).ptr[(i)]); (i)++)
+
+
+GIT_INLINE(int) git_array__search(
+ size_t *out,
+ void *array_ptr,
+ size_t item_size,
+ size_t array_len,
+ int (*compare)(const void *, const void *),
+ const void *key)
+{
+ size_t lim;
+ unsigned char *part, *array = array_ptr, *base = array_ptr;
+ int cmp;
+
+ for (lim = array_len; lim != 0; lim >>= 1) {
+ part = base + (lim >> 1) * item_size;
+ cmp = (*compare)(key, part);
+
+ if (cmp == 0) {
+ base = part;
+ break;
+ }
+ if (cmp > 0) { /* key > p; take right partition */
+ base = part + 1 * item_size;
+ lim--;
+ } /* else take left partition */
+ }
+
+ if (out)
+ *out = (base - array) / item_size;
+
+ return (cmp == 0) ? 0 : GIT_ENOTFOUND;
+}
+
+#define git_array_search(out, a, cmp, key) \
+ git_array__search(out, (a).ptr, sizeof(*(a).ptr), (a).size, \
+ (cmp), (key))
+
#endif
diff --git a/src/blame.c b/src/blame.c
index 2daf915..2c8584b 100644
--- a/src/blame.c
+++ b/src/blame.c
@@ -178,7 +178,7 @@
return NULL;
}
-static void normalize_options(
+static int normalize_options(
git_blame_options *out,
const git_blame_options *in,
git_repository *repo)
@@ -190,7 +190,9 @@
/* No newest_commit => HEAD */
if (git_oid_iszero(&out->newest_commit)) {
- git_reference_name_to_id(&out->newest_commit, repo, "HEAD");
+ if (git_reference_name_to_id(&out->newest_commit, repo, "HEAD") < 0) {
+ return -1;
+ }
}
/* min_line 0 really means 1 */
@@ -204,6 +206,8 @@
out->flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES;
if (out->flags & GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES)
out->flags |= GIT_BLAME_TRACK_COPIES_SAME_FILE;
+
+ return 0;
}
static git_blame_hunk *split_hunk_in_vector(
@@ -362,7 +366,8 @@
git_blame *blame = NULL;
assert(out && repo && path);
- normalize_options(&normOptions, options, repo);
+ if ((error = normalize_options(&normOptions, options, repo)) < 0)
+ goto on_error;
blame = git_blame__alloc(repo, normOptions, path);
GITERR_CHECK_ALLOC(blame);
diff --git a/src/blame_git.c b/src/blame_git.c
index b8b5682..700207e 100644
--- a/src/blame_git.c
+++ b/src/blame_git.c
@@ -525,7 +525,8 @@
if (sg_origin[i])
continue;
- git_commit_parent(&p, origin->commit, i);
+ if ((error = git_commit_parent(&p, origin->commit, i)) < 0)
+ goto finish;
porigin = find_origin(blame, p, origin);
if (!porigin)
diff --git a/src/commit.c b/src/commit.c
index 685c642..5ed9c47 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -676,7 +676,7 @@
buf = git_odb_object_data(obj);
- while ((h = strchr(buf, '\n')) && h[1] != '\0' && h[1] != '\n') {
+ while ((h = strchr(buf, '\n')) && h[1] != '\0') {
h++;
if (git__prefixcmp(buf, field)) {
if (git_buf_put(signed_data, buf, h - buf) < 0)
diff --git a/src/config_cache.c b/src/config_cache.c
index c859ec1..dbea871 100644
--- a/src/config_cache.c
+++ b/src/config_cache.c
@@ -86,7 +86,8 @@
struct map_data *data = &_cvar_maps[(int)cvar];
git_config_entry *entry;
- git_config__lookup_entry(&entry, config, data->cvar_name, false);
+ if ((error = git_config__lookup_entry(&entry, config, data->cvar_name, false)) < 0)
+ return error;
if (!entry)
*out = data->default_value;
diff --git a/src/config_file.c b/src/config_file.c
index 5f5e309..ca4345c 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -553,30 +553,15 @@
git_config_backend *cfg, const char *name, const char *regexp, const char *value)
{
diskfile_backend *b = (diskfile_backend *)cfg;
- refcounted_strmap *map;
- git_strmap *values;
char *key;
regex_t preg;
int result;
- khiter_t pos;
assert(regexp);
if ((result = git_config__normalize_name(name, &key)) < 0)
return result;
- map = refcounted_strmap_take(&b->header);
- values = b->header.values->values;
-
- pos = git_strmap_lookup_index(values, key);
- if (!git_strmap_valid_index(values, pos)) {
- /* If we don't have it, behave like a normal set */
- result = config_set(cfg, name, value);
- refcounted_strmap_free(map);
- git__free(key);
- return result;
- }
-
result = regcomp(&preg, regexp, REG_EXTENDED);
if (result != 0) {
giterr_set_regex(&preg, result);
@@ -591,7 +576,6 @@
result = config_refresh(cfg);
out:
- refcounted_strmap_free(map);
git__free(key);
regfree(&preg);
@@ -1032,6 +1016,11 @@
*/
first_quote = strchr(line, '"');
+ if (first_quote == NULL) {
+ set_parse_error(reader, 0, "Missing quotation marks in section header");
+ return -1;
+ }
+
last_quote = strrchr(line, '"');
quoted_len = last_quote - first_quote;
@@ -1483,7 +1472,7 @@
int (*on_section)(struct reader **reader, const char *current_section, const char *line, size_t line_len, void *data),
int (*on_variable)(struct reader **reader, const char *current_section, char *var_name, char *var_value, const char *line, size_t line_len, void *data),
int (*on_comment)(struct reader **reader, const char *line, size_t line_len, void *data),
- int (*on_eof)(struct reader **reader, void *data),
+ int (*on_eof)(struct reader **reader, const char *current_section, void *data),
void *data)
{
char *current_section = NULL, *var_name, *var_value, *line_start;
@@ -1534,7 +1523,7 @@
}
if (on_eof)
- result = on_eof(&reader, data);
+ result = on_eof(&reader, current_section, data);
git__free(current_section);
return result;
@@ -1850,7 +1839,8 @@
return write_line_to(&write_data->buffered_comment, line, line_len);
}
-static int write_on_eof(struct reader **reader, void *data)
+static int write_on_eof(
+ struct reader **reader, const char *current_section, void *data)
{
struct write_data *write_data = (struct write_data *)data;
int result = 0;
@@ -1869,7 +1859,11 @@
* value.
*/
if ((!write_data->preg || !write_data->preg_replaced) && write_data->value) {
- if ((result = write_section(write_data->buf, write_data->section)) == 0)
+ /* write the section header unless we're already in it */
+ if (!current_section || strcmp(current_section, write_data->section))
+ result = write_section(write_data->buf, write_data->section);
+
+ if (!result)
result = write_value(write_data);
}
diff --git a/src/describe.c b/src/describe.c
index 48f04e8..13ddad5 100644
--- a/src/describe.c
+++ b/src/describe.c
@@ -582,7 +582,8 @@
best = (struct possible_tag *)git_vector_get(&all_matches, 0);
if (gave_up_on) {
- git_pqueue_insert(&list, gave_up_on);
+ if ((error = git_pqueue_insert(&list, gave_up_on)) < 0)
+ goto cleanup;
seen_commits--;
}
if ((error = finish_depth_computation(
diff --git a/src/diff_tform.c b/src/diff_tform.c
index 8577f06..6a6a628 100644
--- a/src/diff_tform.c
+++ b/src/diff_tform.c
@@ -261,7 +261,7 @@
if (!given ||
(given->flags & GIT_DIFF_FIND_ALL) == GIT_DIFF_FIND_BY_CONFIG)
{
- if (diff->repo) {
+ if (cfg) {
char *rule =
git_config__get_string_force(cfg, "diff.renames", "true");
int boolval;
@@ -318,8 +318,10 @@
#undef USE_DEFAULT
if (!opts->rename_limit) {
- opts->rename_limit = git_config__get_int_force(
- cfg, "diff.renamelimit", DEFAULT_RENAME_LIMIT);
+ if (cfg) {
+ opts->rename_limit = git_config__get_int_force(
+ cfg, "diff.renamelimit", DEFAULT_RENAME_LIMIT);
+ }
if (opts->rename_limit <= 0)
opts->rename_limit = DEFAULT_RENAME_LIMIT;
diff --git a/src/filebuf.c b/src/filebuf.c
index 17efe87..101d508 100644
--- a/src/filebuf.c
+++ b/src/filebuf.c
@@ -70,6 +70,7 @@
git_file source;
char buffer[FILEIO_BUFSIZE];
ssize_t read_bytes;
+ int error;
source = p_open(file->path_original, O_RDONLY);
if (source < 0) {
@@ -80,7 +81,8 @@
}
while ((read_bytes = p_read(source, buffer, sizeof(buffer))) > 0) {
- p_write(file->fd, buffer, read_bytes);
+ if ((error = p_write(file->fd, buffer, read_bytes)) < 0)
+ break;
if (file->compute_digest)
git_hash_update(&file->digest, buffer, read_bytes);
}
@@ -90,6 +92,9 @@
if (read_bytes < 0) {
giterr_set(GITERR_OS, "Failed to read file '%s'", file->path_original);
return -1;
+ } else if (error < 0) {
+ giterr_set(GITERR_OS, "Failed to write file '%s'", file->path_lock);
+ return -1;
}
}
diff --git a/src/global.c b/src/global.c
index 0bfde1e..adf353d 100644
--- a/src/global.c
+++ b/src/global.c
@@ -27,6 +27,7 @@
static git_atomic git__n_shutdown_callbacks;
static git_atomic git__n_inits;
char *git__user_agent;
+char *git__ssl_ciphers;
void git__on_shutdown(git_global_shutdown_fn callback)
{
@@ -83,6 +84,7 @@
}
git__free(git__user_agent);
+ git__free(git__ssl_ciphers);
#if defined(GIT_MSVC_CRTDBG)
git_win32__crtdbg_stacktrace_cleanup();
@@ -222,6 +224,20 @@
TlsSetValue(_tls_index, NULL);
}
+BOOL WINAPI DllMain(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpvReserved)
+{
+ /* This is how Windows lets us know our thread is being shut down */
+ if (fdwReason == DLL_THREAD_DETACH) {
+ git__free_tls_data();
+ }
+
+ /*
+ * Windows pays attention to this during library loading. We don't do anything
+ * so we trivially succeed.
+ */
+ return TRUE;
+}
+
#elif defined(GIT_THREADS) && defined(_POSIX_THREADS)
static pthread_key_t _tls_key;
diff --git a/src/global.h b/src/global.h
index 9fdcee5..2199515 100644
--- a/src/global.h
+++ b/src/global.h
@@ -36,5 +36,6 @@
extern void git__free_tls_data(void);
extern const char *git_libgit2__user_agent(void);
+extern const char *git_libgit2__ssl_ciphers(void);
#endif
diff --git a/src/ignore.c b/src/ignore.c
index aedc140..ac2af4f 100644
--- a/src/ignore.c
+++ b/src/ignore.c
@@ -263,10 +263,18 @@
goto cleanup;
/* given a unrooted path in a non-bare repo, resolve it */
- if (workdir && git_path_root(path) < 0)
- error = git_path_find_dir(&ignores->dir, path, workdir);
- else
+ if (workdir && git_path_root(path) < 0) {
+ git_buf local = GIT_BUF_INIT;
+
+ if ((error = git_path_dirname_r(&local, path)) < 0 ||
+ (error = git_path_resolve_relative(&local, 0)) < 0 ||
+ (error = git_path_to_dir(&local)) < 0 ||
+ (error = git_buf_joinpath(&ignores->dir, workdir, local.ptr)) < 0)
+ {;} /* Nothing, we just want to stop on the first error */
+ git_buf_free(&local);
+ } else {
error = git_buf_joinpath(&ignores->dir, path, "");
+ }
if (error < 0)
goto cleanup;
diff --git a/src/index.c b/src/index.c
index b97f809..63e4796 100644
--- a/src/index.c
+++ b/src/index.c
@@ -963,14 +963,20 @@
*reuc_out = reuc = reuc_entry_alloc(path);
GITERR_CHECK_ALLOC(reuc);
- if ((reuc->mode[0] = ancestor_mode) > 0)
+ if ((reuc->mode[0] = ancestor_mode) > 0) {
+ assert(ancestor_oid);
git_oid_cpy(&reuc->oid[0], ancestor_oid);
+ }
- if ((reuc->mode[1] = our_mode) > 0)
+ if ((reuc->mode[1] = our_mode) > 0) {
+ assert(our_oid);
git_oid_cpy(&reuc->oid[1], our_oid);
+ }
- if ((reuc->mode[2] = their_mode) > 0)
+ if ((reuc->mode[2] = their_mode) > 0) {
+ assert(their_oid);
git_oid_cpy(&reuc->oid[2], their_oid);
+ }
return 0;
}
@@ -2830,7 +2836,7 @@
return -1;
entry->mode = tentry->attr;
- entry->id = tentry->oid;
+ git_oid_cpy(&entry->id, git_tree_entry_id(tentry));
/* look for corresponding old entry and copy data to new entry */
if (data->old_entries != NULL &&
diff --git a/src/indexer.c b/src/indexer.c
index 9aa0925..a3a8669 100644
--- a/src/indexer.c
+++ b/src/indexer.c
@@ -449,7 +449,7 @@
static int write_at(git_indexer *idx, const void *data, git_off_t offset, size_t size)
{
git_file fd = idx->pack->mwf.fd;
- size_t page_size;
+ size_t mmap_alignment;
size_t page_offset;
git_off_t page_start;
unsigned char *map_data;
@@ -458,11 +458,11 @@
assert(data && size);
- if ((error = git__page_size(&page_size)) < 0)
+ if ((error = git__mmap_alignment(&mmap_alignment)) < 0)
return error;
- /* the offset needs to be at the beginning of the a page boundary */
- page_offset = offset % page_size;
+ /* the offset needs to be at the mmap boundary for the platform */
+ page_offset = offset % mmap_alignment;
page_start = offset - page_offset;
if ((error = p_mmap(&map, page_offset + size, GIT_PROT_WRITE, GIT_MAP_SHARED, fd, page_start)) < 0)
@@ -777,7 +777,6 @@
curpos = delta->delta_off;
error = git_packfile_unpack_header(&size, &type, &idx->pack->mwf, &w, &curpos);
- git_mwindow_close(&w);
if (error < 0)
return error;
@@ -914,12 +913,17 @@
git_filebuf index_file = {0};
void *packfile_trailer;
+ if (!idx->parsed_header) {
+ giterr_set(GITERR_INDEXER, "incomplete pack header");
+ return -1;
+ }
+
if (git_hash_ctx_init(&ctx) < 0)
return -1;
/* Test for this before resolve_deltas(), as it plays with idx->off */
- if (idx->off < idx->pack->mwf.size - 20) {
- giterr_set(GITERR_INDEXER, "Unexpected data at the end of the pack");
+ if (idx->off + 20 < idx->pack->mwf.size) {
+ giterr_set(GITERR_INDEXER, "unexpected data at the end of the pack");
return -1;
}
diff --git a/src/iterator.c b/src/iterator.c
index 024a975..cb1ea6a 100644
--- a/src/iterator.c
+++ b/src/iterator.c
@@ -458,7 +458,7 @@
/* try to load trees for items in [current,next) range */
if (!error && git_tree_entry__is_tree(te))
error = git_tree_lookup(
- &tf->entries[tf->next]->tree, ti->base.repo, &te->oid);
+ &tf->entries[tf->next]->tree, ti->base.repo, te->oid);
}
if (tf->next > tf->current + 1)
@@ -603,7 +603,7 @@
te = tf->entries[tf->current]->te;
ti->entry.mode = te->attr;
- git_oid_cpy(&ti->entry.id, &te->oid);
+ git_oid_cpy(&ti->entry.id, te->oid);
ti->entry.path = tree_iterator__current_filename(ti, te);
GITERR_CHECK_ALLOC(ti->entry.path);
diff --git a/src/mwindow.c b/src/mwindow.c
index 55c8d89..d3e9be7 100644
--- a/src/mwindow.c
+++ b/src/mwindow.c
@@ -296,8 +296,18 @@
*/
if (git_futils_mmap_ro(&w->window_map, fd, w->offset, (size_t)len) < 0) {
- git__free(w);
- return NULL;
+ /*
+ * The first error might be down to memory fragmentation even if
+ * we're below our soft limits, so free up what we can and try again.
+ */
+
+ while (git_mwindow_close_lru(mwf) == 0)
+ /* nop */;
+
+ if (git_futils_mmap_ro(&w->window_map, fd, w->offset, (size_t)len) < 0) {
+ git__free(w);
+ return NULL;
+ }
}
ctl->mmap_calls++;
diff --git a/src/object.c b/src/object.c
index ebf77fb..1d45f9f 100644
--- a/src/object.c
+++ b/src/object.c
@@ -12,6 +12,7 @@
#include "commit.h"
#include "tree.h"
#include "blob.h"
+#include "oid.h"
#include "tag.h"
bool git_object__strict_input_validation = true;
@@ -166,13 +167,9 @@
error = git_odb_read(&odb_obj, odb, id);
}
} else {
- git_oid short_oid;
+ git_oid short_oid = {{ 0 }};
- /* We copy the first len*4 bits from id and fill the remaining with 0s */
- memcpy(short_oid.id, id->id, (len + 1) / 2);
- if (len % 2)
- short_oid.id[len / 2] &= 0xF0;
- memset(short_oid.id + (len + 1) / 2, 0, (GIT_OID_HEXSZ - len) / 2);
+ git_oid__cpy_prefix(&short_oid, id, len);
/* If len < GIT_OID_HEXSZ (a strict short oid was given), we have
* 2 options :
diff --git a/src/odb.c b/src/odb.c
index 1c877c9..cb0f706 100644
--- a/src/odb.c
+++ b/src/odb.c
@@ -725,7 +725,8 @@
git_oid_cpy(out, short_id);
return 0;
} else {
- return git_odb__error_notfound("no match for id prefix", short_id);
+ return git_odb__error_notfound(
+ "no match for id prefix", short_id, len);
}
}
@@ -740,7 +741,7 @@
error = odb_exists_prefix_1(out, db, &key, len, true);
if (error == GIT_ENOTFOUND)
- return git_odb__error_notfound("no match for id prefix", &key);
+ return git_odb__error_notfound("no match for id prefix", &key, len);
return error;
}
@@ -881,7 +882,7 @@
error = odb_read_1(out, db, id, true);
if (error == GIT_ENOTFOUND)
- return git_odb__error_notfound("no match for id", id);
+ return git_odb__error_notfound("no match for id", id, GIT_OID_HEXSZ);
return error;
}
@@ -967,7 +968,7 @@
error = read_prefix_1(out, db, &key, len, true);
if (error == GIT_ENOTFOUND)
- return git_odb__error_notfound("no match for prefix", &key);
+ return git_odb__error_notfound("no match for prefix", &key, len);
return error;
}
@@ -1223,12 +1224,14 @@
return 0;
}
-int git_odb__error_notfound(const char *message, const git_oid *oid)
+int git_odb__error_notfound(
+ const char *message, const git_oid *oid, size_t oid_len)
{
if (oid != NULL) {
char oid_str[GIT_OID_HEXSZ + 1];
- git_oid_tostr(oid_str, sizeof(oid_str), oid);
- giterr_set(GITERR_ODB, "Object not found - %s (%s)", message, oid_str);
+ git_oid_tostr(oid_str, oid_len, oid);
+ giterr_set(GITERR_ODB, "Object not found - %s (%.*s)",
+ message, oid_len, oid_str);
} else
giterr_set(GITERR_ODB, "Object not found - %s", message);
diff --git a/src/odb.h b/src/odb.h
index 281bd3a..31a9fd1 100644
--- a/src/odb.h
+++ b/src/odb.h
@@ -82,7 +82,8 @@
/*
* Generate a GIT_ENOTFOUND error for the ODB.
*/
-int git_odb__error_notfound(const char *message, const git_oid *oid);
+int git_odb__error_notfound(
+ const char *message, const git_oid *oid, size_t oid_len);
/*
* Generate a GIT_EAMBIGUOUS error for the ODB.
diff --git a/src/odb_loose.c b/src/odb_loose.c
index 730c4b1..9d9bffd 100644
--- a/src/odb_loose.c
+++ b/src/odb_loose.c
@@ -547,7 +547,8 @@
/* Check that directory exists */
if (git_path_isdir(object_location->ptr) == false)
- return git_odb__error_notfound("no matching loose object for prefix", short_oid);
+ return git_odb__error_notfound("no matching loose object for prefix",
+ short_oid, len);
state.dir_len = git_buf_len(object_location);
state.short_oid_len = len;
@@ -560,7 +561,8 @@
return error;
if (!state.found)
- return git_odb__error_notfound("no matching loose object for prefix", short_oid);
+ return git_odb__error_notfound("no matching loose object for prefix",
+ short_oid, len);
if (state.found > 1)
return git_odb__error_ambiguous("multiple matches in loose objects");
@@ -613,9 +615,10 @@
raw.len = 0;
raw.type = GIT_OBJ_BAD;
- if (locate_object(&object_path, (loose_backend *)backend, oid) < 0)
- error = git_odb__error_notfound("no matching loose object", oid);
- else if ((error = read_header_loose(&raw, &object_path)) == 0) {
+ if (locate_object(&object_path, (loose_backend *)backend, oid) < 0) {
+ error = git_odb__error_notfound("no matching loose object",
+ oid, GIT_OID_HEXSZ);
+ } else if ((error = read_header_loose(&raw, &object_path)) == 0) {
*len_p = raw.len;
*type_p = raw.type;
}
@@ -633,9 +636,10 @@
assert(backend && oid);
- if (locate_object(&object_path, (loose_backend *)backend, oid) < 0)
- error = git_odb__error_notfound("no matching loose object", oid);
- else if ((error = read_loose(&raw, &object_path)) == 0) {
+ if (locate_object(&object_path, (loose_backend *)backend, oid) < 0) {
+ error = git_odb__error_notfound("no matching loose object",
+ oid, GIT_OID_HEXSZ);
+ } else if ((error = read_loose(&raw, &object_path)) == 0) {
*buffer_p = raw.data;
*len_p = raw.len;
*type_p = raw.type;
diff --git a/src/odb_pack.c b/src/odb_pack.c
index 77d2c75..5a57864 100644
--- a/src/odb_pack.c
+++ b/src/odb_pack.c
@@ -264,7 +264,8 @@
if (!pack_entry_find_inner(e, backend, oid, last_found))
return 0;
- return git_odb__error_notfound("failed to find pack entry", oid);
+ return git_odb__error_notfound(
+ "failed to find pack entry", oid, GIT_OID_HEXSZ);
}
static int pack_entry_find_prefix(
@@ -309,7 +310,8 @@
}
if (!found)
- return git_odb__error_notfound("no matching pack entry for prefix", short_oid);
+ return git_odb__error_notfound("no matching pack entry for prefix",
+ short_oid, len);
else
return 0;
}
@@ -333,7 +335,7 @@
return 0;
if (p_stat(backend->pack_folder, &st) < 0 || !S_ISDIR(st.st_mode))
- return git_odb__error_notfound("failed to refresh packfiles", NULL);
+ return git_odb__error_notfound("failed to refresh packfiles", NULL, 0);
git_buf_sets(&path, backend->pack_folder);
diff --git a/src/oid.h b/src/oid.h
index aa1f0bf..922a2a3 100644
--- a/src/oid.h
+++ b/src/oid.h
@@ -44,4 +44,13 @@
return git_oid__hashcmp(a->id, b->id);
}
+GIT_INLINE(void) git_oid__cpy_prefix(
+ git_oid *out, const git_oid *id, size_t len)
+{
+ memcpy(&out->id, id->id, (len + 1) / 2);
+
+ if (len & 1)
+ out->id[len / 2] &= 0xF0;
+}
+
#endif
diff --git a/src/openssl_stream.c b/src/openssl_stream.c
index 97736b7..a65f558 100644
--- a/src/openssl_stream.c
+++ b/src/openssl_stream.c
@@ -34,6 +34,8 @@
SSL_CTX *git__ssl_ctx;
+#define GIT_SSL_DEFAULT_CIPHERS "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-DSS-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-DSS-AES128-SHA256:DHE-DSS-AES256-SHA256:DHE-DSS-AES128-SHA:DHE-DSS-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA"
+
#ifdef GIT_THREADS
static git_mutex *openssl_locks;
@@ -85,6 +87,7 @@
{
#ifdef GIT_OPENSSL
long ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
+ const char *ciphers = git_libgit2__ssl_ciphers();
/* Older OpenSSL and MacOS OpenSSL doesn't have this */
#ifdef SSL_OP_NO_COMPRESSION
@@ -108,6 +111,16 @@
git__ssl_ctx = NULL;
return -1;
}
+
+ if (!ciphers) {
+ ciphers = GIT_SSL_DEFAULT_CIPHERS;
+ }
+
+ if(!SSL_CTX_set_cipher_list(git__ssl_ctx, ciphers)) {
+ SSL_CTX_free(git__ssl_ctx);
+ git__ssl_ctx = NULL;
+ return -1;
+ }
#endif
git__on_shutdown(shutdown_ssl);
diff --git a/src/pack-objects.c b/src/pack-objects.c
index 46fe8f3..11e13f7 100644
--- a/src/pack-objects.c
+++ b/src/pack-objects.c
@@ -848,8 +848,10 @@
git_packbuilder__cache_unlock(pb);
- if (overflow)
+ if (overflow) {
+ git__free(delta_buf);
return -1;
+ }
trg_object->delta_data = git__realloc(delta_buf, delta_size);
GITERR_CHECK_ALLOC(trg_object->delta_data);
diff --git a/src/pack.c b/src/pack.c
index 52c6521..e7003e6 100644
--- a/src/pack.c
+++ b/src/pack.c
@@ -494,7 +494,6 @@
int error;
error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
- git_mwindow_close(&w_curs);
if (error < 0)
return error;
@@ -517,7 +516,6 @@
while (type == GIT_OBJ_OFS_DELTA || type == GIT_OBJ_REF_DELTA) {
curpos = base_offset;
error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
- git_mwindow_close(&w_curs);
if (error < 0)
return error;
if (type != GIT_OBJ_OFS_DELTA && type != GIT_OBJ_REF_DELTA)
@@ -585,7 +583,6 @@
elem->base_key = obj_offset;
error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
- git_mwindow_close(&w_curs);
if (error < 0)
goto on_error;
@@ -1018,7 +1015,7 @@
unsigned char *idx_sha1;
if (p->index_version == -1 && pack_index_open(p) < 0)
- return git_odb__error_notfound("failed to open packfile", NULL);
+ return git_odb__error_notfound("failed to open packfile", NULL, 0);
/* if mwf opened by another thread, return now */
if (git_mutex_lock(&p->lock) < 0)
@@ -1099,7 +1096,7 @@
path_len = strlen(path);
if (path_len < strlen(".idx"))
- return git_odb__error_notfound("invalid packfile path", NULL);
+ return git_odb__error_notfound("invalid packfile path", NULL, 0);
if (git_buf_printf(&buf, "%.*s.pack", (int)(path_len - strlen(".idx")), path) < 0)
return -1;
@@ -1117,7 +1114,7 @@
*pack_out = NULL;
if (path_len < strlen(".idx"))
- return git_odb__error_notfound("invalid packfile path", NULL);
+ return git_odb__error_notfound("invalid packfile path", NULL, 0);
GITERR_CHECK_ALLOC_ADD(&alloc_len, sizeof(*p), path_len);
GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 2);
@@ -1143,7 +1140,7 @@
if (p_stat(p->pack_name, &st) < 0 || !S_ISREG(st.st_mode)) {
git__free(p);
- return git_odb__error_notfound("packfile not found", NULL);
+ return git_odb__error_notfound("packfile not found", NULL, 0);
}
/* ok, it looks sane as far as we can check without
@@ -1344,7 +1341,7 @@
}
if (!found)
- return git_odb__error_notfound("failed to find offset for pack entry", short_oid);
+ return git_odb__error_notfound("failed to find offset for pack entry", short_oid, len);
if (found > 1)
return git_odb__error_ambiguous("found multiple offsets for pack entry");
diff --git a/src/posix.c b/src/posix.c
index c7201ba..b3f1a1c 100644
--- a/src/posix.c
+++ b/src/posix.c
@@ -224,6 +224,13 @@
return 0;
}
+int git__mmap_alignment(size_t *alignment)
+{
+ /* dummy; here we don't need any alignment anyway */
+ *alignment = 4096;
+ return 0;
+}
+
int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
{
diff --git a/src/posix.h b/src/posix.h
index 8785a4c..f204751 100644
--- a/src/posix.h
+++ b/src/posix.h
@@ -109,6 +109,7 @@
extern int p_rename(const char *from, const char *to);
extern int git__page_size(size_t *page_size);
+extern int git__mmap_alignment(size_t *page_size);
/**
* Platform-dependent methods
diff --git a/src/push.c b/src/push.c
index 3c9fa2f..0747259 100644
--- a/src/push.c
+++ b/src/push.c
@@ -374,9 +374,9 @@
case GIT_OBJ_COMMIT:
return 0;
case GIT_OBJ_TREE:
- return git_packbuilder_insert_tree(pb, &entry->oid);
+ return git_packbuilder_insert_tree(pb, entry->oid);
default:
- return git_packbuilder_insert(pb, &entry->oid, entry->filename);
+ return git_packbuilder_insert(pb, entry->oid, entry->filename);
}
}
@@ -396,7 +396,7 @@
const git_tree_entry *d_entry = git_tree_entry_byindex(delta, j);
int cmp = 0;
- if (!git_oid__cmp(&b_entry->oid, &d_entry->oid))
+ if (!git_oid__cmp(b_entry->oid, d_entry->oid))
goto loop;
cmp = strcmp(b_entry->filename, d_entry->filename);
@@ -407,15 +407,15 @@
git_tree_entry__is_tree(b_entry) &&
git_tree_entry__is_tree(d_entry)) {
/* Add the right-hand entry */
- if ((error = git_packbuilder_insert(pb, &d_entry->oid,
+ if ((error = git_packbuilder_insert(pb, d_entry->oid,
d_entry->filename)) < 0)
goto on_error;
/* Acquire the subtrees and recurse */
if ((error = git_tree_lookup(&b_child,
- git_tree_owner(base), &b_entry->oid)) < 0 ||
+ git_tree_owner(base), b_entry->oid)) < 0 ||
(error = git_tree_lookup(&d_child,
- git_tree_owner(delta), &d_entry->oid)) < 0 ||
+ git_tree_owner(delta), d_entry->oid)) < 0 ||
(error = queue_differences(b_child, d_child, pb)) < 0)
goto on_error;
diff --git a/src/refdb_fs.c b/src/refdb_fs.c
index f6ed720..f978038 100644
--- a/src/refdb_fs.c
+++ b/src/refdb_fs.c
@@ -962,6 +962,7 @@
for (i = 0; i < git_sortedcache_entrycount(refcache); ++i) {
struct packref *ref = git_sortedcache_entry(refcache, i);
+ assert(ref);
if (packed_find_peel(backend, ref) < 0)
goto fail;
diff --git a/src/refs.c b/src/refs.c
index a15e31b..26c8002 100644
--- a/src/refs.c
+++ b/src/refs.c
@@ -289,6 +289,9 @@
"Could not use '%s' as valid reference name", git_buf_cstr(&name));
}
+ if (error == GIT_ENOTFOUND)
+ giterr_set(GITERR_REFERENCE, "no reference found for shorthand '%s'", refname);
+
git_buf_free(&name);
git_buf_free(&refnamebuf);
return error;
diff --git a/src/settings.c b/src/settings.c
index 88602ba..0da19ea 100644
--- a/src/settings.c
+++ b/src/settings.c
@@ -71,12 +71,18 @@
}
extern char *git__user_agent;
+extern char *git__ssl_ciphers;
const char *git_libgit2__user_agent()
{
return git__user_agent;
}
+const char *git_libgit2__ssl_ciphers()
+{
+ return git__ssl_ciphers;
+}
+
int git_libgit2_opts(int key, ...)
{
int error = 0;
@@ -169,7 +175,7 @@
}
}
#else
- giterr_set(GITERR_NET, "Cannot set certificate locations: OpenSSL is not enabled");
+ giterr_set(GITERR_NET, "cannot set certificate locations: OpenSSL is not enabled");
error = -1;
#endif
break;
@@ -187,6 +193,22 @@
git_object__strict_input_validation = (va_arg(ap, int) != 0);
break;
+ case GIT_OPT_SET_SSL_CIPHERS:
+#ifdef GIT_OPENSSL
+ {
+ git__free(git__ssl_ciphers);
+ git__ssl_ciphers = git__strdup(va_arg(ap, const char *));
+ if (!git__ssl_ciphers) {
+ giterr_set_oom();
+ error = -1;
+ }
+ }
+#else
+ giterr_set(GITERR_NET, "cannot set custom ciphers: OpenSSL is not enabled");
+ error = -1;
+#endif
+ break;
+
default:
giterr_set(GITERR_INVALID, "invalid option key");
error = -1;
diff --git a/src/submodule.c b/src/submodule.c
index 38db415..c903cf9 100644
--- a/src/submodule.c
+++ b/src/submodule.c
@@ -80,7 +80,8 @@
if (blen > 0 && b[blen - 1] == '/')
blen--;
- return (alen == blen && strncmp(a, b, alen) == 0);
+ return (alen == 0 && blen == 0) ||
+ (alen == blen && strncmp(a, b, alen) == 0);
}
__KHASH_IMPL(
@@ -1416,7 +1417,7 @@
git_tree_entry_bypath(&te, head, submodule->path) < 0)
giterr_clear();
else
- submodule_update_from_head_data(submodule, te->attr, &te->oid);
+ submodule_update_from_head_data(submodule, te->attr, git_tree_entry_id(te));
git_tree_entry_free(te);
git_tree_free(head);
diff --git a/src/transport.c b/src/transport.c
index 5c65c7c..327052f 100644
--- a/src/transport.c
+++ b/src/transport.c
@@ -35,6 +35,8 @@
{ "file://", git_transport_local, NULL },
#ifdef GIT_SSH
{ "ssh://", git_transport_smart, &ssh_subtransport_definition },
+ { "ssh+git://", git_transport_smart, &ssh_subtransport_definition },
+ { "git+ssh://", git_transport_smart, &ssh_subtransport_definition },
#endif
{ NULL, 0, 0 }
};
diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c
index 6363378..02e1ecf 100644
--- a/src/transports/smart_protocol.c
+++ b/src/transports/smart_protocol.c
@@ -721,18 +721,39 @@
return 0;
}
-static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt)
+static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt, git_buf *data_pkt_buf)
{
git_pkt *pkt;
- const char *line = data_pkt->data, *line_end;
- size_t line_len = data_pkt->len;
+ const char *line, *line_end;
+ size_t line_len;
int error;
+ int reading_from_buf = data_pkt_buf->size > 0;
+
+ if (reading_from_buf) {
+ /* We had an existing partial packet, so add the new
+ * packet to the buffer and parse the whole thing */
+ git_buf_put(data_pkt_buf, data_pkt->data, data_pkt->len);
+ line = data_pkt_buf->ptr;
+ line_len = data_pkt_buf->size;
+ }
+ else {
+ line = data_pkt->data;
+ line_len = data_pkt->len;
+ }
while (line_len > 0) {
error = git_pkt_parse_line(&pkt, line, &line_end, line_len);
- if (error < 0)
- return error;
+ if (error == GIT_EBUFS) {
+ /* Buffer the data when the inner packet is split
+ * across multiple sideband packets */
+ if (!reading_from_buf)
+ git_buf_put(data_pkt_buf, line, line_len);
+ error = 0;
+ goto done;
+ }
+ else if (error < 0)
+ goto done;
/* Advance in the buffer */
line_len -= (line_end - line);
@@ -743,10 +764,15 @@
git_pkt_free(pkt);
if (error < 0 && error != GIT_ITEROVER)
- return error;
+ goto done;
}
- return 0;
+ error = 0;
+
+done:
+ if (reading_from_buf)
+ git_buf_consume(data_pkt_buf, line_end);
+ return error;
}
static int parse_report(transport_smart *transport, git_push *push)
@@ -755,6 +781,7 @@
const char *line_end = NULL;
gitno_buffer *buf = &transport->buffer;
int error, recvd;
+ git_buf data_pkt_buf = GIT_BUF_INIT;
for (;;) {
if (buf->offset > 0)
@@ -763,16 +790,21 @@
else
error = GIT_EBUFS;
- if (error < 0 && error != GIT_EBUFS)
- return -1;
+ if (error < 0 && error != GIT_EBUFS) {
+ error = -1;
+ goto done;
+ }
if (error == GIT_EBUFS) {
- if ((recvd = gitno_recv(buf)) < 0)
- return recvd;
+ if ((recvd = gitno_recv(buf)) < 0) {
+ error = recvd;
+ goto done;
+ }
if (recvd == 0) {
giterr_set(GITERR_NET, "early EOF");
- return GIT_EEOF;
+ error = GIT_EEOF;
+ goto done;
}
continue;
}
@@ -784,7 +816,7 @@
switch (pkt->type) {
case GIT_PKT_DATA:
/* This is a sideband packet which contains other packets */
- error = add_push_report_sideband_pkt(push, (git_pkt_data *)pkt);
+ error = add_push_report_sideband_pkt(push, (git_pkt_data *)pkt, &data_pkt_buf);
break;
case GIT_PKT_ERR:
giterr_set(GITERR_NET, "report-status: Error reported: %s",
@@ -805,12 +837,24 @@
git_pkt_free(pkt);
/* add_push_report_pkt returns GIT_ITEROVER when it receives a flush */
- if (error == GIT_ITEROVER)
- return 0;
+ if (error == GIT_ITEROVER) {
+ error = 0;
+ if (data_pkt_buf.size > 0) {
+ /* If there was data remaining in the pack data buffer,
+ * then the server sent a partial pkt-line */
+ giterr_set(GITERR_NET, "Incomplete pack data pkt-line");
+ error = GIT_ERROR;
+ }
+ goto done;
+ }
- if (error < 0)
- return error;
+ if (error < 0) {
+ goto done;
+ }
}
+done:
+ git_buf_free(&data_pkt_buf);
+ return error;
}
static int add_ref_from_push_spec(git_vector *refs, push_spec *push_spec)
diff --git a/src/transports/ssh.c b/src/transports/ssh.c
index 35739ab..cfd5736 100644
--- a/src/transports/ssh.c
+++ b/src/transports/ssh.c
@@ -21,7 +21,8 @@
#define OWNING_SUBTRANSPORT(s) ((ssh_subtransport *)(s)->parent.subtransport)
-static const char prefix_ssh[] = "ssh://";
+static const char *ssh_prefixes[] = { "ssh://", "ssh+git://", "git+ssh://" };
+
static const char cmd_uploadpack[] = "git-upload-pack";
static const char cmd_receivepack[] = "git-receive-pack";
@@ -63,17 +64,24 @@
{
char *repo;
int len;
+ size_t i;
- if (!git__prefixcmp(url, prefix_ssh)) {
- url = url + strlen(prefix_ssh);
- repo = strchr(url, '/');
- if (repo && repo[1] == '~')
- ++repo;
- } else {
- repo = strchr(url, ':');
- if (repo) repo++;
+ for (i = 0; i < ARRAY_SIZE(ssh_prefixes); ++i) {
+ const char *p = ssh_prefixes[i];
+
+ if (!git__prefixcmp(url, p)) {
+ url = url + strlen(p);
+ repo = strchr(url, '/');
+ if (repo && repo[1] == '~')
+ ++repo;
+
+ goto done;
+ }
}
+ repo = strchr(url, ':');
+ if (repo) repo++;
+done:
if (!repo) {
giterr_set(GITERR_NET, "Malformed git protocol URL");
return -1;
@@ -500,6 +508,7 @@
char *host=NULL, *port=NULL, *path=NULL, *user=NULL, *pass=NULL;
const char *default_port="22";
int auth_methods, error = 0;
+ size_t i;
ssh_stream *s;
git_cred *cred = NULL;
LIBSSH2_SESSION* session=NULL;
@@ -515,16 +524,22 @@
s->session = NULL;
s->channel = NULL;
- if (!git__prefixcmp(url, prefix_ssh)) {
- if ((error = gitno_extract_url_parts(&host, &port, &path, &user, &pass, url, default_port)) < 0)
- goto done;
- } else {
- if ((error = git_ssh_extract_url_parts(&host, &user, url)) < 0)
- goto done;
- port = git__strdup(default_port);
- GITERR_CHECK_ALLOC(port);
- }
+ for (i = 0; i < ARRAY_SIZE(ssh_prefixes); ++i) {
+ const char *p = ssh_prefixes[i];
+ if (!git__prefixcmp(url, p)) {
+ if ((error = gitno_extract_url_parts(&host, &port, &path, &user, &pass, url, default_port)) < 0)
+ goto done;
+
+ goto post_extract;
+ }
+ }
+ if ((error = git_ssh_extract_url_parts(&host, &user, url)) < 0)
+ goto done;
+ port = git__strdup(default_port);
+ GITERR_CHECK_ALLOC(port);
+
+post_extract:
if ((error = git_socket_stream_new(&s->io, host, port)) < 0 ||
(error = git_stream_connect(s->io)) < 0)
goto done;
diff --git a/src/tree.c b/src/tree.c
index 48b9f12..6ce460c 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -85,9 +85,10 @@
}
/**
- * Allocate either from the pool or from the system allocator
+ * Allocate a new self-contained entry, with enough space after it to
+ * store the filename and the id.
*/
-static git_tree_entry *alloc_entry_base(git_pool *pool, const char *filename, size_t filename_len)
+static git_tree_entry *alloc_entry(const char *filename, size_t filename_len, const git_oid *id)
{
git_tree_entry *entry = NULL;
size_t tree_len;
@@ -95,44 +96,32 @@
TREE_ENTRY_CHECK_NAMELEN(filename_len);
if (GIT_ADD_SIZET_OVERFLOW(&tree_len, sizeof(git_tree_entry), filename_len) ||
- GIT_ADD_SIZET_OVERFLOW(&tree_len, tree_len, 1))
+ GIT_ADD_SIZET_OVERFLOW(&tree_len, tree_len, 1) ||
+ GIT_ADD_SIZET_OVERFLOW(&tree_len, tree_len, GIT_OID_RAWSZ))
return NULL;
- entry = pool ? git_pool_malloc(pool, tree_len) :
- git__malloc(tree_len);
+ entry = git__calloc(1, tree_len);
if (!entry)
return NULL;
- memset(entry, 0x0, sizeof(git_tree_entry));
- memcpy(entry->filename, filename, filename_len);
- entry->filename[filename_len] = 0;
+ {
+ char *filename_ptr;
+ void *id_ptr;
+
+ filename_ptr = ((char *) entry) + sizeof(git_tree_entry);
+ memcpy(filename_ptr, filename, filename_len);
+ entry->filename = filename_ptr;
+
+ id_ptr = filename_ptr + filename_len + 1;
+ git_oid_cpy(id_ptr, id);
+ entry->oid = id_ptr;
+ }
+
entry->filename_len = (uint16_t)filename_len;
return entry;
}
-/**
- * Allocate a tree entry, using the poolin the tree which owns
- * it. This is useful when reading trees, so we don't allocate a ton
- * of small strings but can use the pool.
- */
-static git_tree_entry *alloc_entry_pooled(git_pool *pool, const char *filename, size_t filename_len)
-{
- git_tree_entry *entry = NULL;
-
- if (!(entry = alloc_entry_base(pool, filename, filename_len)))
- return NULL;
-
- entry->pooled = true;
-
- return entry;
-}
-
-static git_tree_entry *alloc_entry(const char *filename)
-{
- return alloc_entry_base(NULL, filename, strlen(filename));
-}
-
struct tree_key_search {
const char *filename;
uint16_t filename_len;
@@ -174,7 +163,10 @@
* around the area for our target file.
*/
static int tree_key_search(
- size_t *at_pos, git_vector *entries, const char *filename, size_t filename_len)
+ size_t *at_pos,
+ const git_tree *tree,
+ const char *filename,
+ size_t filename_len)
{
struct tree_key_search ksearch;
const git_tree_entry *entry;
@@ -187,13 +179,15 @@
/* Initial homing search; find an entry on the tree with
* the same prefix as the filename we're looking for */
- if (git_vector_bsearch2(&homing, entries, &homing_search_cmp, &ksearch) < 0)
+
+ if (git_array_search(&homing,
+ tree->entries, &homing_search_cmp, &ksearch) < 0)
return GIT_ENOTFOUND; /* just a signal error; not passed back to user */
/* We found a common prefix. Look forward as long as
* there are entries that share the common prefix */
- for (i = homing; i < entries->length; ++i) {
- entry = entries->contents[i];
+ for (i = homing; i < tree->entries.size; ++i) {
+ entry = git_array_get(tree->entries, i);
if (homing_search_cmp(&ksearch, entry) < 0)
break;
@@ -213,7 +207,7 @@
i = homing - 1;
do {
- entry = entries->contents[i];
+ entry = git_array_get(tree->entries, i);
if (homing_search_cmp(&ksearch, entry) > 0)
break;
@@ -234,7 +228,7 @@
void git_tree_entry_free(git_tree_entry *entry)
{
- if (entry == NULL || entry->pooled)
+ if (entry == NULL)
return;
git__free(entry);
@@ -242,36 +236,26 @@
int git_tree_entry_dup(git_tree_entry **dest, const git_tree_entry *source)
{
- size_t total_size;
- git_tree_entry *copy;
+ git_tree_entry *cpy;
assert(source);
- GITERR_CHECK_ALLOC_ADD(&total_size, sizeof(git_tree_entry), source->filename_len);
- GITERR_CHECK_ALLOC_ADD(&total_size, total_size, 1);
+ cpy = alloc_entry(source->filename, source->filename_len, source->oid);
+ if (cpy == NULL)
+ return -1;
- copy = git__malloc(total_size);
- GITERR_CHECK_ALLOC(copy);
+ cpy->attr = source->attr;
- memcpy(copy, source, total_size);
-
- copy->pooled = 0;
-
- *dest = copy;
+ *dest = cpy;
return 0;
}
void git_tree__free(void *_tree)
{
git_tree *tree = _tree;
- size_t i;
- git_tree_entry *e;
- git_vector_foreach(&tree->entries, i, e)
- git_tree_entry_free(e);
-
- git_vector_free(&tree->entries);
- git_pool_clear(&tree->pool);
+ git_odb_object_free(tree->odb_obj);
+ git_array_clear(tree->entries);
git__free(tree);
}
@@ -294,7 +278,7 @@
const git_oid *git_tree_entry_id(const git_tree_entry *entry)
{
assert(entry);
- return &entry->oid;
+ return entry->oid;
}
git_otype git_tree_entry_type(const git_tree_entry *entry)
@@ -315,7 +299,7 @@
const git_tree_entry *entry)
{
assert(entry && object_out);
- return git_object_lookup(object_out, repo, &entry->oid, GIT_OBJ_ANY);
+ return git_object_lookup(object_out, repo, entry->oid, GIT_OBJ_ANY);
}
static const git_tree_entry *entry_fromname(
@@ -323,13 +307,10 @@
{
size_t idx;
- /* be safe when we cast away constness - i.e. don't trigger a sort */
- assert(git_vector_is_sorted(&tree->entries));
-
- if (tree_key_search(&idx, (git_vector *)&tree->entries, name, name_len) < 0)
+ if (tree_key_search(&idx, tree, name, name_len) < 0)
return NULL;
- return git_vector_get(&tree->entries, idx);
+ return git_array_get(tree->entries, idx);
}
const git_tree_entry *git_tree_entry_byname(
@@ -344,7 +325,7 @@
const git_tree *tree, size_t idx)
{
assert(tree);
- return git_vector_get(&tree->entries, idx);
+ return git_array_get(tree->entries, idx);
}
const git_tree_entry *git_tree_entry_byid(
@@ -355,8 +336,8 @@
assert(tree);
- git_vector_foreach(&tree->entries, i, e) {
- if (memcmp(&e->oid.id, &id->id, sizeof(id->id)) == 0)
+ git_array_foreach(tree->entries, i, e) {
+ if (memcmp(&e->oid->id, &id->id, sizeof(id->id)) == 0)
return e;
}
@@ -365,7 +346,6 @@
int git_tree__prefix_position(const git_tree *tree, const char *path)
{
- const git_vector *entries = &tree->entries;
struct tree_key_search ksearch;
size_t at_pos, path_len;
@@ -378,21 +358,20 @@
ksearch.filename = path;
ksearch.filename_len = (uint16_t)path_len;
- /* be safe when we cast away constness - i.e. don't trigger a sort */
- assert(git_vector_is_sorted(&tree->entries));
-
/* Find tree entry with appropriate prefix */
- git_vector_bsearch2(
- &at_pos, (git_vector *)entries, &homing_search_cmp, &ksearch);
+ git_array_search(
+ &at_pos, tree->entries, &homing_search_cmp, &ksearch);
- for (; at_pos < entries->length; ++at_pos) {
- const git_tree_entry *entry = entries->contents[at_pos];
+ for (; at_pos < tree->entries.size; ++at_pos) {
+ const git_tree_entry *entry = git_array_get(tree->entries, at_pos);
if (homing_search_cmp(&ksearch, entry) < 0)
break;
}
for (; at_pos > 0; --at_pos) {
- const git_tree_entry *entry = entries->contents[at_pos - 1];
+ const git_tree_entry *entry =
+ git_array_get(tree->entries, at_pos - 1);
+
if (homing_search_cmp(&ksearch, entry) > 0)
break;
}
@@ -403,7 +382,7 @@
size_t git_tree_entrycount(const git_tree *tree)
{
assert(tree);
- return tree->entries.length;
+ return tree->entries.size;
}
unsigned int git_treebuilder_entrycount(git_treebuilder *bld)
@@ -444,13 +423,18 @@
int git_tree__parse(void *_tree, git_odb_object *odb_obj)
{
git_tree *tree = _tree;
- const char *buffer = git_odb_object_data(odb_obj);
- const char *buffer_end = buffer + git_odb_object_size(odb_obj);
+ const char *buffer;
+ const char *buffer_end;
- git_pool_init(&tree->pool, 1);
- if (git_vector_init(&tree->entries, DEFAULT_TREE_SIZE, entry_sort_cmp) < 0)
+ if (git_odb_object_dup(&tree->odb_obj, odb_obj) < 0)
return -1;
+ buffer = git_odb_object_data(tree->odb_obj);
+ buffer_end = buffer + git_odb_object_size(tree->odb_obj);
+
+ git_array_init_to_size(tree->entries, DEFAULT_TREE_SIZE);
+ GITERR_CHECK_ARRAY(tree->entries);
+
while (buffer < buffer_end) {
git_tree_entry *entry;
size_t filename_len;
@@ -464,27 +448,21 @@
return tree_error("Failed to parse tree. Object is corrupted", NULL);
filename_len = nul - buffer;
- /** Allocate the entry and store it in the entries vector */
+ /* Allocate the entry */
{
- entry = alloc_entry_pooled(&tree->pool, buffer, filename_len);
+ entry = git_array_alloc(tree->entries);
GITERR_CHECK_ALLOC(entry);
- if (git_vector_insert(&tree->entries, entry) < 0)
- return -1;
-
entry->attr = attr;
+ entry->filename_len = filename_len;
+ entry->filename = buffer;
+ entry->oid = (git_oid *) ((char *) buffer + filename_len + 1);
}
- /* Advance to the ID just after the path */
buffer += filename_len + 1;
-
- git_oid_fromraw(&entry->oid, (const unsigned char *)buffer);
buffer += GIT_OID_RAWSZ;
}
- /* The tree is sorted by definition. Bad inputs give bad outputs */
- tree->entries.flags |= GIT_VECTOR_SORTED;
-
return 0;
}
@@ -517,10 +495,9 @@
if (!valid_entry_name(bld->repo, filename))
return tree_error("Failed to insert entry. Invalid name for a tree entry", filename);
- entry = alloc_entry(filename);
+ entry = alloc_entry(filename, strlen(filename), id);
GITERR_CHECK_ALLOC(entry);
- git_oid_cpy(&entry->oid, id);
entry->attr = (uint16_t)filemode;
git_strmap_insert(bld->map, entry->filename, entry, error);
@@ -709,10 +686,10 @@
if (source != NULL) {
git_tree_entry *entry_src;
- git_vector_foreach(&source->entries, i, entry_src) {
+ git_array_foreach(source->entries, i, entry_src) {
if (append_entry(
bld, entry_src->filename,
- &entry_src->oid,
+ entry_src->oid,
entry_src->attr) < 0)
goto on_error;
}
@@ -764,8 +741,9 @@
pos = git_strmap_lookup_index(bld->map, filename);
if (git_strmap_valid_index(bld->map, pos)) {
entry = git_strmap_value_at(bld->map, pos);
+ git_oid_cpy((git_oid *) entry->oid, id);
} else {
- entry = alloc_entry(filename);
+ entry = alloc_entry(filename, strlen(filename), id);
GITERR_CHECK_ALLOC(entry);
git_strmap_insert(bld->map, entry->filename, entry, error);
@@ -777,7 +755,6 @@
}
}
- git_oid_cpy(&entry->oid, id);
entry->attr = filemode;
if (entry_out)
@@ -848,19 +825,20 @@
git_buf_printf(&tree, "%o ", entry->attr);
git_buf_put(&tree, entry->filename, entry->filename_len + 1);
- git_buf_put(&tree, (char *)entry->oid.id, GIT_OID_RAWSZ);
+ git_buf_put(&tree, (char *)entry->oid->id, GIT_OID_RAWSZ);
if (git_buf_oom(&tree))
error = -1;
}
- git_vector_free(&entries);
if (!error &&
!(error = git_repository_odb__weakptr(&odb, bld->repo)))
error = git_odb_write(oid, odb, tree.ptr, tree.size, GIT_OBJ_TREE);
git_buf_free(&tree);
+ git_vector_free(&entries);
+
return error;
}
@@ -960,7 +938,7 @@
return git_tree_entry_dup(entry_out, entry);
}
- if (git_tree_lookup(&subtree, root->object.repo, &entry->oid) < 0)
+ if (git_tree_lookup(&subtree, root->object.repo, entry->oid) < 0)
return -1;
error = git_tree_entry_bypath(
@@ -984,7 +962,7 @@
size_t i;
const git_tree_entry *entry;
- git_vector_foreach(&tree->entries, i, entry) {
+ git_array_foreach(tree->entries, i, entry) {
if (preorder) {
error = callback(path->ptr, entry, payload);
if (error < 0) { /* negative value stops iteration */
@@ -1001,7 +979,7 @@
git_tree *subtree;
size_t path_len = git_buf_len(path);
- error = git_tree_lookup(&subtree, tree->object.repo, &entry->oid);
+ error = git_tree_lookup(&subtree, tree->object.repo, entry->oid);
if (error < 0)
break;
diff --git a/src/tree.h b/src/tree.h
index 914d788..5e7a66e 100644
--- a/src/tree.h
+++ b/src/tree.h
@@ -17,15 +17,14 @@
struct git_tree_entry {
uint16_t attr;
uint16_t filename_len;
- git_oid oid;
- bool pooled;
- char filename[GIT_FLEX_ARRAY];
+ const git_oid *oid;
+ const char *filename;
};
struct git_tree {
git_object object;
- git_vector entries;
- git_pool pool;
+ git_odb_object *odb_obj;
+ git_array_t(git_tree_entry) entries;
};
struct git_treebuilder {
diff --git a/src/unix/map.c b/src/unix/map.c
index 72abb34..c55ad1a 100644
--- a/src/unix/map.c
+++ b/src/unix/map.c
@@ -24,6 +24,11 @@
return 0;
}
+int git__mmap_alignment(size_t *alignment)
+{
+ return git__page_size(alignment);
+}
+
int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
{
int mprot = PROT_READ;
diff --git a/src/win32/map.c b/src/win32/map.c
index a99c30f..03a3646 100644
--- a/src/win32/map.c
+++ b/src/win32/map.c
@@ -17,22 +17,41 @@
if (!page_size) {
GetSystemInfo(&sys);
- page_size = sys.dwAllocationGranularity;
+ page_size = sys.dwPageSize;
}
return page_size;
}
+static DWORD get_allocation_granularity(void)
+{
+ static DWORD granularity;
+ SYSTEM_INFO sys;
+
+ if (!granularity) {
+ GetSystemInfo(&sys);
+ granularity = sys.dwAllocationGranularity;
+ }
+
+ return granularity;
+}
+
int git__page_size(size_t *page_size)
{
*page_size = get_page_size();
return 0;
}
+int git__mmap_alignment(size_t *page_size)
+{
+ *page_size = get_allocation_granularity();
+ return 0;
+}
+
int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
{
HANDLE fh = (HANDLE)_get_osfhandle(fd);
- DWORD page_size = get_page_size();
+ DWORD alignment = get_allocation_granularity();
DWORD fmap_prot = 0;
DWORD view_prot = 0;
DWORD off_low = 0;
@@ -62,12 +81,12 @@
if (prot & GIT_PROT_READ)
view_prot |= FILE_MAP_READ;
- page_start = (offset / page_size) * page_size;
+ page_start = (offset / alignment) * alignment;
page_offset = offset - page_start;
- if (page_offset != 0) { /* offset must be multiple of page size */
+ if (page_offset != 0) { /* offset must be multiple of the allocation granularity */
errno = EINVAL;
- giterr_set(GITERR_OS, "Failed to mmap. Offset must be multiple of page size");
+ giterr_set(GITERR_OS, "Failed to mmap. Offset must be multiple of allocation granularity");
return -1;
}
diff --git a/src/xdiff/xprepare.c b/src/xdiff/xprepare.c
index 63a22c6..13b55ab 100644
--- a/src/xdiff/xprepare.c
+++ b/src/xdiff/xprepare.c
@@ -301,10 +301,11 @@
xdl_free_ctx(&xe->xdf2);
xdl_free_ctx(&xe->xdf1);
+ xdl_free_classifier(&cf);
return -1;
}
- if (!(xpp->flags & XDF_HISTOGRAM_DIFF))
+ if (XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF)
xdl_free_classifier(&cf);
return 0;
diff --git a/tests/attr/ignore.c b/tests/attr/ignore.c
index 27fed25..91bf984 100644
--- a/tests/attr/ignore.c
+++ b/tests/attr/ignore.c
@@ -252,3 +252,16 @@
if (cl_repo_get_bool(g_repo, "core.ignorecase"))
assert_is_ignored(false, "dir/TeSt");
}
+
+void test_attr_ignore__symlink_to_outside(void)
+{
+#ifdef GIT_WIN32
+ cl_skip();
+#endif
+
+ cl_git_rewritefile("attr/.gitignore", "symlink\n");
+ cl_git_mkfile("target", "target");
+ cl_git_pass(p_symlink("../target", "attr/symlink"));
+ assert_is_ignored(true, "symlink");
+ assert_is_ignored(true, "lala/../symlink");
+}
diff --git a/tests/commit/parse.c b/tests/commit/parse.c
index 838cfb4..297fccc 100644
--- a/tests/commit/parse.c
+++ b/tests/commit/parse.c
@@ -498,6 +498,21 @@
\n\
a simple commit which works\n";
+ const char *oneline_signature = "tree 51832e6397b30309c8bcad9c55fa6ae67778f378\n\
+parent a1b6decaaac768b5e01e1b5dbf5b2cc081bed1eb\n\
+author Some User <someuser@gmail.com> 1454537944 -0700\n\
+committer Some User <someuser@gmail.com> 1454537944 -0700\n\
+gpgsig bad\n\
+\n\
+corrupt signature\n";
+
+ const char *oneline_data = "tree 51832e6397b30309c8bcad9c55fa6ae67778f378\n\
+parent a1b6decaaac768b5e01e1b5dbf5b2cc081bed1eb\n\
+author Some User <someuser@gmail.com> 1454537944 -0700\n\
+committer Some User <someuser@gmail.com> 1454537944 -0700\n\
+\n\
+corrupt signature\n";
+
cl_git_pass(git_repository_odb__weakptr(&odb, g_repo));
cl_git_pass(git_odb_write(&commit_id, odb, passing_commit_cases[4], strlen(passing_commit_cases[4]), GIT_OBJ_COMMIT));
@@ -523,6 +538,15 @@
cl_git_fail_with(GIT_ENOTFOUND, git_commit_extract_signature(&signature, &signed_data, g_repo, &commit_id, NULL));
cl_assert_equal_i(GITERR_OBJECT, giterr_last()->klass);
+ /* Parse the commit with a single-line signature */
+ git_buf_clear(&signature);
+ git_buf_clear(&signed_data);
+ cl_git_pass(git_odb_write(&commit_id, odb, oneline_signature, strlen(oneline_signature), GIT_OBJ_COMMIT));
+ cl_git_pass(git_commit_extract_signature(&signature, &signed_data, g_repo, &commit_id, NULL));
+ cl_assert_equal_s("bad", signature.ptr);
+ cl_assert_equal_s(oneline_data, signed_data.ptr);
+
+
git_buf_free(&signature);
git_buf_free(&signed_data);
diff --git a/tests/config/multivar.c b/tests/config/multivar.c
index 0150089..d1b8c4c 100644
--- a/tests/config/multivar.c
+++ b/tests/config/multivar.c
@@ -163,7 +163,7 @@
cl_git_pass(git_config_open_ondisk(&cfg, "config/config11"));
- cl_git_pass(git_config_set_multivar(cfg, var, "", "variable"));
+ cl_git_pass(git_config_set_multivar(cfg, var, "$^", "variable"));
n = 0;
cl_git_pass(git_config_get_multivar_foreach(cfg, var, NULL, cb, &n));
cl_assert_equal_i(n, 1);
diff --git a/tests/config/write.c b/tests/config/write.c
index e634aa3..56ef2e9 100644
--- a/tests/config/write.c
+++ b/tests/config/write.c
@@ -695,3 +695,30 @@
git_config_free(cfg);
}
+
+void test_config_write__repeated(void)
+{
+ const char *filename = "config-repeated";
+ git_config *cfg;
+ git_buf result = GIT_BUF_INIT;
+ const char *expected = "[sample \"prefix\"]\n\
+\tsetting1 = someValue1\n\
+\tsetting2 = someValue2\n\
+\tsetting3 = someValue3\n\
+\tsetting4 = someValue4\n\
+";
+ cl_git_pass(git_config_open_ondisk(&cfg, filename));
+ cl_git_pass(git_config_set_string(cfg, "sample.prefix.setting1", "someValue1"));
+ cl_git_pass(git_config_set_string(cfg, "sample.prefix.setting2", "someValue2"));
+ cl_git_pass(git_config_set_string(cfg, "sample.prefix.setting3", "someValue3"));
+ cl_git_pass(git_config_set_string(cfg, "sample.prefix.setting4", "someValue4"));
+ git_config_free(cfg);
+
+ cl_git_pass(git_config_open_ondisk(&cfg, filename));
+
+ cl_git_pass(git_futils_readbuffer(&result, filename));
+ cl_assert_equal_s(expected, result.ptr);
+ git_buf_free(&result);
+
+ git_config_free(cfg);
+}
diff --git a/tests/core/array.c b/tests/core/array.c
new file mode 100644
index 0000000..8e626a5
--- /dev/null
+++ b/tests/core/array.c
@@ -0,0 +1,57 @@
+#include "clar_libgit2.h"
+#include "array.h"
+
+static int int_lookup(const void *k, const void *a)
+{
+ const int *one = (const int *)k;
+ int *two = (int *)a;
+
+ return *one - *two;
+}
+
+#define expect_pos(k, n, ret) \
+ key = (k); \
+ cl_assert_equal_i((ret), \
+ git_array_search(&p, integers, int_lookup, &key)); \
+ cl_assert_equal_i((n), p);
+
+void test_core_array__bsearch2(void)
+{
+ git_array_t(int) integers = GIT_ARRAY_INIT;
+ int *i, key;
+ size_t p;
+
+ i = git_array_alloc(integers); *i = 2;
+ i = git_array_alloc(integers); *i = 3;
+ i = git_array_alloc(integers); *i = 5;
+ i = git_array_alloc(integers); *i = 7;
+ i = git_array_alloc(integers); *i = 7;
+ i = git_array_alloc(integers); *i = 8;
+ i = git_array_alloc(integers); *i = 13;
+ i = git_array_alloc(integers); *i = 21;
+ i = git_array_alloc(integers); *i = 25;
+ i = git_array_alloc(integers); *i = 42;
+ i = git_array_alloc(integers); *i = 69;
+ i = git_array_alloc(integers); *i = 121;
+ i = git_array_alloc(integers); *i = 256;
+ i = git_array_alloc(integers); *i = 512;
+ i = git_array_alloc(integers); *i = 513;
+ i = git_array_alloc(integers); *i = 514;
+ i = git_array_alloc(integers); *i = 516;
+ i = git_array_alloc(integers); *i = 516;
+ i = git_array_alloc(integers); *i = 517;
+
+ /* value to search for, expected position, return code */
+ expect_pos(3, 1, GIT_OK);
+ expect_pos(2, 0, GIT_OK);
+ expect_pos(1, 0, GIT_ENOTFOUND);
+ expect_pos(25, 8, GIT_OK);
+ expect_pos(26, 9, GIT_ENOTFOUND);
+ expect_pos(42, 9, GIT_OK);
+ expect_pos(50, 10, GIT_ENOTFOUND);
+ expect_pos(68, 10, GIT_ENOTFOUND);
+ expect_pos(256, 12, GIT_OK);
+
+ git_array_clear(integers);
+}
+
diff --git a/tests/core/stream.c b/tests/core/stream.c
index ace6a05..0cbf442 100644
--- a/tests/core/stream.c
+++ b/tests/core/stream.c
@@ -33,8 +33,12 @@
cl_git_pass(git_stream_register_tls(NULL));
error = git_tls_stream_new(&stream, "localhost", "443");
- /* We don't have arbitrary TLS stream support on Windows */
-#if GIT_WIN32
+ /* We don't have arbitrary TLS stream support on Windows
+ * or when openssl support is disabled (except on OSX
+ * with Security framework).
+ */
+#if defined(GIT_WIN32) || \
+ (!defined(GIT_SECURE_TRANSPORT) && !defined(GIT_OPENSSL))
cl_git_fail_with(-1, error);
#else
cl_git_pass(error);
diff --git a/tests/diff/iterator.c b/tests/diff/iterator.c
index 8417e8e..25a23ed 100644
--- a/tests/diff/iterator.c
+++ b/tests/diff/iterator.c
@@ -268,7 +268,7 @@
cl_git_pass(git_iterator_current_tree_entry(&te, i));
cl_assert(te);
- cl_assert(git_oid_streq(&te->oid, oid) == 0);
+ cl_assert(git_oid_streq(te->oid, oid) == 0);
cl_git_pass(git_iterator_current(&ie, i));
cl_git_pass(git_buf_sets(&path, ie->path));
diff --git a/tests/index/racy.c b/tests/index/racy.c
index 68aa460..1768f5e 100644
--- a/tests/index/racy.c
+++ b/tests/index/racy.c
@@ -105,8 +105,8 @@
{
git_buf path = GIT_BUF_INIT;
git_index *index;
- const git_index_entry *entry;
- int i, found_race = 0;
+ git_index_entry *entry;
+ struct stat st;
/* Make sure we do have a timestamp */
cl_git_pass(git_repository_index__weakptr(&index, g_repo));
@@ -114,27 +114,20 @@
cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "A"));
- /* Make sure writing the file, adding and rewriting happen in the same second */
- for (i = 0; i < 10; i++) {
- struct stat st;
- cl_git_mkfile(path.ptr, "A");
+ cl_git_mkfile(path.ptr, "A");
+ cl_git_pass(git_index_add_bypath(index, "A"));
- cl_git_pass(git_index_add_bypath(index, "A"));
- cl_git_mkfile(path.ptr, "B");
- cl_git_pass(git_index_write(index));
+ cl_git_mkfile(path.ptr, "B");
+ cl_git_pass(git_index_write(index));
- cl_git_mkfile(path.ptr, "");
+ cl_git_mkfile(path.ptr, "");
- cl_git_pass(p_stat(path.ptr, &st));
- cl_assert(entry = git_index_get_bypath(index, "A", 0));
- if (entry->mtime.seconds == (int32_t) st.st_mtime) {
- found_race = 1;
- break;
- }
- }
+ cl_git_pass(p_stat(path.ptr, &st));
+ cl_assert(entry = (git_index_entry *)git_index_get_bypath(index, "A", 0));
- if (!found_race)
- cl_fail("failed to find race after 10 attempts");
+ /* force a race */
+ entry->mtime.seconds = st.st_mtime;
+ entry->mtime.nanoseconds = st.st_mtime_nsec;
git_buf_free(&path);
}
diff --git a/tests/object/tree/attributes.c b/tests/object/tree/attributes.c
index 413514c..8654dfa 100644
--- a/tests/object/tree/attributes.c
+++ b/tests/object/tree/attributes.c
@@ -82,6 +82,7 @@
cl_git_pass(git_treebuilder_new(&builder, repo, tree));
entry = git_treebuilder_get(builder, "old_mode.txt");
+ cl_assert(entry != NULL);
cl_assert_equal_i(
GIT_FILEMODE_BLOB,
git_tree_entry_filemode(entry));
@@ -92,6 +93,7 @@
cl_git_pass(git_tree_lookup(&tree, repo, &tid2));
entry = git_tree_entry_byname(tree, "old_mode.txt");
+ cl_assert(entry != NULL);
cl_assert_equal_i(
GIT_FILEMODE_BLOB,
git_tree_entry_filemode(entry));
diff --git a/tests/online/badssl.c b/tests/online/badssl.c
index 12badbd..66b090d 100644
--- a/tests/online/badssl.c
+++ b/tests/online/badssl.c
@@ -36,3 +36,11 @@
cl_git_fail_with(GIT_ECERTIFICATE,
git_clone(&g_repo, "https://self-signed.badssl.com/fake.git", "./fake", NULL));
}
+
+void test_online_badssl__old_cipher(void)
+{
+ if (!g_has_ssl)
+ cl_skip();
+
+ cl_git_fail(git_clone(&g_repo, "https://rc4.badssl.com/fake.git", "./fake", NULL));
+}
diff --git a/tests/refs/create.c b/tests/refs/create.c
index b96d0c9..6d5a5f1 100644
--- a/tests/refs/create.c
+++ b/tests/refs/create.c
@@ -19,7 +19,7 @@
{
cl_git_sandbox_cleanup();
- cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_OBJECT_CREATION, 0));
+ cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_OBJECT_CREATION, 1));
}
void test_refs_create__symbolic(void)
@@ -122,7 +122,7 @@
}
/* Can by default create a reference that targets at an unknown id */
-void test_refs_create__oid_unknown_succeeds_by_default(void)
+void test_refs_create__oid_unknown_succeeds_without_strict(void)
{
git_reference *new_reference, *looked_up_ref;
git_oid id;
@@ -131,6 +131,8 @@
git_oid_fromstr(&id, "deadbeef3f795b2b4353bcce3a527ad0a4f7f644");
+ cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_OBJECT_CREATION, 0));
+
/* Create and write the new object id reference */
cl_git_pass(git_reference_create(&new_reference, g_repo, new_head, &id, 0, NULL));
git_reference_free(new_reference);
@@ -141,7 +143,7 @@
}
/* Strict object enforcement enforces valid object id */
-void test_refs_create__oid_unknown_fails_strict_mode(void)
+void test_refs_create__oid_unknown_fails_by_default(void)
{
git_reference *new_reference, *looked_up_ref;
git_oid id;
@@ -150,8 +152,6 @@
git_oid_fromstr(&id, "deadbeef3f795b2b4353bcce3a527ad0a4f7f644");
- cl_git_pass(git_libgit2_opts(GIT_OPT_ENABLE_STRICT_OBJECT_CREATION, 1));
-
/* Create and write the new object id reference */
cl_git_fail(git_reference_create(&new_reference, g_repo, new_head, &id, 0, NULL));
diff --git a/tests/refs/lookup.c b/tests/refs/lookup.c
index d076e49..456d0d2 100644
--- a/tests/refs/lookup.c
+++ b/tests/refs/lookup.c
@@ -58,3 +58,11 @@
error = git_reference_lookup(&ref, g_repo, "refs/heads/");
cl_assert_equal_i(error, GIT_EINVALIDSPEC);
}
+
+void test_refs_lookup__dwim_notfound(void)
+{
+ git_reference *ref;
+
+ cl_git_fail_with(GIT_ENOTFOUND, git_reference_dwim(&ref, g_repo, "idontexist"));
+ cl_assert_equal_s("no reference found for shorthand 'idontexist'", giterr_last()->message);
+}
diff --git a/tests/repo/iterator.c b/tests/repo/iterator.c
index c18e24a..6b5795b 100644
--- a/tests/repo/iterator.c
+++ b/tests/repo/iterator.c
@@ -1020,6 +1020,11 @@
if (!cl_is_chmod_supported())
return;
+#ifndef GIT_WIN32
+ if (geteuid() == 0)
+ cl_skip();
+#endif
+
g_repo = cl_git_sandbox_init("empty_standard_repo");
cl_must_pass(p_mkdir("empty_standard_repo/r", 0777));
diff --git a/tests/reset/hard.c b/tests/reset/hard.c
index 0c0af91..e461f80 100644
--- a/tests/reset/hard.c
+++ b/tests/reset/hard.c
@@ -122,9 +122,9 @@
int write_theirs = 4;
git_oid ancestor, ours, theirs;
- git_oid_fromstr(&ancestor, "6bb0d9f700543ba3d318ba7075fc3bd696b4287b");
- git_oid_fromstr(&ours, "b19a1e93bec1317dc6097229e12afaffbfa74dc2");
- git_oid_fromstr(&theirs, "950b81b7eee953d050aa05a641f8e056c85dd1bd");
+ git_oid_fromstr(&ancestor, "452e4244b5d083ddf0460acf1ecc74db9dcfa11a");
+ git_oid_fromstr(&ours, "32504b727382542f9f089e24fddac5e78533e96c");
+ git_oid_fromstr(&theirs, "061d42a44cacde5726057b67558821d95db96f19");
cl_git_rewritefile("status/conflicting_file", "conflicting file\n");
diff --git a/tests/status/worktree.c b/tests/status/worktree.c
index fc4afc6..5d3b4d5 100644
--- a/tests/status/worktree.c
+++ b/tests/status/worktree.c
@@ -657,7 +657,7 @@
entry.mode = 0100644;
entry.path = "modified_file";
- git_oid_fromstr(&entry.id, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
+ git_oid_fromstr(&entry.id, "452e4244b5d083ddf0460acf1ecc74db9dcfa11a");
cl_git_pass(git_repository_index(&index, repo));
cl_git_pass(git_index_conflict_add(index, &entry, &entry, &entry));
@@ -1006,6 +1006,9 @@
git_status_options opts = GIT_STATUS_OPTIONS_INIT;
status_entry_counts counts = {0};
+ if (geteuid() == 0)
+ cl_skip();
+
/* Create directory with no read permission */
cl_git_pass(git_futils_mkdir_r("empty_standard_repo/no_permission", 0777));
cl_git_mkfile("empty_standard_repo/no_permission/foo", "dummy");
diff --git a/tests/transport/register.c b/tests/transport/register.c
index ea917d5..97aae6b 100644
--- a/tests/transport/register.c
+++ b/tests/transport/register.c
@@ -40,15 +40,23 @@
void test_transport_register__custom_transport_ssh(void)
{
+ const char *urls[] = {
+ "ssh://somehost:somepath",
+ "ssh+git://somehost:somepath",
+ "git+ssh://somehost:somepath",
+ "git@somehost:somepath",
+ };
git_transport *transport;
+ unsigned i;
+ for (i = 0; i < ARRAY_SIZE(urls); i++) {
#ifndef GIT_SSH
- cl_git_fail_with(git_transport_new(&transport, NULL, "ssh://somehost:somepath"), -1);
- cl_git_fail_with(git_transport_new(&transport, NULL, "git@somehost:somepath"), -1);
+ cl_git_fail_with(git_transport_new(&transport, NULL, urls[i]), -1);
#else
- cl_git_pass(git_transport_new(&transport, NULL, "git@somehost:somepath"));
- transport->free(transport);
+ cl_git_pass(git_transport_new(&transport, NULL, urls[i]));
+ transport->free(transport);
#endif
+ }
cl_git_pass(git_transport_register("ssh", dummy_transport, NULL));
@@ -58,11 +66,12 @@
cl_git_pass(git_transport_unregister("ssh"));
+ for (i = 0; i < ARRAY_SIZE(urls); i++) {
#ifndef GIT_SSH
- cl_git_fail_with(git_transport_new(&transport, NULL, "ssh://somehost:somepath"), -1);
- cl_git_fail_with(git_transport_new(&transport, NULL, "git@somehost:somepath"), -1);
+ cl_git_fail_with(git_transport_new(&transport, NULL, urls[i]), -1);
#else
- cl_git_pass(git_transport_new(&transport, NULL, "git@somehost:somepath"));
- transport->free(transport);
+ cl_git_pass(git_transport_new(&transport, NULL, urls[i]));
+ transport->free(transport);
#endif
+ }
}