Git development
 help / color / mirror / Atom feed
* Re: [PATCH 2/9] gitweb: change die_error to take "extra" argument for extended die information
From: Jakub Narebski @ 2010-01-15 22:40 UTC (permalink / raw)
  To: John 'Warthog9' Hawley; +Cc: git
In-Reply-To: <1263432185-21334-3-git-send-email-warthog9@eaglescrag.net>

"John 'Warthog9' Hawley" <warthog9@eaglescrag.net> writes:

Don't you want kernel.org address also for authorship?  Also commit
summary can be written in shorter way, see proposal below.

From: "John 'Warthog9' Hawley" <warthog9@kernel.org>
Subject: gitweb: Allow for longer error explanation in die_error()

> This is a small change that just adds a 3rd, optional, parameter to die_error
> that allows for extended error information to be output along with what the
> error was.

Singed-off-by: "John 'Warthog9' Hawley" <warthog9@kernel.org>
> ---
>  gitweb/gitweb.perl |    8 +++++++-
>  1 files changed, 7 insertions(+), 1 deletions(-)
> 
> diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
> index 0a07d3a..8298de5 100755
> --- a/gitweb/gitweb.perl
> +++ b/gitweb/gitweb.perl
> @@ -3391,6 +3391,7 @@ sub git_footer_html {
>  sub die_error {
>  	my $status = shift || 500;
>  	my $error = shift || "Internal server error";
> +	my $extra = shift;
>  
>  	my %http_responses = (
>  		400 => '400 Bad Request',
> @@ -3405,8 +3406,13 @@ sub die_error {
>  <br /><br />
>  $status - $error
>  <br />
> -</div>
>  EOF
> +	if (defined $extra) {
> +		print "<hr />\n" .
> +			"$extra\n";

Following gitweb whitespace convention (tab for indent, space for
align), it should be:

 +		print "<hr />\n" .
 +		      "$extra\n";

(6 x space in place of last tab).

> +	}
> +	print "</div>\n";
> +
>  	git_footer_html();
>  	exit;
>  }
> -- 
> 1.6.5.2
> 

-- 
Jakub Narebski
Poland
ShadeHawk on #git

^ permalink raw reply

* Re: [PATCH v2 08/14] daemon: use explicit file descriptor
From: Johannes Sixt @ 2010-01-15 22:36 UTC (permalink / raw)
  To: Erik Faye-Lund; +Cc: msysgit, git, Erik Faye-Lund
In-Reply-To: <1263591033-4992-9-git-send-email-kusmabite@gmail.com>

On Freitag, 15. Januar 2010, Erik Faye-Lund wrote:
> This patch adds support to specify an explicit file
> descriotor for communication with the client, instead
> of using stdin/stdout.
>
> This will be useful for the Windows port, because it
> will use threads instead of fork() to serve multiple
> clients, making it impossible to reuse stdin/stdout.

This statement is a bit outdated.

-- Hannes

^ permalink raw reply

* Re: [PATCH v2 07/14] mingw: add kill emulation
From: Johannes Sixt @ 2010-01-15 22:31 UTC (permalink / raw)
  To: Erik Faye-Lund; +Cc: msysgit, git, Erik Faye-Lund
In-Reply-To: <1263591033-4992-8-git-send-email-kusmabite@gmail.com>

On Freitag, 15. Januar 2010, Erik Faye-Lund wrote:
> +int mingw_kill(pid_t pid, int sig)
> +{
> ...
> +		CloseHandle(h);
> +		errno = err_win_to_posix(GetLastError());

Set errno before CloseHandle() to get the correct error.

-- Hannes

^ permalink raw reply

* Re: [PATCH v2 06/14] mingw: use real pid
From: Johannes Sixt @ 2010-01-15 22:30 UTC (permalink / raw)
  To: Erik Faye-Lund; +Cc: msysgit, git, Erik Faye-Lund
In-Reply-To: <1263591033-4992-7-git-send-email-kusmabite@gmail.com>

On Freitag, 15. Januar 2010, Erik Faye-Lund wrote:
> @@ -729,7 +729,7 @@ static pid_t mingw_spawnve(const char *cmd, const char
> **argv, char **env, return -1;
>  	}
>  	CloseHandle(pi.hThread);
> -	return (pid_t)pi.hProcess;
> +	return (pid_t)pi.dwProcessId;
>  }

You are not using the pi.hProcess anymore, so you must close it.

-- Hannes

^ permalink raw reply

* Re: [PATCH 1/9] gitweb: Load checking
From: Jakub Narebski @ 2010-01-15 22:30 UTC (permalink / raw)
  To: John 'Warthog9' Hawley; +Cc: git
In-Reply-To: <1263432185-21334-2-git-send-email-warthog9@eaglescrag.net>

This one looks good, but while examining other patch in this series
I have noticed rare situation where we would get Perl error with
this patch.

I have added fix-up for this issue, although I guess that better
solution might be not to add any <script> element for git_footer_html
called from die_error.

I'm sorry I haven't noticed this earlier.


"John 'Warthog9' Hawley" <warthog9@eaglescrag.net> writes:

> From: John 'Warthog9' Hawley <warthog9@kernel.org>
> 
> This changes slightly the behavior of gitweb, so that it verifies
> that the box isn't inundated with before attempting to serve gitweb.
> If the box is overloaded, it basically returns a 503 Server Unavailable
> until the load falls below the defined threshold.  This helps dramatically
> if you have a box that's I/O bound, reaches a certain load and you
> don't want gitweb, the I/O hog that it is, increasing the pain the
> server is already undergoing.
> 
> This behavior is controlled by $maxload configuration variable.
> Default is a load of 300, which for most cases should never be hit.
> Unset it (set it to undefined value, i.e. undef) to turn off checking.
> 
> Currently it requires that '/proc/loadavg' file exists, otherwise the
> load check is bypassed (load is taken to be 0).  So platforms that do
> not implement '/proc/loadavg' currently cannot use this feature.
> (provisions are included for additional checks to be added by others)
>
While at it check that $action is defined before comparing it in
git_footer_html() subroutine.  Until this patch there were no direct
or indirect (via die_error) invocation of git_footer_html() with
$action undefined; each call was after dispatch, which sets $action to
default value if it is undefined.

This would cause Perl error ("Use of uninitialized value in string eq")
if load is too high _and_ gitweb was invoked without action parameter
explicitly set (e.g. for projects list).
 
> Signed-off-by: John 'Warthog9' Hawley <warthog9@kernel.org>
> Signed-off-by: Jakub Narebski <jnareb@gmail.com>
> ---
>  gitweb/README      |    7 ++++++-
>  gitweb/gitweb.perl |   45 +++++++++++++++++++++++++++++++++++++++++----
>  2 files changed, 47 insertions(+), 5 deletions(-)
> 
> diff --git a/gitweb/README b/gitweb/README
> index e34ee79..6c2c8e1 100644
> --- a/gitweb/README
> +++ b/gitweb/README
> @@ -174,7 +174,7 @@ not include variables usually directly set during build):
>     Base URL for relative URLs in pages generated by gitweb,
>     (e.g. $logo, $favicon, @stylesheets if they are relative URLs),
>     needed and used only for URLs with nonempty PATH_INFO via
> -   <base href="$base_url>.  Usually gitweb sets its value correctly,
> +   <base href="$base_url">.  Usually gitweb sets its value correctly,
>     and there is no need to set this variable, e.g. to $my_uri or "/".
>   * $home_link
>     Target of the home link on top of all pages (the first part of view
> @@ -228,6 +228,11 @@ not include variables usually directly set during build):
>     repositories from launching cross-site scripting (XSS) attacks.  Set this
>     to true if you don't trust the content of your repositories. The default
>     is false.
> + * $maxload
> +   Used to set the maximum load that we will still respond to gitweb queries.
> +   If server load exceed this value then return "503 Service Unavaliable" error.
> +   Server load is taken to be 0 if gitweb cannot determine its value.  Set it to
> +   undefined value to turn it off.  The default is 300.
>  
>  
>  Projects list file format
> diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
> index 7e477af..0a07d3a 100755
> --- a/gitweb/gitweb.perl
> +++ b/gitweb/gitweb.perl
> @@ -221,6 +221,12 @@ our %avatar_size = (
>  	'double'  => 32
>  );
>  
> +# Used to set the maximum load that we will still respond to gitweb queries.
> +# If server load exceed this value then return "503 server busy" error.
> +# If gitweb cannot determined server load, it is taken to be 0.
> +# Leave it undefined (or set to 'undef') to turn off load checking.
> +our $maxload = 300;
> +
>  # You define site-wide feature defaults here; override them with
>  # $GITWEB_CONFIG as necessary.
>  our %feature = (
> @@ -551,6 +557,32 @@ if (-e $GITWEB_CONFIG) {
>  	do $GITWEB_CONFIG_SYSTEM if -e $GITWEB_CONFIG_SYSTEM;
>  }
>  
> +# Get loadavg of system, to compare against $maxload.
> +# Currently it requires '/proc/loadavg' present to get loadavg;
> +# if it is not present it returns 0, which means no load checking.
> +sub get_loadavg {
> +	if( -e '/proc/loadavg' ){
> +		open my $fd, '<', '/proc/loadavg'
> +			or return 0;
> +		my @load = split(/\s+/, scalar <$fd>);
> +		close $fd;
> +
> +		# The first three columns measure CPU and IO utilization of the last one,
> +		# five, and 10 minute periods.  The fourth column shows the number of
> +		# currently running processes and the total number of processes in the m/n
> +		# format.  The last column displays the last process ID used.
> +		return $load[0] || 0;
> +	}
> +	# additional checks for load average should go here for things that don't export
> +	# /proc/loadavg
> +
> +	return 0;
> +}
> +
> +if (defined $maxload && get_loadavg() > $maxload) {
> +	die_error(503, "The load average on the server is too high");
> +}
> +
>  # version of the core git binary
>  our $git_version = qx("$GIT" --version) =~ m/git version (.*)$/ ? $1 : "unknown";
>  $number_of_git_cmds++;
> @@ -3354,14 +3386,19 @@ sub git_footer_html {
>  # 500: The server isn't configured properly, or
>  #      an internal error occurred (e.g. failed assertions caused by bugs), or
>  #      an unknown error occurred (e.g. the git binary died unexpectedly).
> +# 503: The server is currently unavailable (because it is overloaded,
> +#      or down for maintenance).  Generally, this is a temporary state.
>  sub die_error {
>  	my $status = shift || 500;
>  	my $error = shift || "Internal server error";
>  
> -	my %http_responses = (400 => '400 Bad Request',
> -			      403 => '403 Forbidden',
> -			      404 => '404 Not Found',
> -			      500 => '500 Internal Server Error');
> +	my %http_responses = (
> +		400 => '400 Bad Request',
> +		403 => '403 Forbidden',
> +		404 => '404 Not Found',
> +		500 => '500 Internal Server Error',
> +		503 => '503 Service Unavailable',
> +	);
>  	git_header_html($http_responses{$status});
>  	print <<EOF;
>  <div class="page_body">
@@ -3354,7 +3354,8 @@ sub git_footer_html {
 	}
 
 	print qq!<script type="text/javascript" src="$javascript"></script>\n!;
-	if ($action eq 'blame_incremental') {
+	if (defined $action &&
+	    $action eq 'blame_incremental') {
 		print qq!<script type="text/javascript">\n!.
 		      qq!startBlame("!. href(action=>"blame_data", -replay=>1) .qq!",\n!.
 		      qq!           "!. href() .qq!");\n!.

> -- 
> 1.6.5.2
> 

-- 
Jakub Narebski
Poland
ShadeHawk on #git

^ permalink raw reply

* Re: [PATCH v2 05/14] mingw: support waitpid with pid > 0 and WNOHANG
From: Johannes Sixt @ 2010-01-15 22:28 UTC (permalink / raw)
  To: Erik Faye-Lund; +Cc: msysgit, git, Erik Faye-Lund
In-Reply-To: <1263591033-4992-6-git-send-email-kusmabite@gmail.com>

On Freitag, 15. Januar 2010, Erik Faye-Lund wrote:
>  static inline int waitpid(pid_t pid, int *status, unsigned options)
>  {
> +	if (pid > 0 && options & WNOHANG) {
> +		if (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)pid, 0))
> +			return 0;
> +		options &= ~WNOHANG;
> +	}
> +
>  	if (options == 0)
>  		return _cwait(status, pid, 0);
>  	errno = EINVAL;

With this change, and in particular the one in the next patch, this function 
grows too large to be 'static inline'.

-- Hannes

^ permalink raw reply

* Re: [PATCH] Remove some junk characters from COPYING
From: David Aguilar @ 2010-01-15 22:28 UTC (permalink / raw)
  To: Ramkumar Ramachandra; +Cc: git
In-Reply-To: <f3271551001150022p342dccd3r5e93b5f5354d208c@mail.gmail.com>

Hello,

On Fri, Jan 15, 2010 at 01:52:30PM +0530, Ramkumar Ramachandra wrote:
> I removed a few ^L characters from COPYING. Kindly find patch
> attached. Again, I'm sorry I couldn't include it inline- I'm behind a
> restrictive firewall, and Gmail mangles up patches.
> 
> -- Ram

I've had great success with the 'git send-email', msmtp, and
gmail combination.

http://git.or.cz/gitwiki/GitTips#Usingmsmtptosendyourpatches

I highly recommend using that setup.


I'm sure there are other ways, but that's the one that works for
me.  I also use mutt to read gmail; also highly recommended :)


Have a nice day,

-- 
		David

^ permalink raw reply

* Re: [PATCH v2 00/14] daemon-win32
From: Johannes Sixt @ 2010-01-15 22:27 UTC (permalink / raw)
  To: Erik Faye-Lund; +Cc: msysgit, git, Erik Faye-Lund
In-Reply-To: <1263591033-4992-1-git-send-email-kusmabite@gmail.com>

A very nicely done series. Thank you very much!

On Freitag, 15. Januar 2010, Erik Faye-Lund wrote:
> Here's the long overdue v2 of my daemon-win32 attempt. A lot
> has happened since v1. Most importantly, I abandoned using
> the async API to replace fork(), and went for explicitly
> spawning child process that handle the connection.

IOW, you run git-daemon recursively in inetd mode (almost). Let's see what 
people say about this approach.

-- Hannes

^ permalink raw reply

* Re: [PATCH] Add push --set-upstream
From: Jeff King @ 2010-01-15 22:08 UTC (permalink / raw)
  To: Ilari Liusvaara; +Cc: git
In-Reply-To: <20100115220658.GA14755@Knoppix>

On Sat, Jan 16, 2010 at 12:06:58AM +0200, Ilari Liusvaara wrote:

> On Fri, Jan 15, 2010 at 12:17:45PM -0500, Jeff King wrote:
> > On Fri, Jan 15, 2010 at 06:36:47PM +0200, Ilari Liusvaara wrote:
> > 
> > No tests. But since in writing this you have crossed an item off of my
> > long-term todo, I feel obliged to help out by providing some. :)
>  
> Signoff for those tests? Or do they need it anyway?

Sorry, yes:

Signed-off-by: Jeff King <peff@peff.net>

-Peff

^ permalink raw reply

* [msysGit] [PATCH] Installer: Create builtins as symbolic links on Vista
From: Michael Lukashov @ 2010-01-15 22:06 UTC (permalink / raw)
  To: msysgit; +Cc: Michael Lukashov, git, Sebastian Schuberth, Johannes Schindelin

When create builtins, first try to use CreateSymbolicLinkW function.
If symbolic link creating fails, hard links are created.

Tested under WinXP (both FAT32 and NTFS), Vista and Win7.

This patch applies on top of ss/installer-improvements branch.

Signed-off-by: Michael Lukashov <michael.lukashov@gmail.com>
---
 share/WinGit/install.iss |   30 ++++++++++++++++++++++++------
 1 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/share/WinGit/install.iss b/share/WinGit/install.iss
index 91eac9c..f64f754 100644
--- a/share/WinGit/install.iss
+++ b/share/WinGit/install.iss
@@ -83,8 +83,10 @@ Type: dirifempty; Name: {app}\home
 
 // Note: Since we are using the Unicode version of Inno Setup, "String" is a Unicode
 // string, and thus we need to call the "W" (Wide-String) Windows API variant.
+function CreateSymbolicLink(lpFileName,lpExistingFileName:String;lpSecurityAttributes:Integer):Boolean;
+external 'CreateSymbolicLinkW@Kernel32.dll stdcall setuponly delayload';
 function CreateHardLink(lpFileName,lpExistingFileName:String;lpSecurityAttributes:Integer):Boolean;
-external 'CreateHardLinkW@Kernel32.dll stdcall setuponly';
+external 'CreateHardLinkW@Kernel32.dll stdcall setuponly delayload';
 
 const
     // Git Path options.
@@ -474,7 +476,11 @@ var
     IsNTFS:Boolean;
     FindRec:TFindRec;
     RootKey:Integer;
+    Version:TWindowsVersion;
+    LinkCreated:Boolean;
 begin
+    GetWindowsVersionEx(Version);
+
     if CurStep<>ssPostInstall then begin
         Exit;
     end;
@@ -511,13 +517,25 @@ begin
             for i:=0 to Count do begin
                 FileName:=AppDir+'\'+BuiltIns[i];
 
-                // On non-NTFS partitions, create hard links.
-                if (FileExists(FileName) and (not DeleteFile(FileName))) or
-                   (not CreateHardLink(FileName,AppDir+'\bin\git.exe',0)) then begin
-                    Log('Line {#emit __LINE__}: Unable to create hard link "'+FileName+'", will try to copy files.');
-                    IsNTFS:=False;
+                // First check if file exists.
+                if (FileExists(FileName) and (not DeleteFile(FileName))) then begin
+                    Log('Line {#emit __LINE__}: Unable to delete file "'+FileName);
                     Break;
                 end;
+                // Try to create symbolic link
+                if Version.Major>=6 then
+                try
+                  LinkCreated:=CreateSymbolicLink(FileName,AppDir+'\bin\git.exe',0);
+                except
+                  LinkCreated:=False;
+                end;
+                // Try to create hard link
+                if (not LinkCreated) and
+                   (not CreateHardLink(FileName,AppDir+'\bin\git.exe',0)) then begin
+                  Log('Line {#emit __LINE__}: Unable to create hard link "'+FileName+'", will try to copy files.');
+                  IsNTFS:=False;
+                  Break;
+                end;
             end;
 
             Log('Line {#emit __LINE__}: Successfully created built-in aliases as hard links.');
-- 
1.6.6.1536.g1ac8c

^ permalink raw reply related

* Re: [PATCH] Add push --set-upstream
From: Ilari Liusvaara @ 2010-01-15 22:06 UTC (permalink / raw)
  To: Jeff King; +Cc: git
In-Reply-To: <20100115171745.GB2115@coredump.intra.peff.net>

On Fri, Jan 15, 2010 at 12:17:45PM -0500, Jeff King wrote:
> On Fri, Jan 15, 2010 at 06:36:47PM +0200, Ilari Liusvaara wrote:
> 
> No tests. But since in writing this you have crossed an item off of my
> long-term todo, I feel obliged to help out by providing some. :)
 
Signoff for those tests? Or do they need it anyway?

<Snip testscript> 

^ permalink raw reply

* [PATCH v2 3/3] difftool: Use eval to expand '--extcmd' expressions
From: David Aguilar @ 2010-01-15 22:03 UTC (permalink / raw)
  To: gitster; +Cc: git, j.sixt
In-Reply-To: <1263593024-12093-1-git-send-email-davvid@gmail.com>

It was not possible to pass quoted commands to '--extcmd'.
By using 'eval' we ensure that expressions with spaces and
quotes are supported.

Signed-off-by: David Aguilar <davvid@gmail.com>
---

Updates since v1:
* Uses a more readable quoting style as suggested by J6t.
* We no longer use a subshell.

 git-difftool--helper.sh |    3 +--
 t/t7800-difftool.sh     |   13 +++++++++++++
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/git-difftool--helper.sh b/git-difftool--helper.sh
index d806eae..a1c5c09 100755
--- a/git-difftool--helper.sh
+++ b/git-difftool--helper.sh
@@ -48,11 +48,10 @@ launch_merge_tool () {
 	fi
 
 	if use_ext_cmd; then
-		$GIT_DIFFTOOL_EXTCMD "$LOCAL" "$REMOTE"
+		eval $GIT_DIFFTOOL_EXTCMD '"$LOCAL"' '"$REMOTE"'
 	else
 		run_merge_tool "$merge_tool"
 	fi
-
 }
 
 if ! use_ext_cmd; then
diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh
index 69e1c34..a183f1d 100755
--- a/t/t7800-difftool.sh
+++ b/t/t7800-difftool.sh
@@ -235,8 +235,21 @@ test_expect_success 'difftool --extcmd cat' '
 test_expect_success 'difftool -x cat' '
 	diff=$(git difftool --no-prompt -x cat branch) &&
 	test "$diff" = branch"$LF"master
+'
+
+test_expect_success 'difftool --extcmd echo arg1' '
+	diff=$(git difftool --no-prompt --extcmd sh\ -c\ \"echo\ \$1\" branch)
+	test "$diff" = file
+'
 
+test_expect_success 'difftool --extcmd cat arg1' '
+	diff=$(git difftool --no-prompt --extcmd sh\ -c\ \"cat\ \$1\" branch)
+	test "$diff" = master
+'
 
+test_expect_success 'difftool --extcmd cat arg2' '
+	diff=$(git difftool --no-prompt --extcmd sh\ -c\ \"cat\ \$2\" branch)
+	test "$diff" = branch
 '
 
 test_done
-- 
1.6.6.6.g627fb.dirty

^ permalink raw reply related

* [PATCH v2 2/3] difftool: Add '-x' and as an alias for '--extcmd'
From: David Aguilar @ 2010-01-15 22:03 UTC (permalink / raw)
  To: gitster; +Cc: git, j.sixt
In-Reply-To: <1263593024-12093-1-git-send-email-davvid@gmail.com>

This adds '-x' as a shorthand for the '--extcmd' option.
Arguments to '--extcmd' can be specified separately, which
was not originally possible.

This also fixes the brief help text so that it mentions
both '-x' and '--extcmd'.

Signed-off-by: David Aguilar <davvid@gmail.com>
---

Changes since v1:

The copyright notice to says "2009, 2010" instead of "2009-2010"

 Documentation/git-difftool.txt |    3 ++-
 git-difftool.perl              |   21 ++++++++++++++-------
 t/t7800-difftool.sh            |    8 ++++++++
 3 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/Documentation/git-difftool.txt b/Documentation/git-difftool.txt
index f67d2db..5c68cff 100644
--- a/Documentation/git-difftool.txt
+++ b/Documentation/git-difftool.txt
@@ -7,7 +7,7 @@ git-difftool - Show changes using common diff tools
 
 SYNOPSIS
 --------
-'git difftool' [--tool=<tool>] [-y|--no-prompt|--prompt] [<'git diff' options>]
+'git difftool' [<options>] <commit>{0,2} [--] [<path>...]
 
 DESCRIPTION
 -----------
@@ -58,6 +58,7 @@ is set to the name of the temporary file containing the contents
 of the diff post-image.  `$BASE` is provided for compatibility
 with custom merge tool commands and has the same value as `$LOCAL`.
 
+-x <command>::
 --extcmd=<command>::
 	Specify a custom command for viewing diffs.
 	'git-difftool' ignores the configured defaults and runs
diff --git a/git-difftool.perl b/git-difftool.perl
index f8ff245..d639de3 100755
--- a/git-difftool.perl
+++ b/git-difftool.perl
@@ -1,5 +1,5 @@
 #!/usr/bin/env perl
-# Copyright (c) 2009 David Aguilar
+# Copyright (c) 2009, 2010 David Aguilar
 #
 # This is a wrapper around the GIT_EXTERNAL_DIFF-compatible
 # git-difftool--helper script.
@@ -23,8 +23,9 @@ my $DIR = abs_path(dirname($0));
 sub usage
 {
 	print << 'USAGE';
-usage: git difftool [-g|--gui] [-t|--tool=<tool>] [-y|--no-prompt]
-                    ["git diff" options]
+usage: git difftool [-t|--tool=<tool>] [-x|--extcmd=<cmd>]
+                    [-y|--no-prompt]   [-g|--gui]
+                    ['git diff' options]
 USAGE
 	exit 1;
 }
@@ -62,14 +63,20 @@ sub generate_command
 			$skip_next = 1;
 			next;
 		}
-		if ($arg =~ /^--extcmd=/) {
-			$ENV{GIT_DIFFTOOL_EXTCMD} = substr($arg, 9);
-			next;
-		}
 		if ($arg =~ /^--tool=/) {
 			$ENV{GIT_DIFF_TOOL} = substr($arg, 7);
 			next;
 		}
+		if ($arg eq '-x' || $arg eq '--extcmd') {
+			usage() if $#ARGV <= $idx;
+			$ENV{GIT_DIFFTOOL_EXTCMD} = $ARGV[$idx + 1];
+			$skip_next = 1;
+			next;
+		}
+		if ($arg =~ /^--extcmd=/) {
+			$ENV{GIT_DIFFTOOL_EXTCMD} = substr($arg, 9);
+			next;
+		}
 		if ($arg eq '-g' || $arg eq '--gui') {
 			my $tool = Git::command_oneline('config',
 			                                'diff.guitool');
diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh
index 1d9e07b..69e1c34 100755
--- a/t/t7800-difftool.sh
+++ b/t/t7800-difftool.sh
@@ -225,8 +225,16 @@ test_expect_success 'difftool.<tool>.path' '
 test_expect_success 'difftool --extcmd=cat' '
 	diff=$(git difftool --no-prompt --extcmd=cat branch) &&
 	test "$diff" = branch"$LF"master
+'
 
+test_expect_success 'difftool --extcmd cat' '
+	diff=$(git difftool --no-prompt --extcmd cat branch) &&
+	test "$diff" = branch"$LF"master
+'
 
+test_expect_success 'difftool -x cat' '
+	diff=$(git difftool --no-prompt -x cat branch) &&
+	test "$diff" = branch"$LF"master
 
 
 '
-- 
1.6.6.6.g627fb.dirty

^ permalink raw reply related

* [PATCH v2 1/3] t7800-difftool.sh: Simplify the --extcmd test
From: David Aguilar @ 2010-01-15 22:03 UTC (permalink / raw)
  To: gitster; +Cc: git, j.sixt

Instead of running 'grep', 'echo', and 'wc' we simply compare
git-difftool's output against a known good value.

Signed-off-by: David Aguilar <davvid@gmail.com>
---

This is unchanged from v1 but is included in the series
for completeness.

These all apply to 'next', specifically the da/difftool branch.

 t/t7800-difftool.sh |   13 +++++--------
 1 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh
index 8ee186a..1d9e07b 100755
--- a/t/t7800-difftool.sh
+++ b/t/t7800-difftool.sh
@@ -15,6 +15,9 @@ if ! test_have_prereq PERL; then
 	test_done
 fi
 
+LF='
+'
+
 remove_config_vars()
 {
 	# Unset all config variables used by git-difftool
@@ -219,19 +222,13 @@ test_expect_success 'difftool.<tool>.path' '
 	restore_test_defaults
 '
 
-test_expect_success 'difftool --extcmd=...' '
+test_expect_success 'difftool --extcmd=cat' '
 	diff=$(git difftool --no-prompt --extcmd=cat branch) &&
+	test "$diff" = branch"$LF"master
 
-	lines=$(echo "$diff" | wc -l) &&
-	test "$lines" -eq 2 &&
 
-	lines=$(echo "$diff" | grep master | wc -l) &&
-	test "$lines" -eq 1 &&
 
-	lines=$(echo "$diff" | grep branch | wc -l) &&
-	test "$lines" -eq 1 &&
 
-	restore_test_defaults
 '
 
 test_done
-- 
1.6.6.6.g627fb.dirty

^ permalink raw reply related

* [PATCH v2 14/14] daemon: report connection from  root-process
From: Erik Faye-Lund @ 2010-01-15 21:30 UTC (permalink / raw)
  To: msysgit; +Cc: git, j6t, Erik Faye-Lund
In-Reply-To: <1263591033-4992-1-git-send-email-kusmabite@gmail.com>

Report incoming connections from the process that
accept() the connection instead of the handling
process.

This enables "Connection from"-reporting on
Windows, where getpeername(0, ...) consistently
fails.

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
 daemon.c |   70 +++++++++++++++++++++++++++++++++++--------------------------
 1 files changed, 40 insertions(+), 30 deletions(-)

diff --git a/daemon.c b/daemon.c
index 95cf299..3423ffa 100644
--- a/daemon.c
+++ b/daemon.c
@@ -493,33 +493,6 @@ static int execute(int fd[2], struct sockaddr *addr)
 	static char line[1000];
 	int pktlen, len, i;
 
-	if (addr) {
-		char addrbuf[256] = "";
-		int port = -1;
-
-		if (addr->sa_family == AF_INET) {
-			struct sockaddr_in *sin_addr = (void *) addr;
-			inet_ntop(addr->sa_family, &sin_addr->sin_addr, addrbuf, sizeof(addrbuf));
-			port = ntohs(sin_addr->sin_port);
-#ifndef NO_IPV6
-		} else if (addr && addr->sa_family == AF_INET6) {
-			struct sockaddr_in6 *sin6_addr = (void *) addr;
-
-			char *buf = addrbuf;
-			*buf++ = '['; *buf = '\0'; /* stpcpy() is cool */
-			inet_ntop(AF_INET6, &sin6_addr->sin6_addr, buf, sizeof(addrbuf) - 1);
-			strcat(buf, "]");
-
-			port = ntohs(sin6_addr->sin6_port);
-#endif
-		}
-		loginfo("Connection from %s:%d", addrbuf, port);
-		setenv("REMOTE_ADDR", addrbuf, 1);
-	}
-	else {
-		unsetenv("REMOTE_ADDR");
-	}
-
 	alarm(init_timeout ? init_timeout : timeout);
 	pktlen = packet_read_line(fd[0], line, sizeof(line));
 	alarm(0);
@@ -645,10 +618,35 @@ static void check_dead_children(void)
 			cradle = &blanket->next;
 }
 
+static char *get_addrstr(int *port, struct sockaddr *addr)
+{
+	static char addrbuf[256] = "";
+	if (addr->sa_family == AF_INET) {
+		struct sockaddr_in *sin_addr = (void *) addr;
+		inet_ntop(addr->sa_family, &sin_addr->sin_addr, addrbuf, sizeof(addrbuf));
+		*port = ntohs(sin_addr->sin_port);
+#ifndef NO_IPV6
+	} else if (addr && addr->sa_family == AF_INET6) {
+		struct sockaddr_in6 *sin6_addr = (void *) addr;
+
+		char *buf = addrbuf;
+		*buf++ = '['; *buf = '\0'; /* stpcpy() is cool */
+		inet_ntop(AF_INET6, &sin6_addr->sin6_addr, buf, sizeof(addrbuf) - 1);
+		strcat(buf, "]");
+
+		*port = ntohs(sin6_addr->sin6_port);
+#endif
+	}
+	return addrbuf;
+}
+
 char **cld_argv;
 static void handle(int incoming, struct sockaddr *addr, socklen_t addrlen)
 {
 	struct child_process cld = { 0 };
+	char *addrstr, envbuf[300] = "REMOTE_ADDR=";
+	char *env[] = { envbuf, NULL };
+	int port = -1;
 
 	if (max_connections && live_children >= max_connections) {
 		kill_some_child();
@@ -661,14 +659,21 @@ static void handle(int incoming, struct sockaddr *addr, socklen_t addrlen)
 		}
 	}
 
+	addrstr = get_addrstr(&port, addr);
+	strcat(envbuf, addrstr);
+
+	cld.env = (const char **)env;
 	cld.argv = (const char **)cld_argv;
 	cld.in = incoming;
 	cld.out = dup(incoming);
 
 	if (start_command(&cld))
 		logerror("unable to fork");
-	else
+	else {
+		loginfo("[%"PRIuMAX"] Connection from %s:%d",
+		    (uintmax_t)cld.pid, addrstr, port);
 		add_child(&cld, addr, addrlen);
+	}
 	close(incoming);
 }
 
@@ -1115,8 +1120,13 @@ int main(int argc, char **argv)
 		if (inetd_mode && !freopen("/dev/null", "w", stderr))
 			die_errno("failed to redirect stderr to /dev/null");
 
-		if (getpeername(0, peer, &slen))
-			peer = NULL;
+		if (!getpeername(0, peer, &slen)) {
+			int port = -1;
+			char *addrstr = get_addrstr(&port, peer);
+			setenv("REMOTE_ADDR", addrstr, 1);
+			loginfo("[%"PRIuMAX"] Connection from %s:%d",
+			    (uintmax_t)getpid(), addrstr, port);
+		}
 
 		return execute(fd, peer);
 	}
-- 
1.6.6.211.g26720

^ permalink raw reply related

* [PATCH v2 13/14] daemon: use select() instead of poll()
From: Erik Faye-Lund @ 2010-01-15 21:30 UTC (permalink / raw)
  To: msysgit; +Cc: git, j6t, Erik Faye-Lund
In-Reply-To: <1263591033-4992-1-git-send-email-kusmabite@gmail.com>

Windows doesn't have poll(), and the poll-emulation in
compat/mingw.c doesn't support checking multiple sockets.

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
 compat/mingw.h |    7 +++++++
 daemon.c       |   27 ++++++++++++---------------
 2 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/compat/mingw.h b/compat/mingw.h
index 173bec5..e515726 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -269,6 +269,13 @@ int mingw_accept(int sockfd, struct sockaddr *sa, socklen_t *sz);
 int mingw_rename(const char*, const char*);
 #define rename mingw_rename
 
+#undef FD_SET
+#define FD_SET(fd, set) do { \
+	((fd_set*)(set))->fd_array[((fd_set *)(set))->fd_count++] = _get_osfhandle(fd); \
+	} while(0)
+#undef FD_ISSET
+#define FD_ISSET(fd, set) __WSAFDIsSet(_get_osfhandle(fd), (fd_set *)(set))
+
 #if defined(USE_WIN32_MMAP) || defined(_MSC_VER)
 int mingw_getpagesize(void);
 #define getpagesize mingw_getpagesize
diff --git a/daemon.c b/daemon.c
index cdf5c72..95cf299 100644
--- a/daemon.c
+++ b/daemon.c
@@ -818,26 +818,23 @@ static int socksetup(char *listen_addr, int listen_port, int **socklist_p)
 
 static int service_loop(int socknum, int *socklist)
 {
-	struct pollfd *pfd;
-	int i;
-
-	pfd = xcalloc(socknum, sizeof(struct pollfd));
-
-	for (i = 0; i < socknum; i++) {
-		pfd[i].fd = socklist[i];
-		pfd[i].events = POLLIN;
-	}
-
 	signal(SIGCHLD, child_handler);
 
 	for (;;) {
-		int i;
+		int i, maxfd = 0;
+		fd_set fds;
 
 		check_dead_children();
 
-		if (poll(pfd, socknum, -1) < 0) {
+		FD_ZERO(&fds);
+		for (i = 0; i < socknum; i++) {
+			FD_SET(socklist[i], &fds);
+			maxfd = socklist[i] > maxfd ? socklist[i] : maxfd;
+		}
+
+		if (select(maxfd + 1, &fds, NULL, NULL, NULL) < 0) {
 			if (errno != EINTR) {
-				logerror("Poll failed, resuming: %s",
+				logerror("select() failed, resuming: %s",
 				      strerror(errno));
 				sleep(1);
 			}
@@ -845,10 +842,10 @@ static int service_loop(int socknum, int *socklist)
 		}
 
 		for (i = 0; i < socknum; i++) {
-			if (pfd[i].revents & POLLIN) {
+			if (FD_ISSET(socklist[i], &fds)) {
 				struct sockaddr_storage ss;
 				socklen_t sslen = sizeof(ss);
-				int incoming = accept(pfd[i].fd, (struct sockaddr *)&ss, &sslen);
+				int incoming = accept(socklist[i], (struct sockaddr *)&ss, &sslen);
 				if (incoming < 0) {
 					switch (errno) {
 					case EAGAIN:
-- 
1.6.6.211.g26720

^ permalink raw reply related

* [PATCH v2 12/14] Improve the mingw getaddrinfo stub to  handle more use cases
From: Erik Faye-Lund @ 2010-01-15 21:30 UTC (permalink / raw)
  To: msysgit; +Cc: git, j6t, Martin Storsjö
In-Reply-To: <1263591033-4992-1-git-send-email-kusmabite@gmail.com>

From: Martin Storsjö <martin@martin.st>

Allow the node parameter to be null, which is used for getting
the default bind address.

Also allow the hints parameter to be null, to improve standard
conformance of the stub implementation a little.

Signed-off-by: Martin Storsjo <martin@martin.st>
---
 compat/mingw.c |   28 +++++++++++++++++++++-------
 1 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/compat/mingw.c b/compat/mingw.c
index 89b9b89..02d411a 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -932,19 +932,22 @@ static int WSAAPI getaddrinfo_stub(const char *node, const char *service,
 				   const struct addrinfo *hints,
 				   struct addrinfo **res)
 {
-	struct hostent *h = gethostbyname(node);
+	struct hostent *h = NULL;
 	struct addrinfo *ai;
 	struct sockaddr_in *sin;
 
-	if (!h)
-		return WSAGetLastError();
+	if (node) {
+		h = gethostbyname(node);
+		if (!h)
+			return WSAGetLastError();
+	}
 
 	ai = xmalloc(sizeof(struct addrinfo));
 	*res = ai;
 	ai->ai_flags = 0;
 	ai->ai_family = AF_INET;
-	ai->ai_socktype = hints->ai_socktype;
-	switch (hints->ai_socktype) {
+	ai->ai_socktype = hints ? hints->ai_socktype : 0;
+	switch (ai->ai_socktype) {
 	case SOCK_STREAM:
 		ai->ai_protocol = IPPROTO_TCP;
 		break;
@@ -956,14 +959,25 @@ static int WSAAPI getaddrinfo_stub(const char *node, const char *service,
 		break;
 	}
 	ai->ai_addrlen = sizeof(struct sockaddr_in);
-	ai->ai_canonname = strdup(h->h_name);
+	if (hints && (hints->ai_flags & AI_CANONNAME))
+		ai->ai_canonname = h ? strdup(h->h_name) : NULL;
+	else
+		ai->ai_canonname = NULL;
 
 	sin = xmalloc(ai->ai_addrlen);
 	memset(sin, 0, ai->ai_addrlen);
 	sin->sin_family = AF_INET;
+	/* Note: getaddrinfo is supposed to allow service to be a string,
+	 * which should be looked up using getservbyname. This is
+	 * currently not implemented */
 	if (service)
 		sin->sin_port = htons(atoi(service));
-	sin->sin_addr = *(struct in_addr *)h->h_addr;
+	if (h)
+		sin->sin_addr = *(struct in_addr *)h->h_addr;
+	else if (hints && (hints->ai_flags & AI_PASSIVE))
+		sin->sin_addr.s_addr = INADDR_ANY;
+	else
+		sin->sin_addr.s_addr = INADDR_LOOPBACK;
 	ai->ai_addr = (struct sockaddr *)sin;
 	ai->ai_next = 0;
 	return 0;
-- 
1.6.6.211.g26720

^ permalink raw reply related

* [PATCH v2 11/14] mingw: compile git-daemon
From: Erik Faye-Lund @ 2010-01-15 21:30 UTC (permalink / raw)
  To: msysgit; +Cc: git, j6t, Erik Faye-Lund
In-Reply-To: <1263591033-4992-1-git-send-email-kusmabite@gmail.com>

--user and --detach are disabled on Windows due to lack of
fork(), setuid(), setgid(), setsid() and initgroups().

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
 Makefile       |    8 +++-----
 compat/mingw.h |    1 +
 daemon.c       |   19 ++++++++++++++-----
 3 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/Makefile b/Makefile
index d81b392..cb6c36d 100644
--- a/Makefile
+++ b/Makefile
@@ -390,6 +390,7 @@ EXTRA_PROGRAMS =
 
 # ... and all the rest that could be moved out of bindir to gitexecdir
 PROGRAMS += $(EXTRA_PROGRAMS)
+PROGRAMS += git-daemon$X
 PROGRAMS += git-fast-import$X
 PROGRAMS += git-hash-object$X
 PROGRAMS += git-imap-send$X
@@ -986,7 +987,6 @@ ifeq ($(uname_S),Windows)
 	NO_SVN_TESTS = YesPlease
 	NO_PERL_MAKEMAKER = YesPlease
 	RUNTIME_PREFIX = YesPlease
-	NO_POSIX_ONLY_PROGRAMS = YesPlease
 	NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
 	NO_NSEC = YesPlease
 	USE_WIN32_MMAP = YesPlease
@@ -1037,7 +1037,6 @@ ifneq (,$(findstring MINGW,$(uname_S)))
 	NO_SVN_TESTS = YesPlease
 	NO_PERL_MAKEMAKER = YesPlease
 	RUNTIME_PREFIX = YesPlease
-	NO_POSIX_ONLY_PROGRAMS = YesPlease
 	NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
 	NO_NSEC = YesPlease
 	USE_WIN32_MMAP = YesPlease
@@ -1047,6 +1046,8 @@ ifneq (,$(findstring MINGW,$(uname_S)))
 	NO_REGEX = YesPlease
 	BLK_SHA1 = YesPlease
 	NO_PYTHON = YesPlease
+	NO_INET_PTON = YesPlease
+	NO_INET_NTOP = YesPlease
 	COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/fnmatch
 	COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
 	COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o
@@ -1141,9 +1142,6 @@ ifdef ZLIB_PATH
 endif
 EXTLIBS += -lz
 
-ifndef NO_POSIX_ONLY_PROGRAMS
-	PROGRAMS += git-daemon$X
-endif
 ifndef NO_OPENSSL
 	OPENSSL_LIBSSL = -lssl
 	ifdef OPENSSLDIR
diff --git a/compat/mingw.h b/compat/mingw.h
index e72c2ee..173bec5 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -7,6 +7,7 @@
 
 typedef int pid_t;
 typedef int socklen_t;
+typedef unsigned int gid_t;
 #define hstrerror strerror
 
 #define S_IFLNK    0120000 /* Symbolic link */
diff --git a/daemon.c b/daemon.c
index fc2c150..cdf5c72 100644
--- a/daemon.c
+++ b/daemon.c
@@ -589,7 +589,7 @@ static struct child {
 	struct sockaddr_storage address;
 } *firstborn;
 
-static void add_child(struct child_process *cld, struct sockaddr *addr, int addrlen)
+static void add_child(struct child_process *cld, struct sockaddr *addr, socklen_t addrlen)
 {
 	struct child *newborn, **cradle;
 
@@ -646,7 +646,7 @@ static void check_dead_children(void)
 }
 
 char **cld_argv;
-static void handle(int incoming, struct sockaddr *addr, int addrlen)
+static void handle(int incoming, struct sockaddr *addr, socklen_t addrlen)
 {
 	struct child_process cld = { 0 };
 
@@ -847,7 +847,7 @@ static int service_loop(int socknum, int *socklist)
 		for (i = 0; i < socknum; i++) {
 			if (pfd[i].revents & POLLIN) {
 				struct sockaddr_storage ss;
-				unsigned int sslen = sizeof(ss);
+				socklen_t sslen = sizeof(ss);
 				int incoming = accept(pfd[i].fd, (struct sockaddr *)&ss, &sslen);
 				if (incoming < 0) {
 					switch (errno) {
@@ -879,6 +879,7 @@ static void sanitize_stdfds(void)
 
 static void daemonize(void)
 {
+#ifndef WIN32
 	switch (fork()) {
 		case 0:
 			break;
@@ -893,6 +894,9 @@ static void daemonize(void)
 	close(1);
 	close(2);
 	sanitize_stdfds();
+#else
+	die("--detach is not supported on Windows");
+#endif
 }
 
 static void store_pid(const char *path)
@@ -913,10 +917,12 @@ static int serve(char *listen_addr, int listen_port, struct passwd *pass, gid_t
 		die("unable to allocate any listen sockets on host %s port %u",
 		    listen_addr, listen_port);
 
+#ifndef WIN32
 	if (pass && gid &&
 	    (initgroups(pass->pw_name, gid) || setgid (gid) ||
 	     setuid(pass->pw_uid)))
 		die("cannot drop privileges");
+#endif
 
 	return service_loop(socknum, socklist);
 }
@@ -929,7 +935,6 @@ int main(int argc, char **argv)
 	const char *pid_file = NULL, *user_name = NULL, *group_name = NULL;
 	int detach = 0;
 	struct passwd *pass = NULL;
-	struct group *group;
 	gid_t gid = 0;
 	int i;
 
@@ -1078,6 +1083,7 @@ int main(int argc, char **argv)
 		die("--group supplied without --user");
 
 	if (user_name) {
+#ifndef WIN32
 		pass = getpwnam(user_name);
 		if (!pass)
 			die("user not found - %s", user_name);
@@ -1085,12 +1091,15 @@ int main(int argc, char **argv)
 		if (!group_name)
 			gid = pass->pw_gid;
 		else {
-			group = getgrnam(group_name);
+			struct group *group = getgrnam(group_name);
 			if (!group)
 				die("group not found - %s", group_name);
 
 			gid = group->gr_gid;
 		}
+#else
+		die("--user is not supported on Windows");
+#endif
 	}
 
 	if (strict_paths && (!ok_paths || !*ok_paths))
-- 
1.6.6.211.g26720

^ permalink raw reply related

* [PATCH v2 10/14] daemon: use full buffered mode for stderr
From: Erik Faye-Lund @ 2010-01-15 21:30 UTC (permalink / raw)
  To: msysgit; +Cc: git, j6t, Erik Faye-Lund
In-Reply-To: <1263591033-4992-1-git-send-email-kusmabite@gmail.com>

Windows doesn't support line buffered mode for file
streams, so let's just use full buffered mode with
a big buffer ("4096 should be enough for everyone")
and add explicit flushing.

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
 daemon.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/daemon.c b/daemon.c
index 2d63cbc..fc2c150 100644
--- a/daemon.c
+++ b/daemon.c
@@ -66,12 +66,14 @@ static void logreport(int priority, const char *err, va_list params)
 		syslog(priority, "%s", buf);
 	} else {
 		/*
-		 * Since stderr is set to linebuffered mode, the
+		 * Since stderr is set to buffered mode, the
 		 * logging of different processes will not overlap
+		 * unless they overflow the (rather big) buffers.
 		 */
 		fprintf(stderr, "[%"PRIuMAX"] ", (uintmax_t)getpid());
 		vfprintf(stderr, err, params);
 		fputc('\n', stderr);
+		fflush(stderr);
 	}
 }
 
@@ -1062,7 +1064,7 @@ int main(int argc, char **argv)
 		set_die_routine(daemon_die);
 	} else
 		/* avoid splitting a message in the middle */
-		setvbuf(stderr, NULL, _IOLBF, 0);
+		setvbuf(stderr, NULL, _IOFBF, 4096);
 
 	if (inetd_mode && (group_name || user_name))
 		die("--user and --group are incompatible with --inetd");
-- 
1.6.6.211.g26720

^ permalink raw reply related

* [PATCH v2 09/14] daemon: use run-command api for async serving
From: Erik Faye-Lund @ 2010-01-15 21:30 UTC (permalink / raw)
  To: msysgit; +Cc: git, j6t, Erik Faye-Lund
In-Reply-To: <1263591033-4992-1-git-send-email-kusmabite@gmail.com>

fork() is only available on POSIX, so to support git-daemon
on Windows we have to use something else. Conveniently
enough, we have an API for async operation already.

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
 daemon.c |   87 +++++++++++++++++++++++++++++++------------------------------
 1 files changed, 44 insertions(+), 43 deletions(-)

diff --git a/daemon.c b/daemon.c
index b42792f..2d63cbc 100644
--- a/daemon.c
+++ b/daemon.c
@@ -583,17 +583,17 @@ static unsigned int live_children;
 
 static struct child {
 	struct child *next;
-	pid_t pid;
+	struct child_process cld;
 	struct sockaddr_storage address;
 } *firstborn;
 
-static void add_child(pid_t pid, struct sockaddr *addr, int addrlen)
+static void add_child(struct child_process *cld, struct sockaddr *addr, int addrlen)
 {
 	struct child *newborn, **cradle;
 
 	newborn = xcalloc(1, sizeof(*newborn));
 	live_children++;
-	newborn->pid = pid;
+	memcpy(&newborn->cld, cld, sizeof(*cld));
 	memcpy(&newborn->address, addr, addrlen);
 	for (cradle = &firstborn; *cradle; cradle = &(*cradle)->next)
 		if (!addrcmp(&(*cradle)->address, &newborn->address))
@@ -602,19 +602,6 @@ static void add_child(pid_t pid, struct sockaddr *addr, int addrlen)
 	*cradle = newborn;
 }
 
-static void remove_child(pid_t pid)
-{
-	struct child **cradle, *blanket;
-
-	for (cradle = &firstborn; (blanket = *cradle); cradle = &blanket->next)
-		if (blanket->pid == pid) {
-			*cradle = blanket->next;
-			live_children--;
-			free(blanket);
-			break;
-		}
-}
-
 /*
  * This gets called if the number of connections grows
  * past "max_connections".
@@ -623,14 +610,14 @@ static void remove_child(pid_t pid)
  */
 static void kill_some_child(void)
 {
-	const struct child *blanket, *next;
+	struct child *blanket, *next;
 
 	if (!(blanket = firstborn))
 		return;
 
 	for (; (next = blanket->next); blanket = next)
 		if (!addrcmp(&blanket->address, &next->address)) {
-			kill(blanket->pid, SIGTERM);
+			kill(blanket->cld.pid, SIGTERM);
 			break;
 		}
 }
@@ -640,19 +627,26 @@ static void check_dead_children(void)
 	int status;
 	pid_t pid;
 
-	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
-		const char *dead = "";
-		remove_child(pid);
-		if (!WIFEXITED(status) || (WEXITSTATUS(status) > 0))
-			dead = " (with error)";
-		loginfo("[%"PRIuMAX"] Disconnected%s", (uintmax_t)pid, dead);
-	}
+	struct child **cradle, *blanket;
+	for (cradle = &firstborn; (blanket = *cradle);)
+		if ((pid = waitpid(blanket->cld.pid, &status, WNOHANG)) > 1) {
+			const char *dead = "";
+			if (status)
+				dead = " (with error)";
+			loginfo("[%"PRIuMAX"] Disconnected%s", (uintmax_t)pid, dead);
+
+			/* remove the child */
+			*cradle = blanket->next;
+			live_children--;
+			free(blanket);
+		} else
+			cradle = &blanket->next;
 }
 
+char **cld_argv;
 static void handle(int incoming, struct sockaddr *addr, int addrlen)
 {
-	int fd[2];
-	pid_t pid;
+	struct child_process cld = { 0 };
 
 	if (max_connections && live_children >= max_connections) {
 		kill_some_child();
@@ -665,20 +659,15 @@ static void handle(int incoming, struct sockaddr *addr, int addrlen)
 		}
 	}
 
-	if ((pid = fork())) {
-		close(incoming);
-		if (pid < 0) {
-			logerror("Couldn't fork %s", strerror(errno));
-			return;
-		}
-
-		add_child(pid, addr, addrlen);
-		return;
-	}
+	cld.argv = (const char **)cld_argv;
+	cld.in = incoming;
+	cld.out = dup(incoming);
 
-	fd[0] = incoming;
-	fd[1] = dup(incoming);
-	exit(execute(fd, addr));
+	if (start_command(&cld))
+		logerror("unable to fork");
+	else
+		add_child(&cld, addr, addrlen);
+	close(incoming);
 }
 
 static void child_handler(int signo)
@@ -934,7 +923,7 @@ int main(int argc, char **argv)
 {
 	int listen_port = 0;
 	char *listen_addr = NULL;
-	int inetd_mode = 0;
+	int serve_mode = 0, inetd_mode = 0;
 	const char *pid_file = NULL, *user_name = NULL, *group_name = NULL;
 	int detach = 0;
 	struct passwd *pass = NULL;
@@ -960,7 +949,12 @@ int main(int argc, char **argv)
 				continue;
 			}
 		}
+		if (!strcmp(arg, "--serve")) {
+			serve_mode = 1;
+			continue;
+		}
 		if (!strcmp(arg, "--inetd")) {
+			serve_mode = 1;
 			inetd_mode = 1;
 			log_syslog = 1;
 			continue;
@@ -1104,13 +1098,13 @@ int main(int argc, char **argv)
 		die("base-path '%s' does not exist or is not a directory",
 		    base_path);
 
-	if (inetd_mode) {
+	if (serve_mode) {
 		int fd[2] = { 0, 1 };
 		struct sockaddr_storage ss;
 		struct sockaddr *peer = (struct sockaddr *)&ss;
 		socklen_t slen = sizeof(ss);
 
-		if (!freopen("/dev/null", "w", stderr))
+		if (inetd_mode && !freopen("/dev/null", "w", stderr))
 			die_errno("failed to redirect stderr to /dev/null");
 
 		if (getpeername(0, peer, &slen))
@@ -1129,5 +1123,12 @@ int main(int argc, char **argv)
 	if (pid_file)
 		store_pid(pid_file);
 
+	/* prepare argv for serving-processes */
+	cld_argv = xmalloc(sizeof (char *) * (argc + 2));
+	for (i = 0; i < argc; ++i)
+		cld_argv[i] = argv[i];
+	cld_argv[argc] = "--serve";
+	cld_argv[argc+1] = NULL;
+
 	return serve(listen_addr, listen_port, pass, gid);
 }
-- 
1.6.6.211.g26720

^ permalink raw reply related

* [PATCH v2 08/14] daemon: use explicit file descriptor
From: Erik Faye-Lund @ 2010-01-15 21:30 UTC (permalink / raw)
  To: msysgit; +Cc: git, j6t, Erik Faye-Lund
In-Reply-To: <1263591033-4992-1-git-send-email-kusmabite@gmail.com>

This patch adds support to specify an explicit file
descriotor for communication with the client, instead
of using stdin/stdout.

This will be useful for the Windows port, because it
will use threads instead of fork() to serve multiple
clients, making it impossible to reuse stdin/stdout.

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
 daemon.c |   43 +++++++++++++++++++++----------------------
 1 files changed, 21 insertions(+), 22 deletions(-)

diff --git a/daemon.c b/daemon.c
index 79ba1aa..b42792f 100644
--- a/daemon.c
+++ b/daemon.c
@@ -218,7 +218,7 @@ static char *path_ok(char *directory)
 	return NULL;		/* Fallthrough. Deny by default */
 }
 
-typedef int (*daemon_service_fn)(void);
+typedef int (*daemon_service_fn)(int [2]);
 struct daemon_service {
 	const char *name;
 	const char *config_name;
@@ -242,7 +242,7 @@ static int git_daemon_config(const char *var, const char *value, void *cb)
 	return 0;
 }
 
-static int run_service(char *dir, struct daemon_service *service)
+static int run_service(int fd[2], char *dir, struct daemon_service *service)
 {
 	const char *path;
 	int enabled = service->enabled;
@@ -295,7 +295,7 @@ static int run_service(char *dir, struct daemon_service *service)
 	 */
 	signal(SIGTERM, SIG_IGN);
 
-	return service->fn();
+	return service->fn(fd);
 }
 
 static void copy_to_log(int fd)
@@ -319,7 +319,7 @@ static void copy_to_log(int fd)
 	fclose(fp);
 }
 
-static int run_service_command(const char **argv)
+static int run_service_command(int fd[2], const char **argv)
 {
 	struct child_process cld;
 
@@ -327,37 +327,36 @@ static int run_service_command(const char **argv)
 	cld.argv = argv;
 	cld.git_cmd = 1;
 	cld.err = -1;
+	cld.in = fd[0];
+	cld.out = fd[1];
 	if (start_command(&cld))
 		return -1;
 
-	close(0);
-	close(1);
-
 	copy_to_log(cld.err);
 
 	return finish_command(&cld);
 }
 
-static int upload_pack(void)
+static int upload_pack(int fd[2])
 {
 	/* Timeout as string */
 	char timeout_buf[64];
 	const char *argv[] = { "upload-pack", "--strict", timeout_buf, ".", NULL };
 
 	snprintf(timeout_buf, sizeof timeout_buf, "--timeout=%u", timeout);
-	return run_service_command(argv);
+	return run_service_command(fd, argv);
 }
 
-static int upload_archive(void)
+static int upload_archive(int fd[2])
 {
 	static const char *argv[] = { "upload-archive", ".", NULL };
-	return run_service_command(argv);
+	return run_service_command(fd, argv);
 }
 
-static int receive_pack(void)
+static int receive_pack(int fd[2])
 {
 	static const char *argv[] = { "receive-pack", ".", NULL };
-	return run_service_command(argv);
+	return run_service_command(fd, argv);
 }
 
 static struct daemon_service daemon_service[] = {
@@ -487,7 +486,7 @@ static void parse_host_arg(char *extra_args, int buflen)
 }
 
 
-static int execute(struct sockaddr *addr)
+static int execute(int fd[2], struct sockaddr *addr)
 {
 	static char line[1000];
 	int pktlen, len, i;
@@ -520,7 +519,7 @@ static int execute(struct sockaddr *addr)
 	}
 
 	alarm(init_timeout ? init_timeout : timeout);
-	pktlen = packet_read_line(0, line, sizeof(line));
+	pktlen = packet_read_line(fd[0], line, sizeof(line));
 	alarm(0);
 
 	len = strlen(line);
@@ -552,7 +551,7 @@ static int execute(struct sockaddr *addr)
 			 * Note: The directory here is probably context sensitive,
 			 * and might depend on the actual service being performed.
 			 */
-			return run_service(line + namelen + 5, s);
+			return run_service(fd, line + namelen + 5, s);
 		}
 	}
 
@@ -652,6 +651,7 @@ static void check_dead_children(void)
 
 static void handle(int incoming, struct sockaddr *addr, int addrlen)
 {
+	int fd[2];
 	pid_t pid;
 
 	if (max_connections && live_children >= max_connections) {
@@ -676,11 +676,9 @@ static void handle(int incoming, struct sockaddr *addr, int addrlen)
 		return;
 	}
 
-	dup2(incoming, 0);
-	dup2(incoming, 1);
-	close(incoming);
-
-	exit(execute(addr));
+	fd[0] = incoming;
+	fd[1] = dup(incoming);
+	exit(execute(fd, addr));
 }
 
 static void child_handler(int signo)
@@ -1107,6 +1105,7 @@ int main(int argc, char **argv)
 		    base_path);
 
 	if (inetd_mode) {
+		int fd[2] = { 0, 1 };
 		struct sockaddr_storage ss;
 		struct sockaddr *peer = (struct sockaddr *)&ss;
 		socklen_t slen = sizeof(ss);
@@ -1117,7 +1116,7 @@ int main(int argc, char **argv)
 		if (getpeername(0, peer, &slen))
 			peer = NULL;
 
-		return execute(peer);
+		return execute(fd, peer);
 	}
 
 	if (detach) {
-- 
1.6.6.211.g26720

^ permalink raw reply related

* [PATCH v2 07/14] mingw: add kill emulation
From: Erik Faye-Lund @ 2010-01-15 21:30 UTC (permalink / raw)
  To: msysgit; +Cc: git, j6t, Erik Faye-Lund
In-Reply-To: <1263591033-4992-1-git-send-email-kusmabite@gmail.com>

This is a quite limited kill-emulation; it can only handle
SIGTERM on positive pids. However, it's enough for git-daemon.

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
 compat/mingw.c |   19 +++++++++++++++++++
 compat/mingw.h |    3 +++
 2 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/compat/mingw.c b/compat/mingw.c
index ce4f829..89b9b89 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -829,6 +829,25 @@ void mingw_execvp(const char *cmd, char *const *argv)
 	free_path_split(path);
 }
 
+int mingw_kill(pid_t pid, int sig)
+{
+	if (pid > 0 && sig == SIGTERM) {
+		HANDLE h = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
+
+		if (TerminateProcess(h, -1)) {
+			CloseHandle(h);
+			return 0;
+		}
+
+		CloseHandle(h);
+		errno = err_win_to_posix(GetLastError());
+		return -1;
+	}
+
+	errno = EINVAL;
+	return -1;
+}
+
 static char **copy_environ(void)
 {
 	char **env;
diff --git a/compat/mingw.h b/compat/mingw.h
index ff4a76b..e72c2ee 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -176,6 +176,9 @@ static inline int waitpid(pid_t pid, int *status, unsigned options)
 	return -1;
 }
 
+#define kill mingw_kill
+int mingw_kill(pid_t pid, int sig);
+
 #ifndef NO_OPENSSL
 #include <openssl/ssl.h>
 static inline int mingw_SSL_set_fd(SSL *ssl, int fd)
-- 
1.6.6.211.g26720

^ permalink raw reply related

* [PATCH v2 06/14] mingw: use real pid
From: Erik Faye-Lund @ 2010-01-15 21:30 UTC (permalink / raw)
  To: msysgit; +Cc: git, j6t, Erik Faye-Lund
In-Reply-To: <1263591033-4992-1-git-send-email-kusmabite@gmail.com>

The Windows port so far used process handles as PID. However,
this does not work consistently with getpid.

Change the code to use the real PID, and use OpenProcess to
get a process-handle.

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
 compat/mingw.c |    2 +-
 compat/mingw.h |   35 +++++++++++++++++++++++++++++++----
 2 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/compat/mingw.c b/compat/mingw.c
index 54be905..ce4f829 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -729,7 +729,7 @@ static pid_t mingw_spawnve(const char *cmd, const char **argv, char **env,
 		return -1;
 	}
 	CloseHandle(pi.hThread);
-	return (pid_t)pi.hProcess;
+	return (pid_t)pi.dwProcessId;
 }
 
 pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env)
diff --git a/compat/mingw.h b/compat/mingw.h
index 3005472..ff4a76b 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -137,14 +137,41 @@ static inline int mingw_unlink(const char *pathname)
 #define WNOHANG 1
 static inline int waitpid(pid_t pid, int *status, unsigned options)
 {
-	if (pid > 0 && options & WNOHANG) {
-		if (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)pid, 0))
+	HANDLE h;
+
+	if (pid <= 0) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	h = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, FALSE, pid);
+	if (!h) {
+		errno = ECHILD;
+		return -1;
+	}
+
+	if (options & WNOHANG) {
+		if (WaitForSingleObject(h, 0) != WAIT_OBJECT_0) {
+			CloseHandle(h);
 			return 0;
+		}
 		options &= ~WNOHANG;
 	}
 
-	if (options == 0)
-		return _cwait(status, pid, 0);
+	if (options == 0) {
+		if (WaitForSingleObject(h, INFINITE) != WAIT_OBJECT_0) {
+			CloseHandle(h);
+			return 0;
+		}
+
+		if (status)
+			GetExitCodeProcess(h, (LPDWORD)status);
+
+		CloseHandle(h);
+		return pid;
+	}
+	CloseHandle(h);
+
 	errno = EINVAL;
 	return -1;
 }
-- 
1.6.6.211.g26720

^ permalink raw reply related

* [PATCH v2 05/14] mingw: support waitpid with pid > 0 and WNOHANG
From: Erik Faye-Lund @ 2010-01-15 21:30 UTC (permalink / raw)
  To: msysgit; +Cc: git, j6t, Erik Faye-Lund
In-Reply-To: <1263591033-4992-1-git-send-email-kusmabite@gmail.com>

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
 compat/mingw.h |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/compat/mingw.h b/compat/mingw.h
index d934e56..3005472 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -134,8 +134,15 @@ static inline int mingw_unlink(const char *pathname)
 }
 #define unlink mingw_unlink
 
+#define WNOHANG 1
 static inline int waitpid(pid_t pid, int *status, unsigned options)
 {
+	if (pid > 0 && options & WNOHANG) {
+		if (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)pid, 0))
+			return 0;
+		options &= ~WNOHANG;
+	}
+
 	if (options == 0)
 		return _cwait(status, pid, 0);
 	errno = EINVAL;
-- 
1.6.6.211.g26720

^ permalink raw reply related

* [PATCH v2 04/14] inet_ntop: fix a couple of old-style decls
From: Erik Faye-Lund @ 2010-01-15 21:30 UTC (permalink / raw)
  To: msysgit; +Cc: git, j6t, Erik Faye-Lund
In-Reply-To: <1263591033-4992-1-git-send-email-kusmabite@gmail.com>

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
 compat/inet_ntop.c |   16 +++-------------
 1 files changed, 3 insertions(+), 13 deletions(-)

diff --git a/compat/inet_ntop.c b/compat/inet_ntop.c
index e5b46a0..ea249c6 100644
--- a/compat/inet_ntop.c
+++ b/compat/inet_ntop.c
@@ -50,10 +50,7 @@
  *	Paul Vixie, 1996.
  */
 static const char *
-inet_ntop4(src, dst, size)
-	const u_char *src;
-	char *dst;
-	size_t size;
+inet_ntop4(const u_char *src, char *dst, size_t size)
 {
 	static const char fmt[] = "%u.%u.%u.%u";
 	char tmp[sizeof "255.255.255.255"];
@@ -78,10 +75,7 @@ inet_ntop4(src, dst, size)
  *	Paul Vixie, 1996.
  */
 static const char *
-inet_ntop6(src, dst, size)
-	const u_char *src;
-	char *dst;
-	size_t size;
+inet_ntop6(const u_char *src, char *dst, size_t size)
 {
 	/*
 	 * Note that int32_t and int16_t need only be "at least" large enough
@@ -178,11 +172,7 @@ inet_ntop6(src, dst, size)
  *	Paul Vixie, 1996.
  */
 const char *
-inet_ntop(af, src, dst, size)
-	int af;
-	const void *src;
-	char *dst;
-	size_t size;
+inet_ntop(int af, const void *src, char *dst, size_t size)
 {
 	switch (af) {
 	case AF_INET:
-- 
1.6.6.211.g26720

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox