Merge branch 'master' into nsec_fix_next

This commit is contained in:
Axel Rasmussen 2015-10-01 18:01:32 -07:00
commit c7b17fb5cd
57 changed files with 460 additions and 84 deletions

View File

@ -19,6 +19,7 @@ CMAKE_POLICY(SET CMP0015 NEW)
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/")
INCLUDE(CheckLibraryExists)
INCLUDE(CheckFunctionExists)
INCLUDE(CheckStructHasMember)
INCLUDE(AddCFlagIfSupported)
INCLUDE(FindPkgConfig)
@ -476,6 +477,21 @@ ELSE ()
ENDIF ()
ENDIF()
CHECK_FUNCTION_EXISTS(futimens HAVE_FUTIMENS)
IF (HAVE_FUTIMENS)
ADD_DEFINITIONS(-DHAVE_FUTIMENS)
ENDIF ()
CHECK_FUNCTION_EXISTS(qsort_r HAVE_QSORT_R)
IF (HAVE_QSORT_R)
ADD_DEFINITIONS(-DHAVE_QSORT_R)
ENDIF ()
CHECK_FUNCTION_EXISTS(qsort_s HAVE_QSORT_S)
IF (HAVE_QSORT_S)
ADD_DEFINITIONS(-DHAVE_QSORT_S)
ENDIF ()
IF( NOT CMAKE_CONFIGURATION_TYPES )
# Build Debug by default
IF (NOT CMAKE_BUILD_TYPE)

View File

@ -26,7 +26,7 @@ static int use_remote(git_repository *repo, char *name)
*/
callbacks.credentials = cred_acquire_cb;
error = git_remote_connect(remote, GIT_DIRECTION_FETCH, &callbacks);
error = git_remote_connect(remote, GIT_DIRECTION_FETCH, &callbacks, NULL);
if (error < 0)
goto cleanup;

View File

@ -241,9 +241,10 @@ GIT_EXTERN(const git_refspec *)git_remote_get_refspec(const git_remote *remote,
* @param direction GIT_DIRECTION_FETCH if you want to fetch or
* GIT_DIRECTION_PUSH if you want to push
* @param callbacks the callbacks to use for this connection
* @param custom_headers extra HTTP headers to use in this connection
* @return 0 or an error code
*/
GIT_EXTERN(int) git_remote_connect(git_remote *remote, git_direction direction, const git_remote_callbacks *callbacks);
GIT_EXTERN(int) git_remote_connect(git_remote *remote, git_direction direction, const git_remote_callbacks *callbacks, const git_strarray *custom_headers);
/**
* Get the remote repository's reference advertisement list
@ -546,6 +547,11 @@ typedef struct {
* The default is to auto-follow tags.
*/
git_remote_autotag_option_t download_tags;
/**
* Extra headers for this fetch operation
*/
git_strarray custom_headers;
} git_fetch_options;
#define GIT_FETCH_OPTIONS_VERSION 1
@ -585,6 +591,11 @@ typedef struct {
* Callbacks to use for this push operation
*/
git_remote_callbacks callbacks;
/**
* Extra headers for this push operation
*/
git_strarray custom_headers;
} git_push_options;
#define GIT_PUSH_OPTIONS_VERSION 1

View File

@ -83,6 +83,10 @@ struct git_odb_backend {
git_odb_writepack **, git_odb_backend *, git_odb *odb,
git_transfer_progress_cb progress_cb, void *progress_payload);
/**
* Frees any resources held by the odb (including the `git_odb_backend`
* itself). An odb backend implementation must provide this function.
*/
void (* free)(git_odb_backend *);
};

View File

