From: Junio C Hamano Date: Sat, 20 Dec 2008 03:32:29 +0000 (-0800) Subject: Merge branch 'maint' to sync with GIT 1.6.0.6 X-Git-Tag: v1.6.1-rc4~16 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/efe05b019ca19328d27c07ef32b4698a7f36166f?ds=inline;hp=-c Merge branch 'maint' to sync with GIT 1.6.0.6 Signed-off-by: Junio C Hamano --- efe05b019ca19328d27c07ef32b4698a7f36166f diff --combined Documentation/SubmittingPatches index f0295c60f5,34fdc83ad4..ba07c8c571 --- a/Documentation/SubmittingPatches +++ b/Documentation/SubmittingPatches @@@ -71,7 -71,7 +71,7 @@@ run git diff --check on your changes be (1a) Try to be nice to older C compilers -We try to support wide range of C compilers to compile +We try to support a wide range of C compilers to compile git with. That means that you should not use C99 initializers, even if a lot of compilers grok it. @@@ -222,6 -222,9 +222,9 @@@ D-C-O. Indeed you are encouraged to d place an in-body "From: " line at the beginning to properly attribute the change to its true author (see (2) above). + Also notice that a real name is used in the Signed-off-by: line. Please + don't hide your real name. + Some people also put extra tags at the end. "Acked-by:" says that the patch was reviewed by the person who diff --combined Documentation/git-commit.txt index 6203461f41,5cce3a3791..b5d81be7ec --- a/Documentation/git-commit.txt +++ b/Documentation/git-commit.txt @@@ -29,8 -29,7 +29,8 @@@ The content to be added can be specifie 3. by listing files as arguments to the 'commit' command, in which case the commit will ignore changes staged in the index, and instead - record the current content of the listed files; + record the current content of the listed files (which must already + be known to git); 4. by using the -a switch with the 'commit' command to automatically "add" changes from all known files (i.e. all files that are already @@@ -76,10 -75,8 +76,10 @@@ OPTION read the message from the standard input. --author=:: - Override the author name used in the commit. Use - `A U Thor ` format. + Override the author name used in the commit. You can use the + standard `A U Thor ` format. Otherwise, + an existing commit that matches the given string and its author + name is used. -m :: --message=:: @@@ -146,10 -143,6 +146,10 @@@ It is a rough equivalent for ------ but can be used to amend a merge commit. -- ++ +You should understand the implications of rewriting history if you +amend a commit that has already been published. (See the "RECOVERING +FROM UPSTREAM REBASE" section in linkgit:git-rebase[1].) -i:: --include:: @@@ -166,7 -159,7 +166,7 @@@ 'git-commit' if any paths are given on the command line, in which case this option can be omitted. If this option is specified together with '--amend', then - no paths need be specified, which can be used to amend + no paths need to be specified, which can be used to amend the last commit without committing changes that have already been staged. diff --combined Documentation/git-diff-tree.txt index 5d48664e62,4e83067c4a..fdf8e7b277 --- a/Documentation/git-diff-tree.txt +++ b/Documentation/git-diff-tree.txt @@@ -43,28 -43,19 +43,28 @@@ include::diff-options.txt[ show tree entry itself as well as subtrees. Implies -r. --root:: - When '--root' is specified the initial commit will be showed as a big + When '--root' is specified the initial commit will be shown as a big creation event. This is equivalent to a diff against the NULL tree. --stdin:: When '--stdin' is specified, the command does not take arguments from the command line. Instead, it - reads either one or a list of - separated with a single space from its standard input. + reads lines containing either two , one , or a + list of from its standard input. (Use a single space + as separator.) + -When a single commit is given on one line of such input, it compares -the commit with its parents. The following flags further affects its -behavior. The remaining commits, when given, are used as if they are +When two trees are given, it compares the first tree with the second. +When a single commit is given, it compares the commit with its +parents. The remaining commits, when given, are used as if they are parents of the first commit. ++ +When comparing two trees, the ID of both trees (separated by a space +and terminated by a newline) is printed before the difference. When +comparing commits, the ID of the first (or only) commit, followed by a +newline, is printed. ++ +The following flags further affects the behavior when comparing +commits (but not trees). -m:: By default, 'git-diff-tree --stdin' does not show diff --combined Documentation/git-fast-export.txt index 99a1c3158d,539decbeb2..0c9eb567cb --- a/Documentation/git-fast-export.txt +++ b/Documentation/git-fast-export.txt @@@ -15,7 -15,7 +15,7 @@@ DESCRIPTIO This program dumps the given revisions in a form suitable to be piped into 'git-fast-import'. -You can use it as a human readable bundle replacement (see +You can use it as a human-readable bundle replacement (see linkgit:git-bundle[1]), or as a kind of an interactive 'git-filter-branch'. @@@ -65,6 -65,12 +65,12 @@@ If the backend uses a similar \--import incremental bidirectional exporting of the repository by keeping the marks the same across runs. + --fake-missing-tagger:: + Some old repositories have tags without a tagger. The + fast-import protocol was pretty strict about that, and did not + allow that. So fake a tagger to be able to fast-import the + output. + EXAMPLES -------- diff --combined Documentation/git-submodule.txt index babaa9bc46,e6652a7de1..2f207fbbda --- a/Documentation/git-submodule.txt +++ b/Documentation/git-submodule.txt @@@ -14,8 -14,6 +14,8 @@@ SYNOPSI 'git submodule' [--quiet] init [--] [...] 'git submodule' [--quiet] update [--init] [--] [...] 'git submodule' [--quiet] summary [--summary-limit ] [commit] [--] [...] +'git submodule' [--quiet] foreach +'git submodule' [--quiet] sync [--] [...] DESCRIPTION @@@ -87,7 -85,7 +87,7 @@@ use by subsequent users cloning the sup given relative to the superproject's repository, the presumption is the superproject and submodule repositories will be kept together in the same relative location, and only the - superproject's URL need be provided: git-submodule will correctly + superproject's URL needs to be provided: git-submodule will correctly locate the submodule using the relative URL in .gitmodules. status:: @@@ -125,30 -123,6 +125,30 @@@ summary: in the submodule between the given super project commit and the index or working tree (switched by --cached) are shown. +foreach:: + Evaluates an arbitrary shell command in each checked out submodule. + The command has access to the variables $path and $sha1: + $path is the name of the submodule directory relative to the + superproject, and $sha1 is the commit as recorded in the superproject. + Any submodules defined in the superproject but not checked out are + ignored by this command. Unless given --quiet, foreach prints the name + of each submodule before evaluating the command. + A non-zero return from the command in any submodule causes + the processing to terminate. This can be overridden by adding '|| :' + to the end of the command. ++ +As an example, "git submodule foreach 'echo $path `git rev-parse HEAD`' will +show the path and currently checked out commit for each submodule. + +sync:: + Synchronizes submodules' remote URL configuration setting + to the value specified in .gitmodules. This is useful when + submodule URLs change upstream and you need to update your local + repositories accordingly. ++ +"git submodule sync" synchronizes all submodules while +"git submodule sync -- A" synchronizes submodule "A" only. + OPTIONS ------- -q:: diff --combined Documentation/git.txt index 585af7a0d0,df420aeb33..2c0c23003f --- a/Documentation/git.txt +++ b/Documentation/git.txt @@@ -43,19 -43,16 +43,21 @@@ unreleased) version of git, that is ava branch of the `git.git` repository. Documentation for older releases are available here: - * link:v1.6.0.5/git.html[documentation for release 1.6.0.5] -* link:v1.6.0.2/git.html[documentation for release 1.6.0.2] ++* link:v1.6.0.6/git.html[documentation for release 1.6.0.6] * release notes for ++ link:RelNotes-1.6.0.6.txt[1.6.0.6], + link:RelNotes-1.6.0.5.txt[1.6.0.5], + link:RelNotes-1.6.0.4.txt[1.6.0.4], + link:RelNotes-1.6.0.3.txt[1.6.0.3], link:RelNotes-1.6.0.2.txt[1.6.0.2], link:RelNotes-1.6.0.1.txt[1.6.0.1], link:RelNotes-1.6.0.txt[1.6.0]. --* link:v1.5.6.5/git.html[documentation for release 1.5.6.5] ++* link:v1.5.6.6/git.html[documentation for release 1.5.6.6] * release notes for ++ link:RelNotes-1.5.6.6.txt[1.5.6.6], link:RelNotes-1.5.6.5.txt[1.5.6.5], link:RelNotes-1.5.6.4.txt[1.5.6.4], link:RelNotes-1.5.6.3.txt[1.5.6.3], @@@ -63,18 -60,18 +65,22 @@@ link:RelNotes-1.5.6.1.txt[1.5.6.1], link:RelNotes-1.5.6.txt[1.5.6]. --* link:v1.5.5.4/git.html[documentation for release 1.5.5.4] ++* link:v1.5.5.6/git.html[documentation for release 1.5.5.6] * release notes for ++ link:RelNotes-1.5.5.6.txt[1.5.5.6], ++ link:RelNotes-1.5.5.5.txt[1.5.5.5], link:RelNotes-1.5.5.4.txt[1.5.5.4], link:RelNotes-1.5.5.3.txt[1.5.5.3], link:RelNotes-1.5.5.2.txt[1.5.5.2], link:RelNotes-1.5.5.1.txt[1.5.5.1], link:RelNotes-1.5.5.txt[1.5.5]. --* link:v1.5.4.5/git.html[documentation for release 1.5.4.5] ++* link:v1.5.4.7/git.html[documentation for release 1.5.4.7] * release notes for ++ link:RelNotes-1.5.4.7.txt[1.5.4.7], ++ link:RelNotes-1.5.4.6.txt[1.5.4.6], link:RelNotes-1.5.4.5.txt[1.5.4.5], link:RelNotes-1.5.4.4.txt[1.5.4.4], link:RelNotes-1.5.4.3.txt[1.5.4.3], diff --combined Documentation/gitcore-tutorial.txt index df48045ef6,896cbdf686..e4dd5518c8 --- a/Documentation/gitcore-tutorial.txt +++ b/Documentation/gitcore-tutorial.txt @@@ -899,7 -899,7 +899,7 @@@ file, which had no differences in the ` ---------------- Auto-merging hello CONFLICT (content): Merge conflict in hello - Automatic merge failed; fix up by hand + Automatic merge failed; fix conflicts and then commit the result. ---------------- It tells you that it did an "Automatic merge", which @@@ -993,14 -993,14 +993,14 @@@ would be different ---------------- Updating from ae3a2da... to a80b4aa.... -Fast forward +Fast forward (no commit created; -m option ignored) example | 1 + hello | 1 + 2 files changed, 2 insertions(+), 0 deletions(-) ---------------- - Because your branch did not contain anything more than what are - already merged into the `master` branch, the merge operation did + Because your branch did not contain anything more than what had + already been merged into the `master` branch, the merge operation did not actually do a merge. Instead, it just updated the top of the tree of your branch to that of the `master` branch. This is often called 'fast forward' merge. @@@ -1265,8 -1265,9 +1265,8 @@@ file, using 3-way merge. This is done ------------ $ git merge-index git-merge-one-file hello -Auto-merging hello. -merge: warning: conflicts during merge -ERROR: Merge conflict in hello. +Auto-merging hello +ERROR: Merge conflict in hello fatal: merge program failed ------------ @@@ -1352,7 -1353,7 +1352,7 @@@ $ GIT_DIR=my-git.git git ini ------------ Make sure this directory is available for others you want your - changes to be pulled by via the transport of your choice. Also + changes to be pulled via the transport of your choice. Also you need to make sure that you have the 'git-receive-pack' program on the `$PATH`. @@@ -1446,7 -1447,7 +1446,7 @@@ public repository you might want to rep never. If you run `git repack` again at this point, it will say -"Nothing to pack". Once you continue your development and +"Nothing new to pack.". Once you continue your development and accumulate the changes, running `git repack` again will create a new pack, that contains objects created since you packed your repository the last time. We recommend that you pack your project @@@ -1511,7 -1512,7 +1511,7 @@@ You can repack this private repository 6. Push your changes to the public repository, and announce it to the public. - 7. Every once in a while, "git-repack" the public repository. + 7. Every once in a while, 'git-repack' the public repository. Go back to step 5. and continue working. @@@ -1692,7 -1693,6 +1692,7 @@@ SEE ALS linkgit:gittutorial[7], linkgit:gittutorial-2[7], linkgit:gitcvs-migration[7], +linkgit:git-help[1], link:everyday.html[Everyday git], link:user-manual.html[The Git User's Manual] diff --combined Documentation/gitk.txt index 317f6317c2,5ef3687e39..4673a75a98 --- a/Documentation/gitk.txt +++ b/Documentation/gitk.txt @@@ -21,7 -21,7 +21,7 @@@ git repository OPTIONS ------- - To control which revisions to shown, the command takes options applicable to + To control which revisions to show, the command takes options applicable to the 'git-rev-list' command (see linkgit:git-rev-list[1]). This manual page describes only the most frequently used options. @@@ -56,11 -56,6 +56,11 @@@ Use this instead of explicitly specifying if the set of commits to show may vary between refreshes. +--select-commit=:: + + Automatically select the specified commit after loading the graph. + Default behavior is equivalent to specifying '--select-commit=HEAD'. + :: Limit the revisions to show. This can be either a single revision @@@ -80,7 -75,7 +80,7 @@@ Example -------- gitk v2.6.12.. include/scsi drivers/scsi:: - Show as the changes since version 'v2.6.12' that changed any + Show the changes since version 'v2.6.12' that changed any file in the include/scsi or drivers/scsi subdirectories gitk --since="2 weeks ago" \-- gitk:: diff --combined Documentation/i18n.txt index 2cdacd94cd,c673966331..708da6ca31 --- a/Documentation/i18n.txt +++ b/Documentation/i18n.txt @@@ -7,11 -7,11 +7,11 @@@ At the core level, git is character enc to be what lstat(2) and creat(2) accepts. There is no such thing as pathname encoding translation. - - The contents of the blob objects are uninterpreted sequence + - The contents of the blob objects are uninterpreted sequences of bytes. There is no encoding translation at the core level. - - The commit log messages are uninterpreted sequence of non-NUL + - The commit log messages are uninterpreted sequences of non-NUL bytes. Although we encourage that the commit log messages are encoded @@@ -37,9 -37,9 +37,9 @@@ of `i18n.commitencoding` in its `encodi help other people who look at them later. Lack of this header implies that the commit log message is encoded in UTF-8. -. 'git-log', 'git-show' and friends looks at the `encoding` - header of a commit object, and tries to re-code the log - message into UTF-8 unless otherwise specified. You can +. 'git-log', 'git-show', 'git-blame' and friends look at the + `encoding` header of a commit object, and try to re-code the + log message into UTF-8 unless otherwise specified. You can specify the desired output encoding with `i18n.logoutputencoding` in `.git/config` file, like this: + diff --combined fast-import.c index 201d4ffa13,d58cca58e5..171d178339 --- a/fast-import.c +++ b/fast-import.c @@@ -43,7 -43,7 +43,7 @@@ Format of STDIN stream new_tag ::= 'tag' sp tag_str lf 'from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf - 'tagger' sp name '<' email '>' when lf + ('tagger' sp name '<' email '>' when lf)? tag_msg; tag_msg ::= data; @@@ -376,7 -376,7 +376,7 @@@ static void dump_marks_helper(FILE *, u static void write_crash_report(const char *err) { - char *loc = git_path("fast_import_crash_%d", getpid()); + char *loc = git_path("fast_import_crash_%"PRIuMAX, (uintmax_t) getpid()); FILE *rpt = fopen(loc, "w"); struct branch *b; unsigned long lu; @@@ -390,8 -390,8 +390,8 @@@ fprintf(stderr, "fast-import: dumping crash report to %s\n", loc); fprintf(rpt, "fast-import crash report:\n"); - fprintf(rpt, " fast-import process: %d\n", getpid()); - fprintf(rpt, " parent process : %d\n", getppid()); + fprintf(rpt, " fast-import process: %"PRIuMAX"\n", (uintmax_t) getpid()); + fprintf(rpt, " parent process : %"PRIuMAX"\n", (uintmax_t) getppid()); fprintf(rpt, " at %s\n", show_date(time(NULL), 0, DATE_LOCAL)); fputc('\n', rpt); @@@ -554,10 -554,6 +554,10 @@@ static void *pool_alloc(size_t len struct mem_pool *p; void *r; + /* round up to a 'uintmax_t' alignment */ + if (len & (sizeof(uintmax_t) - 1)) + len += sizeof(uintmax_t) - (len & (sizeof(uintmax_t) - 1)); + for (p = mem_pool; p; p = p->next_pool) if ((p->end - p->next_free >= len)) break; @@@ -576,6 -572,9 +576,6 @@@ } r = p->next_free; - /* round out to a 'uintmax_t' alignment */ - if (len & (sizeof(uintmax_t) - 1)) - len += sizeof(uintmax_t) - (len & (sizeof(uintmax_t) - 1)); p->next_free += len; return r; } @@@ -846,7 -845,7 +846,7 @@@ static int oecmp (const void *a_, cons static char *create_index(void) { static char tmpfile[PATH_MAX]; - SHA_CTX ctx; + git_SHA_CTX ctx; struct sha1file *f; struct object_entry **idx, **c, **last, *e; struct object_entry_pool *o; @@@ -883,17 -882,17 +883,17 @@@ idx_fd = xmkstemp(tmpfile); f = sha1fd(idx_fd, tmpfile); sha1write(f, array, 256 * sizeof(int)); - SHA1_Init(&ctx); + git_SHA1_Init(&ctx); for (c = idx; c != last; c++) { uint32_t offset = htonl((*c)->offset); sha1write(f, &offset, 4); sha1write(f, (*c)->sha1, sizeof((*c)->sha1)); - SHA1_Update(&ctx, (*c)->sha1, 20); + git_SHA1_Update(&ctx, (*c)->sha1, 20); } sha1write(f, pack_data->sha1, sizeof(pack_data->sha1)); sha1close(f, NULL, CSUM_FSYNC); free(idx); - SHA1_Final(pack_data->sha1, &ctx); + git_SHA1_Final(pack_data->sha1, &ctx); return tmpfile; } @@@ -1036,15 -1035,15 +1036,15 @@@ static int store_object unsigned char hdr[96]; unsigned char sha1[20]; unsigned long hdrlen, deltalen; - SHA_CTX c; + git_SHA_CTX c; z_stream s; hdrlen = sprintf((char*)hdr,"%s %lu", typename(type), (unsigned long)dat->len) + 1; - SHA1_Init(&c); - SHA1_Update(&c, hdr, hdrlen); - SHA1_Update(&c, dat->buf, dat->len); - SHA1_Final(sha1, &c); + git_SHA1_Init(&c); + git_SHA1_Update(&c, hdr, hdrlen); + git_SHA1_Update(&c, dat->buf, dat->len); + git_SHA1_Final(sha1, &c); if (sha1out) hashcpy(sha1out, sha1); @@@ -2265,23 -2264,27 +2265,27 @@@ static void parse_new_tag(void read_next_command(); /* tagger ... */ - if (prefixcmp(command_buf.buf, "tagger ")) - die("Expected tagger command, got %s", command_buf.buf); - tagger = parse_ident(command_buf.buf + 7); + if (!prefixcmp(command_buf.buf, "tagger ")) { + tagger = parse_ident(command_buf.buf + 7); + read_next_command(); + } else + tagger = NULL; /* tag payload/message */ - read_next_command(); parse_data(&msg); /* build the tag object */ strbuf_reset(&new_data); + strbuf_addf(&new_data, - "object %s\n" - "type %s\n" - "tag %s\n" - "tagger %s\n" - "\n", - sha1_to_hex(sha1), commit_type, t->name, tagger); + "object %s\n" + "type %s\n" + "tag %s\n", + sha1_to_hex(sha1), commit_type, t->name); + if (tagger) + strbuf_addf(&new_data, + "tagger %s\n", tagger); + strbuf_addch(&new_data, '\n'); strbuf_addbuf(&new_data, &msg); free(tagger); diff --combined git-send-email.perl index 3112f769cd,449d938ba9..61144011d0 --- a/git-send-email.perl +++ b/git-send-email.perl @@@ -20,14 -20,11 +20,15 @@@ use strict use warnings; use Term::ReadLine; use Getopt::Long; + use Text::ParseWords; use Data::Dumper; use Term::ANSIColor; +use File::Temp qw/ tempdir /; +use Error qw(:try); use Git; +Getopt::Long::Configure qw/ pass_through /; + package FakeTerm; sub new { my ($class, $reason) = @_; @@@ -42,44 -39,76 +43,44 @@@ package main sub usage { print <... -Options: - --from Specify the "From:" line of the email to be sent. - - --to Specify the primary "To:" line of the email. - - --cc Specify an initial "Cc:" list for the entire series - of emails. - - --cc-cmd Specify a command to execute per file which adds - per file specific cc address entries - - --bcc Specify a list of email addresses that should be Bcc: - on all the emails. - - --compose Use \$GIT_EDITOR, core.editor, \$EDITOR, or \$VISUAL to edit - an introductory message for the patch series. - - --subject Specify the initial "Subject:" line. - Only necessary if --compose is also set. If --compose - is not set, this will be prompted for. - - --in-reply-to Specify the first "In-Reply-To:" header line. - Only used if --compose is also set. If --compose is not - set, this will be prompted for. - - --chain-reply-to If set, the replies will all be to the previous - email sent, rather than to the first email sent. - Defaults to on. - - --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. 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. - - --smtp-pass The password for SMTP-AUTH. - - --smtp-encryption Specify 'tls' for STARTTLS encryption, or 'ssl' for SSL. - Any other value disables the feature. - - --smtp-ssl Synonym for '--smtp-encryption=ssl'. Deprecated. - - --suppress-cc Suppress the specified category of auto-CC. The category - can be one of 'author' for the patch author, 'self' to - avoid copying yourself, 'sob' for Signed-off-by lines, - 'cccmd' for the output of the cccmd, or 'all' to suppress - all of these. - - --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. - - --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. - - --no-validate Don't perform any sanity checks on patches. +git send-email [options] + + Composing: + --from * Email From: + --to * Email To: + --cc * Email Cc: + --bcc * Email Bcc: + --subject * Email "Subject:" + --in-reply-to * Email "In-Reply-To:" + --annotate * Review each patch that will be sent in an editor. + --compose * Open an editor for introduction. + + Sending: + --envelope-sender * Email envelope sender. + --smtp-server * Outgoing SMTP server to use. The port + is optional. Default 'localhost'. + --smtp-server-port * Outgoing SMTP server port. + --smtp-user * Username for SMTP-AUTH. + --smtp-pass * Password for SMTP-AUTH; not necessary. + --smtp-encryption * tls or ssl; anything else disables. + --smtp-ssl * Deprecated. Use '--smtp-encryption ssl'. + + Automating: + --identity * Use the sendemail. options. + --cc-cmd * Email Cc: via ` \$patch_path` + --suppress-cc * author, self, sob, cccmd, all. + --[no-]signed-off-by-cc * Send to Cc: and Signed-off-by: + addresses. Default on. + --[no-]suppress-from * Send to self. Default off. + --[no-]chain-reply-to * Chain In-Reply-To: fields. Default on. + --[no-]thread * Use In-Reply-To: field. Default on. + + Administering: + --quiet * Output one line of info per email. + --dry-run * Don't actually send the emails. + --[no-]validate * Perform patch sanity checks. Default on. + --[no-]format-patch * understand any non optional arguments as + `git format-patch` ones. EOT exit(1); @@@ -131,10 -160,12 +132,10 @@@ my $auth sub unique_email_list(@); sub cleanup_compose_files(); -# Constants (essentially) -my $compose_filename = ".msg.$$"; - # Variables we fill in automatically, or via prompting: my (@to,@cc,@initial_cc,@bcclist,@xh, - $initial_reply_to,$initial_subject,@files,$author,$sender,$smtp_authpass,$compose,$time); + $initial_reply_to,$initial_subject,@files, + $author,$sender,$smtp_authpass,$annotate,$compose,$time); my $envelope_sender; @@@ -154,42 -185,19 +155,42 @@@ if ($@) # Behavior modification variables my ($quiet, $dry_run) = (0, 0); +my $format_patch; +my $compose_filename = $repo->repo_path() . "/.gitsendemail.msg.$$"; + +# Handle interactive edition of files. +my $multiedit; +my $editor = $ENV{GIT_EDITOR} || Git::config(@repo, "core.editor") || $ENV{VISUAL} || $ENV{EDITOR} || "vi"; +sub do_edit { + if (defined($multiedit) && !$multiedit) { + map { + system('sh', '-c', $editor.' "$@"', $editor, $_); + if (($? & 127) || ($? >> 8)) { + die("the editor exited uncleanly, aborting everything"); + } + } @_; + } else { + system('sh', '-c', $editor.' "$@"', $editor, @_); + if (($? & 127) || ($? >> 8)) { + die("the editor exited uncleanly, aborting everything"); + } + } +} # Variables with corresponding config settings -my ($thread, $chain_reply_to, $suppress_from, $signed_off_cc, $cc_cmd); +my ($thread, $chain_reply_to, $suppress_from, $signed_off_by_cc, $cc_cmd); my ($smtp_server, $smtp_server_port, $smtp_authuser, $smtp_encryption); my ($identity, $aliasfiletype, @alias_files, @smtp_host_parts); -my ($no_validate); +my ($validate); my (@suppress_cc); my %config_bool_settings = ( "thread" => [\$thread, 1], "chainreplyto" => [\$chain_reply_to, 1], "suppressfrom" => [\$suppress_from, undef], - "signedoffcc" => [\$signed_off_cc, undef], + "signedoffbycc" => [\$signed_off_by_cc, undef], + "signedoffcc" => [\$signed_off_by_cc, undef], # Deprecated + "validate" => [\$validate, 1], ); my %config_settings = ( @@@ -205,7 -213,6 +206,7 @@@ "aliasesfile" => \@alias_files, "suppresscc" => \@suppress_cc, "envelopesender" => \$envelope_sender, + "multiedit" => \$multiedit, ); # Handle Uncouth Termination @@@ -248,18 -255,16 +249,18 @@@ my $rc = GetOptions("sender|from=s" => "smtp-ssl" => sub { $smtp_encryption = 'ssl' }, "smtp-encryption=s" => \$smtp_encryption, "identity=s" => \$identity, + "annotate" => \$annotate, "compose" => \$compose, "quiet" => \$quiet, "cc-cmd=s" => \$cc_cmd, "suppress-from!" => \$suppress_from, "suppress-cc=s" => \@suppress_cc, - "signed-off-cc|signed-off-by-cc!" => \$signed_off_cc, + "signed-off-cc|signed-off-by-cc!" => \$signed_off_by_cc, "dry-run" => \$dry_run, "envelope-sender=s" => \$envelope_sender, "thread!" => \$thread, - "no-validate" => \$no_validate, + "validate!" => \$validate, + "format-patch!" => \$format_patch, ); unless ($rc) { @@@ -331,7 -336,7 +332,7 @@@ if ($suppress_cc{'all'}) # If explicit old-style ones are specified, they trump --suppress-cc. $suppress_cc{'self'} = $suppress_from if defined $suppress_from; -$suppress_cc{'sob'} = !$signed_off_cc if defined $signed_off_cc; +$suppress_cc{'sob'} = !$signed_off_by_cc if defined $signed_off_by_cc; # Debugging, print out the suppressions. if (0) { @@@ -359,6 -364,10 +360,10 @@@ foreach my $entry (@bcclist) die "Comma in --bcclist entry: $entry'\n" unless $entry !~ m/,/; } + sub split_addrs { + return parse_line('\s*,\s*', 1, @_); + } + my %aliases; my %parse_alias = ( # multiline formats can be supported in the future @@@ -367,20 -376,17 +372,20 @@@ my ($alias, $addr) = ($1, $2); $addr =~ s/#.*$//; # mutt allows # comments # commas delimit multiple addresses - $aliases{$alias} = [ split(/\s*,\s*/, $addr) ]; + $aliases{$alias} = [ split_addrs($addr) ]; }}}, mailrc => sub { my $fh = shift; while (<$fh>) { if (/^alias\s+(\S+)\s+(.*)$/) { # spaces delimit multiple addresses $aliases{$1} = [ split(/\s+/, $2) ]; }}}, - pine => sub { my $fh = shift; while (<$fh>) { - if (/^(\S+)\t.*\t(.*)$/) { + pine => sub { my $fh = shift; my $f='\t[^\t]*'; + for (my $x = ''; defined($x); $x = $_) { + chomp $x; + $x .= $1 while(defined($_ = <$fh>) && /^ +(.*)$/); + $x =~ /^(\S+)$f\t\(?([^\t]+?)\)?(:?$f){0,2}$/ or next; - $aliases{$1} = [ split(/\s*,\s*/, $2) ]; + $aliases{$1} = [ split_addrs($2) ]; - }}}, + }}, gnus => sub { my $fh = shift; while (<$fh>) { if (/\(define-mail-alias\s+"(\S+?)"\s+"(\S+?)"\)/) { $aliases{$1} = [ $2 ]; @@@ -397,53 -403,24 +402,53 @@@ if (@alias_files and $aliasfiletype an ($sender) = expand_aliases($sender) if defined $sender; +# returns 1 if the conflict must be solved using it as a format-patch argument +sub check_file_rev_conflict($) { + my $f = shift; + try { + $repo->command('rev-parse', '--verify', '--quiet', $f); + if (defined($format_patch)) { + print "foo\n"; + return $format_patch; + } + die(<command('format-patch', '-o', tempdir(CLEANUP => 1), @rev_list_opts); +} + +if ($validate) { foreach my $f (@files) { unless (-p $f) { my $error = validate_patch($f); @@@ -461,108 -438,6 +466,108 @@@ if (@files) usage(); } +sub get_patch_subject($) { + my $fn = shift; + open (my $fh, '<', $fn); + while (my $line = <$fh>) { + next unless ($line =~ /^Subject: (.*)$/); + close $fh; + return "GIT: $1\n"; + } + close $fh; + die "No subject line in $fn ?"; +} + +if ($compose) { + # Note that this does not need to be secure, but we will make a small + # effort to have it be unique + open(C,">",$compose_filename) + or die "Failed to open for writing $compose_filename: $!"; + + + my $tpl_sender = $sender || $repoauthor || $repocommitter || ''; + my $tpl_subject = $initial_subject || ''; + my $tpl_reply_to = $initial_reply_to || ''; + + print C <",$compose_filename . ".final") + or die "Failed to open $compose_filename.final : " . $!; + + open(C,"<",$compose_filename) + or die "Failed to open $compose_filename : " . $!; + + my $need_8bit_cte = file_has_nonascii($compose_filename); + my $in_body = 0; + my $summary_empty = 1; + while() { + next if m/^GIT: /; + if ($in_body) { + $summary_empty = 0 unless (/^\n$/); + } elsif (/^\n$/) { + $in_body = 1; + if ($need_8bit_cte) { + print C2 "MIME-Version: 1.0\n", + "Content-Type: text/plain; ", + "charset=utf-8\n", + "Content-Transfer-Encoding: 8bit\n"; + } + } elsif (/^MIME-Version:/i) { + $need_8bit_cte = 0; + } elsif (/^Subject:\s*(.+)\s*$/i) { + $initial_subject = $1; + my $subject = $initial_subject; + $_ = "Subject: " . + ($subject =~ /[^[:ascii:]]/ ? + quote_rfc2047($subject) : + $subject) . + "\n"; + } elsif (/^In-Reply-To:\s*(.+)\s*$/i) { + $initial_reply_to = $1; + next; + } elsif (/^From:\s*(.+)\s*$/i) { + $sender = $1; + next; + } elsif (/^(?:To|Cc|Bcc):/i) { + print "To/Cc/Bcc fields are not interpreted yet, they have been ignored\n"; + next; + } + print C2 $_; + } + close(C); + close(C2); + + if ($summary_empty) { + print "Summary email is empty, skipping it\n"; + $compose = -1; + } +} elsif ($annotate) { + do_edit(@files); +} + my $prompting = 0; if (!defined $sender) { $sender = $repoauthor || $repocommitter || ''; @@@ -588,7 -463,7 +593,7 @@@ if (!@to) } my $to = $_; - push @to, split /,\s*/, $to; + push @to, split_addrs($to); $prompting++; } @@@ -607,6 -482,17 +612,6 @@@ sub expand_aliases @initial_cc = expand_aliases(@initial_cc); @bcclist = expand_aliases(@bcclist); -if (!defined $initial_subject && $compose) { - while (1) { - $_ = $term->readline("What subject should the initial email start with? ", $initial_subject); - last if defined $_; - print "\n"; - } - - $initial_subject = $_; - $prompting++; -} - if ($thread && !defined $initial_reply_to && $prompting) { while (1) { $_= $term->readline("Message-ID to be used as In-Reply-To for the first email? ", $initial_reply_to); @@@ -633,6 -519,59 +638,6 @@@ if (!defined $smtp_server) } if ($compose) { - # Note that this does not need to be secure, but we will make a small - # effort to have it be unique - open(C,">",$compose_filename) - or die "Failed to open for writing $compose_filename: $!"; - print C "From $sender # This line is ignored.\n"; - printf C "Subject: %s\n\n", $initial_subject; - printf C <",$compose_filename . ".final") - or die "Failed to open $compose_filename.final : " . $!; - - open(C,"<",$compose_filename) - or die "Failed to open $compose_filename : " . $!; - - my $need_8bit_cte = file_has_nonascii($compose_filename); - my $in_body = 0; - while() { - next if m/^GIT: /; - if (!$in_body && /^\n$/) { - $in_body = 1; - if ($need_8bit_cte) { - print C2 "MIME-Version: 1.0\n", - "Content-Type: text/plain; ", - "charset=utf-8\n", - "Content-Transfer-Encoding: 8bit\n"; - } - } - if (!$in_body && /^MIME-Version:/i) { - $need_8bit_cte = 0; - } - if (!$in_body && /^Subject: ?(.*)/i) { - my $subject = $1; - $_ = "Subject: " . - ($subject =~ /[^[:ascii:]]/ ? - quote_rfc2047($subject) : - $subject) . - "\n"; - } - print C2 $_; - } - close(C); - close(C2); - while (1) { $_ = $term->readline("Send this email? (y|n) "); last if defined $_; @@@ -644,9 -583,7 +649,9 @@@ exit(0); } - @files = ($compose_filename . ".final", @files); + if ($compose > 0) { + @files = ($compose_filename . ".final", @files); + } } # Variables we set as part of the loop over files diff --combined t/t9300-fast-import.sh index 91b5aced1b,8b79de5b63..821be7ce8d --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@@ -3,9 -3,9 +3,9 @@@ # Copyright (c) 2007 Shawn Pearce # -test_description='test git-fast-import utility' +test_description='test git fast-import utility' . ./test-lib.sh -. ../diff-lib.sh ;# test-lib chdir's into trash +. "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash file2_data='file2 second line of EOF' @@@ -56,10 -56,16 +56,16 @@@ M 644 :2 file M 644 :3 file3 M 755 :4 file4 + tag series-A + from :5 + data <actual && test_cmp expect actual' + cat >expect <actual && + test_cmp expect actual + ' + cat >expect <input <expect <output && test_cmp expect output' @@@ -649,7 -667,7 +667,7 @@@ cat >expect <actual && compare_diff_raw expect actual' @@@ -670,7 -688,7 +688,7 @@@ cat >expect <actual && compare_diff_raw expect actual' @@@ -691,7 -709,7 +709,7 @@@ cat >expect <actual && compare_diff_raw expect actual' @@@ -717,7 -735,7 +735,7 @@@ cat >expect <actual && compare_diff_raw expect actual' @@@ -751,7 -769,7 +769,7 @@@ cat >expect <actual && compare_diff_raw expect actual' @@@ -775,8 -793,8 +793,8 @@@ INPUT_EN test_expect_success \ 'N: copy dirty subdirectory' \ - 'git-fast-import input <actual && @@@ -914,7 -932,7 +932,7 @@@ progress I'm done INPUT_END test_expect_success \ 'O: progress outputs as requested by input' \ - 'git-fast-import actual && + 'git fast-import actual && grep "progress " expect && test_cmp expect actual' @@@ -979,7 -997,7 +997,7 @@@ INPUT_EN test_expect_success \ 'P: supermodule & submodule mix' \ - 'git-fast-import input <input <input <file && git commit -s -m den file && @@@ -239,4 -239,24 +239,24 @@@ test_expect_success 'fast-export | fast ' + cat > tag-content << EOF + object $(git rev-parse HEAD) + type commit + tag rosten + EOF + + test_expect_success 'cope with tagger-less tags' ' + + TAG=$(git hash-object -t tag -w tag-content) && + git update-ref refs/tags/sonnenschein $TAG && + git fast-export -C -C --signed-tags=strip --all > output && + test $(grep -c "^tag " output) = 4 && + ! grep "Unspecified Tagger" output && + git fast-export -C -C --signed-tags=strip --all \ + --fake-missing-tagger > output && + test $(grep -c "^tag " output) = 4 && + grep "Unspecified Tagger" output + + ' + test_done