* maint:
  Start preparing for 1.5.1.3
  Sanitize @to recipients.
  git-svn: Ignore usernames in URLs in find_by_url
  Document --dry-run and envelope-sender for git-send-email.
  Allow users to optionally specify their envelope sender.
  Ensure clean addresses are always used with Net::SMTP
  Validate @recipients before using it for sendmail and Net::SMTP.
  Perform correct quoting of recipient names.
  Change the scope of the $cc variable as it is not needed outside of send_message.
  Debugging cleanup improvements
  Prefix Dry- to the message status to denote dry-runs.
  Document --dry-run parameter to send-email.
  git-svn: Don't rely on $_ after making a function call
  Fix handle leak in write_tree
  Actually handle some-low memory conditions

Conflicts:

	RelNotes
	git-send-email.perl
This commit is contained in:
Junio C Hamano 2007-04-25 23:31:45 -07:00
Родитель a7b02ccf9a 8abe88a29c
Коммит 6169a89c4f
7 изменённых файлов: 111 добавлений и 33 удалений

Просмотреть файл

@ -0,0 +1,38 @@
GIT v1.5.1.3 Release Notes (draft)
==========================
Fixes since v1.5.1.2
--------------------
* Bugfixes
- git-add tried to optimize by finding common leading
directories across its arguments but botched, causing very
confused behaviour.
- unofficial rpm.spec file shipped with git was letting
ETC_GITCONFIG set to /usr/etc/gitconfig. Tweak the official
Makefile to make it harder for distro people to make the
same mistake, by setting the variable to /etc/gitconfig if
prefix is set to /usr.
- git-svn inconsistently stripped away username from the URL
only when svnsync_props was in use.
- git-send-email was not quoting recipient names that have
period '.' in them. Also it did not allow overriding
envelope sender, which made it impossible to send patches to
certain subscriber-only lists.
- built-in write_tree() routine had a sequence that renamed a
file that is still open, which some systems did not like.
- when memory is very tight, sliding mmap code to read
packfiles incorrectly closed the fd that was still being
used to read the pack.
---
exec >/var/tmp/1
O=v1.5.1.2-23-gbf7af11
echo O=`git describe refs/heads/maint`
git shortlog --no-merges $O..refs/heads/maint

Просмотреть файл

@ -85,6 +85,15 @@ The --cc option must be repeated for each user you want on the cc list.
Do not add the From: address to the cc: list, if it shows up in a From:
line.
--dry-run::
Do everything except actually send the emails.
--envelope-sender::
Specify the envelope sender used to send the emails.
This is useful if your default address is not the address that is
subscribed to a list. If you use the sendmail binary, you must have
suitable privileges for the -f parameter.
--to::
Specify the primary recipient of the emails generated.
Generally, this will be the upstream maintainer of the

Просмотреть файл

