From: Junio C Hamano Date: Tue, 18 Dec 2007 04:49:42 +0000 (-0800) Subject: Merge branch 'maint' X-Git-Tag: v1.5.4-rc1~20 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/bd8ff616c998da8b08bd59b47644408048b3016d?ds=sidebyside;hp=-c Merge branch 'maint' * maint: git-send-email: avoid duplicate message-ids clone: correctly report http_fetch errors --- bd8ff616c998da8b08bd59b47644408048b3016d diff --combined git-clone.sh index 68085a3225,036a37e85c..9a160eea52 --- a/git-clone.sh +++ b/git-clone.sh @@@ -8,36 -8,15 +8,36 @@@ # See git-sh-setup why. unset CDPATH +OPTIONS_SPEC="\ +git-clone [options] [--] [] +-- +n,no-checkout don't create a checkout +bare create a bare repository +naked create a bare repository +l,local to clone from a local repository +no-hardlinks don't use local hardlinks, always copy +s,shared setup as a shared repository +template= path to the template directory +q,quiet be quiet +reference= reference repository +o,origin= use instead of 'origin' to track upstream +u,upload-pack= path to git-upload-pack on the remote +depth= create a shallow clone of that depth + +use-separate-remote compatibility, do not use +no-separate-remote compatibility, do not use" + die() { echo >&2 "$@" exit 1 } usage() { - die "Usage: $0 [--template=] [--reference ] [--bare] [-l [-s]] [-q] [-u ] [--origin ] [--depth ] [-n] []" + exec "$0" -h } +eval "$(echo "$OPTIONS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?)" + get_repo_base() { ( cd "`/bin/pwd`" && @@@ -56,11 -35,12 +56,12 @@@ f http_fetch () { # $1 = Remote, $2 = Local - curl -nsfL $curl_extra_args "$1" >"$2" || - case $? in - 126|127) exit ;; - *) return $? ;; - esac + curl -nsfL $curl_extra_args "$1" >"$2" + curl_exit_status=$? + case $curl_exit_status in + 126|127) exit ;; + *) return $curl_exit_status ;; + esac } clone_dumb_http () { @@@ -127,57 -107,64 +128,57 @@@ depth no_progress= local_explicitly_asked_for= test -t 1 || no_progress=--no-progress -while - case "$#,$1" in - 0,*) break ;; - *,-n|*,--no|*,--no-|*,--no-c|*,--no-ch|*,--no-che|*,--no-chec|\ - *,--no-check|*,--no-checko|*,--no-checkou|*,--no-checkout) - no_checkout=yes ;; - *,--na|*,--nak|*,--nake|*,--naked|\ - *,-b|*,--b|*,--ba|*,--bar|*,--bare) bare=yes ;; - *,-l|*,--l|*,--lo|*,--loc|*,--loca|*,--local) - local_explicitly_asked_for=yes - use_local_hardlink=yes ;; - *,--no-h|*,--no-ha|*,--no-har|*,--no-hard|*,--no-hardl|\ - *,--no-hardli|*,--no-hardlin|*,--no-hardlink|*,--no-hardlinks) - use_local_hardlink=no ;; - *,-s|*,--s|*,--sh|*,--sha|*,--shar|*,--share|*,--shared) - local_shared=yes; ;; - 1,--template) usage ;; - *,--template) + +while test $# != 0 +do + case "$1" in + -n|--no-checkout) + no_checkout=yes ;; + --naked|--bare) + bare=yes ;; + -l|--local) + local_explicitly_asked_for=yes + use_local_hardlink=yes + ;; + --no-hardlinks) + use_local_hardlink=no ;; + -s|--shared) + local_shared=yes ;; + --template) shift; template="--template=$1" ;; - *,--template=*) - template="$1" ;; - *,-q|*,--quiet) quiet=-q ;; - *,--use-separate-remote) ;; - *,--no-separate-remote) + -q|--quiet) + quiet=-q ;; + --use-separate-remote|--no-separate-remote) die "clones are always made with separate-remote layout" ;; - 1,--reference) usage ;; - *,--reference) + --reference) shift; reference="$1" ;; - *,--reference=*) - reference=`expr "z$1" : 'z--reference=\(.*\)'` ;; - *,-o|*,--or|*,--ori|*,--orig|*,--origi|*,--origin) - case "$2" in + -o,--origin) + shift; + case "$1" in '') usage ;; */*) - die "'$2' is not suitable for an origin name" + die "'$1' is not suitable for an origin name" esac - git check-ref-format "heads/$2" || - die "'$2' is not suitable for a branch name" + git check-ref-format "heads/$1" || + die "'$1' is not suitable for a branch name" test -z "$origin_override" || die "Do not give more than one --origin options." origin_override=yes - origin="$2"; shift + origin="$1" ;; - 1,-u|1,--upload-pack) usage ;; - *,-u|*,--upload-pack) + -u|--upload-pack) shift upload_pack="--upload-pack=$1" ;; - *,--upload-pack=*) - upload_pack=--upload-pack=$(expr "z$1" : 'z-[^=]*=\(.*\)') ;; - 1,--depth) usage;; - *,--depth) + --depth) + shift + depth="--depth=$1" ;; + --) shift - depth="--depth=$1";; - *,-*) usage ;; - *) break ;; + break ;; + *) + usage ;; esac -do shift done @@@ -205,10 -192,7 +206,10 @@@ f # it is local if base=$(get_repo_base "$repo"); then repo="$base" - local=yes + if test -z "$depth" + then + local=yes + fi fi dir="$2" @@@ -232,7 -216,7 +233,7 @@@ cleanup() trap cleanup 0 mkdir -p "$dir" && D=$(cd "$dir" && pwd) || usage test -n "$GIT_WORK_TREE" && mkdir -p "$GIT_WORK_TREE" && -W=$(cd "$GIT_WORK_TREE" && pwd) && export GIT_WORK_TREE="$W" +W=$(cd "$GIT_WORK_TREE" && pwd) && GIT_WORK_TREE="$W" && export GIT_WORK_TREE if test yes = "$bare" || test -n "$GIT_WORK_TREE"; then GIT_DIR="$D" else @@@ -300,8 -284,7 +301,8 @@@ yes find objects -type f -print | sed -e 1q) # objects directory should not be empty because # we are cloning! - test -f "$repo/$sample_file" || exit + test -f "$repo/$sample_file" || + die "fatal: cannot clone empty repository" if ln "$repo/$sample_file" "$GIT_DIR/objects/sample" 2>/dev/null then rm -f "$GIT_DIR/objects/sample" diff --combined git-send-email.perl index 1d6f466453,e8354c760b..248d035088 --- a/git-send-email.perl +++ b/git-send-email.perl @@@ -73,22 -73,11 +73,22 @@@ Options --signed-off-cc Automatically add email addresses that appear in Signed-off-by: or Cc: lines to the cc: list. Defaults to on. + --identity The configuration identity, a subsection to prioritise over + the default section. + --smtp-server If set, specifies the outgoing SMTP server to use. - Defaults to localhost. + Defaults to localhost. Port number can be specified here with + hostname:port format or by using --smtp-server-port option. + + --smtp-server-port Specify a port on the outgoing SMTP server to connect to. + + --smtp-user The username for SMTP-AUTH. - --suppress-from Suppress sending emails to yourself if your address - appears in a From: line. Defaults to off. + --smtp-pass The password for SMTP-AUTH. + + --smtp-ssl If set, connects to the SMTP server using SSL. + + --suppress-from Suppress sending emails to yourself. Defaults to off. --thread Specify that the "In-Reply-To:" header should be set on all emails. Defaults to on. @@@ -145,7 -134,6 +145,7 @@@ sub format_2822_time my $have_email_valid = eval { require Email::Valid; 1 }; my $smtp; +my $auth; sub unique_email_list(@); sub cleanup_compose_files(); @@@ -157,6 -145,7 +157,6 @@@ my $compose_filename = ".msg.$$" my (@to,@cc,@initial_cc,@bcclist,@xh, $initial_reply_to,$initial_subject,@files,$author,$sender,$compose,$time); -my $smtp_server; my $envelope_sender; # Example reply to: @@@ -175,28 -164,24 +175,28 @@@ my ($quiet, $dry_run) = (0, 0) # Variables with corresponding config settings my ($thread, $chain_reply_to, $suppress_from, $signed_off_cc, $cc_cmd); +my ($smtp_server, $smtp_server_port, $smtp_authuser, $smtp_authpass, $smtp_ssl); +my ($identity, $aliasfiletype, @alias_files, @smtp_host_parts); -my %config_settings = ( +my %config_bool_settings = ( "thread" => [\$thread, 1], "chainreplyto" => [\$chain_reply_to, 1], "suppressfrom" => [\$suppress_from, 0], "signedoffcc" => [\$signed_off_cc, 1], - "cccmd" => [\$cc_cmd, ""], + "smtpssl" => [\$smtp_ssl, 0], ); -foreach my $setting (keys %config_settings) { - my $config = $repo->config_bool("sendemail.$setting"); - ${$config_settings{$setting}->[0]} = (defined $config) ? $config : $config_settings{$setting}->[1]; -} - -@bcclist = $repo->config('sendemail.bcc'); -if (!@bcclist or !$bcclist[0]) { - @bcclist = (); -} +my %config_settings = ( + "smtpserver" => \$smtp_server, + "smtpserverport" => \$smtp_server_port, + "smtpuser" => \$smtp_authuser, + "smtppass" => \$smtp_authpass, + "to" => \@to, + "cccmd" => \$cc_cmd, + "aliasfiletype" => \$aliasfiletype, + "bcc" => \@bcclist, + "aliasesfile" => \@alias_files, +); # Begin by accumulating all the variables (defined above), that we will end up # needing, first, from the command line: @@@ -209,11 -194,6 +209,11 @@@ my $rc = GetOptions("sender|from=s" => "bcc=s" => \@bcclist, "chain-reply-to!" => \$chain_reply_to, "smtp-server=s" => \$smtp_server, + "smtp-server-port=s" => \$smtp_server_port, + "smtp-user=s" => \$smtp_authuser, + "smtp-pass=s" => \$smtp_authpass, + "smtp-ssl!" => \$smtp_ssl, + "identity=s" => \$identity, "compose" => \$compose, "quiet" => \$quiet, "cc-cmd=s" => \$cc_cmd, @@@ -228,43 -208,6 +228,43 @@@ unless ($rc) usage(); } +# Now, let's fill any that aren't set in with defaults: + +sub read_config { + my ($prefix) = @_; + + foreach my $setting (keys %config_bool_settings) { + my $target = $config_bool_settings{$setting}->[0]; + $$target = $repo->config_bool("$prefix.$setting") unless (defined $$target); + } + + foreach my $setting (keys %config_settings) { + my $target = $config_settings{$setting}; + if (ref($target) eq "ARRAY") { + unless (@$target) { + my @values = $repo->config("$prefix.$setting"); + @$target = @values if (@values && defined $values[0]); + } + } + else { + $$target = $repo->config("$prefix.$setting") unless (defined $$target); + } + } +} + +# read configuration from [sendemail "$identity"], fall back on [sendemail] +$identity = $repo->config("sendemail.identity") unless (defined $identity); +read_config("sendemail.$identity") if (defined $identity); +read_config("sendemail"); + +# fall back on builtin bool defaults +foreach my $setting (values %config_bool_settings) { + ${$setting->[0]} = $setting->[1] unless (defined (${$setting->[0]})); +} + +my ($repoauthor) = $repo->ident_person('author'); +my ($repocommitter) = $repo->ident_person('committer'); + # Verify the user input foreach my $entry (@to) { @@@ -279,7 -222,14 +279,7 @@@ foreach my $entry (@bcclist) die "Comma in --bcclist entry: $entry'\n" unless $entry !~ m/,/; } -# Now, let's fill any that aren't set in with defaults: - -my ($repoauthor) = $repo->ident_person('author'); -my ($repocommitter) = $repo->ident_person('committer'); - my %aliases; -my @alias_files = $repo->config('sendemail.aliasesfile'); -my $aliasfiletype = $repo->config('sendemail.aliasfiletype'); my %parse_alias = ( # multiline formats can be supported in the future mutt => sub { my $fh = shift; while (<$fh>) { @@@ -367,13 -317,14 +367,13 @@@ if ($thread && !defined $initial_reply_ } while (!defined $_); $initial_reply_to = $_; - $initial_reply_to =~ s/^\s+?\s+$/>/; } - -if (!$smtp_server) { - $smtp_server = $repo->config('sendemail.smtpserver'); +if (defined $initial_reply_to && $_ ne "") { + $initial_reply_to =~ s/^\s*?\s*$/>/; } -if (!$smtp_server) { + +if (!defined $smtp_server) { foreach (qw( /usr/sbin/sendmail /usr/lib/sendmail )) { if (-x $_) { $smtp_server = $_; @@@ -560,11 -511,7 +560,11 @@@ sub sanitize_addres sub send_message { my @recipients = unique_email_list(@to); - @cc = (map { sanitize_address($_) } @cc); + @cc = (grep { my $cc = extract_valid_address($_); + not grep { $cc eq $_ } @recipients + } + map { sanitize_address($_) } + @cc); my $to = join (",\n\t", @recipients); @recipients = unique_email_list(@recipients,@cc,@bcclist); @recipients = (map { extract_valid_address($_) } @recipients); @@@ -580,7 -527,7 +580,7 @@@ $ccline = "\nCc: $cc"; } my $sanitized_sender = sanitize_address($sender); - make_message_id(); + make_message_id() unless defined($message_id); my $header = "From: $sanitized_sender To: $to${ccline} @@@ -616,30 -563,8 +616,30 @@@ X-Mailer: git-send-email $gitversio print $sm "$header\n$message"; close $sm or die $?; } else { - require Net::SMTP; - $smtp ||= Net::SMTP->new( $smtp_server ); + + if (!defined $smtp_server) { + die "The required SMTP server is not properly defined." + } + + if ($smtp_ssl) { + $smtp_server_port ||= 465; # ssmtp + require Net::SMTP::SSL; + $smtp ||= Net::SMTP::SSL->new($smtp_server, Port => $smtp_server_port); + } + else { + require Net::SMTP; + $smtp ||= Net::SMTP->new((defined $smtp_server_port) + ? "$smtp_server:$smtp_server_port" + : $smtp_server); + } + + if (!$smtp) { + die "Unable to initialize SMTP properly. Is there something wrong with your config?"; + } + + if ((defined $smtp_authuser) && (defined $smtp_authpass)) { + $auth ||= $smtp->auth( $smtp_authuser, $smtp_authpass ) or die $smtp->message; + } $smtp->mail( $raw_from ) or die $smtp->message; $smtp->to( @recipients ) or die $smtp->message; $smtp->data or die $smtp->message; @@@ -650,7 -575,7 +650,7 @@@ if ($quiet) { printf (($dry_run ? "Dry-" : "")."Sent %s\n", $subject); } else { - print (($dry_run ? "Dry-" : "")."OK. Log says:\nDate: $date\n"); + print (($dry_run ? "Dry-" : "")."OK. Log says:\n"); if ($smtp_server !~ m#^/#) { print "Server: $smtp_server\n"; print "MAIL FROM:<$raw_from>\n"; @@@ -658,7 -583,7 +658,7 @@@ } else { print "Sendmail: $smtp_server ".join(' ',@sendmail_parameters)."\n"; } - print "From: $sanitized_sender\nSubject: $subject\nCc: $cc\nTo: $to\n\n"; + print $header, "\n"; if ($smtp) { print "Result: ", $smtp->code, ' ', ($smtp->message =~ /\n([^\n]+\n)$/s), "\n"; @@@ -718,6 -643,9 +718,9 @@@ foreach my $t (@files) } push @xh, $_; } + elsif (/^Message-Id: (.*)/i) { + $message_id = $1; + } elsif (!/^Date:\s/ && /^[-A-Za-z]+:\s+\S/) { push @xh, $_; } @@@ -749,7 -677,6 +752,7 @@@ if (/^(Signed-off-by|Cc): (.*)$/i && $signed_off_cc) { my $c = $2; chomp $c; + next if ($c eq $sender and $suppress_from); push @cc, $c; printf("(sob) Adding cc: %s from line '%s'\n", $c, $_) unless $quiet; @@@ -758,14 -685,13 +761,14 @@@ } close F; - if ($cc_cmd ne "") { + if (defined $cc_cmd) { open(F, "$cc_cmd $t |") or die "(cc-cmd) Could not execute '$cc_cmd'"; while() { my $c = $_; $c =~ s/^\s*//g; $c =~ s/\n$//g; + next if ($c eq $sender and $suppress_from); push @cc, $c; printf("(cc-cmd) Adding cc: %s from: '%s'\n", $c, $cc_cmd) unless $quiet; @@@ -805,6 -731,7 +808,7 @@@ $references = "$message_id"; } } + $message_id = undef; } if ($compose) {