Merge branches 'jc/daemon' and 'mw/http'
authorJunio C Hamano <junkio@cox.net>
Mon, 6 Feb 2006 07:54:14 +0000 (23:54 -0800)
committerJunio C Hamano <junkio@cox.net>
Mon, 6 Feb 2006 07:54:14 +0000 (23:54 -0800)
* jc/daemon:
daemon: extend user-relative path notation.
daemon: Set SO_REUSEADDR on listening sockets.
daemon: do not forbid user relative paths unconditionally under --base-path

* mw/http:
http-fetch: Tidy control flow in process_alternate_response
http: Turn on verbose Curl messages if GIT_CURL_VERBOSE set in environment
http-fetch: Fix message reporting rename of object file.
http-fetch: Fix object list corruption in fill_active_slots().

Documentation/git-daemon.txt
Documentation/git-send-email.txt
daemon.c
git-send-email.perl
index a20e0533fcfc1ed2c9940021ab65ef2967f16856..2cc6075fb0b316f4254273caa4fe184fdc5afb35 100644 (file)
@@ -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.
 
index b9bec55e53ad191e4cb0b052551aa7e45049013e..00537d8907872aa25c39f07513ef661b1bef1f17 100644 (file)
@@ -24,25 +24,23 @@ OPTIONS
 -------
 The options available are:
 
---to::
-       Specify the primary recipient of the emails generated.
-       Generally, this will be the upstream maintainer of the
-       project involved.
+--chain-reply-to, --no-chain-reply-to::
+       If this is set, each email will be sent as a reply to the previous
+       email sent.  If disabled with "--no-chain-reply-to", all emails after
+       the first will be sent as replies to the first email sent.  When using
+       this, it is recommended that the first file given be an overview of the
+       entire patch series.
+       Default is --chain-reply-to
+
+--compose::
+       Use $EDITOR to edit an introductory message for the
+       patch series.
 
 --from::
        Specify the sender of the emails.  This will default to
        the value GIT_COMMITTER_IDENT, as returned by "git-var -l".
        The user will still be prompted to confirm this entry.
 
---compose::
-       Use \$EDITOR to edit an introductory message for the
-       patch series.
-
---subject::
-       Specify the initial subject of the email thread.
-       Only necessary if --compose is also set.  If --compose
-       is not set, this will be prompted for.
-
 --in-reply-to::
        Specify the contents of the first In-Reply-To header.
        Subsequent emails will refer to the previous email 
@@ -50,18 +48,24 @@ The options available are:
        Only necessary if --compose is also set.  If --compose
        is not set, this will be prompted for.
 
---chain-reply-to, --no-chain-reply-to::
-       If this is set, each email will be sent as a reply to the previous
-       email sent.  If disabled with "--no-chain-reply-to", all emails after
-       the first will be sent as replies to the first email sent.  When using
-       this, it is recommended that the first file given be an overview of the
-       entire patch series.
-       Default is --chain-reply-to
+--quiet::
+       Make git-send-email less verbose.  One line per email should be
+       all that is output.
 
 --smtp-server::
        If set, specifies the outgoing SMTP server to use.  Defaults to
        localhost.
 
+--subject::
+       Specify the initial subject of the email thread.
+       Only necessary if --compose is also set.  If --compose
+       is not set, this will be prompted for.
+
+--to::
+       Specify the primary recipient of the emails generated.
+       Generally, this will be the upstream maintainer of the
+       project involved.
+
 
 Author
 ------
index 532bb0c325fd07e13360389297807a19a11ee33e..a1ccda30e2211368c66c1186437891f548f0e338 100644 (file)
--- a/daemon.c
+++ b/daemon.c
 
 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;
index 2977b9adebff3180f156327622a9a11067e01696..3f1b3ca78897ef1eb85dea266eea6afcc404a1db 100755 (executable)
 }
 
 if (@files) {
-       print $_,"\n" for @files;
+       unless ($quiet) {
+               print $_,"\n" for (@files);
+       }
 } else {
        print <<EOT;
 git-send-email [options] <file | directory> [... file | directory ]
    --smtp-server  If set, specifies the outgoing SMTP server to use.
                   Defaults to localhost.
 
+   --quiet     Make git-send-email less verbose.  One line per email should be
+               all that is output.
+
+
 Error: Please specify a file or a directory on the command line.
 EOT
        exit(1);
@@ -268,7 +274,9 @@ sub send_message
 
        sendmail(%mail) or die $Mail::Sendmail::error;
 
-       unless ($quiet) {
+       if ($quiet) {
+               printf "Sent %s\n", $subject;
+       } else {
                print "OK. Log says:\n", $Mail::Sendmail::log;
                print "\n\n"
        }
@@ -280,7 +288,6 @@ sub send_message
 $subject = $initial_subject;
 
 foreach my $t (@files) {
-       my $F = $t;
        open(F,"<",$t) or die "can't open file $t";
 
        @cc = ();
@@ -298,7 +305,7 @@ sub send_message
 
                                } elsif (/^(Cc|From):\s+(.*)$/) {
                                        printf("(mbox) Adding cc: %s from line '%s'\n",
-                                               $2, $_);
+                                               $2, $_) unless $quiet;
                                        push @cc, $2;
                                }
 
@@ -310,7 +317,7 @@ sub send_message
                                # So let's support that, too.
                                if (@cc == 0) {
                                        printf("(non-mbox) Adding cc: %s from line '%s'\n",
-                                               $_, $_);
+                                               $_, $_) unless $quiet;
 
                                        push @cc, $_;
 
@@ -330,7 +337,7 @@ sub send_message
                                chomp $c;
                                push @cc, $c;
                                printf("(sob) Adding cc: %s from line '%s'\n",
-                                       $c, $_);
+                                       $c, $_) unless $quiet;
                        }
                }
        }