Browse Source
This is not 1.0rc4 yet, but to push the recent fixes out. Signed-off-by: Junio C Hamano <junkio@cox.net>maint v0.99.9k
Junio C Hamano
19 years ago
77 changed files with 2856 additions and 1804 deletions
@ -0,0 +1,170 @@
@@ -0,0 +1,170 @@
|
||||
git-repo-config(1) |
||||
================== |
||||
|
||||
NAME |
||||
---- |
||||
git-repo-config - Get and set options in .git/config. |
||||
|
||||
|
||||
SYNOPSIS |
||||
-------- |
||||
'git-repo-config' name [value [value_regex]] |
||||
'git-repo-config' --replace-all name [value [value_regex]] |
||||
'git-repo-config' --get name [value_regex] |
||||
'git-repo-config' --get-all name [value_regex] |
||||
'git-repo-config' --unset name [value_regex] |
||||
'git-repo-config' --unset-all name [value_regex] |
||||
|
||||
DESCRIPTION |
||||
----------- |
||||
You can query/set/replace/unset options with this command. The name is |
||||
actually the section and the key separated by a dot, and the value will be |
||||
escaped. |
||||
|
||||
If you want to set/unset an option which can occor on multiple lines, you |
||||
should provide a POSIX regex for the value. If you want to handle the lines |
||||
*not* matching the regex, just prepend a single exlamation mark in front |
||||
(see EXAMPLES). |
||||
|
||||
This command will fail if |
||||
|
||||
. .git/config is invalid, |
||||
. .git/config can not be written to, |
||||
. no section was provided, |
||||
. the section or key is invalid, |
||||
. you try to unset an option which does not exist, or |
||||
. you try to unset/set an option for which multiple lines match. |
||||
|
||||
|
||||
OPTIONS |
||||
------- |
||||
|
||||
--replace-all:: |
||||
Default behaviour is to replace at most one line. This replaces |
||||
all lines matching the key (and optionally the value_regex) |
||||
|
||||
--get:: |
||||
Get the value for a given key (optionally filtered by a regex |
||||
matching the value). |
||||
|
||||
--get-all:: |
||||
Like get, but does not fail if the number of values for the key |
||||
is not exactly one. |
||||
|
||||
--unset:: |
||||
Remove the line matching the key from .git/config. |
||||
|
||||
--unset-all:: |
||||
Remove all matching lines from .git/config. |
||||
|
||||
|
||||
EXAMPLE |
||||
------- |
||||
|
||||
Given a .git/config like this: |
||||
|
||||
# |
||||
# This is the config file, and |
||||
# a '#' or ';' character indicates |
||||
# a comment |
||||
# |
||||
|
||||
; core variables |
||||
[core] |
||||
; Don't trust file modes |
||||
filemode = false |
||||
|
||||
; Our diff algorithm |
||||
[diff] |
||||
external = "/usr/local/bin/gnu-diff -u" |
||||
renames = true |
||||
|
||||
; Proxy settings |
||||
[proxy] |
||||
command="ssh" for "ssh://kernel.org/" |
||||
command="proxy-command" for kernel.org |
||||
command="myprotocol-command" for "my://" |
||||
command=default-proxy ; for all the rest |
||||
|
||||
you can set the filemode to true with |
||||
|
||||
------------ |
||||
% git repo-config core.filemode true |
||||
------------ |
||||
|
||||
The hypothetic proxy command entries actually have a postfix to discern |
||||
to what URL they apply. Here is how to change the entry for kernel.org |
||||
to "ssh". |
||||
|
||||
------------ |
||||
% git repo-config proxy.command '"ssh" for kernel.org' 'for kernel.org$' |
||||
------------ |
||||
|
||||
This makes sure that only the key/value pair for kernel.org is replaced. |
||||
|
||||
To delete the entry for renames, do |
||||
|
||||
------------ |
||||
% git repo-config --unset diff.renames |
||||
------------ |
||||
|
||||
If you want to delete an entry for a multivar (like proxy.command above), |
||||
you have to provide a regex matching the value of exactly one line. |
||||
|
||||
To query the value for a given key, do |
||||
|
||||
------------ |
||||
% git repo-config --get core.filemode |
||||
------------ |
||||
|
||||
or |
||||
|
||||
------------ |
||||
% git repo-config core.filemode |
||||
------------ |
||||
|
||||
or, to query a multivar: |
||||
|
||||
------------ |
||||
% git repo-config --get proxy.command "for kernel.org$" |
||||
------------ |
||||
|
||||
If you want to know all the values for a multivar, do: |
||||
|
||||
------------ |
||||
% git repo-config --get-all proxy.command |
||||
------------ |
||||
|
||||
If you like to live dangerous, you can replace *all* proxy.commands by a |
||||
new one with |
||||
|
||||
------------ |
||||
% git repo-config --replace-all proxy.command ssh |
||||
------------ |
||||
|
||||
However, if you really only want to replace the line for the default proxy, |
||||
i.e. the one without a "for ..." postfix, do something like this: |
||||
|
||||
------------ |
||||
% git repo-config proxy.command ssh '! for ' |
||||
------------ |
||||
|
||||
To actually match only values with an exclamation mark, you have to |
||||
|
||||
------------ |
||||
% git repo-config section.key value '[!]' |
||||
------------ |
||||
|
||||
|
||||
Author |
||||
------ |
||||
Written by Johannes Schindelin <Johannes.Schindelin@gmx.de> |
||||
|
||||
Documentation |
||||
-------------- |
||||
Documentation by Johannes Schindelin. |
||||
|
||||
GIT |
||||
--- |
||||
Part of the gitlink:git[7] suite |
||||
|
@ -0,0 +1,105 @@
@@ -0,0 +1,105 @@
|
||||
From: Junio C Hamano <junkio@cox.net> |
||||
Subject: control access to branches. |
||||
Date: Thu, 17 Nov 2005 23:55:32 -0800 |
||||
Message-ID: <7vfypumlu3.fsf@assigned-by-dhcp.cox.net> |
||||
Abstract: An example hooks/update script is presented to |
||||
implement repository maintenance policies, such as who can push |
||||
into which branch and who can make a tag. |
||||
|
||||
When your developer runs git-push into the repository, |
||||
git-receive-pack is run (either locally or over ssh) as that |
||||
developer, so is hooks/update script. Quoting from the relevant |
||||
section of the documentation: |
||||
|
||||
Before each ref is updated, if $GIT_DIR/hooks/update file exists |
||||
and executable, it is called with three parameters: |
||||
|
||||
$GIT_DIR/hooks/update refname sha1-old sha1-new |
||||
|
||||
The refname parameter is relative to $GIT_DIR; e.g. for the |
||||
master head this is "refs/heads/master". Two sha1 are the |
||||
object names for the refname before and after the update. Note |
||||
that the hook is called before the refname is updated, so either |
||||
sha1-old is 0{40} (meaning there is no such ref yet), or it |
||||
should match what is recorded in refname. |
||||
|
||||
So if your policy is (1) always require fast-forward push |
||||
(i.e. never allow "git-push repo +branch:branch"), (2) you |
||||
have a list of users allowed to update each branch, and (3) you |
||||
do not let tags to be overwritten, then: |
||||
|
||||
#!/bin/sh |
||||
# This is a sample hooks/update script, written by JC |
||||
# in his e-mail buffer, so naturally it is not tested |
||||
# but hopefully would convey the idea. |
||||
|
||||
umask 002 |
||||
case "$1" in |
||||
refs/tags/*) |
||||
# No overwriting an existing tag |
||||
if test -f "$GIT_DIR/$1" |
||||
then |
||||
exit 1 |
||||
fi |
||||
;; |
||||
refs/heads/*) |
||||
# No rebasing or rewinding |
||||
if expr "$2" : '0*$' >/dev/null |
||||
then |
||||
# creating a new branch |
||||
; |
||||
else |
||||
# updating -- make sure it is a fast forward |
||||
mb=`git-merge-base "$2" "$3"` |
||||
case "$mb,$2" in |
||||
"$2,$mb") |
||||
;; # fast forward -- happy |
||||
*) |
||||
exit 1 ;; # unhappy |
||||
esac |
||||
fi |
||||
;; |
||||
*) |
||||
# No funny refs allowed |
||||
exit 1 |
||||
;; |
||||
esac |
||||
|
||||
# Is the user allowed to update it? |
||||
me=`id -u -n` ;# e.g. "junio" |
||||
while read head_pattern users |
||||
do |
||||
if expr "$1" : "$head_pattern" >/dev/null |
||||
then |
||||
case " $users " in |
||||
*" $me "*) |
||||
exit 0 ;; # happy |
||||
' * ') |
||||
exit 0 ;; # anybody |
||||
esac |
||||
fi |
||||
done |
||||
exit 1 |
||||
|
||||
For the sake of simplicity, I assumed that you keep something |
||||
like this in $GIT_DIR/info/allowed-pushers file: |
||||
|
||||
refs/heads/master junio |
||||
refs/heads/cogito$ pasky |
||||
refs/heads/bw/ linus |
||||
refs/heads/tmp/ * |
||||
refs/tags/v[0-9]* junio |
||||
|
||||
With this, Linus can push or create "bw/penguin" or "bw/zebra" |
||||
or "bw/panda" branches, Pasky can do only "cogito", and I can do |
||||
master branch and make versioned tags. And anybody can do |
||||
tmp/blah branches. This assumes all the users are in a single |
||||
group that can write into $GIT_DIR/ and underneath. |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,442 @@
@@ -0,0 +1,442 @@
|
||||
#include "http.h" |
||||
|
||||
int data_received; |
||||
int active_requests = 0; |
||||
|
||||
#ifdef USE_CURL_MULTI |
||||
int max_requests = -1; |
||||
CURLM *curlm; |
||||
#endif |
||||
#ifndef NO_CURL_EASY_DUPHANDLE |
||||
CURL *curl_default; |
||||
#endif |
||||
char curl_errorstr[CURL_ERROR_SIZE]; |
||||
|
||||
int curl_ssl_verify = -1; |
||||
char *ssl_cert = NULL; |
||||
#if LIBCURL_VERSION_NUM >= 0x070902 |
||||
char *ssl_key = NULL; |
||||
#endif |
||||
#if LIBCURL_VERSION_NUM >= 0x070908 |
||||
char *ssl_capath = NULL; |
||||
#endif |
||||
char *ssl_cainfo = NULL; |
||||
long curl_low_speed_limit = -1; |
||||
long curl_low_speed_time = -1; |
||||
|
||||
struct curl_slist *pragma_header; |
||||
struct curl_slist *no_range_header; |
||||
|
||||
struct active_request_slot *active_queue_head = NULL; |
||||
|
||||
size_t fread_buffer(void *ptr, size_t eltsize, size_t nmemb, |
||||
struct buffer *buffer) |
||||
{ |
||||
size_t size = eltsize * nmemb; |
||||
if (size > buffer->size - buffer->posn) |
||||
size = buffer->size - buffer->posn; |
||||
memcpy(ptr, buffer->buffer + buffer->posn, size); |
||||
buffer->posn += size; |
||||
return size; |
||||
} |
||||
|
||||
size_t fwrite_buffer(const void *ptr, size_t eltsize, |
||||
size_t nmemb, struct buffer *buffer) |
||||
{ |
||||
size_t size = eltsize * nmemb; |
||||
if (size > buffer->size - buffer->posn) { |
||||
buffer->size = buffer->size * 3 / 2; |
||||
if (buffer->size < buffer->posn + size) |
||||
buffer->size = buffer->posn + size; |
||||
buffer->buffer = xrealloc(buffer->buffer, buffer->size); |
||||
} |
||||
memcpy(buffer->buffer + buffer->posn, ptr, size); |
||||
buffer->posn += size; |
||||
data_received++; |
||||
return size; |
||||
} |
||||
|
||||
size_t fwrite_null(const void *ptr, size_t eltsize, |
||||
size_t nmemb, struct buffer *buffer) |
||||
{ |
||||
data_received++; |
||||
return eltsize * nmemb; |
||||
} |
||||
|
||||
static void finish_active_slot(struct active_request_slot *slot); |
||||
|
||||
#ifdef USE_CURL_MULTI |
||||
static void process_curl_messages(void) |
||||
{ |
||||
int num_messages; |
||||
struct active_request_slot *slot; |
||||
CURLMsg *curl_message = curl_multi_info_read(curlm, &num_messages); |
||||
|
||||
while (curl_message != NULL) { |
||||
if (curl_message->msg == CURLMSG_DONE) { |
||||
int curl_result = curl_message->data.result; |
||||
slot = active_queue_head; |
||||
while (slot != NULL && |
||||
slot->curl != curl_message->easy_handle) |
||||
slot = slot->next; |
||||
if (slot != NULL) { |
||||
curl_multi_remove_handle(curlm, slot->curl); |
||||
slot->curl_result = curl_result; |
||||
finish_active_slot(slot); |
||||
} else { |
||||
fprintf(stderr, "Received DONE message for unknown request!\n"); |
||||
} |
||||
} else { |
||||
fprintf(stderr, "Unknown CURL message received: %d\n", |
||||
(int)curl_message->msg); |
||||
} |
||||
curl_message = curl_multi_info_read(curlm, &num_messages); |
||||
} |
||||
} |
||||
#endif |
||||
|
||||
static int http_options(const char *var, const char *value) |
||||
{ |
||||
if (!strcmp("http.sslverify", var)) { |
||||
if (curl_ssl_verify == -1) { |
||||
curl_ssl_verify = git_config_bool(var, value); |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
if (!strcmp("http.sslcert", var)) { |
||||
if (ssl_cert == NULL) { |
||||
ssl_cert = xmalloc(strlen(value)+1); |
||||
strcpy(ssl_cert, value); |
||||
} |
||||
return 0; |
||||
} |
||||
#if LIBCURL_VERSION_NUM >= 0x070902 |
||||
if (!strcmp("http.sslkey", var)) { |
||||
if (ssl_key == NULL) { |
||||
ssl_key = xmalloc(strlen(value)+1); |
||||
strcpy(ssl_key, value); |
||||
} |
||||
return 0; |
||||
} |
||||
#endif |
||||
#if LIBCURL_VERSION_NUM >= 0x070908 |
||||
if (!strcmp("http.sslcapath", var)) { |
||||
if (ssl_capath == NULL) { |
||||
ssl_capath = xmalloc(strlen(value)+1); |
||||
strcpy(ssl_capath, value); |
||||
} |
||||
return 0; |
||||
} |
||||
#endif |
||||
if (!strcmp("http.sslcainfo", var)) { |
||||
if (ssl_cainfo == NULL) { |
||||
ssl_cainfo = xmalloc(strlen(value)+1); |
||||
strcpy(ssl_cainfo, value); |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
#ifdef USE_CURL_MULTI |
||||
if (!strcmp("http.maxrequests", var)) { |
||||
if (max_requests == -1) |
||||
max_requests = git_config_int(var, value); |
||||
return 0; |
||||
} |
||||
#endif |
||||
|
||||
if (!strcmp("http.lowspeedlimit", var)) { |
||||
if (curl_low_speed_limit == -1) |
||||
curl_low_speed_limit = (long)git_config_int(var, value); |
||||
return 0; |
||||
} |
||||
if (!strcmp("http.lowspeedtime", var)) { |
||||
if (curl_low_speed_time == -1) |
||||
curl_low_speed_time = (long)git_config_int(var, value); |
||||
return 0; |
||||
} |
||||
|
||||
/* Fall back on the default ones */ |
||||
return git_default_config(var, value); |
||||
} |
||||
|
||||
static CURL* get_curl_handle(void) |
||||
{ |
||||
CURL* result = curl_easy_init(); |
||||
|
||||
curl_easy_setopt(result, CURLOPT_SSL_VERIFYPEER, curl_ssl_verify); |
||||
#if LIBCURL_VERSION_NUM >= 0x070907 |
||||
curl_easy_setopt(result, CURLOPT_NETRC, CURL_NETRC_OPTIONAL); |
||||
#endif |
||||
|
||||
if (ssl_cert != NULL) |
||||
curl_easy_setopt(result, CURLOPT_SSLCERT, ssl_cert); |
||||
#if LIBCURL_VERSION_NUM >= 0x070902 |
||||
if (ssl_key != NULL) |
||||
curl_easy_setopt(result, CURLOPT_SSLKEY, ssl_key); |
||||
#endif |
||||
#if LIBCURL_VERSION_NUM >= 0x070908 |
||||
if (ssl_capath != NULL) |
||||
curl_easy_setopt(result, CURLOPT_CAPATH, ssl_capath); |
||||
#endif |
||||
if (ssl_cainfo != NULL) |
||||
curl_easy_setopt(result, CURLOPT_CAINFO, ssl_cainfo); |
||||
curl_easy_setopt(result, CURLOPT_FAILONERROR, 1); |
||||
|
||||
if (curl_low_speed_limit > 0 && curl_low_speed_time > 0) { |
||||
curl_easy_setopt(result, CURLOPT_LOW_SPEED_LIMIT, |
||||
curl_low_speed_limit); |
||||
curl_easy_setopt(result, CURLOPT_LOW_SPEED_TIME, |
||||
curl_low_speed_time); |
||||
} |
||||
|
||||
curl_easy_setopt(result, CURLOPT_FOLLOWLOCATION, 1); |
||||
|
||||
return result; |
||||
} |
||||
|
||||
void http_init(void) |
||||
{ |
||||
char *low_speed_limit; |
||||
char *low_speed_time; |
||||
|
||||
curl_global_init(CURL_GLOBAL_ALL); |
||||
|
||||
pragma_header = curl_slist_append(pragma_header, "Pragma: no-cache"); |
||||
no_range_header = curl_slist_append(no_range_header, "Range:"); |
||||
|
||||
#ifdef USE_CURL_MULTI |
||||
{ |
||||
char *http_max_requests = getenv("GIT_HTTP_MAX_REQUESTS"); |
||||
if (http_max_requests != NULL) |
||||
max_requests = atoi(http_max_requests); |
||||
} |
||||
|
||||
curlm = curl_multi_init(); |
||||
if (curlm == NULL) { |
||||
fprintf(stderr, "Error creating curl multi handle.\n"); |
||||
exit(1); |
||||
} |
||||
#endif |
||||
|
||||
if (getenv("GIT_SSL_NO_VERIFY")) |
||||
curl_ssl_verify = 0; |
||||
|
||||
ssl_cert = getenv("GIT_SSL_CERT"); |
||||
#if LIBCURL_VERSION_NUM >= 0x070902 |
||||
ssl_key = getenv("GIT_SSL_KEY"); |
||||
#endif |
||||
#if LIBCURL_VERSION_NUM >= 0x070908 |
||||
ssl_capath = getenv("GIT_SSL_CAPATH"); |
||||
#endif |
||||
ssl_cainfo = getenv("GIT_SSL_CAINFO"); |
||||
|
||||
low_speed_limit = getenv("GIT_HTTP_LOW_SPEED_LIMIT"); |
||||
if (low_speed_limit != NULL) |
||||
curl_low_speed_limit = strtol(low_speed_limit, NULL, 10); |
||||
low_speed_time = getenv("GIT_HTTP_LOW_SPEED_TIME"); |
||||
if (low_speed_time != NULL) |
||||
curl_low_speed_time = strtol(low_speed_time, NULL, 10); |
||||
|
||||
git_config(http_options); |
||||
|
||||
if (curl_ssl_verify == -1) |
||||
curl_ssl_verify = 1; |
||||
|
||||
#ifdef USE_CURL_MULTI |
||||
if (max_requests < 1) |
||||
max_requests = DEFAULT_MAX_REQUESTS; |
||||
#endif |
||||
|
||||
#ifndef NO_CURL_EASY_DUPHANDLE |
||||
curl_default = get_curl_handle(); |
||||
#endif |
||||
} |
||||
|
||||
void http_cleanup(void) |
||||
{ |
||||
struct active_request_slot *slot = active_queue_head; |
||||
#ifdef USE_CURL_MULTI |
||||
char *wait_url; |
||||
#endif |
||||
|
||||
while (slot != NULL) { |
||||
#ifdef USE_CURL_MULTI |
||||
if (slot->in_use) { |
||||
curl_easy_getinfo(slot->curl, |
||||
CURLINFO_EFFECTIVE_URL, |
||||
&wait_url); |
||||
fprintf(stderr, "Waiting for %s\n", wait_url); |
||||
run_active_slot(slot); |
||||
} |
||||
#endif |
||||
if (slot->curl != NULL) |
||||
curl_easy_cleanup(slot->curl); |
||||
slot = slot->next; |
||||
} |
||||
|
||||
#ifndef NO_CURL_EASY_DUPHANDLE |
||||
curl_easy_cleanup(curl_default); |
||||
#endif |
||||
|
||||
#ifdef USE_CURL_MULTI |
||||
curl_multi_cleanup(curlm); |
||||
#endif |
||||
curl_global_cleanup(); |
||||
|
||||
} |
||||
|
||||
struct active_request_slot *get_active_slot(void) |
||||
{ |
||||
struct active_request_slot *slot = active_queue_head; |
||||
struct active_request_slot *newslot; |
||||
|
||||
#ifdef USE_CURL_MULTI |
||||
int num_transfers; |
||||
|
||||
/* Wait for a slot to open up if the queue is full */ |
||||
while (active_requests >= max_requests) { |
||||
curl_multi_perform(curlm, &num_transfers); |
||||
if (num_transfers < active_requests) { |
||||
process_curl_messages(); |
||||
} |
||||
} |
||||
#endif |
||||
|
||||
while (slot != NULL && slot->in_use) { |
||||
slot = slot->next; |
||||
} |
||||
if (slot == NULL) { |
||||
newslot = xmalloc(sizeof(*newslot)); |
||||
newslot->curl = NULL; |
||||
newslot->in_use = 0; |
||||
newslot->next = NULL; |
||||
|
||||
slot = active_queue_head; |
||||
if (slot == NULL) { |
||||
active_queue_head = newslot; |
||||
} else { |
||||
while (slot->next != NULL) { |
||||
slot = slot->next; |
||||
} |
||||
slot->next = newslot; |
||||
} |
||||
slot = newslot; |
||||
} |
||||
|
||||
if (slot->curl == NULL) { |
||||
#ifdef NO_CURL_EASY_DUPHANDLE |
||||
slot->curl = get_curl_handle(); |
||||
#else |
||||
slot->curl = curl_easy_duphandle(curl_default); |
||||
#endif |
||||
} |
||||
|
||||
active_requests++; |
||||
slot->in_use = 1; |
||||
slot->local = NULL; |
||||
slot->callback_data = NULL; |
||||
slot->callback_func = NULL; |
||||
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, pragma_header); |
||||
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, no_range_header); |
||||
curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, curl_errorstr); |
||||
|
||||
return slot; |
||||
} |
||||
|
||||
int start_active_slot(struct active_request_slot *slot) |
||||
{ |
||||
#ifdef USE_CURL_MULTI |
||||
CURLMcode curlm_result = curl_multi_add_handle(curlm, slot->curl); |
||||
|
||||
if (curlm_result != CURLM_OK && |
||||
curlm_result != CURLM_CALL_MULTI_PERFORM) { |
||||
active_requests--; |
||||
slot->in_use = 0; |
||||
return 0; |
||||
} |
||||
#endif |
||||
return 1; |
||||
} |
||||
|
||||
#ifdef USE_CURL_MULTI |
||||
void step_active_slots(void) |
||||
{ |
||||
int num_transfers; |
||||
CURLMcode curlm_result; |
||||
|
||||
do { |
||||
curlm_result = curl_multi_perform(curlm, &num_transfers); |
||||
} while (curlm_result == CURLM_CALL_MULTI_PERFORM); |
||||
if (num_transfers < active_requests) { |
||||
process_curl_messages(); |
||||
fill_active_slots(); |
||||
} |
||||
} |
||||
#endif |
||||
|
||||
void run_active_slot(struct active_request_slot *slot) |
||||
{ |
||||
#ifdef USE_CURL_MULTI |
||||
long last_pos = 0; |
||||
long current_pos; |
||||
fd_set readfds; |
||||
fd_set writefds; |
||||
fd_set excfds; |
||||
int max_fd; |
||||
struct timeval select_timeout; |
||||
|
||||
while (slot->in_use) { |
||||
data_received = 0; |
||||
step_active_slots(); |
||||
|
||||
if (!data_received && slot->local != NULL) { |
||||
current_pos = ftell(slot->local); |
||||
if (current_pos > last_pos) |
||||
data_received++; |
||||
last_pos = current_pos; |
||||
} |
||||
|
||||
if (slot->in_use && !data_received) { |
||||
max_fd = 0; |
||||
FD_ZERO(&readfds); |
||||
FD_ZERO(&writefds); |
||||
FD_ZERO(&excfds); |
||||
select_timeout.tv_sec = 0; |
||||
select_timeout.tv_usec = 50000; |
||||
select(max_fd, &readfds, &writefds, |
||||
&excfds, &select_timeout); |
||||
} |
||||
} |
||||
#else |
||||
while (slot->in_use) { |
||||
slot->curl_result = curl_easy_perform(slot->curl); |
||||
finish_active_slot(slot); |
||||
} |
||||
#endif |
||||
} |
||||
|
||||
static void finish_active_slot(struct active_request_slot *slot) |
||||
{ |
||||
active_requests--; |
||||
slot->in_use = 0; |
||||
curl_easy_getinfo(slot->curl, CURLINFO_HTTP_CODE, &slot->http_code); |
||||
|
||||
/* Run callback if appropriate */ |
||||
if (slot->callback_func != NULL) { |
||||
slot->callback_func(slot->callback_data); |
||||
} |
||||
} |
||||
|
||||
void finish_all_active_slots(void) |
||||
{ |
||||
struct active_request_slot *slot = active_queue_head; |
||||
|
||||
while (slot != NULL) |
||||
if (slot->in_use) { |
||||
run_active_slot(slot); |
||||
slot = active_queue_head; |
||||
} else { |
||||
slot = slot->next; |
||||
} |
||||
} |
@ -0,0 +1,95 @@
@@ -0,0 +1,95 @@
|
||||
#ifndef HTTP_H |
||||
#define HTTP_H |
||||
|
||||
#include "cache.h" |
||||
|
||||
#include <curl/curl.h> |
||||
#include <curl/easy.h> |
||||
|
||||
#if LIBCURL_VERSION_NUM >= 0x070908 |
||||
#define USE_CURL_MULTI |
||||
#define DEFAULT_MAX_REQUESTS 5 |
||||
#endif |
||||
|
||||
#if LIBCURL_VERSION_NUM < 0x070704 |
||||
#define curl_global_cleanup() do { /* nothing */ } while(0) |
||||
#endif |
||||
#if LIBCURL_VERSION_NUM < 0x070800 |
||||
#define curl_global_init(a) do { /* nothing */ } while(0) |
||||
#endif |
||||
|
||||
#if LIBCURL_VERSION_NUM < 0x070c04 |
||||
#define NO_CURL_EASY_DUPHANDLE |
||||
#endif |
||||
|
||||
struct active_request_slot |
||||
{ |
||||
CURL *curl; |
||||
FILE *local; |
||||
int in_use; |
||||
CURLcode curl_result; |
||||
long http_code; |
||||
void *callback_data; |
||||
void (*callback_func)(void *data); |
||||
struct active_request_slot *next; |
||||
}; |
||||
|
||||
struct buffer |
||||
{ |
||||
size_t posn; |
||||
size_t size; |
||||
void *buffer; |
||||
}; |
||||
|
||||
/* Curl request read/write callbacks */ |
||||
extern size_t fread_buffer(void *ptr, size_t eltsize, size_t nmemb, |
||||
struct buffer *buffer); |
||||
extern size_t fwrite_buffer(const void *ptr, size_t eltsize, |
||||
size_t nmemb, struct buffer *buffer); |
||||
extern size_t fwrite_null(const void *ptr, size_t eltsize, |
||||
size_t nmemb, struct buffer *buffer); |
||||
|
||||
/* Slot lifecycle functions */ |
||||
extern struct active_request_slot *get_active_slot(void); |
||||
extern int start_active_slot(struct active_request_slot *slot); |
||||
extern void run_active_slot(struct active_request_slot *slot); |
||||
extern void finish_all_active_slots(void); |
||||
|
||||
#ifdef USE_CURL_MULTI |
||||
extern void fill_active_slots(void); |
||||
extern void step_active_slots(void); |
||||
#endif |
||||
|
||||
extern void http_init(void); |
||||
extern void http_cleanup(void); |
||||
|
||||
extern int data_received; |
||||
extern int active_requests; |
||||
|
||||
#ifdef USE_CURL_MULTI |
||||
extern int max_requests; |
||||
extern CURLM *curlm; |
||||
#endif |
||||
#ifndef NO_CURL_EASY_DUPHANDLE |
||||
extern CURL *curl_default; |
||||
#endif |
||||
extern char curl_errorstr[CURL_ERROR_SIZE]; |
||||
|
||||
extern int curl_ssl_verify; |
||||
extern char *ssl_cert; |
||||
#if LIBCURL_VERSION_NUM >= 0x070902 |
||||
extern char *ssl_key; |
||||
#endif |
||||
#if LIBCURL_VERSION_NUM >= 0x070908 |
||||
extern char *ssl_capath; |
||||
#endif |
||||
extern char *ssl_cainfo; |
||||
extern long curl_low_speed_limit; |
||||
extern long curl_low_speed_time; |
||||
|
||||
extern struct curl_slist *pragma_header; |
||||
extern struct curl_slist *no_range_header; |
||||
|
||||
extern struct active_request_slot *active_queue_head; |
||||
|
||||
#endif /* HTTP_H */ |
@ -0,0 +1,116 @@
@@ -0,0 +1,116 @@
|
||||
#include "cache.h" |
||||
#include <regex.h> |
||||
|
||||
static const char git_config_set_usage[] = |
||||
"git-repo-config [--get | --get-all | --replace-all | --unset | --unset-all] name [value [value_regex]]"; |
||||
|
||||
static char* key = NULL; |
||||
static char* value = NULL; |
||||
static regex_t* regex = NULL; |
||||
static int do_all = 0; |
||||
static int do_not_match = 0; |
||||
static int seen = 0; |
||||
|
||||
static int show_config(const char* key_, const char* value_) |
||||
{ |
||||
if (!strcmp(key_, key) && |
||||
(regex == NULL || |
||||
(do_not_match ^ |
||||
!regexec(regex, value_, 0, NULL, 0)))) { |
||||
if (do_all) { |
||||
printf("%s\n", value_); |
||||
return 0; |
||||
} |
||||
if (seen > 0) { |
||||
fprintf(stderr, "More than one value: %s\n", value); |
||||
free(value); |
||||
} |
||||
value = strdup(value_); |
||||
seen++; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
static int get_value(const char* key_, const char* regex_) |
||||
{ |
||||
int i; |
||||
|
||||
key = malloc(strlen(key_)+1); |
||||
for (i = 0; key_[i]; i++) |
||||
key[i] = tolower(key_[i]); |
||||
key[i] = 0; |
||||
|
||||
if (regex_) { |
||||
if (regex_[0] == '!') { |
||||
do_not_match = 1; |
||||
regex_++; |
||||
} |
||||
|
||||
regex = (regex_t*)malloc(sizeof(regex_t)); |
||||
if (regcomp(regex, regex_, REG_EXTENDED)) { |
||||
fprintf(stderr, "Invalid pattern: %s\n", regex_); |
||||
return -1; |
||||
} |
||||
} |
||||
|
||||
i = git_config(show_config); |
||||
if (value) { |
||||
printf("%s\n", value); |
||||
free(value); |
||||
} |
||||
free(key); |
||||
if (regex) { |
||||
regfree(regex); |
||||
free(regex); |
||||
} |
||||
|
||||
if (do_all) |
||||
return 0; |
||||
|
||||
return seen == 1 ? 0 : 1; |
||||
} |
||||
|
||||
int main(int argc, const char **argv) |
||||
{ |
||||
setup_git_directory(); |
||||
switch (argc) { |
||||
case 2: |
||||
return get_value(argv[1], NULL); |
||||
case 3: |
||||
if (!strcmp(argv[1], "--unset")) |
||||
return git_config_set(argv[2], NULL); |
||||
else if (!strcmp(argv[1], "--unset-all")) |
||||
return git_config_set_multivar(argv[2], NULL, NULL, 1); |
||||
else if (!strcmp(argv[1], "--get")) |
||||
return get_value(argv[2], NULL); |
||||
else if (!strcmp(argv[1], "--get-all")) { |
||||
do_all = 1; |
||||
return get_value(argv[2], NULL); |
||||
} else |
||||
|
||||
return git_config_set(argv[1], argv[2]); |
||||
case 4: |
||||
if (!strcmp(argv[1], "--unset")) |
||||
return git_config_set_multivar(argv[2], NULL, argv[3], 0); |
||||
else if (!strcmp(argv[1], "--unset-all")) |
||||
return git_config_set_multivar(argv[2], NULL, argv[3], 1); |
||||
else if (!strcmp(argv[1], "--get")) |
||||
return get_value(argv[2], argv[3]); |
||||
else if (!strcmp(argv[1], "--get-all")) { |
||||
do_all = 1; |
||||
return get_value(argv[2], argv[3]); |
||||
} else if (!strcmp(argv[1], "--replace-all")) |
||||
|
||||
return git_config_set_multivar(argv[2], argv[3], NULL, 1); |
||||
else |
||||
|
||||
return git_config_set_multivar(argv[1], argv[2], argv[3], 0); |
||||
case 5: |
||||
if (!strcmp(argv[1], "--replace-all")) |
||||
return git_config_set_multivar(argv[2], argv[3], argv[4], 1); |
||||
case 1: |
||||
default: |
||||
usage(git_config_set_usage); |
||||
} |
||||
return 0; |
||||
} |
@ -0,0 +1,271 @@
@@ -0,0 +1,271 @@
|
||||
#!/bin/sh |
||||
# |
||||
# Copyright (c) 2005 Johannes Schindelin |
||||
# |
||||
|
||||
test_description='Test git-repo-config in different settings' |
||||
|
||||
. ./test-lib.sh |
||||
|
||||
test -f .git/config && rm .git/config |
||||
|
||||
git-repo-config core.penguin "little blue" |
||||
|
||||
cat > expect << EOF |
||||
# |
||||
# This is the config file |
||||
# |
||||
|
||||
[core] |
||||
penguin = little blue |
||||
EOF |
||||
|
||||
test_expect_success 'initial' 'cmp .git/config expect' |
||||
|
||||
git-repo-config Core.Movie BadPhysics |
||||
|
||||
cat > expect << EOF |
||||
# |
||||
# This is the config file |
||||
# |
||||
|
||||
[core] |
||||
penguin = little blue |
||||
Movie = BadPhysics |
||||
EOF |
||||
|
||||
test_expect_success 'mixed case' 'cmp .git/config expect' |
||||
|
||||
git-repo-config Cores.WhatEver Second |
||||
|
||||
cat > expect << EOF |
||||
# |
||||
# This is the config file |
||||
# |
||||
|
||||
[core] |
||||
penguin = little blue |
||||
Movie = BadPhysics |
||||
[Cores] |
||||
WhatEver = Second |
||||
EOF |
||||
|
||||
test_expect_success 'similar section' 'cmp .git/config expect' |
||||
|
||||
git-repo-config CORE.UPPERCASE true |
||||
|
||||
cat > expect << EOF |
||||
# |
||||
# This is the config file |
||||
# |
||||
|
||||
[core] |
||||
penguin = little blue |
||||
Movie = BadPhysics |
||||
UPPERCASE = true |
||||
[Cores] |
||||
WhatEver = Second |
||||
EOF |
||||
|
||||
test_expect_success 'similar section' 'cmp .git/config expect' |
||||
|
||||
test_expect_success 'replace with non-match' \ |
||||
'git-repo-config core.penguin kingpin !blue' |
||||
|
||||
test_expect_success 'replace with non-match (actually matching)' \ |
||||
'git-repo-config core.penguin "very blue" !kingpin' |
||||
|
||||
cat > expect << EOF |
||||
# |
||||
# This is the config file |
||||
# |
||||
|
||||
[core] |
||||
penguin = very blue |
||||
Movie = BadPhysics |
||||
UPPERCASE = true |
||||
penguin = kingpin |
||||
[Cores] |
||||
WhatEver = Second |
||||
EOF |
||||
|
||||
test_expect_success 'non-match result' 'cmp .git/config expect' |
||||
|
||||
cat > .git/config << EOF |
||||
[beta] ; silly comment # another comment |
||||
noIndent= sillyValue ; 'nother silly comment |
||||
|
||||
# empty line |
||||
; comment |
||||
haha ="beta" # last silly comment |
||||
haha = hello |
||||
haha = bello |
||||
[nextSection] noNewline = ouch |
||||
EOF |
||||
|
||||
cp .git/config .git/config2 |
||||
|
||||
test_expect_success 'multiple unset' \ |
||||
'git-repo-config --unset-all beta.haha' |
||||
|
||||
cat > expect << EOF |
||||
[beta] ; silly comment # another comment |
||||
noIndent= sillyValue ; 'nother silly comment |
||||
|
||||
# empty line |
||||
; comment |
||||
[nextSection] noNewline = ouch |
||||
EOF |
||||
|
||||
test_expect_success 'multiple unset is correct' 'cmp .git/config expect' |
||||
|
||||
mv .git/config2 .git/config |
||||
|
||||
test_expect_success '--replace-all' \ |
||||
'git-repo-config --replace-all beta.haha gamma' |
||||
|
||||
cat > expect << EOF |
||||
[beta] ; silly comment # another comment |
||||
noIndent= sillyValue ; 'nother silly comment |
||||
|
||||
# empty line |
||||
; comment |
||||
haha = gamma |
||||
[nextSection] noNewline = ouch |
||||
EOF |
||||
|
||||
test_expect_success 'all replaced' 'cmp .git/config expect' |
||||
|
||||
git-repo-config beta.haha alpha |
||||
|
||||
cat > expect << EOF |
||||
[beta] ; silly comment # another comment |
||||
noIndent= sillyValue ; 'nother silly comment |
||||
|
||||
# empty line |
||||
; comment |
||||
haha = alpha |
||||
[nextSection] noNewline = ouch |
||||
EOF |
||||
|
||||
test_expect_success 'really mean test' 'cmp .git/config expect' |
||||
|
||||
git-repo-config nextsection.nonewline wow |
||||
|
||||
cat > expect << EOF |
||||
[beta] ; silly comment # another comment |
||||
noIndent= sillyValue ; 'nother silly comment |
||||
|
||||
# empty line |
||||
; comment |
||||
haha = alpha |
||||
[nextSection] |
||||
nonewline = wow |
||||
EOF |
||||
|
||||
test_expect_success 'really really mean test' 'cmp .git/config expect' |
||||
|
||||
test_expect_success 'get value' 'test alpha = $(git-repo-config beta.haha)' |
||||
git-repo-config --unset beta.haha |
||||
|
||||
cat > expect << EOF |
||||
[beta] ; silly comment # another comment |
||||
noIndent= sillyValue ; 'nother silly comment |
||||
|
||||
# empty line |
||||
; comment |
||||
[nextSection] |
||||
nonewline = wow |
||||
EOF |
||||
|
||||
test_expect_success 'unset' 'cmp .git/config expect' |
||||
|
||||
git-repo-config nextsection.NoNewLine "wow2 for me" "for me$" |
||||
|
||||
cat > expect << EOF |
||||
[beta] ; silly comment # another comment |
||||
noIndent= sillyValue ; 'nother silly comment |
||||
|
||||
# empty line |
||||
; comment |
||||
[nextSection] |
||||
nonewline = wow |
||||
NoNewLine = wow2 for me |
||||
EOF |
||||
|
||||
test_expect_success 'multivar' 'cmp .git/config expect' |
||||
|
||||
test_expect_success 'non-match' \ |
||||
'git-repo-config --get nextsection.nonewline !for' |
||||
|
||||
test_expect_success 'non-match value' \ |
||||
'test wow = $(git-repo-config --get nextsection.nonewline !for)' |
||||
|
||||
test_expect_failure 'ambiguous get' \ |
||||
'git-repo-config --get nextsection.nonewline' |
||||
|
||||
test_expect_success 'get multivar' \ |
||||
'git-repo-config --get-all nextsection.nonewline' |
||||
|
||||
git-repo-config nextsection.nonewline "wow3" "wow$" |
||||
|
||||
cat > expect << EOF |
||||
[beta] ; silly comment # another comment |
||||
noIndent= sillyValue ; 'nother silly comment |
||||
|
||||
# empty line |
||||
; comment |
||||
[nextSection] |
||||
nonewline = wow3 |
||||
NoNewLine = wow2 for me |
||||
EOF |
||||
|
||||
test_expect_success 'multivar replace' 'cmp .git/config expect' |
||||
|
||||
test_expect_failure 'ambiguous value' 'git-repo-config nextsection.nonewline' |
||||
|
||||
test_expect_failure 'ambiguous unset' \ |
||||
'git-repo-config --unset nextsection.nonewline' |
||||
|
||||
test_expect_failure 'invalid unset' \ |
||||
'git-repo-config --unset somesection.nonewline' |
||||
|
||||
git-repo-config --unset nextsection.nonewline "wow3$" |
||||
|
||||
cat > expect << EOF |
||||
[beta] ; silly comment # another comment |
||||
noIndent= sillyValue ; 'nother silly comment |
||||
|
||||
# empty line |
||||
; comment |
||||
[nextSection] |
||||
NoNewLine = wow2 for me |
||||
EOF |
||||
|
||||
test_expect_success 'multivar unset' 'cmp .git/config expect' |
||||
|
||||
test_expect_failure 'invalid key' 'git-repo-config inval.2key blabla' |
||||
|
||||
test_expect_success 'correct key' 'git-repo-config 123456.a123 987' |
||||
|
||||
test_expect_success 'hierarchical section' \ |
||||
'git-repo-config 1.2.3.alpha beta' |
||||
|
||||
cat > expect << EOF |
||||
[beta] ; silly comment # another comment |
||||
noIndent= sillyValue ; 'nother silly comment |
||||
|
||||
# empty line |
||||
; comment |
||||
[nextSection] |
||||
NoNewLine = wow2 for me |
||||
[123456] |
||||
a123 = 987 |
||||
[1.2.3] |
||||
alpha = beta |
||||
EOF |
||||
|
||||
test_expect_success 'hierarchical section value' 'cmp .git/config expect' |
||||
|
||||
test_done |
||||
|
Loading…
Reference in new issue