diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Documentation/git-daemon.txt | 15 | ||||
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | daemon.c | 76 | ||||
-rwxr-xr-x | git-whatchanged.sh | 18 | ||||
-rw-r--r-- | http-fetch.c | 13 | ||||
-rw-r--r-- | http.c | 3 | ||||
-rw-r--r-- | rev-parse.c | 16 |
8 files changed, 118 insertions, 29 deletions
diff --git a/.gitignore b/.gitignore index 5382e74271..513f22eb1d 100644 --- a/.gitignore +++ b/.gitignore @@ -88,6 +88,7 @@ git-send-pack git-sh-setup git-shell git-shortlog +git-show git-show-branch git-show-index git-ssh-fetch diff --git a/Documentation/git-daemon.txt b/Documentation/git-daemon.txt index a20e0533fc..2cc6075fb0 100644 --- a/Documentation/git-daemon.txt +++ b/Documentation/git-daemon.txt @@ -10,7 +10,8 @@ SYNOPSIS [verse] 'git-daemon' [--verbose] [--syslog] [--inetd | --port=n] [--export-all] [--timeout=n] [--init-timeout=n] [--strict-paths] - [--base-path=path] [directory...] + [--base-path=path] [--user-path | --user-path=path] + [directory...] DESCRIPTION ----------- @@ -42,8 +43,7 @@ OPTIONS This is sort of "GIT root" - if you run git-daemon with '--base-path=/srv/git' on example.com, then if you later try to pull 'git://example.com/hello.git', `git-daemon` will interpret the path - as '/srv/git/hello.git'. Home directories (the '~login' notation) - access is disabled. + as '/srv/git/hello.git'. --export-all:: Allow pulling from all directories that look like GIT repositories @@ -70,6 +70,15 @@ OPTIONS Log to syslog instead of stderr. Note that this option does not imply --verbose, thus by default only error conditions will be logged. +--user-path, --user-path=path:: + Allow ~user notation to be used in requests. When + specified with no parameter, requests to + git://host/~alice/foo is taken as a request to access + 'foo' repository in the home directory of user `alice`. + If `--user-path=path` is specified, the same request is + taken as a request to access `path/foo` repository in + the home directory of user `alice`. + --verbose:: Log details about the incoming connections and requested files. @@ -125,7 +125,7 @@ SCRIPT_PYTHON = \ SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \ $(patsubst %.perl,%,$(SCRIPT_PERL)) \ $(patsubst %.py,%,$(SCRIPT_PYTHON)) \ - git-cherry-pick + git-cherry-pick git-show # The ones that do not have to link with lcrypto nor lz. SIMPLE_PROGRAMS = \ @@ -440,6 +440,9 @@ $(patsubst %.py,%,$(SCRIPT_PYTHON)) : % : %.py git-cherry-pick: git-revert cp $< $@ +git-show: git-whatchanged + cp $< $@ + # These can record GIT_VERSION git$X git.spec \ $(patsubst %.sh,%,$(SCRIPT_SH)) \ @@ -13,11 +13,13 @@ static int log_syslog; static int verbose; +static int reuseaddr; static const char daemon_usage[] = "git-daemon [--verbose] [--syslog] [--inetd | --port=n] [--export-all]\n" " [--timeout=n] [--init-timeout=n] [--strict-paths]\n" -" [--base-path=path] [directory...]"; +" [--base-path=path] [--user-path | --user-path=path]\n" +" [--reuseaddr] [directory...]"; /* List of acceptable pathname prefixes */ static char **ok_paths = NULL; @@ -29,6 +31,12 @@ static int export_all_trees = 0; /* Take all paths relative to this one if non-NULL */ static char *base_path = NULL; +/* If defined, ~user notation is allowed and the string is inserted + * after ~user/. E.g. a request to git://host/~alice/frotz would + * go to /home/alice/pub_git/frotz with --user-path=pub_git. + */ +static char *user_path = NULL; + /* Timeout, and initial timeout */ static unsigned int timeout = 0; static unsigned int init_timeout = 0; @@ -136,6 +144,7 @@ static int avoid_alias(char *p) static char *path_ok(char *dir) { + static char rpath[PATH_MAX]; char *path; if (avoid_alias(dir)) { @@ -143,15 +152,38 @@ static char *path_ok(char *dir) return NULL; } - if (base_path) { - static char rpath[PATH_MAX]; + if (*dir == '~') { + if (!user_path) { + logerror("'%s': User-path not allowed", dir); + return NULL; + } + if (*user_path) { + /* Got either "~alice" or "~alice/foo"; + * rewrite them to "~alice/%s" or + * "~alice/%s/foo". + */ + int namlen, restlen = strlen(dir); + char *slash = strchr(dir, '/'); + if (!slash) + slash = dir + restlen; + namlen = slash - dir; + restlen -= namlen; + loginfo("userpath <%s>, request <%s>, namlen %d, restlen %d, slash <%s>", user_path, dir, namlen, restlen, slash); + snprintf(rpath, PATH_MAX, "%.*s/%s%.*s", + namlen, dir, user_path, restlen, slash); + dir = rpath; + } + } + else if (base_path) { if (*dir != '/') { - /* Forbid possible base-path evasion using ~paths. */ + /* Allow only absolute */ logerror("'%s': Non-absolute path denied (base-path active)", dir); return NULL; } - snprintf(rpath, PATH_MAX, "%s%s", base_path, dir); - dir = rpath; + else { + snprintf(rpath, PATH_MAX, "%s%s", base_path, dir); + dir = rpath; + } } path = enter_repo(dir, strict_paths); @@ -447,6 +479,16 @@ static void child_handler(int signo) } } +static int set_reuse_addr(int sockfd) +{ + int on = 1; + + if (!reuseaddr) + return 0; + return setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, + &on, sizeof(on)); +} + #ifndef NO_IPV6 static int socksetup(int port, int **socklist_p) @@ -491,6 +533,11 @@ static int socksetup(int port, int **socklist_p) } #endif + if (set_reuse_addr(sockfd)) { + close(sockfd); + return 0; /* not fatal */ + } + if (bind(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) { close(sockfd); continue; /* not fatal */ @@ -533,6 +580,11 @@ static int socksetup(int port, int **socklist_p) sin.sin_addr.s_addr = htonl(INADDR_ANY); sin.sin_port = htons(port); + if (set_reuse_addr(sockfd)) { + close(sockfd); + return 0; + } + if ( bind(sockfd, (struct sockaddr *)&sin, sizeof sin) < 0 ) { close(sockfd); return 0; @@ -659,6 +711,18 @@ int main(int argc, char **argv) base_path = arg+12; continue; } + if (!strcmp(arg, "--reuseaddr")) { + reuseaddr = 1; + continue; + } + if (!strcmp(arg, "--user-path")) { + user_path = ""; + continue; + } + if (!strncmp(arg, "--user-path=", 12)) { + user_path = arg + 12; + continue; + } if (!strcmp(arg, "--")) { ok_paths = &argv[i+1]; break; diff --git a/git-whatchanged.sh b/git-whatchanged.sh index d4f985b5eb..574fc3558e 100755 --- a/git-whatchanged.sh +++ b/git-whatchanged.sh @@ -5,14 +5,24 @@ SUBDIRECTORY_OK='Yes' . git-sh-setup diff_tree_flags=$(git-rev-parse --sq --no-revs --flags "$@") || exit +case "$0" in +*whatchanged) + count= + test -z "$diff_tree_flags" && + diff_tree_flags=$(git-repo-config --get whatchanged.difftree) + diff_tree_default_flags='-M --abbrev' ;; +*show) + count=-n1 + test -z "$diff_tree_flags" && + diff_tree_flags=$(git-repo-config --get show.difftree) + diff_tree_default_flags='--cc --always' ;; +esac test -z "$diff_tree_flags" && - diff_tree_flags=$(git-repo-config --get whatchanged.difftree) -test -z "$diff_tree_flags" && - diff_tree_flags='-M --abbrev' + diff_tree_flags="$diff_tree_default_flags" rev_list_args=$(git-rev-parse --sq --default HEAD --revs-only "$@") && diff_tree_args=$(git-rev-parse --sq --no-revs --no-flags "$@") && -eval "git-rev-list $rev_list_args" | +eval "git-rev-list $count $rev_list_args" | eval "git-diff-tree --stdin --pretty -r $diff_tree_flags $diff_tree_args" | LESS="$LESS -S" ${PAGER:-less} diff --git a/http-fetch.c b/http-fetch.c index 72edf28b00..bddbd6b100 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -311,7 +311,7 @@ void fill_active_slots(void) while (active_requests < max_requests && obj_req != NULL) { if (obj_req->state == WAITING) { if (has_sha1_file(obj_req->sha1)) - release_object_request(obj_req); + obj_req->state = COMPLETE; else start_object_request(obj_req); curl_multi_perform(curlm, &num_transfers); @@ -468,13 +468,11 @@ static void process_alternates_response(void *callback_data) alt_req->url); active_requests++; slot->in_use = 1; - if (start_active_slot(slot)) { - return; - } else { + if (!start_active_slot(slot)) { got_alternates = -1; slot->in_use = 0; - return; } + return; } } else if (slot->curl_result != CURLE_OK) { if (slot->http_code != 404 && @@ -822,9 +820,8 @@ static int fetch_object(struct alt_base *repo, unsigned char *sha1) } else if (memcmp(obj_req->sha1, obj_req->real_sha1, 20)) { ret = error("File %s has bad hash\n", hex); } else if (obj_req->rename < 0) { - ret = error("unable to write sha1 filename %s: %s", - obj_req->filename, - strerror(obj_req->rename)); + ret = error("unable to write sha1 filename %s", + obj_req->filename); } release_object_request(obj_req); @@ -192,6 +192,9 @@ static CURL* get_curl_handle(void) curl_easy_setopt(result, CURLOPT_FOLLOWLOCATION, 1); + if (getenv("GIT_CURL_VERBOSE")) + curl_easy_setopt(result, CURLOPT_VERBOSE, 1); + return result; } diff --git a/rev-parse.c b/rev-parse.c index 9cec33b8c0..b82f294a78 100644 --- a/rev-parse.c +++ b/rev-parse.c @@ -150,11 +150,14 @@ static void show_datestring(const char *flag, const char *datestr) show(buffer); } -static void show_file(const char *arg) +static int show_file(const char *arg) { show_default(); - if ((filter & (DO_NONFLAGS|DO_NOREV)) == (DO_NONFLAGS|DO_NOREV)) + if ((filter & (DO_NONFLAGS|DO_NOREV)) == (DO_NONFLAGS|DO_NOREV)) { show(arg); + return 1; + } + return 0; } int main(int argc, char **argv) @@ -329,14 +332,13 @@ int main(int argc, char **argv) show_rev(REVERSED, sha1, arg+1); continue; } + as_is = 1; + if (!show_file(arg)) + continue; if (verify) die("Needed a single revision"); - if ((filter & DO_REVS) && - (filter & DO_NONFLAGS) && /* !def && */ - lstat(arg, &st) < 0) + if (lstat(arg, &st) < 0) die("'%s': %s", arg, strerror(errno)); - as_is = 1; - show_file(arg); } show_default(); if (verify && revs_count != 1) |