@ -130,8 +130,8 @@ struct git_refdb_backend {
int (*ensure_log)(git_refdb_backend *backend, const char *refname);
/**
* Frees any resources held by the refdb. A refdb implementation may
* provide this function; if it is not provided, nothing will be done.
* Frees any resources held by the refdb (including the `git_refdb_backend`
* itself). A refdb backend implementation must provide this function.
*/
void (*free)(git_refdb_backend *backend);

View File

@ -40,6 +40,11 @@ struct git_transport {
git_transport_certificate_check_cb certificate_check_cb,
void *payload);
/* Set custom headers for HTTP requests */
int (*set_custom_headers)(
git_transport *transport,
const git_strarray *custom_headers);
/* Connect the transport to the remote repository, using the given
* direction. */
int (*connect)(

View File

@ -358,6 +358,7 @@ static int format_binary(
scan += chunk_len;
pi->line.num_lines++;
}
git_buf_putc(pi->buf, '\n');
return 0;
}
@ -416,7 +417,6 @@ static int diff_print_patch_file_binary(
if ((error = format_binary(pi, binary->new_file.type, binary->new_file.data,
binary->new_file.datalen, binary->new_file.inflatedlen)) < 0 ||
(error = git_buf_putc(pi->buf, '\n')) < 0 ||
(error = format_binary(pi, binary->old_file.type, binary->old_file.data,
binary->old_file.datalen, binary->old_file.inflatedlen)) < 0) {

View File

@ -600,8 +600,7 @@ static void odb_free(git_odb *db)
backend_internal *internal = git_vector_get(&db->backends, i);
git_odb_backend *backend = internal->backend;
if (backend->free) backend->free(backend);
else git__free(backend);
backend->free(backend);
git__free(internal);
}

View File

@ -302,6 +302,7 @@ cert_fail_name:
typedef struct {
git_stream parent;
git_stream *io;
bool connected;
char *host;
SSL *ssl;
git_cert_x509 cert_info;
@ -318,6 +319,8 @@ int openssl_connect(git_stream *stream)
if ((ret = git_stream_connect(st->io)) < 0)
return ret;
st->connected = true;
bio = BIO_new(&git_stream_bio_method);
GITERR_CHECK_ALLOC(bio);
bio->ptr = st->io;
@ -406,9 +409,11 @@ int openssl_close(git_stream *stream)
openssl_stream *st = (openssl_stream *) stream;
int ret;
if ((ret = ssl_teardown(st->ssl)) < 0)
if (st->connected && (ret = ssl_teardown(st->ssl)) < 0)
return -1;
st->connected = false;
return git_stream_close(st->io);
}

View File

@ -73,6 +73,7 @@ int git_push_set_options(git_push *push, const git_push_options *opts)
GITERR_CHECK_VERSION(opts, GIT_PUSH_OPTIONS_VERSION, "git_push_options");
push->pb_parallelism = opts->pb_parallelism;
push->custom_headers = &opts->custom_headers;
return 0;
}
@ -638,7 +639,7 @@ int git_push_finish(git_push *push, const git_remote_callbacks *callbacks)
int error;
if (!git_remote_connected(push->remote) &&
(error = git_remote_connect(push->remote, GIT_DIRECTION_PUSH, callbacks)) < 0)
(error = git_remote_connect(push->remote, GIT_DIRECTION_PUSH, callbacks, push->custom_headers)) < 0)
return error;
if ((error = filter_refs(push->remote)) < 0 ||

View File

@ -38,6 +38,7 @@ struct git_push {
/* options */
unsigned pb_parallelism;
const git_strarray *custom_headers;
};
/**

View File

@ -61,12 +61,8 @@ int git_refdb_open(git_refdb **out, git_repository *repo)
static void refdb_free_backend(git_refdb *db)
{
if (db->backend) {
if (db->backend->free)
db->backend->free(db->backend);
else
git__free(db->backend);
}
if (db->backend)
db->backend->free(db->backend);
}
int git_refdb_set_backend(git_refdb *db, git_refdb_backend *backend)

View File

@ -687,7 +687,15 @@ int set_transport_callbacks(git_transport *t, const git_remote_callbacks *cbs)
cbs->certificate_check, cbs->payload);
}
int git_remote_connect(git_remote *remote, git_direction direction, const git_remote_callbacks *callbacks)
static int set_transport_custom_headers(git_transport *t, const git_strarray *custom_headers)
{
if (!t->set_custom_headers)
return 0;
return t->set_custom_headers(t, custom_headers);
}
int git_remote_connect(git_remote *remote, git_direction direction, const git_remote_callbacks *callbacks, const git_strarray *custom_headers)
{
git_transport *t;
const char *url;
@ -726,6 +734,9 @@ int git_remote_connect(git_remote *remote, git_direction direction, const git_re
if (!t && (error = git_transport_new(&t, remote, url)) < 0)
return error;
if ((error = set_transport_custom_headers(t, custom_headers)) != 0)
goto on_error;
if ((error = set_transport_callbacks(t, callbacks)) < 0 ||
(error = t->connect(t, url, credentials, payload, direction, flags)) != 0)
goto on_error;
@ -884,16 +895,18 @@ int git_remote_download(git_remote *remote, const git_strarray *refspecs, const
size_t i;
git_vector *to_active, specs = GIT_VECTOR_INIT, refs = GIT_VECTOR_INIT;
const git_remote_callbacks *cbs = NULL;
const git_strarray *custom_headers = NULL;
assert(remote);
if (opts) {
GITERR_CHECK_VERSION(&opts->callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
cbs = &opts->callbacks;
custom_headers = &opts->custom_headers;
}
if (!git_remote_connected(remote) &&
(error = git_remote_connect(remote, GIT_DIRECTION_FETCH, cbs)) < 0)
(error = git_remote_connect(remote, GIT_DIRECTION_FETCH, cbs, custom_headers)) < 0)
goto on_error;
if (ls_to_vector(&refs, remote) < 0)
@ -957,16 +970,18 @@ int git_remote_fetch(
bool prune = false;
git_buf reflog_msg_buf = GIT_BUF_INIT;
const git_remote_callbacks *cbs = NULL;
const git_strarray *custom_headers = NULL;
if (opts) {
GITERR_CHECK_VERSION(&opts->callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
cbs = &opts->callbacks;
custom_headers = &opts->custom_headers;
update_fetchhead = opts->update_fetchhead;
tagopt = opts->download_tags;
}
/* Connect and download everything */
if ((error = git_remote_connect(remote, GIT_DIRECTION_FETCH, cbs)) != 0)
if ((error = git_remote_connect(remote, GIT_DIRECTION_FETCH, cbs, custom_headers)) != 0)
return error;
error = git_remote_download(remote, refspecs, opts);
@ -2377,14 +2392,17 @@ int git_remote_upload(git_remote *remote, const git_strarray *refspecs, const gi
git_push *push;
git_refspec *spec;
const git_remote_callbacks *cbs = NULL;
const git_strarray *custom_headers = NULL;
assert(remote);
if (opts)
if (opts) {
cbs = &opts->callbacks;
custom_headers = &opts->custom_headers;
}
if (!git_remote_connected(remote) &&
(error = git_remote_connect(remote, GIT_DIRECTION_PUSH, cbs)) < 0)
(error = git_remote_connect(remote, GIT_DIRECTION_PUSH, cbs, custom_headers)) < 0)
goto cleanup;
free_refspecs(&remote->active_refspecs);
@ -2433,15 +2451,17 @@ int git_remote_push(git_remote *remote, const git_strarray *refspecs, const git_
{
int error;
const git_remote_callbacks *cbs = NULL;
const git_strarray *custom_headers = NULL;
if (opts) {
GITERR_CHECK_VERSION(&opts->callbacks, GIT_REMOTE_CALLBACKS_VERSION, "git_remote_callbacks");
cbs = &opts->callbacks;
custom_headers = &opts->custom_headers;
}
assert(remote && refspecs);
if ((error = git_remote_connect(remote, GIT_DIRECTION_PUSH, cbs)) < 0)
if ((error = git_remote_connect(remote, GIT_DIRECTION_PUSH, cbs, custom_headers)) < 0)
return error;
if ((error = git_remote_upload(remote, refspecs, opts)) < 0)

View File

@ -908,12 +908,28 @@ bool git_repository__reserved_names(
buf->size = git_repository__reserved_names_win32[i].size;
}
/* Try to add any repo-specific reserved names */
/* Try to add any repo-specific reserved names - the gitlink file
* within a submodule or the repository (if the repository directory
* is beneath the workdir). These are typically `.git`, but should
* be protected in case they are not. Note, repo and workdir paths
* are always prettified to end in `/`, so a prefixcmp is safe.
*/
if (!repo->is_bare) {
const char *reserved_path = repo->path_gitlink ?
repo->path_gitlink : repo->path_repository;
int (*prefixcmp)(const char *, const char *);
int error, ignorecase;
if (reserved_names_add8dot3(repo, reserved_path) < 0)
error = git_repository__cvar(
&ignorecase, repo, GIT_CVAR_IGNORECASE);
prefixcmp = (error || ignorecase) ? git__prefixcmp_icase :
git__prefixcmp;
if (repo->path_gitlink &&
reserved_names_add8dot3(repo, repo->path_gitlink) < 0)
goto on_error;
if (repo->path_repository &&
prefixcmp(repo->path_repository, repo->workdir) == 0 &&
reserved_names_add8dot3(repo, repo->path_repository) < 0)
goto on_error;
}
}

View File

@ -170,7 +170,7 @@ static int name_from_path(git_buf *out, git_config *cfg, const char *path)
git_buf_clear(out);
git_buf_put(out, fdot + 1, ldot - fdot - 1);
return 0;
goto cleanup;
}
if (error == GIT_ITEROVER) {
@ -178,6 +178,8 @@ static int name_from_path(git_buf *out, git_config *cfg, const char *path)
error = GIT_ENOTFOUND;
}
cleanup:
git_config_iterator_free(iter);
return error;
}
@ -227,6 +229,7 @@ int git_submodule_lookup(
if (error < 0) {
git_submodule_free(sm);
git_buf_free(&path);
return error;
}
@ -1697,11 +1700,13 @@ static int submodule_read_config(git_submodule *sm, git_config *cfg)
* should be strcasecmp
*/
if (strcmp(sm->name, value) != 0) {
if (sm->path != sm->name)
git__free(sm->path);
sm->path = git__strdup(value);
GITERR_CHECK_ALLOC(sm->path);
}
} else if (error != GIT_ENOTFOUND) {
return error;
goto cleanup;
}
if ((error = get_value(&value, cfg, &key, sm->name, "url")) == 0) {
@ -1709,7 +1714,7 @@ static int submodule_read_config(git_submodule *sm, git_config *cfg)
sm->url = git__strdup(value);
GITERR_CHECK_ALLOC(sm->url);
} else if (error != GIT_ENOTFOUND) {
return error;
goto cleanup;
}
if ((error = get_value(&value, cfg, &key, sm->name, "branch")) == 0) {
@ -1717,40 +1722,44 @@ static int submodule_read_config(git_submodule *sm, git_config *cfg)
sm->branch = git__strdup(value);
GITERR_CHECK_ALLOC(sm->branch);
} else if (error != GIT_ENOTFOUND) {
return error;
goto cleanup;
}
if ((error = get_value(&value, cfg, &key, sm->name, "update")) == 0) {
in_config = 1;
if ((error = git_submodule_parse_update(&sm->update, value)) < 0)
return error;
goto cleanup;
sm->update_default = sm->update;
} else if (error != GIT_ENOTFOUND) {
return error;
goto cleanup;
}
if ((error = get_value(&value, cfg, &key, sm->name, "fetchRecurseSubmodules")) == 0) {
in_config = 1;
if ((error = git_submodule_parse_recurse(&sm->fetch_recurse, value)) < 0)
return error;
goto cleanup;
sm->fetch_recurse_default = sm->fetch_recurse;
} else if (error != GIT_ENOTFOUND) {
return error;
goto cleanup;
}
if ((error = get_value(&value, cfg, &key, sm->name, "ignore")) == 0) {
in_config = 1;
if ((error = git_submodule_parse_ignore(&sm->ignore, value)) < 0)
return error;
goto cleanup;
sm->ignore_default = sm->ignore;
} else if (error != GIT_ENOTFOUND) {
return error;
goto cleanup;
}
if (in_config)
sm->flags |= GIT_SUBMODULE_STATUS_IN_CONFIG;
return 0;
error = 0;
cleanup:
git_buf_free(&key);
return error;
}
static int submodule_load_each(const git_config_entry *entry, void *payload)
@ -1784,8 +1793,10 @@ static int submodule_load_each(const git_config_entry *entry, void *payload)
* already inserted, we've already loaded it, so we skip.
*/
pos = git_strmap_lookup_index(map, name.ptr);
if (git_strmap_valid_index(map, pos))
return 0;
if (git_strmap_valid_index(map, pos)) {
error = 0;
goto done;
}
if ((error = submodule_alloc(&sm, data->repo, name.ptr)) < 0)
goto done;

