Commit 211e117a by Carlos Martín Nieto

Merge pull request #3739 from ethomson/0.24.1

Backport bug fixes to 0.24
parents 785d8c48 8edadbf9
...@@ -412,7 +412,7 @@ IF (MSVC) ...@@ -412,7 +412,7 @@ IF (MSVC)
# /MTd - Statically link the multithreaded debug version of the CRT # /MTd - Statically link the multithreaded debug version of the CRT
# /MDd - Dynamically link the multithreaded debug version of the CRT # /MDd - Dynamically link the multithreaded debug version of the CRT
# /RTC1 - Run time checks # /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 # /DNDEBUG - Disables asserts
# /MT - Statically link the multithreaded release version of the CRT # /MT - Statically link the multithreaded release version of the CRT
...@@ -464,7 +464,7 @@ ELSE () ...@@ -464,7 +464,7 @@ ELSE ()
ENDIF() ENDIF()
IF (WIN32 AND NOT CYGWIN) IF (WIN32 AND NOT CYGWIN)
SET(CMAKE_C_FLAGS_DEBUG "-D_DEBUG") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
ENDIF () ENDIF ()
IF (MINGW) # MinGW always does PIC and complains if we tell it to IF (MINGW) # MinGW always does PIC and complains if we tell it to
...@@ -608,6 +608,8 @@ IF (SONAME) ...@@ -608,6 +608,8 @@ IF (SONAME)
IF (LIBGIT2_FILENAME) IF (LIBGIT2_FILENAME)
ADD_DEFINITIONS(-DLIBGIT2_FILENAME=\"${LIBGIT2_FILENAME}\") ADD_DEFINITIONS(-DLIBGIT2_FILENAME=\"${LIBGIT2_FILENAME}\")
SET_TARGET_PROPERTIES(git2 PROPERTIES OUTPUT_NAME ${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()
ENDIF() ENDIF()
STRING(REPLACE ";" " " LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS}") STRING(REPLACE ";" " " LIBGIT2_PC_LIBS "${LIBGIT2_PC_LIBS}")
......
...@@ -99,7 +99,7 @@ do { \ ...@@ -99,7 +99,7 @@ do { \
FOR##_mark = NULL; \ FOR##_mark = NULL; \
} \ } \
} while (0) } while (0)
/* Run the data callback FOR and consume the current byte */ /* Run the data callback FOR and consume the current byte */
#define CALLBACK_DATA(FOR) \ #define CALLBACK_DATA(FOR) \
CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1) CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1)
...@@ -444,6 +444,9 @@ parse_url_char(enum state s, const char ch) ...@@ -444,6 +444,9 @@ parse_url_char(enum state s, const char ch)
return s_req_path; 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)) { if (IS_ALPHA(ch)) {
return s_req_schema; return s_req_schema;
} }
...@@ -451,7 +454,7 @@ parse_url_char(enum state s, const char ch) ...@@ -451,7 +454,7 @@ parse_url_char(enum state s, const char ch)
break; break;
case s_req_schema: case s_req_schema:
if (IS_ALPHA(ch)) { if (IS_ALPHANUM(ch) || ch == '+' || ch == '-' || ch == '.') {
return s; return s;
} }
......
...@@ -24,10 +24,19 @@ ...@@ -24,10 +24,19 @@
GIT_BEGIN_DECL GIT_BEGIN_DECL
# include "inttypes.h" # include "inttypes.h"
GIT_END_DECL 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> # include <inttypes.h>
#endif #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. */ /** Declare a public function exported for application use. */
#if __GNUC__ >= 4 #if __GNUC__ >= 4
# define GIT_EXTERN(type) extern \ # define GIT_EXTERN(type) extern \
...@@ -148,6 +157,7 @@ typedef enum { ...@@ -148,6 +157,7 @@ typedef enum {
GIT_OPT_SET_SSL_CERT_LOCATIONS, GIT_OPT_SET_SSL_CERT_LOCATIONS,
GIT_OPT_SET_USER_AGENT, GIT_OPT_SET_USER_AGENT,
GIT_OPT_ENABLE_STRICT_OBJECT_CREATION, GIT_OPT_ENABLE_STRICT_OBJECT_CREATION,
GIT_OPT_SET_SSL_CIPHERS,
} git_libgit2_opt_t; } git_libgit2_opt_t;
/** /**
...@@ -259,6 +269,11 @@ typedef enum { ...@@ -259,6 +269,11 @@ typedef enum {
* > example, when this is enabled, the parent(s) and tree inputs * > example, when this is enabled, the parent(s) and tree inputs
* > will be validated when creating a new commit. This defaults * > will be validated when creating a new commit. This defaults
* > to disabled. * > 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 option Option key
* @param ... value to set the option * @param ... value to set the option
......
...@@ -49,10 +49,24 @@ COVERITY_UNSUPPORTED=1 \ ...@@ -49,10 +49,24 @@ COVERITY_UNSUPPORTED=1 \
# Upload results # Upload results
tar czf libgit2.tgz cov-int tar czf libgit2.tgz cov-int
SHA=$(git rev-parse --short HEAD) SHA=$(git rev-parse --short HEAD)
curl \
HTML="$(curl \
--silent \
--write-out "\n%{http_code}" \
--form token="$COVERITY_TOKEN" \ --form token="$COVERITY_TOKEN" \
--form email=bs@github.com \ --form email=bs@github.com \
--form file=@libgit2.tgz \ --form file=@libgit2.tgz \
--form version="$SHA" \ --form version="$SHA" \
--form description="Travis build" \ --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
...@@ -82,4 +82,44 @@ on_oom: ...@@ -82,4 +82,44 @@ on_oom:
#define git_array_valid_index(a, i) ((i) < (a).size) #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 #endif
...@@ -178,7 +178,7 @@ const git_blame_hunk *git_blame_get_hunk_byline(git_blame *blame, size_t lineno) ...@@ -178,7 +178,7 @@ const git_blame_hunk *git_blame_get_hunk_byline(git_blame *blame, size_t lineno)
return NULL; return NULL;
} }
static void normalize_options( static int normalize_options(
git_blame_options *out, git_blame_options *out,
const git_blame_options *in, const git_blame_options *in,
git_repository *repo) git_repository *repo)
...@@ -190,7 +190,9 @@ static void normalize_options( ...@@ -190,7 +190,9 @@ static void normalize_options(
/* No newest_commit => HEAD */ /* No newest_commit => HEAD */
if (git_oid_iszero(&out->newest_commit)) { 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 */ /* min_line 0 really means 1 */
...@@ -204,6 +206,8 @@ static void normalize_options( ...@@ -204,6 +206,8 @@ static void normalize_options(
out->flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES; out->flags |= GIT_BLAME_TRACK_COPIES_SAME_COMMIT_MOVES;
if (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; out->flags |= GIT_BLAME_TRACK_COPIES_SAME_FILE;
return 0;
} }
static git_blame_hunk *split_hunk_in_vector( static git_blame_hunk *split_hunk_in_vector(
...@@ -362,7 +366,8 @@ int git_blame_file( ...@@ -362,7 +366,8 @@ int git_blame_file(
git_blame *blame = NULL; git_blame *blame = NULL;
assert(out && repo && path); 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); blame = git_blame__alloc(repo, normOptions, path);
GITERR_CHECK_ALLOC(blame); GITERR_CHECK_ALLOC(blame);
......
...@@ -525,7 +525,8 @@ static int pass_blame(git_blame *blame, git_blame__origin *origin, uint32_t opt) ...@@ -525,7 +525,8 @@ static int pass_blame(git_blame *blame, git_blame__origin *origin, uint32_t opt)
if (sg_origin[i]) if (sg_origin[i])
continue; 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); porigin = find_origin(blame, p, origin);
if (!porigin) if (!porigin)
......
...@@ -676,7 +676,7 @@ int git_commit_extract_signature(git_buf *signature, git_buf *signed_data, git_r ...@@ -676,7 +676,7 @@ int git_commit_extract_signature(git_buf *signature, git_buf *signed_data, git_r
buf = git_odb_object_data(obj); 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++; h++;
if (git__prefixcmp(buf, field)) { if (git__prefixcmp(buf, field)) {
if (git_buf_put(signed_data, buf, h - buf) < 0) if (git_buf_put(signed_data, buf, h - buf) < 0)
......
...@@ -86,7 +86,8 @@ int git_config__cvar(int *out, git_config *config, git_cvar_cached cvar) ...@@ -86,7 +86,8 @@ int git_config__cvar(int *out, git_config *config, git_cvar_cached cvar)
struct map_data *data = &_cvar_maps[(int)cvar]; struct map_data *data = &_cvar_maps[(int)cvar];
git_config_entry *entry; 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) if (!entry)
*out = data->default_value; *out = data->default_value;
......
...@@ -553,30 +553,15 @@ static int config_set_multivar( ...@@ -553,30 +553,15 @@ static int config_set_multivar(
git_config_backend *cfg, const char *name, const char *regexp, const char *value) git_config_backend *cfg, const char *name, const char *regexp, const char *value)
{ {
diskfile_backend *b = (diskfile_backend *)cfg; diskfile_backend *b = (diskfile_backend *)cfg;
refcounted_strmap *map;
git_strmap *values;
char *key; char *key;
regex_t preg; regex_t preg;
int result; int result;
khiter_t pos;
assert(regexp); assert(regexp);
if ((result = git_config__normalize_name(name, &key)) < 0) if ((result = git_config__normalize_name(name, &key)) < 0)
return result; 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); result = regcomp(&preg, regexp, REG_EXTENDED);
if (result != 0) { if (result != 0) {
giterr_set_regex(&preg, result); giterr_set_regex(&preg, result);
...@@ -591,7 +576,6 @@ static int config_set_multivar( ...@@ -591,7 +576,6 @@ static int config_set_multivar(
result = config_refresh(cfg); result = config_refresh(cfg);
out: out:
refcounted_strmap_free(map);
git__free(key); git__free(key);
regfree(&preg); regfree(&preg);
...@@ -1032,6 +1016,11 @@ static int parse_section_header_ext(struct reader *reader, const char *line, con ...@@ -1032,6 +1016,11 @@ static int parse_section_header_ext(struct reader *reader, const char *line, con
*/ */
first_quote = strchr(line, '"'); 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, '"'); last_quote = strrchr(line, '"');
quoted_len = last_quote - first_quote; quoted_len = last_quote - first_quote;
...@@ -1483,7 +1472,7 @@ static int config_parse( ...@@ -1483,7 +1472,7 @@ static int config_parse(
int (*on_section)(struct reader **reader, const char *current_section, const char *line, size_t line_len, void *data), 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_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_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) void *data)
{ {
char *current_section = NULL, *var_name, *var_value, *line_start; char *current_section = NULL, *var_name, *var_value, *line_start;
...@@ -1534,7 +1523,7 @@ static int config_parse( ...@@ -1534,7 +1523,7 @@ static int config_parse(
} }
if (on_eof) if (on_eof)
result = on_eof(&reader, data); result = on_eof(&reader, current_section, data);
git__free(current_section); git__free(current_section);
return result; return result;
...@@ -1850,7 +1839,8 @@ static int write_on_comment(struct reader **reader, const char *line, size_t lin ...@@ -1850,7 +1839,8 @@ static int write_on_comment(struct reader **reader, const char *line, size_t lin
return write_line_to(&write_data->buffered_comment, line, line_len); 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; struct write_data *write_data = (struct write_data *)data;
int result = 0; int result = 0;
...@@ -1869,7 +1859,11 @@ static int write_on_eof(struct reader **reader, void *data) ...@@ -1869,7 +1859,11 @@ static int write_on_eof(struct reader **reader, void *data)
* value. * value.
*/ */
if ((!write_data->preg || !write_data->preg_replaced) && write_data->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); result = write_value(write_data);
} }
......
...@@ -582,7 +582,8 @@ static int describe( ...@@ -582,7 +582,8 @@ static int describe(
best = (struct possible_tag *)git_vector_get(&all_matches, 0); best = (struct possible_tag *)git_vector_get(&all_matches, 0);
if (gave_up_on) { 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--; seen_commits--;
} }
if ((error = finish_depth_computation( if ((error = finish_depth_computation(
......
...@@ -261,7 +261,7 @@ static int normalize_find_opts( ...@@ -261,7 +261,7 @@ static int normalize_find_opts(
if (!given || if (!given ||
(given->flags & GIT_DIFF_FIND_ALL) == GIT_DIFF_FIND_BY_CONFIG) (given->flags & GIT_DIFF_FIND_ALL) == GIT_DIFF_FIND_BY_CONFIG)
{ {
if (diff->repo) { if (cfg) {
char *rule = char *rule =
git_config__get_string_force(cfg, "diff.renames", "true"); git_config__get_string_force(cfg, "diff.renames", "true");
int boolval; int boolval;
...@@ -318,8 +318,10 @@ static int normalize_find_opts( ...@@ -318,8 +318,10 @@ static int normalize_find_opts(
#undef USE_DEFAULT #undef USE_DEFAULT
if (!opts->rename_limit) { if (!opts->rename_limit) {
opts->rename_limit = git_config__get_int_force( if (cfg) {
cfg, "diff.renamelimit", DEFAULT_RENAME_LIMIT); opts->rename_limit = git_config__get_int_force(
cfg, "diff.renamelimit", DEFAULT_RENAME_LIMIT);
}
if (opts->rename_limit <= 0) if (opts->rename_limit <= 0)
opts->rename_limit = DEFAULT_RENAME_LIMIT; opts->rename_limit = DEFAULT_RENAME_LIMIT;
......
...@@ -70,6 +70,7 @@ static int lock_file(git_filebuf *file, int flags, mode_t mode) ...@@ -70,6 +70,7 @@ static int lock_file(git_filebuf *file, int flags, mode_t mode)
git_file source; git_file source;
char buffer[FILEIO_BUFSIZE]; char buffer[FILEIO_BUFSIZE];
ssize_t read_bytes; ssize_t read_bytes;
int error;
source = p_open(file->path_original, O_RDONLY); source = p_open(file->path_original, O_RDONLY);
if (source < 0) { if (source < 0) {
...@@ -80,7 +81,8 @@ static int lock_file(git_filebuf *file, int flags, mode_t mode) ...@@ -80,7 +81,8 @@ static int lock_file(git_filebuf *file, int flags, mode_t mode)
} }
while ((read_bytes = p_read(source, buffer, sizeof(buffer))) > 0) { 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) if (file->compute_digest)
git_hash_update(&file->digest, buffer, read_bytes); git_hash_update(&file->digest, buffer, read_bytes);
} }
...@@ -90,6 +92,9 @@ static int lock_file(git_filebuf *file, int flags, mode_t mode) ...@@ -90,6 +92,9 @@ static int lock_file(git_filebuf *file, int flags, mode_t mode)
if (read_bytes < 0) { if (read_bytes < 0) {
giterr_set(GITERR_OS, "Failed to read file '%s'", file->path_original); giterr_set(GITERR_OS, "Failed to read file '%s'", file->path_original);
return -1; return -1;
} else if (error < 0) {
giterr_set(GITERR_OS, "Failed to write file '%s'", file->path_lock);
return -1;
} }
} }
......
...@@ -27,6 +27,7 @@ static git_global_shutdown_fn git__shutdown_callbacks[MAX_SHUTDOWN_CB]; ...@@ -27,6 +27,7 @@ static git_global_shutdown_fn git__shutdown_callbacks[MAX_SHUTDOWN_CB];
static git_atomic git__n_shutdown_callbacks; static git_atomic git__n_shutdown_callbacks;
static git_atomic git__n_inits; static git_atomic git__n_inits;
char *git__user_agent; char *git__user_agent;
char *git__ssl_ciphers;
void git__on_shutdown(git_global_shutdown_fn callback) void git__on_shutdown(git_global_shutdown_fn callback)
{ {
...@@ -83,6 +84,7 @@ static void shutdown_common(void) ...@@ -83,6 +84,7 @@ static void shutdown_common(void)
} }
git__free(git__user_agent); git__free(git__user_agent);
git__free(git__ssl_ciphers);
#if defined(GIT_MSVC_CRTDBG) #if defined(GIT_MSVC_CRTDBG)
git_win32__crtdbg_stacktrace_cleanup(); git_win32__crtdbg_stacktrace_cleanup();
...@@ -222,6 +224,20 @@ void git__free_tls_data(void) ...@@ -222,6 +224,20 @@ void git__free_tls_data(void)
TlsSetValue(_tls_index, NULL); 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) #elif defined(GIT_THREADS) && defined(_POSIX_THREADS)
static pthread_key_t _tls_key; static pthread_key_t _tls_key;
......
...@@ -36,5 +36,6 @@ extern void git__on_shutdown(git_global_shutdown_fn callback); ...@@ -36,5 +36,6 @@ extern void git__on_shutdown(git_global_shutdown_fn callback);
extern void git__free_tls_data(void); extern void git__free_tls_data(void);
extern const char *git_libgit2__user_agent(void); extern const char *git_libgit2__user_agent(void);
extern const char *git_libgit2__ssl_ciphers(void);
#endif #endif
...@@ -263,10 +263,18 @@ int git_ignore__for_path( ...@@ -263,10 +263,18 @@ int git_ignore__for_path(
goto cleanup; goto cleanup;
/* given a unrooted path in a non-bare repo, resolve it */ /* given a unrooted path in a non-bare repo, resolve it */
if (workdir && git_path_root(path) < 0) if (workdir && git_path_root(path) < 0) {
error = git_path_find_dir(&ignores->dir, path, workdir); git_buf local = GIT_BUF_INIT;
else
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, ""); error = git_buf_joinpath(&ignores->dir, path, "");
}
if (error < 0) if (error < 0)
goto cleanup; goto cleanup;
......
...@@ -963,14 +963,20 @@ static int index_entry_reuc_init(git_index_reuc_entry **reuc_out, ...@@ -963,14 +963,20 @@ static int index_entry_reuc_init(git_index_reuc_entry **reuc_out,
*reuc_out = reuc = reuc_entry_alloc(path); *reuc_out = reuc = reuc_entry_alloc(path);
GITERR_CHECK_ALLOC(reuc); 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); 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); 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); git_oid_cpy(&reuc->oid[2], their_oid);
}
return 0; return 0;
} }
...@@ -2830,7 +2836,7 @@ static int read_tree_cb( ...@@ -2830,7 +2836,7 @@ static int read_tree_cb(
return -1; return -1;
entry->mode = tentry->attr; 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 */ /* look for corresponding old entry and copy data to new entry */
if (data->old_entries != NULL && if (data->old_entries != NULL &&
......
...@@ -449,7 +449,7 @@ static void hash_partially(git_indexer *idx, const uint8_t *data, size_t size) ...@@ -449,7 +449,7 @@ static void hash_partially(git_indexer *idx, const uint8_t *data, size_t size)
static int write_at(git_indexer *idx, const void *data, git_off_t offset, size_t size) static int write_at(git_indexer *idx, const void *data, git_off_t offset, size_t size)
{ {
git_file fd = idx->pack->mwf.fd; git_file fd = idx->pack->mwf.fd;
size_t page_size; size_t mmap_alignment;
size_t page_offset; size_t page_offset;
git_off_t page_start; git_off_t page_start;
unsigned char *map_data; unsigned char *map_data;
...@@ -458,11 +458,11 @@ static int write_at(git_indexer *idx, const void *data, git_off_t offset, size_t ...@@ -458,11 +458,11 @@ static int write_at(git_indexer *idx, const void *data, git_off_t offset, size_t
assert(data && size); assert(data && size);
if ((error = git__page_size(&page_size)) < 0) if ((error = git__mmap_alignment(&mmap_alignment)) < 0)
return error; return error;
/* the offset needs to be at the beginning of the a page boundary */ /* the offset needs to be at the mmap boundary for the platform */
page_offset = offset % page_size; page_offset = offset % mmap_alignment;
page_start = offset - page_offset; page_start = offset - page_offset;
if ((error = p_mmap(&map, page_offset + size, GIT_PROT_WRITE, GIT_MAP_SHARED, fd, page_start)) < 0) if ((error = p_mmap(&map, page_offset + size, GIT_PROT_WRITE, GIT_MAP_SHARED, fd, page_start)) < 0)
...@@ -777,7 +777,6 @@ static int fix_thin_pack(git_indexer *idx, git_transfer_progress *stats) ...@@ -777,7 +777,6 @@ static int fix_thin_pack(git_indexer *idx, git_transfer_progress *stats)
curpos = delta->delta_off; curpos = delta->delta_off;
error = git_packfile_unpack_header(&size, &type, &idx->pack->mwf, &w, &curpos); error = git_packfile_unpack_header(&size, &type, &idx->pack->mwf, &w, &curpos);
git_mwindow_close(&w);
if (error < 0) if (error < 0)
return error; return error;
...@@ -914,12 +913,17 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats) ...@@ -914,12 +913,17 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats)
git_filebuf index_file = {0}; git_filebuf index_file = {0};
void *packfile_trailer; void *packfile_trailer;
if (!idx->parsed_header) {
giterr_set(GITERR_INDEXER, "incomplete pack header");
return -1;
}
if (git_hash_ctx_init(&ctx) < 0) if (git_hash_ctx_init(&ctx) < 0)
return -1; return -1;
/* Test for this before resolve_deltas(), as it plays with idx->off */ /* Test for this before resolve_deltas(), as it plays with idx->off */
if (idx->off < idx->pack->mwf.size - 20) { if (idx->off + 20 < idx->pack->mwf.size) {
giterr_set(GITERR_INDEXER, "Unexpected data at the end of the pack"); giterr_set(GITERR_INDEXER, "unexpected data at the end of the pack");
return -1; return -1;
} }
......
...@@ -458,7 +458,7 @@ static int tree_iterator__set_next(tree_iterator *ti, tree_iterator_frame *tf) ...@@ -458,7 +458,7 @@ static int tree_iterator__set_next(tree_iterator *ti, tree_iterator_frame *tf)
/* try to load trees for items in [current,next) range */ /* try to load trees for items in [current,next) range */
if (!error && git_tree_entry__is_tree(te)) if (!error && git_tree_entry__is_tree(te))
error = git_tree_lookup( 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) if (tf->next > tf->current + 1)
...@@ -603,7 +603,7 @@ static int tree_iterator__update_entry(tree_iterator *ti) ...@@ -603,7 +603,7 @@ static int tree_iterator__update_entry(tree_iterator *ti)
te = tf->entries[tf->current]->te; te = tf->entries[tf->current]->te;
ti->entry.mode = te->attr; 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); ti->entry.path = tree_iterator__current_filename(ti, te);
GITERR_CHECK_ALLOC(ti->entry.path); GITERR_CHECK_ALLOC(ti->entry.path);
......
...@@ -296,8 +296,18 @@ static git_mwindow *new_window( ...@@ -296,8 +296,18 @@ static git_mwindow *new_window(
*/ */
if (git_futils_mmap_ro(&w->window_map, fd, w->offset, (size_t)len) < 0) { 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++; ctl->mmap_calls++;
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "commit.h" #include "commit.h"
#include "tree.h" #include "tree.h"
#include "blob.h" #include "blob.h"
#include "oid.h"
#include "tag.h" #include "tag.h"
bool git_object__strict_input_validation = true; bool git_object__strict_input_validation = true;
...@@ -166,13 +167,9 @@ int git_object_lookup_prefix( ...@@ -166,13 +167,9 @@ int git_object_lookup_prefix(
error = git_odb_read(&odb_obj, odb, id); error = git_odb_read(&odb_obj, odb, id);
} }
} else { } 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 */ git_oid__cpy_prefix(&short_oid, id, len);
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);
/* If len < GIT_OID_HEXSZ (a strict short oid was given), we have /* If len < GIT_OID_HEXSZ (a strict short oid was given), we have
* 2 options : * 2 options :
......
...@@ -725,7 +725,8 @@ int git_odb_exists_prefix( ...@@ -725,7 +725,8 @@ int git_odb_exists_prefix(
git_oid_cpy(out, short_id); git_oid_cpy(out, short_id);
return 0; return 0;
} else { } 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 @@ int git_odb_exists_prefix( ...@@ -740,7 +741,7 @@ int git_odb_exists_prefix(
error = odb_exists_prefix_1(out, db, &key, len, true); error = odb_exists_prefix_1(out, db, &key, len, true);
if (error == GIT_ENOTFOUND) 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; return error;
} }
...@@ -881,7 +882,7 @@ int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id) ...@@ -881,7 +882,7 @@ int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id)
error = odb_read_1(out, db, id, true); error = odb_read_1(out, db, id, true);
if (error == GIT_ENOTFOUND) 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; return error;
} }
...@@ -967,7 +968,7 @@ int git_odb_read_prefix( ...@@ -967,7 +968,7 @@ int git_odb_read_prefix(
error = read_prefix_1(out, db, &key, len, true); error = read_prefix_1(out, db, &key, len, true);
if (error == GIT_ENOTFOUND) 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; return error;
} }
...@@ -1223,12 +1224,14 @@ int git_odb_refresh(struct git_odb *db) ...@@ -1223,12 +1224,14 @@ int git_odb_refresh(struct git_odb *db)
return 0; 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) { if (oid != NULL) {
char oid_str[GIT_OID_HEXSZ + 1]; char oid_str[GIT_OID_HEXSZ + 1];
git_oid_tostr(oid_str, sizeof(oid_str), oid); git_oid_tostr(oid_str, oid_len, oid);
giterr_set(GITERR_ODB, "Object not found - %s (%s)", message, oid_str); giterr_set(GITERR_ODB, "Object not found - %s (%.*s)",
message, oid_len, oid_str);
} else } else
giterr_set(GITERR_ODB, "Object not found - %s", message); giterr_set(GITERR_ODB, "Object not found - %s", message);
......
...@@ -82,7 +82,8 @@ int git_odb__hashlink(git_oid *out, const char *path); ...@@ -82,7 +82,8 @@ int git_odb__hashlink(git_oid *out, const char *path);
/* /*
* Generate a GIT_ENOTFOUND error for the ODB. * 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. * Generate a GIT_EAMBIGUOUS error for the ODB.
......
...@@ -547,7 +547,8 @@ static int locate_object_short_oid( ...@@ -547,7 +547,8 @@ static int locate_object_short_oid(
/* Check that directory exists */ /* Check that directory exists */
if (git_path_isdir(object_location->ptr) == false) 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.dir_len = git_buf_len(object_location);
state.short_oid_len = len; state.short_oid_len = len;
...@@ -560,7 +561,8 @@ static int locate_object_short_oid( ...@@ -560,7 +561,8 @@ static int locate_object_short_oid(
return error; return error;
if (!state.found) 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) if (state.found > 1)
return git_odb__error_ambiguous("multiple matches in loose objects"); return git_odb__error_ambiguous("multiple matches in loose objects");
...@@ -613,9 +615,10 @@ static int loose_backend__read_header(size_t *len_p, git_otype *type_p, git_odb_ ...@@ -613,9 +615,10 @@ static int loose_backend__read_header(size_t *len_p, git_otype *type_p, git_odb_
raw.len = 0; raw.len = 0;
raw.type = GIT_OBJ_BAD; raw.type = GIT_OBJ_BAD;
if (locate_object(&object_path, (loose_backend *)backend, oid) < 0) if (locate_object(&object_path, (loose_backend *)backend, oid) < 0) {
error = git_odb__error_notfound("no matching loose object", oid); error = git_odb__error_notfound("no matching loose object",
else if ((error = read_header_loose(&raw, &object_path)) == 0) { oid, GIT_OID_HEXSZ);
} else if ((error = read_header_loose(&raw, &object_path)) == 0) {
*len_p = raw.len; *len_p = raw.len;
*type_p = raw.type; *type_p = raw.type;
} }
...@@ -633,9 +636,10 @@ static int loose_backend__read(void **buffer_p, size_t *len_p, git_otype *type_p ...@@ -633,9 +636,10 @@ static int loose_backend__read(void **buffer_p, size_t *len_p, git_otype *type_p
assert(backend && oid); assert(backend && oid);
if (locate_object(&object_path, (loose_backend *)backend, oid) < 0) if (locate_object(&object_path, (loose_backend *)backend, oid) < 0) {
error = git_odb__error_notfound("no matching loose object", oid); error = git_odb__error_notfound("no matching loose object",
else if ((error = read_loose(&raw, &object_path)) == 0) { oid, GIT_OID_HEXSZ);
} else if ((error = read_loose(&raw, &object_path)) == 0) {
*buffer_p = raw.data; *buffer_p = raw.data;
*len_p = raw.len; *len_p = raw.len;
*type_p = raw.type; *type_p = raw.type;
......
...@@ -264,7 +264,8 @@ static int pack_entry_find(struct git_pack_entry *e, struct pack_backend *backen ...@@ -264,7 +264,8 @@ static int pack_entry_find(struct git_pack_entry *e, struct pack_backend *backen
if (!pack_entry_find_inner(e, backend, oid, last_found)) if (!pack_entry_find_inner(e, backend, oid, last_found))
return 0; 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( static int pack_entry_find_prefix(
...@@ -309,7 +310,8 @@ static int pack_entry_find_prefix( ...@@ -309,7 +310,8 @@ static int pack_entry_find_prefix(
} }
if (!found) 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 else
return 0; return 0;
} }
...@@ -333,7 +335,7 @@ static int pack_backend__refresh(git_odb_backend *backend_) ...@@ -333,7 +335,7 @@ static int pack_backend__refresh(git_odb_backend *backend_)
return 0; return 0;
if (p_stat(backend->pack_folder, &st) < 0 || !S_ISDIR(st.st_mode)) 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); git_buf_sets(&path, backend->pack_folder);
......
...@@ -44,4 +44,13 @@ GIT_INLINE(int) git_oid__cmp(const git_oid *a, const git_oid *b) ...@@ -44,4 +44,13 @@ GIT_INLINE(int) git_oid__cmp(const git_oid *a, const git_oid *b)
return git_oid__hashcmp(a->id, b->id); 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 #endif
...@@ -34,6 +34,8 @@ ...@@ -34,6 +34,8 @@
SSL_CTX *git__ssl_ctx; 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 #ifdef GIT_THREADS
static git_mutex *openssl_locks; static git_mutex *openssl_locks;
...@@ -85,6 +87,7 @@ int git_openssl_stream_global_init(void) ...@@ -85,6 +87,7 @@ int git_openssl_stream_global_init(void)
{ {
#ifdef GIT_OPENSSL #ifdef GIT_OPENSSL
long ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; 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 */ /* Older OpenSSL and MacOS OpenSSL doesn't have this */
#ifdef SSL_OP_NO_COMPRESSION #ifdef SSL_OP_NO_COMPRESSION
...@@ -108,6 +111,16 @@ int git_openssl_stream_global_init(void) ...@@ -108,6 +111,16 @@ int git_openssl_stream_global_init(void)
git__ssl_ctx = NULL; git__ssl_ctx = NULL;
return -1; 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 #endif
git__on_shutdown(shutdown_ssl); git__on_shutdown(shutdown_ssl);
......
...@@ -848,8 +848,10 @@ static int try_delta(git_packbuilder *pb, struct unpacked *trg, ...@@ -848,8 +848,10 @@ static int try_delta(git_packbuilder *pb, struct unpacked *trg,
git_packbuilder__cache_unlock(pb); git_packbuilder__cache_unlock(pb);
if (overflow) if (overflow) {
git__free(delta_buf);
return -1; return -1;
}
trg_object->delta_data = git__realloc(delta_buf, delta_size); trg_object->delta_data = git__realloc(delta_buf, delta_size);
GITERR_CHECK_ALLOC(trg_object->delta_data); GITERR_CHECK_ALLOC(trg_object->delta_data);
......
...@@ -494,7 +494,6 @@ int git_packfile_resolve_header( ...@@ -494,7 +494,6 @@ int git_packfile_resolve_header(
int error; int error;
error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos); error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
git_mwindow_close(&w_curs);
if (error < 0) if (error < 0)
return error; return error;
...@@ -517,7 +516,6 @@ int git_packfile_resolve_header( ...@@ -517,7 +516,6 @@ int git_packfile_resolve_header(
while (type == GIT_OBJ_OFS_DELTA || type == GIT_OBJ_REF_DELTA) { while (type == GIT_OBJ_OFS_DELTA || type == GIT_OBJ_REF_DELTA) {
curpos = base_offset; curpos = base_offset;
error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos); error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
git_mwindow_close(&w_curs);
if (error < 0) if (error < 0)
return error; return error;
if (type != GIT_OBJ_OFS_DELTA && type != GIT_OBJ_REF_DELTA) if (type != GIT_OBJ_OFS_DELTA && type != GIT_OBJ_REF_DELTA)
...@@ -585,7 +583,6 @@ static int pack_dependency_chain(git_dependency_chain *chain_out, ...@@ -585,7 +583,6 @@ static int pack_dependency_chain(git_dependency_chain *chain_out,
elem->base_key = obj_offset; elem->base_key = obj_offset;
error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos); error = git_packfile_unpack_header(&size, &type, &p->mwf, &w_curs, &curpos);
git_mwindow_close(&w_curs);
if (error < 0) if (error < 0)
goto on_error; goto on_error;
...@@ -1018,7 +1015,7 @@ static int packfile_open(struct git_pack_file *p) ...@@ -1018,7 +1015,7 @@ static int packfile_open(struct git_pack_file *p)
unsigned char *idx_sha1; unsigned char *idx_sha1;
if (p->index_version == -1 && pack_index_open(p) < 0) 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 mwf opened by another thread, return now */
if (git_mutex_lock(&p->lock) < 0) if (git_mutex_lock(&p->lock) < 0)
...@@ -1099,7 +1096,7 @@ int git_packfile__name(char **out, const char *path) ...@@ -1099,7 +1096,7 @@ int git_packfile__name(char **out, const char *path)
path_len = strlen(path); path_len = strlen(path);
if (path_len < strlen(".idx")) 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) if (git_buf_printf(&buf, "%.*s.pack", (int)(path_len - strlen(".idx")), path) < 0)
return -1; return -1;
...@@ -1117,7 +1114,7 @@ int git_packfile_alloc(struct git_pack_file **pack_out, const char *path) ...@@ -1117,7 +1114,7 @@ int git_packfile_alloc(struct git_pack_file **pack_out, const char *path)
*pack_out = NULL; *pack_out = NULL;
if (path_len < strlen(".idx")) 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, sizeof(*p), path_len);
GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 2); GITERR_CHECK_ALLOC_ADD(&alloc_len, alloc_len, 2);
...@@ -1143,7 +1140,7 @@ int git_packfile_alloc(struct git_pack_file **pack_out, const char *path) ...@@ -1143,7 +1140,7 @@ int git_packfile_alloc(struct git_pack_file **pack_out, const char *path)
if (p_stat(p->pack_name, &st) < 0 || !S_ISREG(st.st_mode)) { if (p_stat(p->pack_name, &st) < 0 || !S_ISREG(st.st_mode)) {
git__free(p); 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 /* ok, it looks sane as far as we can check without
...@@ -1344,7 +1341,7 @@ static int pack_entry_find_offset( ...@@ -1344,7 +1341,7 @@ static int pack_entry_find_offset(
} }
if (!found) 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) if (found > 1)
return git_odb__error_ambiguous("found multiple offsets for pack entry"); return git_odb__error_ambiguous("found multiple offsets for pack entry");
......
...@@ -224,6 +224,13 @@ int git__page_size(size_t *page_size) ...@@ -224,6 +224,13 @@ int git__page_size(size_t *page_size)
return 0; 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) int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
{ {
......
...@@ -109,6 +109,7 @@ extern int p_getcwd(char *buffer_out, size_t size); ...@@ -109,6 +109,7 @@ extern int p_getcwd(char *buffer_out, size_t size);
extern int p_rename(const char *from, const char *to); extern int p_rename(const char *from, const char *to);
extern int git__page_size(size_t *page_size); extern int git__page_size(size_t *page_size);
extern int git__mmap_alignment(size_t *page_size);
/** /**
* Platform-dependent methods * Platform-dependent methods
......
...@@ -374,9 +374,9 @@ static int enqueue_object( ...@@ -374,9 +374,9 @@ static int enqueue_object(
case GIT_OBJ_COMMIT: case GIT_OBJ_COMMIT:
return 0; return 0;
case GIT_OBJ_TREE: case GIT_OBJ_TREE:
return git_packbuilder_insert_tree(pb, &entry->oid); return git_packbuilder_insert_tree(pb, entry->oid);
default: default:
return git_packbuilder_insert(pb, &entry->oid, entry->filename); return git_packbuilder_insert(pb, entry->oid, entry->filename);
} }
} }
...@@ -396,7 +396,7 @@ static int queue_differences( ...@@ -396,7 +396,7 @@ static int queue_differences(
const git_tree_entry *d_entry = git_tree_entry_byindex(delta, j); const git_tree_entry *d_entry = git_tree_entry_byindex(delta, j);
int cmp = 0; 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; goto loop;
cmp = strcmp(b_entry->filename, d_entry->filename); cmp = strcmp(b_entry->filename, d_entry->filename);
...@@ -407,15 +407,15 @@ static int queue_differences( ...@@ -407,15 +407,15 @@ static int queue_differences(
git_tree_entry__is_tree(b_entry) && git_tree_entry__is_tree(b_entry) &&
git_tree_entry__is_tree(d_entry)) { git_tree_entry__is_tree(d_entry)) {
/* Add the right-hand 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) d_entry->filename)) < 0)
goto on_error; goto on_error;
/* Acquire the subtrees and recurse */ /* Acquire the subtrees and recurse */
if ((error = git_tree_lookup(&b_child, 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, (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) (error = queue_differences(b_child, d_child, pb)) < 0)
goto on_error; goto on_error;
......
...@@ -962,6 +962,7 @@ static int packed_write(refdb_fs_backend *backend) ...@@ -962,6 +962,7 @@ static int packed_write(refdb_fs_backend *backend)
for (i = 0; i < git_sortedcache_entrycount(refcache); ++i) { for (i = 0; i < git_sortedcache_entrycount(refcache); ++i) {
struct packref *ref = git_sortedcache_entry(refcache, i); struct packref *ref = git_sortedcache_entry(refcache, i);
assert(ref);
if (packed_find_peel(backend, ref) < 0) if (packed_find_peel(backend, ref) < 0)
goto fail; goto fail;
......
...@@ -289,6 +289,9 @@ cleanup: ...@@ -289,6 +289,9 @@ cleanup:
"Could not use '%s' as valid reference name", git_buf_cstr(&name)); "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(&name);
git_buf_free(&refnamebuf); git_buf_free(&refnamebuf);
return error; return error;
......
...@@ -71,12 +71,18 @@ static int config_level_to_sysdir(int config_level) ...@@ -71,12 +71,18 @@ static int config_level_to_sysdir(int config_level)
} }
extern char *git__user_agent; extern char *git__user_agent;
extern char *git__ssl_ciphers;
const char *git_libgit2__user_agent() const char *git_libgit2__user_agent()
{ {
return git__user_agent; return git__user_agent;
} }
const char *git_libgit2__ssl_ciphers()
{
return git__ssl_ciphers;
}
int git_libgit2_opts(int key, ...) int git_libgit2_opts(int key, ...)
{ {
int error = 0; int error = 0;
...@@ -169,7 +175,7 @@ int git_libgit2_opts(int key, ...) ...@@ -169,7 +175,7 @@ int git_libgit2_opts(int key, ...)
} }
} }
#else #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; error = -1;
#endif #endif
break; break;
...@@ -187,6 +193,22 @@ int git_libgit2_opts(int key, ...) ...@@ -187,6 +193,22 @@ int git_libgit2_opts(int key, ...)
git_object__strict_input_validation = (va_arg(ap, int) != 0); git_object__strict_input_validation = (va_arg(ap, int) != 0);
break; 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: default:
giterr_set(GITERR_INVALID, "invalid option key"); giterr_set(GITERR_INVALID, "invalid option key");
error = -1; error = -1;
......
...@@ -80,7 +80,8 @@ static kh_inline int str_equal_no_trailing_slash(const char *a, const char *b) ...@@ -80,7 +80,8 @@ static kh_inline int str_equal_no_trailing_slash(const char *a, const char *b)
if (blen > 0 && b[blen - 1] == '/') if (blen > 0 && b[blen - 1] == '/')
blen--; blen--;
return (alen == blen && strncmp(a, b, alen) == 0); return (alen == 0 && blen == 0) ||
(alen == blen && strncmp(a, b, alen) == 0);
} }
__KHASH_IMPL( __KHASH_IMPL(
...@@ -1416,7 +1417,7 @@ static int submodule_update_head(git_submodule *submodule) ...@@ -1416,7 +1417,7 @@ static int submodule_update_head(git_submodule *submodule)
git_tree_entry_bypath(&te, head, submodule->path) < 0) git_tree_entry_bypath(&te, head, submodule->path) < 0)
giterr_clear(); giterr_clear();
else 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_entry_free(te);
git_tree_free(head); git_tree_free(head);
......
...@@ -35,6 +35,8 @@ static transport_definition transports[] = { ...@@ -35,6 +35,8 @@ static transport_definition transports[] = {
{ "file://", git_transport_local, NULL }, { "file://", git_transport_local, NULL },
#ifdef GIT_SSH #ifdef GIT_SSH
{ "ssh://", git_transport_smart, &ssh_subtransport_definition }, { "ssh://", git_transport_smart, &ssh_subtransport_definition },
{ "ssh+git://", git_transport_smart, &ssh_subtransport_definition },
{ "git+ssh://", git_transport_smart, &ssh_subtransport_definition },
#endif #endif
{ NULL, 0, 0 } { NULL, 0, 0 }
}; };
......
...@@ -721,18 +721,39 @@ static int add_push_report_pkt(git_push *push, git_pkt *pkt) ...@@ -721,18 +721,39 @@ static int add_push_report_pkt(git_push *push, git_pkt *pkt)
return 0; 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; git_pkt *pkt;
const char *line = data_pkt->data, *line_end; const char *line, *line_end;
size_t line_len = data_pkt->len; size_t line_len;
int error; 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) { while (line_len > 0) {
error = git_pkt_parse_line(&pkt, line, &line_end, line_len); error = git_pkt_parse_line(&pkt, line, &line_end, line_len);
if (error < 0) if (error == GIT_EBUFS) {
return error; /* 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 */ /* Advance in the buffer */
line_len -= (line_end - line); line_len -= (line_end - line);
...@@ -743,10 +764,15 @@ static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt) ...@@ -743,10 +764,15 @@ static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt)
git_pkt_free(pkt); git_pkt_free(pkt);
if (error < 0 && error != GIT_ITEROVER) 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) static int parse_report(transport_smart *transport, git_push *push)
...@@ -755,6 +781,7 @@ static int parse_report(transport_smart *transport, git_push *push) ...@@ -755,6 +781,7 @@ static int parse_report(transport_smart *transport, git_push *push)
const char *line_end = NULL; const char *line_end = NULL;
gitno_buffer *buf = &transport->buffer; gitno_buffer *buf = &transport->buffer;
int error, recvd; int error, recvd;
git_buf data_pkt_buf = GIT_BUF_INIT;
for (;;) { for (;;) {
if (buf->offset > 0) if (buf->offset > 0)
...@@ -763,16 +790,21 @@ static int parse_report(transport_smart *transport, git_push *push) ...@@ -763,16 +790,21 @@ static int parse_report(transport_smart *transport, git_push *push)
else else
error = GIT_EBUFS; error = GIT_EBUFS;
if (error < 0 && error != GIT_EBUFS) if (error < 0 && error != GIT_EBUFS) {
return -1; error = -1;
goto done;
}
if (error == GIT_EBUFS) { if (error == GIT_EBUFS) {
if ((recvd = gitno_recv(buf)) < 0) if ((recvd = gitno_recv(buf)) < 0) {
return recvd; error = recvd;
goto done;
}
if (recvd == 0) { if (recvd == 0) {
giterr_set(GITERR_NET, "early EOF"); giterr_set(GITERR_NET, "early EOF");
return GIT_EEOF; error = GIT_EEOF;
goto done;
} }
continue; continue;
} }
...@@ -784,7 +816,7 @@ static int parse_report(transport_smart *transport, git_push *push) ...@@ -784,7 +816,7 @@ static int parse_report(transport_smart *transport, git_push *push)
switch (pkt->type) { switch (pkt->type) {
case GIT_PKT_DATA: case GIT_PKT_DATA:
/* This is a sideband packet which contains other packets */ /* 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; break;
case GIT_PKT_ERR: case GIT_PKT_ERR:
giterr_set(GITERR_NET, "report-status: Error reported: %s", giterr_set(GITERR_NET, "report-status: Error reported: %s",
...@@ -805,12 +837,24 @@ static int parse_report(transport_smart *transport, git_push *push) ...@@ -805,12 +837,24 @@ static int parse_report(transport_smart *transport, git_push *push)
git_pkt_free(pkt); git_pkt_free(pkt);
/* add_push_report_pkt returns GIT_ITEROVER when it receives a flush */ /* add_push_report_pkt returns GIT_ITEROVER when it receives a flush */
if (error == GIT_ITEROVER) if (error == GIT_ITEROVER) {
return 0; 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) if (error < 0) {
return error; 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) static int add_ref_from_push_spec(git_vector *refs, push_spec *push_spec)
......
...@@ -21,7 +21,8 @@ ...@@ -21,7 +21,8 @@
#define OWNING_SUBTRANSPORT(s) ((ssh_subtransport *)(s)->parent.subtransport) #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_uploadpack[] = "git-upload-pack";
static const char cmd_receivepack[] = "git-receive-pack"; static const char cmd_receivepack[] = "git-receive-pack";
...@@ -63,17 +64,24 @@ static int gen_proto(git_buf *request, const char *cmd, const char *url) ...@@ -63,17 +64,24 @@ static int gen_proto(git_buf *request, const char *cmd, const char *url)
{ {
char *repo; char *repo;
int len; int len;
size_t i;
if (!git__prefixcmp(url, prefix_ssh)) { for (i = 0; i < ARRAY_SIZE(ssh_prefixes); ++i) {
url = url + strlen(prefix_ssh); const char *p = ssh_prefixes[i];
repo = strchr(url, '/');
if (repo && repo[1] == '~') if (!git__prefixcmp(url, p)) {
++repo; url = url + strlen(p);
} else { repo = strchr(url, '/');
repo = strchr(url, ':'); if (repo && repo[1] == '~')
if (repo) repo++; ++repo;
goto done;
}
} }
repo = strchr(url, ':');
if (repo) repo++;
done:
if (!repo) { if (!repo) {
giterr_set(GITERR_NET, "Malformed git protocol URL"); giterr_set(GITERR_NET, "Malformed git protocol URL");
return -1; return -1;
...@@ -500,6 +508,7 @@ static int _git_ssh_setup_conn( ...@@ -500,6 +508,7 @@ static int _git_ssh_setup_conn(
char *host=NULL, *port=NULL, *path=NULL, *user=NULL, *pass=NULL; char *host=NULL, *port=NULL, *path=NULL, *user=NULL, *pass=NULL;
const char *default_port="22"; const char *default_port="22";
int auth_methods, error = 0; int auth_methods, error = 0;
size_t i;
ssh_stream *s; ssh_stream *s;
git_cred *cred = NULL; git_cred *cred = NULL;
LIBSSH2_SESSION* session=NULL; LIBSSH2_SESSION* session=NULL;
...@@ -515,16 +524,22 @@ static int _git_ssh_setup_conn( ...@@ -515,16 +524,22 @@ static int _git_ssh_setup_conn(
s->session = NULL; s->session = NULL;
s->channel = NULL; s->channel = NULL;
if (!git__prefixcmp(url, prefix_ssh)) { for (i = 0; i < ARRAY_SIZE(ssh_prefixes); ++i) {
if ((error = gitno_extract_url_parts(&host, &port, &path, &user, &pass, url, default_port)) < 0) const char *p = ssh_prefixes[i];
goto done;
} else { if (!git__prefixcmp(url, p)) {
if ((error = git_ssh_extract_url_parts(&host, &user, url)) < 0) if ((error = gitno_extract_url_parts(&host, &port, &path, &user, &pass, url, default_port)) < 0)
goto done; goto done;
port = git__strdup(default_port);
GITERR_CHECK_ALLOC(port); 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 || if ((error = git_socket_stream_new(&s->io, host, port)) < 0 ||
(error = git_stream_connect(s->io)) < 0) (error = git_stream_connect(s->io)) < 0)
goto done; goto done;
......
...@@ -17,15 +17,14 @@ ...@@ -17,15 +17,14 @@
struct git_tree_entry { struct git_tree_entry {
uint16_t attr; uint16_t attr;
uint16_t filename_len; uint16_t filename_len;
git_oid oid; const git_oid *oid;
bool pooled; const char *filename;
char filename[GIT_FLEX_ARRAY];
}; };
struct git_tree { struct git_tree {
git_object object; git_object object;
git_vector entries; git_odb_object *odb_obj;
git_pool pool; git_array_t(git_tree_entry) entries;
}; };
struct git_treebuilder { struct git_treebuilder {
......
...@@ -24,6 +24,11 @@ int git__page_size(size_t *page_size) ...@@ -24,6 +24,11 @@ int git__page_size(size_t *page_size)
return 0; 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 p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
{ {
int mprot = PROT_READ; int mprot = PROT_READ;
......
...@@ -17,22 +17,41 @@ static DWORD get_page_size(void) ...@@ -17,22 +17,41 @@ static DWORD get_page_size(void)
if (!page_size) { if (!page_size) {
GetSystemInfo(&sys); GetSystemInfo(&sys);
page_size = sys.dwAllocationGranularity; page_size = sys.dwPageSize;
} }
return page_size; 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) int git__page_size(size_t *page_size)
{ {
*page_size = get_page_size(); *page_size = get_page_size();
return 0; 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) 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); HANDLE fh = (HANDLE)_get_osfhandle(fd);
DWORD page_size = get_page_size(); DWORD alignment = get_allocation_granularity();
DWORD fmap_prot = 0; DWORD fmap_prot = 0;
DWORD view_prot = 0; DWORD view_prot = 0;
DWORD off_low = 0; DWORD off_low = 0;
...@@ -62,12 +81,12 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offs ...@@ -62,12 +81,12 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offs
if (prot & GIT_PROT_READ) if (prot & GIT_PROT_READ)
view_prot |= FILE_MAP_READ; view_prot |= FILE_MAP_READ;
page_start = (offset / page_size) * page_size; page_start = (offset / alignment) * alignment;
page_offset = offset - page_start; 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; 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; return -1;
} }
......
...@@ -301,10 +301,11 @@ int xdl_prepare_env(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, ...@@ -301,10 +301,11 @@ int xdl_prepare_env(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
xdl_free_ctx(&xe->xdf2); xdl_free_ctx(&xe->xdf2);
xdl_free_ctx(&xe->xdf1); xdl_free_ctx(&xe->xdf1);
xdl_free_classifier(&cf);
return -1; return -1;
} }
if (!(xpp->flags & XDF_HISTOGRAM_DIFF)) if (XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF)
xdl_free_classifier(&cf); xdl_free_classifier(&cf);
return 0; return 0;
......
...@@ -252,3 +252,16 @@ void test_attr_ignore__dont_ignore_files_for_folder(void) ...@@ -252,3 +252,16 @@ void test_attr_ignore__dont_ignore_files_for_folder(void)
if (cl_repo_get_bool(g_repo, "core.ignorecase")) if (cl_repo_get_bool(g_repo, "core.ignorecase"))
assert_is_ignored(false, "dir/TeSt"); 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");
}
...@@ -498,6 +498,21 @@ committer Ben Burkert <ben@benburkert.com> 1358451456 -0800\n\ ...@@ -498,6 +498,21 @@ committer Ben Burkert <ben@benburkert.com> 1358451456 -0800\n\
\n\ \n\
a simple commit which works\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_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)); 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 @@ a simple commit which works\n"; ...@@ -523,6 +538,15 @@ a simple commit which works\n";
cl_git_fail_with(GIT_ENOTFOUND, git_commit_extract_signature(&signature, &signed_data, g_repo, &commit_id, NULL)); 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); 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(&signature);
git_buf_free(&signed_data); git_buf_free(&signed_data);
......
...@@ -163,7 +163,7 @@ void test_config_multivar__add_new(void) ...@@ -163,7 +163,7 @@ void test_config_multivar__add_new(void)
cl_git_pass(git_config_open_ondisk(&cfg, "config/config11")); 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; n = 0;
cl_git_pass(git_config_get_multivar_foreach(cfg, var, NULL, cb, &n)); cl_git_pass(git_config_get_multivar_foreach(cfg, var, NULL, cb, &n));
cl_assert_equal_i(n, 1); cl_assert_equal_i(n, 1);
......
...@@ -695,3 +695,30 @@ void test_config_write__locking(void) ...@@ -695,3 +695,30 @@ void test_config_write__locking(void)
git_config_free(cfg); 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);
}
#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);
}
...@@ -33,8 +33,12 @@ void test_core_stream__register_tls(void) ...@@ -33,8 +33,12 @@ void test_core_stream__register_tls(void)
cl_git_pass(git_stream_register_tls(NULL)); cl_git_pass(git_stream_register_tls(NULL));
error = git_tls_stream_new(&stream, "localhost", "443"); error = git_tls_stream_new(&stream, "localhost", "443");
/* We don't have arbitrary TLS stream support on Windows */ /* We don't have arbitrary TLS stream support on Windows
#if GIT_WIN32 * 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); cl_git_fail_with(-1, error);
#else #else
cl_git_pass(error); cl_git_pass(error);
......
...@@ -268,7 +268,7 @@ static void check_tree_entry( ...@@ -268,7 +268,7 @@ static void check_tree_entry(
cl_git_pass(git_iterator_current_tree_entry(&te, i)); cl_git_pass(git_iterator_current_tree_entry(&te, i));
cl_assert(te); 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_iterator_current(&ie, i));
cl_git_pass(git_buf_sets(&path, ie->path)); cl_git_pass(git_buf_sets(&path, ie->path));
......
...@@ -105,8 +105,8 @@ static void setup_race(void) ...@@ -105,8 +105,8 @@ static void setup_race(void)
{ {
git_buf path = GIT_BUF_INIT; git_buf path = GIT_BUF_INIT;
git_index *index; git_index *index;
const git_index_entry *entry; git_index_entry *entry;
int i, found_race = 0; struct stat st;
/* Make sure we do have a timestamp */ /* Make sure we do have a timestamp */
cl_git_pass(git_repository_index__weakptr(&index, g_repo)); cl_git_pass(git_repository_index__weakptr(&index, g_repo));
...@@ -114,27 +114,20 @@ static void setup_race(void) ...@@ -114,27 +114,20 @@ static void setup_race(void)
cl_git_pass(git_buf_joinpath(&path, git_repository_workdir(g_repo), "A")); 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 */ cl_git_mkfile(path.ptr, "A");
for (i = 0; i < 10; i++) { cl_git_pass(git_index_add_bypath(index, "A"));
struct stat st;
cl_git_mkfile(path.ptr, "A");
cl_git_pass(git_index_add_bypath(index, "A")); cl_git_mkfile(path.ptr, "B");
cl_git_mkfile(path.ptr, "B"); cl_git_pass(git_index_write(index));
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_git_pass(p_stat(path.ptr, &st));
cl_assert(entry = git_index_get_bypath(index, "A", 0)); cl_assert(entry = (git_index_entry *)git_index_get_bypath(index, "A", 0));
if (entry->mtime.seconds == (int32_t) st.st_mtime) {
found_race = 1;
break;
}
}
if (!found_race) /* force a race */
cl_fail("failed to find race after 10 attempts"); entry->mtime.seconds = st.st_mtime;
entry->mtime.nanoseconds = st.st_mtime_nsec;
git_buf_free(&path); git_buf_free(&path);
} }
......
...@@ -82,6 +82,7 @@ void test_object_tree_attributes__normalize_attributes_when_creating_a_tree_from ...@@ -82,6 +82,7 @@ void test_object_tree_attributes__normalize_attributes_when_creating_a_tree_from
cl_git_pass(git_treebuilder_new(&builder, repo, tree)); cl_git_pass(git_treebuilder_new(&builder, repo, tree));
entry = git_treebuilder_get(builder, "old_mode.txt"); entry = git_treebuilder_get(builder, "old_mode.txt");
cl_assert(entry != NULL);
cl_assert_equal_i( cl_assert_equal_i(
GIT_FILEMODE_BLOB, GIT_FILEMODE_BLOB,
git_tree_entry_filemode(entry)); git_tree_entry_filemode(entry));
...@@ -92,6 +93,7 @@ void test_object_tree_attributes__normalize_attributes_when_creating_a_tree_from ...@@ -92,6 +93,7 @@ void test_object_tree_attributes__normalize_attributes_when_creating_a_tree_from
cl_git_pass(git_tree_lookup(&tree, repo, &tid2)); cl_git_pass(git_tree_lookup(&tree, repo, &tid2));
entry = git_tree_entry_byname(tree, "old_mode.txt"); entry = git_tree_entry_byname(tree, "old_mode.txt");
cl_assert(entry != NULL);
cl_assert_equal_i( cl_assert_equal_i(
GIT_FILEMODE_BLOB, GIT_FILEMODE_BLOB,
git_tree_entry_filemode(entry)); git_tree_entry_filemode(entry));
......
...@@ -36,3 +36,11 @@ void test_online_badssl__self_signed(void) ...@@ -36,3 +36,11 @@ void test_online_badssl__self_signed(void)
cl_git_fail_with(GIT_ECERTIFICATE, cl_git_fail_with(GIT_ECERTIFICATE,
git_clone(&g_repo, "https://self-signed.badssl.com/fake.git", "./fake", NULL)); 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));
}
...@@ -19,7 +19,7 @@ void test_refs_create__cleanup(void) ...@@ -19,7 +19,7 @@ void test_refs_create__cleanup(void)
{ {
cl_git_sandbox_cleanup(); 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) void test_refs_create__symbolic(void)
...@@ -122,7 +122,7 @@ void test_refs_create__oid(void) ...@@ -122,7 +122,7 @@ void test_refs_create__oid(void)
} }
/* Can by default create a reference that targets at an unknown id */ /* 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_reference *new_reference, *looked_up_ref;
git_oid id; git_oid id;
...@@ -131,6 +131,8 @@ void test_refs_create__oid_unknown_succeeds_by_default(void) ...@@ -131,6 +131,8 @@ void test_refs_create__oid_unknown_succeeds_by_default(void)
git_oid_fromstr(&id, "deadbeef3f795b2b4353bcce3a527ad0a4f7f644"); 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 */ /* Create and write the new object id reference */
cl_git_pass(git_reference_create(&new_reference, g_repo, new_head, &id, 0, NULL)); cl_git_pass(git_reference_create(&new_reference, g_repo, new_head, &id, 0, NULL));
git_reference_free(new_reference); git_reference_free(new_reference);
...@@ -141,7 +143,7 @@ void test_refs_create__oid_unknown_succeeds_by_default(void) ...@@ -141,7 +143,7 @@ void test_refs_create__oid_unknown_succeeds_by_default(void)
} }
/* Strict object enforcement enforces valid object id */ /* 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_reference *new_reference, *looked_up_ref;
git_oid id; git_oid id;
...@@ -150,8 +152,6 @@ void test_refs_create__oid_unknown_fails_strict_mode(void) ...@@ -150,8 +152,6 @@ void test_refs_create__oid_unknown_fails_strict_mode(void)
git_oid_fromstr(&id, "deadbeef3f795b2b4353bcce3a527ad0a4f7f644"); 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 */ /* Create and write the new object id reference */
cl_git_fail(git_reference_create(&new_reference, g_repo, new_head, &id, 0, NULL)); cl_git_fail(git_reference_create(&new_reference, g_repo, new_head, &id, 0, NULL));
......
...@@ -58,3 +58,11 @@ void test_refs_lookup__namespace(void) ...@@ -58,3 +58,11 @@ void test_refs_lookup__namespace(void)
error = git_reference_lookup(&ref, g_repo, "refs/heads/"); error = git_reference_lookup(&ref, g_repo, "refs/heads/");
cl_assert_equal_i(error, GIT_EINVALIDSPEC); 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);
}
...@@ -1020,6 +1020,11 @@ void test_repo_iterator__unreadable_dir(void) ...@@ -1020,6 +1020,11 @@ void test_repo_iterator__unreadable_dir(void)
if (!cl_is_chmod_supported()) if (!cl_is_chmod_supported())
return; return;
#ifndef GIT_WIN32
if (geteuid() == 0)
cl_skip();
#endif
g_repo = cl_git_sandbox_init("empty_standard_repo"); g_repo = cl_git_sandbox_init("empty_standard_repo");
cl_must_pass(p_mkdir("empty_standard_repo/r", 0777)); cl_must_pass(p_mkdir("empty_standard_repo/r", 0777));
......
...@@ -122,9 +122,9 @@ static void unmerged_index_init(git_index *index, int entries) ...@@ -122,9 +122,9 @@ static void unmerged_index_init(git_index *index, int entries)
int write_theirs = 4; int write_theirs = 4;
git_oid ancestor, ours, theirs; git_oid ancestor, ours, theirs;
git_oid_fromstr(&ancestor, "6bb0d9f700543ba3d318ba7075fc3bd696b4287b"); git_oid_fromstr(&ancestor, "452e4244b5d083ddf0460acf1ecc74db9dcfa11a");
git_oid_fromstr(&ours, "b19a1e93bec1317dc6097229e12afaffbfa74dc2"); git_oid_fromstr(&ours, "32504b727382542f9f089e24fddac5e78533e96c");
git_oid_fromstr(&theirs, "950b81b7eee953d050aa05a641f8e056c85dd1bd"); git_oid_fromstr(&theirs, "061d42a44cacde5726057b67558821d95db96f19");
cl_git_rewritefile("status/conflicting_file", "conflicting file\n"); cl_git_rewritefile("status/conflicting_file", "conflicting file\n");
......
...@@ -657,7 +657,7 @@ void test_status_worktree__conflict_has_no_oid(void) ...@@ -657,7 +657,7 @@ void test_status_worktree__conflict_has_no_oid(void)
entry.mode = 0100644; entry.mode = 0100644;
entry.path = "modified_file"; 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_repository_index(&index, repo));
cl_git_pass(git_index_conflict_add(index, &entry, &entry, &entry)); cl_git_pass(git_index_conflict_add(index, &entry, &entry, &entry));
...@@ -1006,6 +1006,9 @@ void test_status_worktree__unreadable(void) ...@@ -1006,6 +1006,9 @@ void test_status_worktree__unreadable(void)
git_status_options opts = GIT_STATUS_OPTIONS_INIT; git_status_options opts = GIT_STATUS_OPTIONS_INIT;
status_entry_counts counts = {0}; status_entry_counts counts = {0};
if (geteuid() == 0)
cl_skip();
/* Create directory with no read permission */ /* Create directory with no read permission */
cl_git_pass(git_futils_mkdir_r("empty_standard_repo/no_permission", 0777)); cl_git_pass(git_futils_mkdir_r("empty_standard_repo/no_permission", 0777));
cl_git_mkfile("empty_standard_repo/no_permission/foo", "dummy"); cl_git_mkfile("empty_standard_repo/no_permission/foo", "dummy");
......
...@@ -40,15 +40,23 @@ void test_transport_register__custom_transport_error_remove_non_existing(void) ...@@ -40,15 +40,23 @@ void test_transport_register__custom_transport_error_remove_non_existing(void)
void test_transport_register__custom_transport_ssh(void) 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; git_transport *transport;
unsigned i;
for (i = 0; i < ARRAY_SIZE(urls); i++) {
#ifndef GIT_SSH #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, urls[i]), -1);
cl_git_fail_with(git_transport_new(&transport, NULL, "git@somehost:somepath"), -1);
#else #else
cl_git_pass(git_transport_new(&transport, NULL, "git@somehost:somepath")); cl_git_pass(git_transport_new(&transport, NULL, urls[i]));
transport->free(transport); transport->free(transport);
#endif #endif
}
cl_git_pass(git_transport_register("ssh", dummy_transport, NULL)); cl_git_pass(git_transport_register("ssh", dummy_transport, NULL));
...@@ -58,11 +66,12 @@ void test_transport_register__custom_transport_ssh(void) ...@@ -58,11 +66,12 @@ void test_transport_register__custom_transport_ssh(void)
cl_git_pass(git_transport_unregister("ssh")); cl_git_pass(git_transport_unregister("ssh"));
for (i = 0; i < ARRAY_SIZE(urls); i++) {
#ifndef GIT_SSH #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, urls[i]), -1);
cl_git_fail_with(git_transport_new(&transport, NULL, "git@somehost:somepath"), -1);
#else #else
cl_git_pass(git_transport_new(&transport, NULL, "git@somehost:somepath")); cl_git_pass(git_transport_new(&transport, NULL, urls[i]));
transport->free(transport); transport->free(transport);
#endif #endif
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment