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)
# /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 @@ ELSE ()
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 (SONAME)
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}")
......
......@@ -99,7 +99,7 @@ do { \
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 @@ parse_url_char(enum state s, const char ch)
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 @@ parse_url_char(enum state s, const char ch)
break;
case s_req_schema:
if (IS_ALPHA(ch)) {
if (IS_ALPHANUM(ch) || ch == '+' || ch == '-' || ch == '.') {
return s;
}
......
......@@ -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 @@ typedef enum {
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 @@ typedef enum {
* > 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
......
......@@ -49,10 +49,24 @@ COVERITY_UNSUPPORTED=1 \
# 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
......@@ -82,4 +82,44 @@ on_oom:
#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
......@@ -178,7 +178,7 @@ const git_blame_hunk *git_blame_get_hunk_byline(git_blame *blame, size_t lineno)
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 @@ static void normalize_options(
/* 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 @@ static void normalize_options(
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 @@ int git_blame_file(
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);
......
......@@ -525,7 +525,8 @@ static int pass_blame(git_blame *blame, git_blame__origin *origin, uint32_t opt)
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)
......
......@@ -676,7 +676,7 @@ int git_commit_extract_signature(git_buf *signature, git_buf *signed_data, git_r
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)
......
......@@ -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];
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;
......
......@@ -553,30 +553,15 @@ static int config_set_multivar(
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 @@ static int config_set_multivar(
result = config_refresh(cfg);
out:
refcounted_strmap_free(map);
git__free(key);
regfree(&preg);
......@@ -1032,6 +1016,11 @@ static int parse_section_header_ext(struct reader *reader, const char *line, con
*/
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 @@ 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_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 @@ static int config_parse(
}
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 @@ 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);
}
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 @@ static int write_on_eof(struct reader **reader, void *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);
}
......
......@@ -582,7 +582,8 @@ static int describe(
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(
......
......@@ -261,7 +261,7 @@ static int normalize_find_opts(
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 @@ static int normalize_find_opts(
#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;
......
......@@ -70,6 +70,7 @@ static int lock_file(git_filebuf *file, int flags, mode_t mode)
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 @@ static int lock_file(git_filebuf *file, int flags, mode_t mode)
}
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 @@ static int lock_file(git_filebuf *file, int flags, mode_t mode)
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;
}
}
......
......@@ -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_inits;
char *git__user_agent;
char *git__ssl_ciphers;
void git__on_shutdown(git_global_shutdown_fn callback)
{
......@@ -83,6 +84,7 @@ static void shutdown_common(void)
}
git__free(git__user_agent);
git__free(git__ssl_ciphers);
#if defined(GIT_MSVC_CRTDBG)
git_win32__crtdbg_stacktrace_cleanup();
......@@ -222,6 +224,20 @@ void git__free_tls_data(void)
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;
......
......@@ -36,5 +36,6 @@ extern void git__on_shutdown(git_global_shutdown_fn callback);
extern void git__free_tls_data(void);
extern const char *git_libgit2__user_agent(void);
extern const char *git_libgit2__ssl_ciphers(void);
#endif
......@@ -263,10 +263,18 @@ int git_ignore__for_path(
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;
......
......@@ -963,14 +963,20 @@ static int index_entry_reuc_init(git_index_reuc_entry **reuc_out,
*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 @@ static int read_tree_cb(
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 &&
......
......@@ -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)
{
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 @@ static int write_at(git_indexer *idx, const void *data, git_off_t offset, size_t
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 @@ static int fix_thin_pack(git_indexer *idx, git_transfer_progress *stats)
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 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats)
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;
}
......
......@@ -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 */
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 @@ static int tree_iterator__update_entry(tree_iterator *ti)
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);
......
......@@ -296,8 +296,18 @@ static git_mwindow *new_window(
*/
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++;
......
......@@ -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 @@ int git_object_lookup_prefix(
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 :
......
......@@ -725,7 +725,8 @@ int git_odb_exists_prefix(
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 @@ int git_odb_exists_prefix(
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 @@ int git_odb_read(git_odb_object **out, git_odb *db, const git_oid *id)
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 @@ int git_odb_read_prefix(
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 @@ int git_odb_refresh(struct git_odb *db)
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);
......
......@@ -82,7 +82,8 @@ int git_odb__hashlink(git_oid *out, const char *path);
/*
* 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.
......
......@@ -547,7 +547,8 @@ static int locate_object_short_oid(
/* 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 @@ static int locate_object_short_oid(
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 @@ static int loose_backend__read_header(size_t *len_p, git_otype *type_p, git_odb_
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 @@ static int loose_backend__read(void **buffer_p, size_t *len_p, git_otype *type_p
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;
......
......@@ -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))
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 @@ static int pack_entry_find_prefix(
}
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 @@ static int pack_backend__refresh(git_odb_backend *backend_)
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);
......
......@@ -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);
}
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
......@@ -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 @@ int git_openssl_stream_global_init(void)
{
#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 @@ int git_openssl_stream_global_init(void)
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);
......
......@@ -848,8 +848,10 @@ static int try_delta(git_packbuilder *pb, struct unpacked *trg,
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);
......
......@@ -494,7 +494,6 @@ int git_packfile_resolve_header(
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 @@ int git_packfile_resolve_header(
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 @@ static int pack_dependency_chain(git_dependency_chain *chain_out,
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 @@ static int packfile_open(struct git_pack_file *p)
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 @@ int git_packfile__name(char **out, const char *path)
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 @@ int git_packfile_alloc(struct git_pack_file **pack_out, const char *path)
*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 @@ 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)) {
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 @@ static int pack_entry_find_offset(
}
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");
......
......@@ -224,6 +224,13 @@ int git__page_size(size_t *page_size)
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)
{
......
......@@ -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 git__page_size(size_t *page_size);
extern int git__mmap_alignment(size_t *page_size);
/**
* Platform-dependent methods
......
......@@ -374,9 +374,9 @@ static int enqueue_object(
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 @@ static int queue_differences(
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 @@ static int queue_differences(
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;
......
......@@ -962,6 +962,7 @@ static int packed_write(refdb_fs_backend *backend)
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;
......
......@@ -289,6 +289,9 @@ cleanup:
"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;
......
......@@ -71,12 +71,18 @@ static int config_level_to_sysdir(int config_level)
}
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 @@ int git_libgit2_opts(int key, ...)
}
}
#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 @@ int git_libgit2_opts(int key, ...)
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;
......
......@@ -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] == '/')
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 @@ static int submodule_update_head(git_submodule *submodule)
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);
......
......@@ -35,6 +35,8 @@ static transport_definition transports[] = {
{ "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 }
};
......
......@@ -721,18 +721,39 @@ static int add_push_report_pkt(git_push *push, git_pkt *pkt)
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 @@ static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt)
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 @@ static int parse_report(transport_smart *transport, git_push *push)
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 @@ static int parse_report(transport_smart *transport, git_push *push)
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 @@ static int parse_report(transport_smart *transport, git_push *push)
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 @@ static int parse_report(transport_smart *transport, git_push *push)
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)
......
......@@ -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 @@ static int gen_proto(git_buf *request, const char *cmd, const char *url)
{
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 @@ static int _git_ssh_setup_conn(
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 @@ static int _git_ssh_setup_conn(
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;
......
......@@ -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 {
......
......@@ -24,6 +24,11 @@ int git__page_size(size_t *page_size)
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;
......
......@@ -17,22 +17,41 @@ static DWORD get_page_size(void)
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 @@ int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offs
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;
}
......
......@@ -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->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;
......
......@@ -252,3 +252,16 @@ void test_attr_ignore__dont_ignore_files_for_folder(void)
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");
}
......@@ -498,6 +498,21 @@ committer Ben Burkert <ben@benburkert.com> 1358451456 -0800\n\
\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 @@ 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_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);
......
......@@ -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_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);
......
......@@ -695,3 +695,30 @@ void test_config_write__locking(void)
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)
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);
......
......@@ -268,7 +268,7 @@ static void check_tree_entry(
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));
......
......@@ -105,8 +105,8 @@ static void setup_race(void)
{
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 @@ static void setup_race(void)
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);
}
......
......@@ -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));
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 @@ void test_object_tree_attributes__normalize_attributes_when_creating_a_tree_from
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));
......
......@@ -36,3 +36,11 @@ void test_online_badssl__self_signed(void)
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));
}
......@@ -19,7 +19,7 @@ void test_refs_create__cleanup(void)
{
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 @@ void test_refs_create__oid(void)
}
/* 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 @@ void test_refs_create__oid_unknown_succeeds_by_default(void)
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 @@ void test_refs_create__oid_unknown_succeeds_by_default(void)
}
/* 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 @@ void test_refs_create__oid_unknown_fails_strict_mode(void)
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));
......
......@@ -58,3 +58,11 @@ void test_refs_lookup__namespace(void)
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);
}
......@@ -1020,6 +1020,11 @@ void test_repo_iterator__unreadable_dir(void)
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));
......
......@@ -122,9 +122,9 @@ static void unmerged_index_init(git_index *index, int entries)
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");
......
......@@ -657,7 +657,7 @@ void test_status_worktree__conflict_has_no_oid(void)
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 @@ void test_status_worktree__unreadable(void)
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");
......
......@@ -40,15 +40,23 @@ void test_transport_register__custom_transport_error_remove_non_existing(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;
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 @@ void test_transport_register__custom_transport_ssh(void)
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
}
}
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