View File

@ -193,6 +193,7 @@ static int gen_request(
{
http_subtransport *t = OWNING_SUBTRANSPORT(s);
const char *path = t->connection_data.path ? t->connection_data.path : "/";
size_t i;
git_buf_printf(buf, "%s %s%s HTTP/1.1\r\n", s->verb, path, s->service_url);
@ -210,6 +211,11 @@ static int gen_request(
} else
git_buf_puts(buf, "Accept: */*\r\n");
for (i = 0; i < t->owner->custom_headers.count; i++) {
if (t->owner->custom_headers.strings[i])
git_buf_printf(buf, "%s\r\n", t->owner->custom_headers.strings[i]);
}
/* Apply credentials to the request */
if (apply_credentials(buf, t) < 0)
return -1;

View File

@ -66,6 +66,84 @@ static int git_smart__set_callbacks(
return 0;
}
static int http_header_name_length(const char *http_header)
{
const char *colon = strchr(http_header, ':');
if (!colon)
return 0;
return colon - http_header;
}
static bool is_malformed_http_header(const char *http_header)
{
const char *c;
int name_len;
// Disallow \r and \n
c = strchr(http_header, '\r');
if (c)
return true;
c = strchr(http_header, '\n');
if (c)
return true;
// Require a header name followed by :
name_len = http_header_name_length(http_header);
if (name_len < 1)
return true;
return false;
}
static char *forbidden_custom_headers[] = {
"User-Agent",
"Host",
"Accept",
"Content-Type",
"Transfer-Encoding",
"Content-Length",
};
static bool is_forbidden_custom_header(const char *custom_header)
{
unsigned long i;
int name_len = http_header_name_length(custom_header);
// Disallow headers that we set
for (i = 0; i < ARRAY_SIZE(forbidden_custom_headers); i++)
if (strncmp(forbidden_custom_headers[i], custom_header, name_len) == 0)
return true;
return false;
}
static int git_smart__set_custom_headers(
git_transport *transport,
const git_strarray *custom_headers)
{
transport_smart *t = (transport_smart *)transport;
size_t i;
if (t->custom_headers.count)
git_strarray_free(&t->custom_headers);
if (!custom_headers)
return 0;
for (i = 0; i < custom_headers->count; i++) {
if (is_malformed_http_header(custom_headers->strings[i])) {
giterr_set(GITERR_INVALID, "custom HTTP header '%s' is malformed", custom_headers->strings[i]);
return -1;
}
if (is_forbidden_custom_header(custom_headers->strings[i])) {
giterr_set(GITERR_INVALID, "custom HTTP header '%s' is already set by libgit2", custom_headers->strings[i]);
return -1;
}
}
return git_strarray_copy(&t->custom_headers, custom_headers);
}
int git_smart__update_heads(transport_smart *t, git_vector *symrefs)
{
size_t i;
@ -362,6 +440,8 @@ static void git_smart__free(git_transport *transport)
git_vector_free(refs);
git_strarray_free(&t->custom_headers);
git__free(t);
}
@ -399,6 +479,7 @@ int git_transport_smart(git_transport **out, git_remote *owner, void *param)
t->parent.version = GIT_TRANSPORT_VERSION;
t->parent.set_callbacks = git_smart__set_callbacks;
t->parent.set_custom_headers = git_smart__set_custom_headers;
t->parent.connect = git_smart__connect;
t->parent.close = git_smart__close;
t->parent.free = git_smart__free;

View File

@ -139,6 +139,7 @@ typedef struct {
git_transport_message_cb error_cb;
git_transport_certificate_check_cb certificate_check_cb;
void *message_cb_payload;
git_strarray custom_headers;
git_smart_subtransport *wrapped;
git_smart_subtransport_stream *current_stream;
transport_smart_caps caps;

View File

@ -277,6 +277,7 @@ static int winhttp_stream_connect(winhttp_stream *s)
unsigned long disable_redirects = WINHTTP_DISABLE_REDIRECTS;
int default_timeout = TIMEOUT_INFINITE;
int default_connect_timeout = DEFAULT_CONNECT_TIMEOUT;
int i;
/* Prepare URL */
git_buf_printf(&buf, "%s%s", t->connection_data.path, s->service_url);
@ -409,6 +410,23 @@ static int winhttp_stream_connect(winhttp_stream *s)
}
}
for (i = 0; i < t->owner->custom_headers.count; i++) {
if (t->owner->custom_headers.strings[i]) {
git_buf_clear(&buf);
git_buf_puts(&buf, t->owner->custom_headers.strings[i]);
if (git__utf8_to_16(ct, MAX_CONTENT_TYPE_LEN, git_buf_cstr(&buf)) < 0) {
giterr_set(GITERR_OS, "Failed to convert custom header to wide characters");
goto on_error;
}
if (!WinHttpAddRequestHeaders(s->request, ct, (ULONG)-1L,
WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE)) {
giterr_set(GITERR_OS, "Failed to add a header to the request");
goto on_error;
}
}
}
/* If requested, disable certificate validation */
if (t->connection_data.use_ssl) {
int flags;

View File

@ -22,7 +22,6 @@ typedef int GIT_SOCKET;
#define p_stat(p,b) stat(p, b)
#define p_utimes(f, t) utimes(f, t)
#define p_futimes(f, t) futimes(f, t)
#define p_readlink(a, b, c) readlink(a, b, c)
#define p_symlink(o,n) symlink(o, n)
@ -53,4 +52,18 @@ extern char *p_realpath(const char *, char *);
#define p_localtime_r(c, r) localtime_r(c, r)
#define p_gmtime_r(c, r) gmtime_r(c, r)
#ifdef HAVE_FUTIMENS
GIT_INLINE(int) p_futimes(int f, const struct timeval t[2])
{
struct timespec s[2];
s[0].tv_sec = t[0].tv_sec;
s[0].tv_nsec = t[0].tv_usec * 1000;
s[1].tv_sec = t[1].tv_sec;
s[1].tv_nsec = t[1].tv_usec * 1000;
return futimens(f, s);
}
#else
# define p_futimes futimes
#endif
#endif

View File

@ -611,7 +611,7 @@ size_t git__unescape(char *str)
return (pos - str);
}
#if defined(GIT_WIN32) || defined(BSD)
#if defined(HAVE_QSORT_S) || (defined(HAVE_QSORT_R) && defined(BSD))
typedef struct {
git__sort_r_cmp cmp;
void *payload;
@ -628,21 +628,16 @@ static int GIT_STDLIB_CALL git__qsort_r_glue_cmp(
void git__qsort_r(
void *els, size_t nel, size_t elsize, git__sort_r_cmp cmp, void *payload)
{
#if defined(__MINGW32__) || defined(AMIGA) || \
defined(__OpenBSD__) || defined(__NetBSD__) || \
defined(__gnu_hurd__) || defined(__ANDROID_API__) || \
defined(__sun) || defined(__CYGWIN__) || \
(__GLIBC__ == 2 && __GLIBC_MINOR__ < 8) || \
(defined(_MSC_VER) && _MSC_VER < 1500)
git__insertsort_r(els, nel, elsize, NULL, cmp, payload);
#elif defined(GIT_WIN32)
git__qsort_r_glue glue = { cmp, payload };
qsort_s(els, nel, elsize, git__qsort_r_glue_cmp, &glue);
#elif defined(BSD)
#if defined(HAVE_QSORT_R) && defined(BSD)
git__qsort_r_glue glue = { cmp, payload };
qsort_r(els, nel, elsize, &glue, git__qsort_r_glue_cmp);
#else
#elif defined(HAVE_QSORT_R) && defined(__GLIBC__)
qsort_r(els, nel, elsize, cmp, payload);
#elif defined(HAVE_QSORT_S)
git__qsort_r_glue glue = { cmp, payload };
qsort_s(els, nel, elsize, git__qsort_r_glue_cmp, &glue);
#else
git__insertsort_r(els, nel, elsize, NULL, cmp, payload);
#endif
}

View File

@ -198,13 +198,13 @@ int git_win32_path_from_utf8(git_win32_path out, const char *src)
/* See if this is an absolute path (beginning with a drive letter) */
if (path__is_absolute(src)) {
if (git__utf8_to_16(dest, MAX_PATH, src) < 0)
return -1;
goto on_error;
}
/* File-prefixed NT-style paths beginning with \\?\ */
else if (path__is_nt_namespace(src)) {
/* Skip the NT prefix, the destination already contains it */
if (git__utf8_to_16(dest, MAX_PATH, src + PATH__NT_NAMESPACE_LEN) < 0)
return -1;
goto on_error;
}
/* UNC paths */
else if (path__is_unc(src)) {
@ -213,36 +213,43 @@ int git_win32_path_from_utf8(git_win32_path out, const char *src)
/* Skip the leading "\\" */
if (git__utf8_to_16(dest, MAX_PATH - 2, src + 2) < 0)
return -1;
goto on_error;
}
/* Absolute paths omitting the drive letter */
else if (src[0] == '\\' || src[0] == '/') {
if (path__cwd(dest, MAX_PATH) < 0)
return -1;
goto on_error;
if (!path__is_absolute(dest)) {
errno = ENOENT;
return -1;
goto on_error;
}
/* Skip the drive letter specification ("C:") */
if (git__utf8_to_16(dest + 2, MAX_PATH - 2, src) < 0)
return -1;
goto on_error;
}
/* Relative paths */
else {
int cwd_len;
if ((cwd_len = git_win32_path__cwd(dest, MAX_PATH)) < 0)
return -1;
goto on_error;
dest[cwd_len++] = L'\\';
if (git__utf8_to_16(dest + cwd_len, MAX_PATH - cwd_len, src) < 0)
return -1;
goto on_error;
}
return git_win32_path_canonicalize(out);
on_error:
/* set windows error code so we can use its error message */
if (errno == ENAMETOOLONG)
SetLastError(ERROR_FILENAME_EXCED_RANGE);
return -1;
}
int git_win32_path_to_utf8(git_win32_utf8_path dest, const wchar_t *src)

View File

@ -48,6 +48,8 @@ void test_core_mkdir__absolute(void)
cl_assert(!git_path_isdir(path.ptr));
cl_git_fail(git_futils_mkdir(path.ptr, 0755, 0));
cl_assert(!git_path_isdir(path.ptr));
git_buf_free(&path);
}
void test_core_mkdir__basic(void)

View File

@ -96,7 +96,8 @@ void test_diff_binary__add(void)
"Kc${Nk-~s>u4FC%O\n"
"\n" \
"literal 0\n" \
"Hc$@<O00001\n";
"Hc$@<O00001\n" \
"\n";
opts.flags = GIT_DIFF_SHOW_BINARY;
opts.id_abbrev = GIT_OID_HEXSZ;
@ -136,7 +137,8 @@ void test_diff_binary__modify(void)
"Mc${NkU}WL~000&M4gdfE\n" \
"\n" \
"literal 3\n" \
"Kc${Nk-~s>u4FC%O\n";
"Kc${Nk-~s>u4FC%O\n" \
"\n";
opts.flags = GIT_DIFF_SHOW_BINARY;
@ -177,7 +179,8 @@ void test_diff_binary__delete(void)
"Hc$@<O00001\n" \
"\n" \
"literal 3\n" \
"Kc${Nk-~s>u4FC%O\n";
"Kc${Nk-~s>u4FC%O\n" \
"\n";
opts.flags = GIT_DIFF_SHOW_BINARY;
opts.id_abbrev = GIT_OID_HEXSZ;
@ -208,7 +211,8 @@ void test_diff_binary__delta(void)
"delta 198\n" \
"zc$}LmI8{(0BqLQJI6p64AwNwaIJGP_Pr*5}Br~;mqJ$<Jl;sX*mF<MGCYv&*L7AHu\n" \
"zGA1*^gt?gYVN82wTbPO_W)+x<&1+cP;HrPHR>PQ;Y(X&QMK*C5^Br3bjG4d=XI^5@\n" \
"JfH567LIF3FM2!Fd\n";
"JfH567LIF3FM2!Fd\n" \
"\n";
opts.flags = GIT_DIFF_SHOW_BINARY | GIT_DIFF_FORCE_BINARY;
opts.id_abbrev = GIT_OID_HEXSZ;
@ -249,7 +253,8 @@ void test_diff_binary__delta_append(void)
"nc%1vf+QYWt3zLL@hC)e3Vu?a>QDRl4f_G*?PG(-ZA}<#J$+QbW\n" \
"\n" \
"delta 7\n" \
"Oc%18D`@*{63ljhg(E~C7\n";
"Oc%18D`@*{63ljhg(E~C7\n" \
"\n";
opts.flags = GIT_DIFF_SHOW_BINARY | GIT_DIFF_FORCE_BINARY;
opts.id_abbrev = GIT_OID_HEXSZ;
@ -314,7 +319,8 @@ void test_diff_binary__index_to_workdir(void)
"nc%1vf+QYWt3zLL@hC)e3Vu?a>QDRl4f_G*?PG(-ZA}<#J$+QbW\n" \
"\n" \
"delta 7\n" \
"Oc%18D`@*{63ljhg(E~C7\n";
"Oc%18D`@*{63ljhg(E~C7\n" \
"\n";
opts.flags = GIT_DIFF_SHOW_BINARY | GIT_DIFF_FORCE_BINARY;
opts.id_abbrev = GIT_OID_HEXSZ;
@ -379,7 +385,8 @@ void test_diff_binary__print_patch_from_diff(void)
"nc%1vf+QYWt3zLL@hC)e3Vu?a>QDRl4f_G*?PG(-ZA}<#J$+QbW\n" \
"\n" \
"delta 7\n" \
"Oc%18D`@*{63ljhg(E~C7\n";
"Oc%18D`@*{63ljhg(E~C7\n" \
"\n";
opts.flags = GIT_DIFF_SHOW_BINARY | GIT_DIFF_FORCE_BINARY;
opts.id_abbrev = GIT_OID_HEXSZ;

View File

@ -77,5 +77,10 @@ void test_index_rename__casechanging(void)
cl_assert_equal_i(1, git_index_entrycount(index));
else
cl_assert_equal_i(2, git_index_entrycount(index));
git_index_free(index);
git_repository_free(repo);
cl_fixture_cleanup("rename");
}

