Commit ecdc0428 by Carlos Martín Nieto

Merge pull request #3448 from libgit2/cmn/custom-agent

Support setting custom user-agent
parents 3f5877d1 027bbaa7
...@@ -10,6 +10,9 @@ v0.23 + 1 ...@@ -10,6 +10,9 @@ v0.23 + 1
* Symlinks are now followed when locking a file, which can be * Symlinks are now followed when locking a file, which can be
necessary when multiple worktrees share a base repository. necessary when multiple worktrees share a base repository.
* You can now set your own user-agent to be sent for HTTP requests by
using the `GIT_OPT_SET_USER_AGENT` with `git_libgit2_opts()`.
### API additions ### API additions
* `git_config_lock()` has been added, which allow for * `git_config_lock()` has been added, which allow for
......
...@@ -145,6 +145,7 @@ typedef enum { ...@@ -145,6 +145,7 @@ typedef enum {
GIT_OPT_GET_TEMPLATE_PATH, GIT_OPT_GET_TEMPLATE_PATH,
GIT_OPT_SET_TEMPLATE_PATH, GIT_OPT_SET_TEMPLATE_PATH,
GIT_OPT_SET_SSL_CERT_LOCATIONS, GIT_OPT_SET_SSL_CERT_LOCATIONS,
GIT_OPT_SET_USER_AGENT,
} git_libgit2_opt_t; } git_libgit2_opt_t;
/** /**
...@@ -240,6 +241,8 @@ typedef enum { ...@@ -240,6 +241,8 @@ typedef enum {
* > * >
* > Either parameter may be `NULL`, but not both. * > Either parameter may be `NULL`, but not both.
* *
* * opts(GIT_OPT_SET_USER_AGENT, const char *user_agent)
*
* @param option Option key * @param option Option key
* @param ... value to set the option * @param ... value to set the option
* @return 0 on success, <0 on failure * @return 0 on success, <0 on failure
......
...@@ -31,6 +31,7 @@ static git_mutex *openssl_locks; ...@@ -31,6 +31,7 @@ static git_mutex *openssl_locks;
static git_global_shutdown_fn git__shutdown_callbacks[MAX_SHUTDOWN_CB]; static git_global_shutdown_fn git__shutdown_callbacks[MAX_SHUTDOWN_CB];
static git_atomic git__n_shutdown_callbacks; static git_atomic git__n_shutdown_callbacks;
static git_atomic git__n_inits; static git_atomic git__n_inits;
char *git__user_agent;
void git__on_shutdown(git_global_shutdown_fn callback) void git__on_shutdown(git_global_shutdown_fn callback)
{ {
...@@ -269,6 +270,8 @@ int git_libgit2_shutdown(void) ...@@ -269,6 +270,8 @@ int git_libgit2_shutdown(void)
git_win32__crtdbg_stacktrace_cleanup(); git_win32__crtdbg_stacktrace_cleanup();
git_win32__stack_cleanup(); git_win32__stack_cleanup();
#endif #endif
git__free(git__user_agent);
} }
/* Exit the lock */ /* Exit the lock */
...@@ -369,6 +372,7 @@ int git_libgit2_shutdown(void) ...@@ -369,6 +372,7 @@ int git_libgit2_shutdown(void)
git__global_state_cleanup(ptr); git__global_state_cleanup(ptr);
git__free(ptr); git__free(ptr);
git__free(git__user_agent);
pthread_key_delete(_tls_key); pthread_key_delete(_tls_key);
git_mutex_free(&git__mwindow_mutex); git_mutex_free(&git__mwindow_mutex);
...@@ -423,6 +427,7 @@ int git_libgit2_shutdown(void) ...@@ -423,6 +427,7 @@ int git_libgit2_shutdown(void)
git__shutdown(); git__shutdown();
git__global_state_cleanup(&__state); git__global_state_cleanup(&__state);
uninit_ssl(); uninit_ssl();
git__free(git__user_agent);
return 0; return 0;
} }
......
...@@ -35,4 +35,6 @@ extern void git__on_shutdown(git_global_shutdown_fn callback); ...@@ -35,4 +35,6 @@ extern void git__on_shutdown(git_global_shutdown_fn callback);
extern void git__free_tls_data(void); extern void git__free_tls_data(void);
extern const char *git_libgit2__user_agent(void);
#endif #endif
...@@ -57,6 +57,13 @@ static int config_level_to_sysdir(int config_level) ...@@ -57,6 +57,13 @@ static int config_level_to_sysdir(int config_level)
return val; return val;
} }
extern char *git__user_agent;
const char *git_libgit2__user_agent()
{
return git__user_agent;
}
int git_libgit2_opts(int key, ...) int git_libgit2_opts(int key, ...)
{ {
int error = 0; int error = 0;
...@@ -153,6 +160,15 @@ int git_libgit2_opts(int key, ...) ...@@ -153,6 +160,15 @@ int git_libgit2_opts(int key, ...)
error = -1; error = -1;
#endif #endif
break; 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); va_end(ap);
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "http_parser.h" #include "http_parser.h"
#include "buffer.h" #include "buffer.h"
#include "netops.h" #include "netops.h"
#include "global.h"
#include "remote.h" #include "remote.h"
#include "smart.h" #include "smart.h"
#include "auth.h" #include "auth.h"
...@@ -186,6 +187,16 @@ static int apply_credentials(git_buf *buf, http_subtransport *t) ...@@ -186,6 +187,16 @@ static int apply_credentials(git_buf *buf, http_subtransport *t)
return context->next_token(buf, context, cred); 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( static int gen_request(
git_buf *buf, git_buf *buf,
http_stream *s, http_stream *s,
...@@ -197,7 +208,7 @@ static int gen_request( ...@@ -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_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); git_buf_printf(buf, "Host: %s\r\n", t->connection_data.host);
if (s->chunked || content_length > 0) { if (s->chunked || content_length > 0) {
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "smart.h" #include "smart.h"
#include "remote.h" #include "remote.h"
#include "repository.h" #include "repository.h"
#include "global.h"
#include <wincrypt.h> #include <wincrypt.h>
#include <winhttp.h> #include <winhttp.h>
...@@ -567,12 +568,28 @@ static int winhttp_close_connection(winhttp_subtransport *t) ...@@ -567,12 +568,28 @@ static int winhttp_close_connection(winhttp_subtransport *t)
return ret; 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( static int winhttp_connect(
winhttp_subtransport *t) winhttp_subtransport *t)
{ {
wchar_t *ua = L"git/1.0 (libgit2 " WIDEN(LIBGIT2_VERSION) L")";
wchar_t *wide_host; wchar_t *wide_host;
int32_t port; int32_t port;
wchar_t *wide_ua;
git_buf ua = GIT_BUF_INIT;
int error = -1; int error = -1;
int default_timeout = TIMEOUT_INFINITE; int default_timeout = TIMEOUT_INFINITE;
int default_connect_timeout = DEFAULT_CONNECT_TIMEOUT; int default_connect_timeout = DEFAULT_CONNECT_TIMEOUT;
...@@ -590,9 +607,23 @@ static int winhttp_connect( ...@@ -590,9 +607,23 @@ static int winhttp_connect(
return -1; 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 */ /* Establish session */
t->session = WinHttpOpen( t->session = WinHttpOpen(
ua, wide_ua,
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS, WINHTTP_NO_PROXY_BYPASS,
...@@ -628,6 +659,7 @@ on_error: ...@@ -628,6 +659,7 @@ on_error:
winhttp_close_connection(t); winhttp_close_connection(t);
git__free(wide_host); git__free(wide_host);
git__free(wide_ua);
return error; return error;
} }
......
#include "clar_libgit2.h"
#include "global.h"
void test_core_useragent__get(void)
{
const char *custom_name = "super duper git";
cl_assert_equal_p(NULL, git_libgit2__user_agent());
cl_git_pass(git_libgit2_opts(GIT_OPT_SET_USER_AGENT, custom_name));
cl_assert_equal_s(custom_name, git_libgit2__user_agent());
}
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