mirror of
https://github.com/git/git.git
synced 2024-11-17 14:34:49 +01:00
Merge branch 'master' into next
* master: send-email: do not pass bogus address to local sendmail binary Add a basic test case for git send-email, and fix some real bugs discovered. Fix a bug in email extraction used in git-send-email. Add support for --bcc to git-send-email. git-send-email: Add References: headers to emails, in addition to In-Reply-To: git-clean fails on files beginning with a dash git-svn: remove assertion that broke with older versions of svn git-svn: t0001: workaround a heredoc bug in old versions of dash Documentation: fix a tutorial-2 typo Documentation: retitle the git-core tutorial documentation: add brief mention of cat-file to tutorial part I documentation: mention gitk font adjustment in tutorial Fix some documentation typoes
This commit is contained in:
commit
62b693a070
9 changed files with 89 additions and 18 deletions
|
@ -1,5 +1,5 @@
|
||||||
A short git tutorial
|
A git core tutorial for developers
|
||||||
====================
|
==================================
|
||||||
|
|
||||||
Introduction
|
Introduction
|
||||||
------------
|
------------
|
||||||
|
|
|
@ -66,7 +66,7 @@ $ git prune <4>
|
||||||
<1> running without "--full" is usually cheap and assures the
|
<1> running without "--full" is usually cheap and assures the
|
||||||
repository health reasonably well.
|
repository health reasonably well.
|
||||||
<2> check how many loose objects there are and how much
|
<2> check how many loose objects there are and how much
|
||||||
diskspace is wasted by not repacking.
|
disk space is wasted by not repacking.
|
||||||
<3> without "-a" repacks incrementally. repacking every 4-5MB
|
<3> without "-a" repacks incrementally. repacking every 4-5MB
|
||||||
of loose objects accumulation may be a good rule of thumb.
|
of loose objects accumulation may be a good rule of thumb.
|
||||||
<4> after repack, prune removes the duplicate loose objects.
|
<4> after repack, prune removes the duplicate loose objects.
|
||||||
|
@ -86,7 +86,7 @@ Individual Developer (Standalone)[[Individual Developer (Standalone)]]
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
A standalone individual developer does not exchange patches with
|
A standalone individual developer does not exchange patches with
|
||||||
other poeple, and works alone in a single repository, using the
|
other people, and works alone in a single repository, using the
|
||||||
following commands.
|
following commands.
|
||||||
|
|
||||||
* gitlink:git-show-branch[1] to see where you are.
|
* gitlink:git-show-branch[1] to see where you are.
|
||||||
|
@ -370,7 +370,7 @@ Examples
|
||||||
Run git-daemon to serve /pub/scm from inetd.::
|
Run git-daemon to serve /pub/scm from inetd.::
|
||||||
+
|
+
|
||||||
------------
|
------------
|
||||||
$ grep git /etc/inet.conf
|
$ grep git /etc/inetd.conf
|
||||||
git stream tcp nowait nobody \
|
git stream tcp nowait nobody \
|
||||||
/usr/bin/git-daemon git-daemon --inetd --syslog --export-all /pub/scm
|
/usr/bin/git-daemon git-daemon --inetd --syslog --export-all /pub/scm
|
||||||
------------
|
------------
|
||||||
|
|
|
@ -377,7 +377,7 @@ At this point you should know everything necessary to read the man
|
||||||
pages for any of the git commands; one good place to start would be
|
pages for any of the git commands; one good place to start would be
|
||||||
with the commands mentioned in link:everyday.html[Everyday git]. You
|
with the commands mentioned in link:everyday.html[Everyday git]. You
|
||||||
should be able to find any unknown jargon in the
|
should be able to find any unknown jargon in the
|
||||||
link:glossary.html[Glosssay].
|
link:glossary.html[Glossary].
|
||||||
|
|
||||||
The link:cvs-migration.html[CVS migration] document explains how to
|
The link:cvs-migration.html[CVS migration] document explains how to
|
||||||
import a CVS repository into git, and shows how to use git in a
|
import a CVS repository into git, and shows how to use git in a
|
||||||
|
|
|
@ -429,16 +429,24 @@ $ gitk --since="2 weeks ago" drivers/
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
allows you to browse any commits from the last 2 weeks of commits
|
allows you to browse any commits from the last 2 weeks of commits
|
||||||
that modified files under the "drivers" directory.
|
that modified files under the "drivers" directory. (Note: you can
|
||||||
|
adjust gitk's fonts by holding down the control key while pressing
|
||||||
|
"-" or "+".)
|
||||||
|
|
||||||
Finally, most commands that take filenames will optionally allow you
|
Finally, most commands that take filenames will optionally allow you
|
||||||
to precede any filename by a commit, to specify a particular version
|
to precede any filename by a commit, to specify a particular version
|
||||||
fo the file:
|
of the file:
|
||||||
|
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
$ git diff v2.5:Makefile HEAD:Makefile.in
|
$ git diff v2.5:Makefile HEAD:Makefile.in
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
|
You can also use "git cat-file -p" to see any such file:
|
||||||
|
|
||||||
|
-------------------------------------
|
||||||
|
$ git cat-file -p v2.5:Makefile
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
Next Steps
|
Next Steps
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
|
|
@ -567,7 +567,6 @@ sub precommit_check {
|
||||||
sub svn_checkout_tree {
|
sub svn_checkout_tree {
|
||||||
my ($svn_rev, $treeish) = @_;
|
my ($svn_rev, $treeish) = @_;
|
||||||
my $from = file_to_s("$REV_DIR/$svn_rev");
|
my $from = file_to_s("$REV_DIR/$svn_rev");
|
||||||
assert_svn_wc_clean($svn_rev);
|
|
||||||
assert_tree($from);
|
assert_tree($from);
|
||||||
print "diff-tree $from $treeish\n";
|
print "diff-tree $from $treeish\n";
|
||||||
my $pid = open my $diff_fh, '-|';
|
my $pid = open my $diff_fh, '-|';
|
||||||
|
|
|
@ -20,9 +20,10 @@ a_empty_cr=
|
||||||
a_empty_crlf=
|
a_empty_crlf=
|
||||||
|
|
||||||
cd import
|
cd import
|
||||||
cat >> kw.c <<''
|
cat >> kw.c <<\EOF
|
||||||
/* Make it look like somebody copied a file from CVS into SVN: */
|
/* Make it look like somebody copied a file from CVS into SVN: */
|
||||||
/* $Id: kw.c,v 1.1.1.1 1994/03/06 00:00:00 eric Exp $ */
|
/* $Id: kw.c,v 1.1.1.1 1994/03/06 00:00:00 eric Exp $ */
|
||||||
|
EOF
|
||||||
|
|
||||||
printf "Hello\r\nWorld\r\n" > crlf
|
printf "Hello\r\nWorld\r\n" > crlf
|
||||||
a_crlf=`git-hash-object -w crlf`
|
a_crlf=`git-hash-object -w crlf`
|
||||||
|
|
|
@ -19,8 +19,8 @@ ignored=
|
||||||
ignoredonly=
|
ignoredonly=
|
||||||
cleandir=
|
cleandir=
|
||||||
quiet=
|
quiet=
|
||||||
rmf="rm -f"
|
rmf="rm -f --"
|
||||||
rmrf="rm -rf"
|
rmrf="rm -rf --"
|
||||||
rm_refuse="echo Not removing"
|
rm_refuse="echo Not removing"
|
||||||
echo1="echo"
|
echo1="echo"
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,8 @@
|
||||||
my $compose_filename = ".msg.$$";
|
my $compose_filename = ".msg.$$";
|
||||||
|
|
||||||
# Variables we fill in automatically, or via prompting:
|
# Variables we fill in automatically, or via prompting:
|
||||||
my (@to,@cc,@initial_cc,$initial_reply_to,$initial_subject,@files,$from,$compose,$time);
|
my (@to,@cc,@initial_cc,@bcclist,
|
||||||
|
$initial_reply_to,$initial_subject,@files,$from,$compose,$time);
|
||||||
|
|
||||||
# Behavior modification variables
|
# Behavior modification variables
|
||||||
my ($chain_reply_to, $quiet, $suppress_from, $no_signed_off_cc) = (1, 0, 0, 0);
|
my ($chain_reply_to, $quiet, $suppress_from, $no_signed_off_cc) = (1, 0, 0, 0);
|
||||||
|
@ -56,6 +57,7 @@
|
||||||
"subject=s" => \$initial_subject,
|
"subject=s" => \$initial_subject,
|
||||||
"to=s" => \@to,
|
"to=s" => \@to,
|
||||||
"cc=s" => \@initial_cc,
|
"cc=s" => \@initial_cc,
|
||||||
|
"bcc=s" => \@bcclist,
|
||||||
"chain-reply-to!" => \$chain_reply_to,
|
"chain-reply-to!" => \$chain_reply_to,
|
||||||
"smtp-server=s" => \$smtp_server,
|
"smtp-server=s" => \$smtp_server,
|
||||||
"compose" => \$compose,
|
"compose" => \$compose,
|
||||||
|
@ -160,6 +162,7 @@ sub expand_aliases {
|
||||||
|
|
||||||
@to = expand_aliases(@to);
|
@to = expand_aliases(@to);
|
||||||
@initial_cc = expand_aliases(@initial_cc);
|
@initial_cc = expand_aliases(@initial_cc);
|
||||||
|
@bcclist = expand_aliases(@bcclist);
|
||||||
|
|
||||||
if (!defined $initial_subject && $compose) {
|
if (!defined $initial_subject && $compose) {
|
||||||
do {
|
do {
|
||||||
|
@ -269,6 +272,9 @@ sub expand_aliases {
|
||||||
--cc Specify an initial "Cc:" list for the entire series
|
--cc Specify an initial "Cc:" list for the entire series
|
||||||
of emails.
|
of emails.
|
||||||
|
|
||||||
|
--bcc Specify a list of email addresses that should be Bcc:
|
||||||
|
on all the emails.
|
||||||
|
|
||||||
--compose Use \$EDITOR to edit an introductory message for the
|
--compose Use \$EDITOR to edit an introductory message for the
|
||||||
patch series.
|
patch series.
|
||||||
|
|
||||||
|
@ -303,7 +309,7 @@ sub expand_aliases {
|
||||||
}
|
}
|
||||||
|
|
||||||
# Variables we set as part of the loop over files
|
# Variables we set as part of the loop over files
|
||||||
our ($message_id, $cc, %mail, $subject, $reply_to, $message);
|
our ($message_id, $cc, %mail, $subject, $reply_to, $references, $message);
|
||||||
|
|
||||||
sub extract_valid_address {
|
sub extract_valid_address {
|
||||||
my $address = shift;
|
my $address = shift;
|
||||||
|
@ -316,7 +322,11 @@ sub extract_valid_address {
|
||||||
} else {
|
} else {
|
||||||
# less robust/correct than the monster regexp in Email::Valid,
|
# less robust/correct than the monster regexp in Email::Valid,
|
||||||
# but still does a 99% job, and one less dependency
|
# but still does a 99% job, and one less dependency
|
||||||
return ($address =~ /([^\"<>\s]+@[^<>\s]+)/);
|
my $cleaned_address;
|
||||||
|
if ($address =~ /([^\"<>\s]+@[^<>\s]+)/) {
|
||||||
|
$cleaned_address = $1;
|
||||||
|
}
|
||||||
|
return $cleaned_address;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,7 +358,7 @@ sub send_message
|
||||||
{
|
{
|
||||||
my @recipients = unique_email_list(@to);
|
my @recipients = unique_email_list(@to);
|
||||||
my $to = join (",\n\t", @recipients);
|
my $to = join (",\n\t", @recipients);
|
||||||
@recipients = unique_email_list(@recipients,@cc);
|
@recipients = unique_email_list(@recipients,@cc,@bcclist);
|
||||||
my $date = strftime('%a, %d %b %Y %H:%M:%S %z', localtime($time++));
|
my $date = strftime('%a, %d %b %Y %H:%M:%S %z', localtime($time++));
|
||||||
my $gitversion = '@@GIT_VERSION@@';
|
my $gitversion = '@@GIT_VERSION@@';
|
||||||
if ($gitversion =~ m/..GIT_VERSION../) {
|
if ($gitversion =~ m/..GIT_VERSION../) {
|
||||||
|
@ -367,13 +377,19 @@ sub send_message
|
||||||
Message-Id: $message_id
|
Message-Id: $message_id
|
||||||
X-Mailer: git-send-email $gitversion
|
X-Mailer: git-send-email $gitversion
|
||||||
";
|
";
|
||||||
$header .= "In-Reply-To: $reply_to\n" if $reply_to;
|
if ($reply_to) {
|
||||||
|
|
||||||
|
$header .= "In-Reply-To: $reply_to\n";
|
||||||
|
$header .= "References: $references\n";
|
||||||
|
}
|
||||||
|
|
||||||
if ($smtp_server =~ m#^/#) {
|
if ($smtp_server =~ m#^/#) {
|
||||||
my $pid = open my $sm, '|-';
|
my $pid = open my $sm, '|-';
|
||||||
defined $pid or die $!;
|
defined $pid or die $!;
|
||||||
if (!$pid) {
|
if (!$pid) {
|
||||||
exec($smtp_server,'-i',@recipients) or die $!;
|
exec($smtp_server,'-i',
|
||||||
|
map { scalar extract_valid_address($_) }
|
||||||
|
@recipients) or die $!;
|
||||||
}
|
}
|
||||||
print $sm "$header\n$message";
|
print $sm "$header\n$message";
|
||||||
close $sm or die $?;
|
close $sm or die $?;
|
||||||
|
@ -406,6 +422,7 @@ sub send_message
|
||||||
}
|
}
|
||||||
|
|
||||||
$reply_to = $initial_reply_to;
|
$reply_to = $initial_reply_to;
|
||||||
|
$references = $initial_reply_to || '';
|
||||||
make_message_id();
|
make_message_id();
|
||||||
$subject = $initial_subject;
|
$subject = $initial_subject;
|
||||||
|
|
||||||
|
@ -482,6 +499,11 @@ sub send_message
|
||||||
# set up for the next message
|
# set up for the next message
|
||||||
if ($chain_reply_to || length($reply_to) == 0) {
|
if ($chain_reply_to || length($reply_to) == 0) {
|
||||||
$reply_to = $message_id;
|
$reply_to = $message_id;
|
||||||
|
if (length $references > 0) {
|
||||||
|
$references .= " $message_id";
|
||||||
|
} else {
|
||||||
|
$references = "$message_id";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
make_message_id();
|
make_message_id();
|
||||||
}
|
}
|
||||||
|
|
41
t/t9001-send-email.sh
Executable file
41
t/t9001-send-email.sh
Executable file
|
@ -0,0 +1,41 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
test_description='git-send-email'
|
||||||
|
. ./test-lib.sh
|
||||||
|
|
||||||
|
PROG='git send-email'
|
||||||
|
test_expect_success \
|
||||||
|
'prepare reference tree' \
|
||||||
|
'echo "1A quick brown fox jumps over the" >file &&
|
||||||
|
echo "lazy dog" >>file &&
|
||||||
|
git add file
|
||||||
|
GIT_AUTHOR_NAME="A" git commit -a -m "Initial."'
|
||||||
|
|
||||||
|
test_expect_success \
|
||||||
|
'Setup helper tool' \
|
||||||
|
'(echo "#!/bin/sh"
|
||||||
|
echo shift
|
||||||
|
echo for a
|
||||||
|
echo do
|
||||||
|
echo " echo \"!\$a!\""
|
||||||
|
echo "done >commandline"
|
||||||
|
echo "cat > msgtxt"
|
||||||
|
) >fake.sendmail
|
||||||
|
chmod +x ./fake.sendmail
|
||||||
|
git add fake.sendmail
|
||||||
|
GIT_AUTHOR_NAME="A" git commit -a -m "Second."'
|
||||||
|
|
||||||
|
test_expect_success \
|
||||||
|
'Extract patches and send' \
|
||||||
|
'git format-patch -n HEAD^1
|
||||||
|
git send-email -from="Example <nobody@example.com>" --to=nobody@example.com --smtp-server="$(pwd)/fake.sendmail" ./0001*txt'
|
||||||
|
|
||||||
|
cat >expected <<\EOF
|
||||||
|
!nobody@example.com!
|
||||||
|
!author@example.com!
|
||||||
|
EOF
|
||||||
|
test_expect_success \
|
||||||
|
'Verify commandline' \
|
||||||
|
'diff commandline expected'
|
||||||
|
|
||||||
|
test_done
|
Loading…
Reference in a new issue