View File

@ -26,7 +26,7 @@ static void assert_default_branch(const char *should)
{
git_buf name = GIT_BUF_INIT;
cl_git_pass(git_remote_connect(g_remote, GIT_DIRECTION_FETCH, NULL));
cl_git_pass(git_remote_connect(g_remote, GIT_DIRECTION_FETCH, NULL, NULL));
cl_git_pass(git_remote_default_branch(&name, g_remote));
cl_assert_equal_s(should, name.ptr);
git_buf_free(&name);
@ -57,7 +57,7 @@ void test_network_remote_defaultbranch__no_default_branch(void)
git_buf buf = GIT_BUF_INIT;
cl_git_pass(git_remote_create(&remote_b, g_repo_b, "self", git_repository_path(g_repo_b)));
cl_git_pass(git_remote_connect(remote_b, GIT_DIRECTION_FETCH, NULL));
cl_git_pass(git_remote_connect(remote_b, GIT_DIRECTION_FETCH, NULL, NULL));
cl_git_pass(git_remote_ls(&heads, &len, remote_b));
cl_assert_equal_i(0, len);
@ -80,7 +80,7 @@ void test_network_remote_defaultbranch__detached_sharing_nonbranch_id(void)
cl_git_pass(git_reference_create(&ref, g_repo_a, "refs/foo/bar", &id, 1, NULL));
git_reference_free(ref);
cl_git_pass(git_remote_connect(g_remote, GIT_DIRECTION_FETCH, NULL));
cl_git_pass(git_remote_connect(g_remote, GIT_DIRECTION_FETCH, NULL, NULL));
cl_git_fail_with(GIT_ENOTFOUND, git_remote_default_branch(&buf, g_remote));
cl_git_pass(git_clone(&cloned_repo, git_repository_path(g_repo_a), "./local-detached", NULL));

View File

@ -40,7 +40,7 @@ static void connect_to_local_repository(const char *local_repository)
git_buf_sets(&file_path_buf, cl_git_path_url(local_repository));
cl_git_pass(git_remote_create_anonymous(&remote, repo, git_buf_cstr(&file_path_buf)));
cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL));
cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL, NULL));
}
void test_network_remote_local__connected(void)
@ -214,7 +214,7 @@ void test_network_remote_local__push_to_bare_remote(void)
/* Connect to the bare repo */
cl_git_pass(git_remote_create_anonymous(&localremote, repo, "./localbare.git"));
cl_git_pass(git_remote_connect(localremote, GIT_DIRECTION_PUSH, NULL));
cl_git_pass(git_remote_connect(localremote, GIT_DIRECTION_PUSH, NULL, NULL));
/* Try to push */
cl_git_pass(git_remote_upload(localremote, &push_array, NULL));
@ -253,7 +253,7 @@ void test_network_remote_local__push_to_bare_remote_with_file_url(void)
/* Connect to the bare repo */
cl_git_pass(git_remote_create_anonymous(&localremote, repo, url));
cl_git_pass(git_remote_connect(localremote, GIT_DIRECTION_PUSH, NULL));
cl_git_pass(git_remote_connect(localremote, GIT_DIRECTION_PUSH, NULL, NULL));
/* Try to push */
cl_git_pass(git_remote_upload(localremote, &push_array, NULL));
@ -290,7 +290,7 @@ void test_network_remote_local__push_to_non_bare_remote(void)
/* Connect to the bare repo */
cl_git_pass(git_remote_create_anonymous(&localremote, repo, "./localnonbare"));
cl_git_pass(git_remote_connect(localremote, GIT_DIRECTION_PUSH, NULL));
cl_git_pass(git_remote_connect(localremote, GIT_DIRECTION_PUSH, NULL, NULL));
/* Try to push */
cl_git_fail_with(GIT_EBAREREPO, git_remote_upload(localremote, &push_array, NULL));

View File

@ -93,7 +93,7 @@ void test_network_remote_remotes__error_when_no_push_available(void)
cl_git_pass(git_remote_create_anonymous(&r, _repo, cl_fixture("testrepo.git")));
callbacks.transport = git_transport_local;
cl_git_pass(git_remote_connect(r, GIT_DIRECTION_PUSH, &callbacks));
cl_git_pass(git_remote_connect(r, GIT_DIRECTION_PUSH, &callbacks, NULL));
/* Make sure that push is really not available */
r->transport->push = NULL;
@ -359,7 +359,7 @@ void test_network_remote_remotes__can_load_with_an_empty_url(void)
cl_assert(remote->url == NULL);
cl_assert(remote->pushurl == NULL);
cl_git_fail(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL));
cl_git_fail(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL, NULL));
cl_assert(giterr_last() != NULL);
cl_assert(giterr_last()->klass == GITERR_INVALID);
@ -376,7 +376,7 @@ void test_network_remote_remotes__can_load_with_only_an_empty_pushurl(void)
cl_assert(remote->url == NULL);
cl_assert(remote->pushurl == NULL);
cl_git_fail(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL));
cl_git_fail(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL, NULL));
git_remote_free(remote);
}

View File

@ -14,6 +14,7 @@ static git_odb_backend *new_backend(size_t position)
if (b == NULL)
return NULL;
b->base.free = (void (*)(git_odb_backend *)) git__free;
b->base.version = GIT_ODB_BACKEND_VERSION;
b->position = position;
return (git_odb_backend *)b;

