summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/commit.c35
-rw-r--r--src/diff.c15
-rw-r--r--src/diff_file.c25
-rw-r--r--src/global.c5
-rw-r--r--src/global.h2
-rw-r--r--src/index.c4
-rw-r--r--src/settings.c16
-rw-r--r--src/stream.h3
-rw-r--r--src/submodule.c42
-rw-r--r--src/tls_stream.c13
-rw-r--r--src/transports/http.c13
-rw-r--r--src/transports/winhttp.c36
12 files changed, 168 insertions, 41 deletions
diff --git a/src/commit.c b/src/commit.c
index 616f947db..b42f9de28 100644
--- a/src/commit.c
+++ b/src/commit.c
@@ -431,22 +431,37 @@ const char *git_commit_summary(git_commit *commit)
{
git_buf summary = GIT_BUF_INIT;
const char *msg, *space;
+ bool space_contains_newline = false;
assert(commit);
if (!commit->summary) {
for (msg = git_commit_message(commit), space = NULL; *msg; ++msg) {
- if (msg[0] == '\n' && (!msg[1] || msg[1] == '\n'))
+ char next_character = msg[0];
+ /* stop processing at the end of the first paragraph */
+ if (next_character == '\n' && (!msg[1] || msg[1] == '\n'))
break;
- else if (msg[0] == '\n')
- git_buf_putc(&summary, ' ');
- else if (git__isspace(msg[0]))
- space = space ? space : msg;
- else if (space) {
- git_buf_put(&summary, space, (msg - space) + 1);
- space = NULL;
- } else
- git_buf_putc(&summary, *msg);
+ /* record the beginning of contiguous whitespace runs */
+ else if (git__isspace(next_character)) {
+ if(space == NULL) {
+ space = msg;
+ space_contains_newline = false;
+ }
+ space_contains_newline |= next_character == '\n';
+ }
+ /* the next character is non-space */
+ else {
+ /* process any recorded whitespace */
+ if (space) {
+ if(space_contains_newline)
+ git_buf_putc(&summary, ' '); /* if the space contains a newline, collapse to ' ' */
+ else
+ git_buf_put(&summary, space, (msg - space)); /* otherwise copy it */
+ space = NULL;
+ }
+ /* copy the next character */
+ git_buf_putc(&summary, next_character);
+ }
}
commit->summary = git_buf_detach(&summary);
diff --git a/src/diff.c b/src/diff.c
index b5e9b6cd5..c2362358a 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -56,7 +56,7 @@ static int diff_insert_delta(
if (diff->opts.notify_cb) {
error = diff->opts.notify_cb(
- diff, delta, matched_pathspec, diff->opts.notify_payload);
+ diff, delta, matched_pathspec, diff->opts.payload);
if (error) {
git__free(delta);
@@ -1260,7 +1260,18 @@ int git_diff__from_iterators(
/* run iterators building diffs */
while (!error && (info.oitem || info.nitem)) {
- int cmp = info.oitem ?
+ int cmp;
+
+ /* report progress */
+ if (opts && opts->progress_cb) {
+ if ((error = opts->progress_cb(diff,
+ info.oitem ? info.oitem->path : NULL,
+ info.nitem ? info.nitem->path : NULL,
+ opts->payload)))
+ break;
+ }
+
+ cmp = info.oitem ?
(info.nitem ? diff->entrycomp(info.oitem, info.nitem) : -1) : 1;
/* create DELETED records for old items not matched in new */
diff --git a/src/diff_file.c b/src/diff_file.c
index c60362865..ecc34cf55 100644
--- a/src/diff_file.c
+++ b/src/diff_file.c
@@ -259,10 +259,35 @@ static int diff_file_content_load_blob(
return error;
}
+static int diff_file_content_load_workdir_symlink_fake(
+ git_diff_file_content *fc, git_buf *path)
+{
+ git_buf target = GIT_BUF_INIT;
+ int error;
+
+ if ((error = git_futils_readbuffer(&target, path->ptr)) < 0)
+ return error;
+
+ fc->map.len = git_buf_len(&target);
+ fc->map.data = git_buf_detach(&target);
+ fc->flags |= GIT_DIFF_FLAG__FREE_DATA;
+
+ git_buf_free(&target);
+ return error;
+}
+
static int diff_file_content_load_workdir_symlink(
git_diff_file_content *fc, git_buf *path)
{
ssize_t alloc_len, read_len;
+ int symlink_supported, error;
+
+ if ((error = git_repository__cvar(
+ &symlink_supported, fc->repo, GIT_CVAR_SYMLINKS)) < 0)
+ return -1;
+
+ if (!symlink_supported)
+ return diff_file_content_load_workdir_symlink_fake(fc, path);
/* link path on disk could be UTF-16, so prepare a buffer that is
* big enough to handle some UTF-8 data expansion
diff --git a/src/global.c b/src/global.c
index 3d37ee4de..0eab8d552 100644
--- a/src/global.c
+++ b/src/global.c
@@ -31,6 +31,7 @@ static git_mutex *openssl_locks;
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;
void git__on_shutdown(git_global_shutdown_fn callback)
{
@@ -269,6 +270,8 @@ int git_libgit2_shutdown(void)
git_win32__crtdbg_stacktrace_cleanup();
git_win32__stack_cleanup();
#endif
+
+ git__free(git__user_agent);
}
/* Exit the lock */
@@ -369,6 +372,7 @@ int git_libgit2_shutdown(void)
git__global_state_cleanup(ptr);
git__free(ptr);
+ git__free(git__user_agent);
pthread_key_delete(_tls_key);
git_mutex_free(&git__mwindow_mutex);
@@ -423,6 +427,7 @@ int git_libgit2_shutdown(void)
git__shutdown();
git__global_state_cleanup(&__state);
uninit_ssl();
+ git__free(git__user_agent);
return 0;
}
diff --git a/src/global.h b/src/global.h
index 37e909ac6..9fdcee573 100644
--- a/src/global.h
+++ b/src/global.h
@@ -35,4 +35,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);
+
#endif
diff --git a/src/index.c b/src/index.c
index dcf46fe50..d3b8afd39 100644
--- a/src/index.c
+++ b/src/index.c
@@ -1691,7 +1691,7 @@ int git_index_conflict_add(git_index *index,
for (i = 0; i < 3; i++) {
if (entries[i] && !valid_filemode(entries[i]->mode)) {
giterr_set(GITERR_INDEX, "invalid filemode for stage %d entry",
- i);
+ i + 1);
return -1;
}
}
@@ -1718,7 +1718,7 @@ int git_index_conflict_add(git_index *index,
/* Make sure stage is correct */
GIT_IDXENTRY_STAGE_SET(entries[i], i + 1);
- if ((ret = index_insert(index, &entries[i], 0, true, true)) < 0)
+ if ((ret = index_insert(index, &entries[i], 1, true, true)) < 0)
goto on_error;
entries[i] = NULL; /* don't free if later entry fails */
diff --git a/src/settings.c b/src/settings.c
index 2097ca314..030d28537 100644
--- a/src/settings.c
+++ b/src/settings.c
@@ -57,6 +57,13 @@ static int config_level_to_sysdir(int config_level)
return val;
}
+extern char *git__user_agent;
+
+const char *git_libgit2__user_agent()
+{
+ return git__user_agent;
+}
+
int git_libgit2_opts(int key, ...)
{
int error = 0;
@@ -153,6 +160,15 @@ int git_libgit2_opts(int key, ...)
error = -1;
#endif
break;
+ case GIT_OPT_SET_USER_AGENT:
+ git__free(git__user_agent);
+ git__user_agent = git__strdup(va_arg(ap, const char *));
+ if (!git__user_agent) {
+ giterr_set_oom();
+ error = -1;
+ }
+
+ break;
}
va_end(ap);
diff --git a/src/stream.h b/src/stream.h
index 43fcc3045..4692c7115 100644
--- a/src/stream.h
+++ b/src/stream.h
@@ -62,6 +62,9 @@ GIT_INLINE(int) git_stream_close(git_stream *st)
GIT_INLINE(void) git_stream_free(git_stream *st)
{
+ if (!st)
+ return;
+
st->free(st);
}
diff --git a/src/submodule.c b/src/submodule.c
index 3fd338843..1148f8790 100644
--- a/src/submodule.c
+++ b/src/submodule.c
@@ -1423,7 +1423,6 @@ static int submodule_update_head(git_submodule *submodule)
return 0;
}
-
int git_submodule_reload(git_submodule *sm, int force)
{
int error = 0;
@@ -1433,35 +1432,30 @@ int git_submodule_reload(git_submodule *sm, int force)
assert(sm);
- /* refresh index data */
- if ((error = submodule_update_index(sm)) < 0)
- return error;
-
- /* refresh HEAD tree data */
- if ((error = submodule_update_head(sm)) < 0)
- return error;
+ if (!git_repository_is_bare(sm->repo)) {
+ /* refresh config data */
+ mods = gitmodules_snapshot(sm->repo);
+ if (mods != NULL) {
+ error = submodule_read_config(sm, mods);
+ git_config_free(mods);
- /* done if bare */
- if (git_repository_is_bare(sm->repo))
- return error;
+ if (error < 0)
+ return error;
+ }
- /* refresh config data */
- mods = gitmodules_snapshot(sm->repo);
- if (mods != NULL) {
- error = submodule_read_config(sm, mods);
- git_config_free(mods);
+ /* refresh wd data */
+ sm->flags &=
+ ~(GIT_SUBMODULE_STATUS_IN_WD |
+ GIT_SUBMODULE_STATUS__WD_OID_VALID |
+ GIT_SUBMODULE_STATUS__WD_FLAGS);
- if (error < 0) {
- return error;
- }
+ error = submodule_load_from_wd_lite(sm);
}
- /* refresh wd data */
- sm->flags &=
- ~(GIT_SUBMODULE_STATUS_IN_WD | GIT_SUBMODULE_STATUS__WD_OID_VALID |
- GIT_SUBMODULE_STATUS__WD_FLAGS);
+ if (error == 0 && (error = submodule_update_index(sm)) == 0)
+ error = submodule_update_head(sm);
- return submodule_load_from_wd_lite(sm);
+ return error;
}
static void submodule_copy_oid_maybe(
diff --git a/src/tls_stream.c b/src/tls_stream.c
index 39a8ce343..83e2d064a 100644
--- a/src/tls_stream.c
+++ b/src/tls_stream.c
@@ -11,8 +11,21 @@
#include "openssl_stream.h"
#include "stransport_stream.h"
+static git_stream_cb tls_ctor;
+
+int git_stream_register_tls(git_stream_cb ctor)
+{
+ tls_ctor = ctor;
+
+ return 0;
+}
+
int git_tls_stream_new(git_stream **out, const char *host, const char *port)
{
+
+ if (tls_ctor)
+ return tls_ctor(out, host, port);
+
#ifdef GIT_SECURE_TRANSPORT
return git_stransport_stream_new(out, host, port);
#elif defined(GIT_OPENSSL)
diff --git a/src/transports/http.c b/src/transports/http.c
index e5f2b9f28..88b124bf7 100644
--- a/src/transports/http.c
+++ b/src/transports/http.c
@@ -10,6 +10,7 @@
#include "http_parser.h"
#include "buffer.h"
#include "netops.h"
+#include "global.h"
#include "remote.h"
#include "smart.h"
#include "auth.h"
@@ -186,6 +187,16 @@ static int apply_credentials(git_buf *buf, http_subtransport *t)
return context->next_token(buf, context, cred);
}
+static const char *user_agent(void)
+{
+ const char *custom = git_libgit2__user_agent();
+
+ if (custom)
+ return custom;
+
+ return "libgit2 " LIBGIT2_VERSION;
+}
+
static int gen_request(
git_buf *buf,
http_stream *s,
@@ -197,7 +208,7 @@ static int gen_request(
git_buf_printf(buf, "%s %s%s HTTP/1.1\r\n", s->verb, path, s->service_url);
- git_buf_puts(buf, "User-Agent: git/1.0 (libgit2 " LIBGIT2_VERSION ")\r\n");
+ git_buf_printf(buf, "User-Agent: git/1.0 (%s)\r\n", user_agent());
git_buf_printf(buf, "Host: %s\r\n", t->connection_data.host);
if (s->chunked || content_length > 0) {
diff --git a/src/transports/winhttp.c b/src/transports/winhttp.c
index b364e906e..77d939bd3 100644
--- a/src/transports/winhttp.c
+++ b/src/transports/winhttp.c
@@ -15,6 +15,7 @@
#include "smart.h"
#include "remote.h"
#include "repository.h"
+#include "global.h"
#include <wincrypt.h>
#include <winhttp.h>
@@ -567,12 +568,28 @@ static int winhttp_close_connection(winhttp_subtransport *t)
return ret;
}
+static int user_agent(git_buf *ua)
+{
+ const char *custom = git_libgit2__user_agent();
+
+ git_buf_clear(ua);
+ git_buf_PUTS(ua, "git/1.0 (");
+
+ if (custom)
+ git_buf_puts(ua, custom);
+ else
+ git_buf_PUTS(ua, "libgit2 " LIBGIT2_VERSION);
+
+ return git_buf_putc(ua, ')');
+}
+
static int winhttp_connect(
winhttp_subtransport *t)
{
- wchar_t *ua = L"git/1.0 (libgit2 " WIDEN(LIBGIT2_VERSION) L")";
wchar_t *wide_host;
int32_t port;
+ wchar_t *wide_ua;
+ git_buf ua = GIT_BUF_INIT;
int error = -1;
int default_timeout = TIMEOUT_INFINITE;
int default_connect_timeout = DEFAULT_CONNECT_TIMEOUT;
@@ -590,9 +607,23 @@ static int winhttp_connect(
return -1;
}
+ if ((error = user_agent(&ua)) < 0) {
+ git__free(wide_host);
+ return error;
+ }
+
+ if (git__utf8_to_16_alloc(&wide_ua, git_buf_cstr(&ua)) < 0) {
+ giterr_set(GITERR_OS, "Unable to convert host to wide characters");
+ git__free(wide_host);
+ git_buf_free(&ua);
+ return -1;
+ }
+
+ git_buf_free(&ua);
+
/* Establish session */
t->session = WinHttpOpen(
- ua,
+ wide_ua,
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS,
@@ -628,6 +659,7 @@ on_error:
winhttp_close_connection(t);
git__free(wide_host);
+ git__free(wide_ua);
return error;
}