@ -36,8 +36,10 @@ int write_tree(unsigned char *sha1, int missing_ok, const char *prefix)
die("git-write-tree: error building trees");
if (0 <= newfd) {
if (!write_cache(newfd, active_cache, active_nr)
&& !close(newfd))
&& !close(newfd)) {
commit_lock_file(lock_file);
newfd = -1;
}
}
/* Not being able to write is fine -- we are only interested
* in updating the cache-tree part, and if the next caller
@ -55,6 +57,8 @@ int write_tree(unsigned char *sha1, int missing_ok, const char *prefix)
else
hashcpy(sha1, active_cache_tree->sha1);
if (0 <= newfd)
close(newfd);
rollback_lock_file(lock_file);
return 0;

Просмотреть файл

@ -164,13 +164,13 @@ extern size_t gitstrlcpy(char *, const char *, size_t);
extern uintmax_t gitstrtoumax(const char *, char **, int);
#endif
extern void release_pack_memory(size_t);
extern void release_pack_memory(size_t, int);
static inline char* xstrdup(const char *str)
{
char *ret = strdup(str);
if (!ret) {
release_pack_memory(strlen(str) + 1);
release_pack_memory(strlen(str) + 1, -1);
ret = strdup(str);
if (!ret)
die("Out of memory, strdup failed");
@ -184,7 +184,7 @@ static inline void *xmalloc(size_t size)
if (!ret && !size)
ret = malloc(1);
if (!ret) {
release_pack_memory(size);
release_pack_memory(size, -1);
ret = malloc(size);
if (!ret && !size)
ret = malloc(1);
@ -203,7 +203,7 @@ static inline void *xrealloc(void *ptr, size_t size)
if (!ret && !size)
ret = realloc(ptr, 1);
if (!ret) {
release_pack_memory(size);
release_pack_memory(size, -1);
ret = realloc(ptr, size);
if (!ret && !size)
ret = realloc(ptr, 1);
@ -219,7 +219,7 @@ static inline void *xcalloc(size_t nmemb, size_t size)
if (!ret && (!nmemb || !size))
ret = calloc(1, 1);
if (!ret) {
release_pack_memory(nmemb * size);
release_pack_memory(nmemb * size, -1);
ret = calloc(nmemb, size);
if (!ret && (!nmemb || !size))
ret = calloc(1, 1);
@ -236,7 +236,7 @@ static inline void *xmmap(void *start, size_t length,
if (ret == MAP_FAILED) {
if (!length)
return NULL;
release_pack_memory(length);
release_pack_memory(length, fd);
ret = mmap(start, length, prot, flags, fd, offset);
if (ret == MAP_FAILED)
die("Out of memory? mmap failed: %s", strerror(errno));

Просмотреть файл

@ -77,6 +77,10 @@ Options:
--quiet Make git-send-email less verbose. One line per email
should be all that is output.
--dry-run Do everything except actually send the emails.
--envelope-sender Specify the envelope sender used to send the emails.
EOT
exit(1);
}
@ -137,6 +141,7 @@ my (@to,@cc,@initial_cc,@bcclist,@xh,
my ($chain_reply_to, $quiet, $suppress_from, $no_signed_off_cc,
$dry_run) = (1, 0, 0, 0, 0);
my $smtp_server;
my $envelope_sender;
# Example reply to:
#$initial_reply_to = ''; #<20050203173208.GA23964@foobar.com>';
@ -175,6 +180,7 @@ my $rc = GetOptions("from=s" => \$from,
"suppress-from" => \$suppress_from,
"no-signed-off-cc|no-signed-off-by-cc" => \$no_signed_off_cc,
"dry-run" => \$dry_run,
"envelope-sender=s" => \$envelope_sender,
);
unless ($rc) {
@ -268,6 +274,7 @@ sub expand_aliases {
}
@to = expand_aliases(@to);
@to = (map { sanitize_address_rfc822($_) } @to);
@initial_cc = expand_aliases(@initial_cc);
@bcclist = expand_aliases(@bcclist);
@ -377,7 +384,7 @@ if (@files) {
}
# Variables we set as part of the loop over files
our ($message_id, $cc, %mail, $subject, $reply_to, $references, $message);
our ($message_id, %mail, $subject, $reply_to, $references, $message);
sub extract_valid_address {
my $address = shift;
@ -418,7 +425,6 @@ sub make_message_id
$cc = "";
$time = time - scalar $#files;
sub unquote_rfc2047 {
@ -430,26 +436,37 @@ sub unquote_rfc2047 {
return "$_";
}
# If an address contains a . in the name portion, the name must be quoted.
sub sanitize_address_rfc822
{
my ($recipient) = @_;
my ($recipient_name) = ($recipient =~ /^(.*?)\s+</);
if ($recipient_name && $recipient_name =~ /\./ && $recipient_name !~ /^".*"$/) {
my ($name, $addr) = ($recipient =~ /^(.*?)(\s+<.*)/);
$recipient = "\"$name\"$addr";
}
return $recipient;
}
sub send_message
{
my @recipients = unique_email_list(@to);
@cc = (map { sanitize_address_rfc822($_) } @cc);
my $to = join (",\n\t", @recipients);
@recipients = unique_email_list(@recipients,@cc,@bcclist);
@recipients = (map { extract_valid_address($_) } @recipients);
my $date = format_2822_time($time++);
my $gitversion = '@@GIT_VERSION@@';
if ($gitversion =~ m/..GIT_VERSION../) {
$gitversion = Git::version();
}
my ($author_name) = ($from =~ /^(.*?)\s+</);
if ($author_name && $author_name =~ /\./ && $author_name !~ /^".*"$/) {
my ($name, $addr) = ($from =~ /^(.*?)(\s+<.*)/);
$from = "\"$name\"$addr";
}
my $cc = join(", ", unique_email_list(@cc));
my $ccline = "";
if ($cc ne '') {
$ccline = "\nCc: $cc";
}
$from = sanitize_address_rfc822($from);
my $header = "From: $from
To: $to${ccline}
Subject: $subject
@ -466,22 +483,27 @@ X-Mailer: git-send-email $gitversion
$header .= join("\n", @xh) . "\n";
}
my @sendmail_parameters = ('-i', @recipients);
my $raw_from = $from;
$raw_from = $envelope_sender if (defined $envelope_sender);
$raw_from = extract_valid_address($raw_from);
unshift (@sendmail_parameters,
'-f', $raw_from) if(defined $envelope_sender);
if ($dry_run) {
# We don't want to send the email.
} elsif ($smtp_server =~ m#^/#) {
my $pid = open my $sm, '|-';
defined $pid or die $!;
if (!$pid) {
exec($smtp_server,'-i',
map { extract_valid_address($_) }
@recipients) or die $!;
exec($smtp_server, @sendmail_parameters) or die $!;
}
print $sm "$header\n$message";
close $sm or die $?;
} else {
require Net::SMTP;
$smtp ||= Net::SMTP->new( $smtp_server );
$smtp->mail( $from ) 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;
$smtp->datasend("$header\n$message") or die $smtp->message;
@ -489,13 +511,15 @@ X-Mailer: git-send-email $gitversion
$smtp->ok or die "Failed to send $subject\n".$smtp->message;
}
if ($quiet) {
printf "Sent %s\n", $subject;
printf (($dry_run ? "Dry-" : "")."Sent %s\n", $subject);
} else {
print "OK. Log says:\nDate: $date\n";
if ($smtp) {
print (($dry_run ? "Dry-" : "")."OK. Log says:\nDate: $date\n");
if ($smtp_server !~ m#^/#) {
print "Server: $smtp_server\n";
print "MAIL FROM:<$raw_from>\n";
print "RCPT TO:".join(',',(map { "<$_>" } @recipients))."\n";
} else {
print "Sendmail: $smtp_server\n";
print "Sendmail: $smtp_server ".join(' ',@sendmail_parameters)."\n";
}
print "From: $from\nSubject: $subject\nCc: $cc\nTo: $to\n\n";
if ($smtp) {
@ -590,7 +614,6 @@ foreach my $t (@files) {
$message = "From: $author_not_sender\n\n$message";
}
$cc = join(", ", unique_email_list(@cc));
send_message();

Просмотреть файл

@ -771,19 +771,19 @@ sub cmt_metadata {
sub working_head_info {
my ($head, $refs) = @_;
my ($fh, $ctx) = command_output_pipe('rev-list', $head);
while (<$fh>) {
chomp;
my ($url, $rev, $uuid) = cmt_metadata($_);
while (my $hash = <$fh>) {
chomp($hash);
my ($url, $rev, $uuid) = cmt_metadata($hash);
if (defined $url && defined $rev) {
if (my $gs = Git::SVN->find_by_url($url)) {
my $c = $gs->rev_db_get($rev);
if ($c && $c eq $_) {
if ($c && $c eq $hash) {
close $fh; # break the pipe
return ($url, $rev, $uuid, $gs);
}
}
}
unshift @$refs, $_ if $refs;
unshift @$refs, $hash if $refs;
}
command_close_pipe($fh, $ctx);
(undef, undef, undef, undef);
@ -1064,7 +1064,10 @@ sub init_remote_config {
sub find_by_url { # repos_root and, path are optional
my ($class, $full_url, $repos_root, $path) = @_;
return undef unless defined $full_url;
remove_username($full_url);
remove_username($repos_root) if defined $repos_root;
my $remotes = read_all_remotes();
if (defined $full_url && defined $repos_root && !defined $path) {
$path = $full_url;
@ -1072,6 +1075,7 @@ sub find_by_url { # repos_root and, path are optional
}
foreach my $repo_id (keys %$remotes) {
my $u = $remotes->{$repo_id}->{url} or next;
remove_username($u);
next if defined $repos_root && $repos_root ne $u;
my $fetch = $remotes->{$repo_id}->{fetch} || {};

Просмотреть файл

@ -549,7 +549,7 @@ static void scan_windows(struct packed_git *p,
}
}
static int unuse_one_window(struct packed_git *current)
static int unuse_one_window(struct packed_git *current, int keep_fd)
{
struct packed_git *p, *lru_p = NULL;
struct pack_window *lru_w = NULL, *lru_l = NULL;
@ -565,7 +565,7 @@ static int unuse_one_window(struct packed_git *current)
lru_l->next = lru_w->next;
else {
lru_p->windows = lru_w->next;
if (!lru_p->windows && lru_p != current) {
if (!lru_p->windows && lru_p->pack_fd != keep_fd) {
close(lru_p->pack_fd);
lru_p->pack_fd = -1;
}
@ -577,10 +577,10 @@ static int unuse_one_window(struct packed_git *current)
return 0;
}
void release_pack_memory(size_t need)
void release_pack_memory(size_t need, int fd)
{
size_t cur = pack_mapped;
while (need >= (cur - pack_mapped) && unuse_one_window(NULL))
while (need >= (cur - pack_mapped) && unuse_one_window(NULL, fd))
; /* nothing */
}
@ -713,7 +713,7 @@ unsigned char* use_pack(struct packed_git *p,
win->len = (size_t)len;
pack_mapped += win->len;
while (packed_git_limit < pack_mapped
&& unuse_one_window(p))
&& unuse_one_window(p, p->pack_fd))
; /* nothing */
win->base = xmmap(NULL, win->len,
PROT_READ, MAP_PRIVATE,