27
tests/online/badssl.c Normal file
View File

@ -0,0 +1,27 @@
#include "clar_libgit2.h"
#include "git2/clone.h"
static git_repository *g_repo;
#if defined(GIT_OPENSSL) || defined(GIT_WINHTTP) || defined(GIT_SECURE_TRANSPORT)
void test_online_badssl__expired(void)
{
cl_git_fail_with(GIT_ECERTIFICATE,
git_clone(&g_repo, "https://expired.badssl.com/fake.git", "./fake", NULL));
}
void test_online_badssl__wrong_host(void)
{
cl_git_fail_with(GIT_ECERTIFICATE,
git_clone(&g_repo, "https://wrong.host.badssl.com/fake.git", "./fake", NULL));
}
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));
}
#endif

View File

@ -213,6 +213,33 @@ void test_online_clone__custom_remote_callbacks(void)
cl_assert(callcount > 0);
}
void test_online_clone__custom_headers(void)
{
char *empty_header = "";
char *unnamed_header = "this is a header about nothing";
char *newlines = "X-Custom: almost OK\n";
char *conflict = "Accept: defined-by-git";
char *ok = "X-Custom: this should be ok";
g_options.fetch_opts.custom_headers.count = 1;
g_options.fetch_opts.custom_headers.strings = &empty_header;
cl_git_fail(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
g_options.fetch_opts.custom_headers.strings = &unnamed_header;
cl_git_fail(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
g_options.fetch_opts.custom_headers.strings = &newlines;
cl_git_fail(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
g_options.fetch_opts.custom_headers.strings = &conflict;
cl_git_fail(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
/* Finally, we got it right! */
g_options.fetch_opts.custom_headers.strings = &ok;
cl_git_pass(git_clone(&g_repo, LIVE_REPO_URL, "./foo", &g_options));
}
static int cred_failure_cb(
git_cred **cred,
const char *url,

View File

@ -81,11 +81,11 @@ void test_online_fetch__fetch_twice(void)
{
git_remote *remote;
cl_git_pass(git_remote_create(&remote, _repo, "test", "git://github.com/libgit2/TestGitRepository.git"));
cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL));
cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL, NULL));
cl_git_pass(git_remote_download(remote, NULL, NULL));
git_remote_disconnect(remote);
git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL);
git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL, NULL);
cl_git_pass(git_remote_download(remote, NULL, NULL));
git_remote_disconnect(remote);
@ -117,7 +117,7 @@ void test_online_fetch__doesnt_retrieve_a_pack_when_the_repository_is_up_to_date
cl_git_pass(git_repository_open(&_repository, "./fetch/lg2"));
cl_git_pass(git_remote_lookup(&remote, _repository, "origin"));
cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL));
cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL, NULL));
cl_assert_equal_i(false, invoked);
@ -155,7 +155,7 @@ void test_online_fetch__can_cancel(void)
options.callbacks.transfer_progress = cancel_at_half;
options.callbacks.payload = &bytes_received;
cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL));
cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL, NULL));
cl_git_fail_with(git_remote_download(remote, NULL, &options), -4321);
git_remote_disconnect(remote);
git_remote_free(remote);
@ -169,7 +169,7 @@ void test_online_fetch__ls_disconnected(void)
cl_git_pass(git_remote_create(&remote, _repo, "test",
"http://github.com/libgit2/TestGitRepository.git"));
cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL));
cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL, NULL));
cl_git_pass(git_remote_ls(&refs, &refs_len_before, remote));
git_remote_disconnect(remote);
cl_git_pass(git_remote_ls(&refs, &refs_len_after, remote));
@ -187,7 +187,7 @@ void test_online_fetch__remote_symrefs(void)
cl_git_pass(git_remote_create(&remote, _repo, "test",
"http://github.com/libgit2/TestGitRepository.git"));
cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL));
cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL, NULL));
git_remote_disconnect(remote);
cl_git_pass(git_remote_ls(&refs, &refs_len, remote));

View File

@ -372,7 +372,7 @@ void test_online_push__initialize(void)
record_callbacks_data_clear(&_record_cbs_data);
cl_git_pass(git_remote_connect(_remote, GIT_DIRECTION_PUSH, &_record_cbs));
cl_git_pass(git_remote_connect(_remote, GIT_DIRECTION_PUSH, &_record_cbs, NULL));
/* Clean up previously pushed branches. Fails if receive.denyDeletes is
* set on the remote. Also, on Git 1.7.0 and newer, you must run

View File

@ -106,3 +106,27 @@ void test_repo_reservedname__submodule_pointer(void)
git_repository_free(sub_repo);
#endif
}
/* Like the `submodule_pointer` test (above), this ensures that we do not
* follow the gitlink to the submodule's repository location and treat that
* as a reserved name. This tests at an initial submodule update, where the
* submodule repo is being created.
*/
void test_repo_reservedname__submodule_pointer_during_create(void)
{
git_repository *repo;
git_submodule *sm;
git_submodule_update_options update_options = GIT_SUBMODULE_UPDATE_OPTIONS_INIT;
git_buf url = GIT_BUF_INIT;
repo = setup_fixture_super();
cl_git_pass(git_buf_joinpath(&url, clar_sandbox_path(), "sub.git"));
cl_repo_set_string(repo, "submodule.sub.url", url.ptr);
cl_git_pass(git_submodule_lookup(&sm, repo, "sub"));
cl_git_pass(git_submodule_update(sm, 1, &update_options));
git_submodule_free(sm);
git_buf_free(&url);
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -126,6 +126,22 @@ git_repository *setup_fixture_submod2(void)
return repo;
}
git_repository *setup_fixture_super(void)
{
git_repository *repo = cl_git_sandbox_init("super");
cl_fixture_sandbox("sub.git");
p_mkdir("super/sub", 0777);
rewrite_gitmodules(git_repository_workdir(repo));
cl_set_cleanup(cleanup_fixture_submodules, "sub.git");
cl_git_pass(git_repository_reinit_filesystem(repo, 1));
return repo;
}
git_repository *setup_fixture_submodule_simple(void)
{
git_repository *repo = cl_git_sandbox_init("submodule_simple");

View File

@ -4,6 +4,7 @@ extern void rewrite_gitmodules(const char *workdir);
extern git_repository *setup_fixture_submodules(void);
extern git_repository *setup_fixture_submod2(void);
extern git_repository *setup_fixture_submodule_simple(void);
extern git_repository *setup_fixture_super(void);
extern unsigned int get_submodule_status(git_repository *, const char *);

60
tests/win32/longpath.c Normal file
View File

@ -0,0 +1,60 @@
#include "clar_libgit2.h"
#include "git2/clone.h"
#include "clone.h"
#include "buffer.h"
#include "fileops.h"
static git_buf path = GIT_BUF_INIT;
void test_win32_longpath__initialize(void)
{
#ifdef GIT_WIN32
const char *base = clar_sandbox_path();
size_t base_len = strlen(base);
size_t remain = MAX_PATH - base_len;
size_t i;
git_buf_clear(&path);
git_buf_puts(&path, base);
git_buf_putc(&path, '/');
cl_assert(remain < (MAX_PATH - 5));
for (i = 0; i < (remain - 5); i++)
git_buf_putc(&path, 'a');
#endif
}
void test_win32_longpath__cleanup(void)
{
git_buf_free(&path);
}
#ifdef GIT_WIN32
void assert_name_too_long(void)
{
const git_error *err;
size_t expected_len, actual_len;
const char *expected_msg;
err = giterr_last();
actual_len = strlen(err->message);
expected_msg = git_win32_get_error_message(ERROR_FILENAME_EXCED_RANGE);
expected_len = strlen(expected_msg);
/* check the suffix */
cl_assert_equal_s(expected_msg, err->message + (actual_len - expected_len));
}
#endif
void test_win32_longpath__errmsg_on_checkout(void)
{
#ifdef GIT_WIN32
git_repository *repo;
cl_git_fail(git_clone(&repo, cl_fixture("testrepo.git"), path.ptr, NULL));
assert_name_too_long();
#endif
}