diff options
-rw-r--r-- | Documentation/config.txt | 5 | ||||
-rw-r--r-- | Documentation/git-apply.txt | 2 | ||||
-rw-r--r-- | Documentation/git-send-email.txt | 27 | ||||
-rw-r--r-- | bisect.c | 79 | ||||
-rw-r--r-- | commit.c | 20 | ||||
-rw-r--r-- | commit.h | 2 | ||||
-rwxr-xr-x | contrib/completion/git-completion.bash | 10 | ||||
-rw-r--r-- | dir.c | 2 | ||||
-rwxr-xr-x | git-send-email.perl | 20 | ||||
-rw-r--r-- | http-push.c | 21 | ||||
-rwxr-xr-x | t/t3700-add.sh | 12 | ||||
-rwxr-xr-x | t/t6030-bisect-porcelain.sh | 13 |
12 files changed, 114 insertions, 99 deletions
diff --git a/Documentation/config.txt b/Documentation/config.txt index 2c031620c5..3a86d1f8f0 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -438,6 +438,11 @@ On some file system/operating system combinations, this is unreliable. Set this config setting to 'rename' there; However, This will remove the check that makes sure that existing object files will not get overwritten. +add.ignore-errors:: + Tells 'git-add' to continue adding files when some files cannot be + added due to indexing errors. Equivalent to the '--ignore-errors' + option of linkgit:git-add[1]. + alias.*:: Command aliases for the linkgit:git[1] command wrapper - e.g. after defining "alias.last = cat-file commit HEAD", the invocation diff --git a/Documentation/git-apply.txt b/Documentation/git-apply.txt index 9e5baa2777..735374d7df 100644 --- a/Documentation/git-apply.txt +++ b/Documentation/git-apply.txt @@ -3,7 +3,7 @@ git-apply(1) NAME ---- -git-apply - Apply a patch on a git index file and a working tree +git-apply - Apply a patch on a git index file and/or a working tree SYNOPSIS diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt index f940770279..7c5ce415c7 100644 --- a/Documentation/git-send-email.txt +++ b/Documentation/git-send-email.txt @@ -39,6 +39,10 @@ OPTIONS Composing ~~~~~~~~~ +--annotate:: + Review and edit each patch you're about to send. See the + CONFIGURATION section for 'sendemail.multiedit'. + --bcc=<address>:: Specify a "Bcc:" value for each email. Default is the value of 'sendemail.bcc'. @@ -51,11 +55,6 @@ The --bcc option must be repeated for each user you want on the bcc list. + The --cc option must be repeated for each user you want on the cc list. ---annotate:: - Review each patch you're about to send in an editor. The setting - 'sendemail.multiedit' defines if this will spawn one editor per patch - or one for all of them at once. - --compose:: Use $GIT_EDITOR, core.editor, $VISUAL, or $EDITOR to edit an introductory message for the patch series. @@ -67,6 +66,8 @@ In-Reply-To headers specified in the message. If the body of the message and In-Reply-To headers will be used unless they are removed. + Missing From or In-Reply-To headers will be prompted for. ++ +See the CONFIGURATION section for 'sendemail.multiedit'. --from=<address>:: Specify the sender of the emails. If not specified on the command line, @@ -138,7 +139,9 @@ user is prompted for a password while the input is masked for privacy. --smtp-server-port=<port>:: Specifies a port different from the default port (SMTP servers typically listen to smtp port 25 and ssmtp port - 465). This can be set with 'sendemail.smtpserverport'. + 465); symbolic port names (e.g. "submission" instead of 465) + are also accepted. The port can also be set with the + 'sendemail.smtpserverport' configuration variable. --smtp-ssl:: Legacy alias for '--smtp-encryption ssl'. @@ -233,6 +236,12 @@ have been specified, in which case default to 'compose'. --dry-run:: Do everything except actually send the emails. +--[no-]format-patch:: + When an argument may be understood either as a reference or as a file name, + choose to understand it as a format-patch argument ('--format-patch') + or as a file name ('--no-format-patch'). By default, when such a conflict + occurs, git send-email will fail. + --quiet:: Make git-send-email less verbose. One line per email should be all that is output. @@ -249,12 +258,6 @@ have been specified, in which case default to 'compose'. Default is the value of 'sendemail.validate'; if this is not set, default to '--validate'. ---[no-]format-patch:: - When an argument may be understood either as a reference or as a file name, - choose to understand it as a format-patch argument ('--format-patch') - or as a file name ('--no-format-patch'). By default, when such a conflict - occurs, git send-email will fail. - CONFIGURATION ------------- @@ -553,7 +553,9 @@ struct commit_list *filter_skipped(struct commit_list *list, return filtered; } -static void bisect_rev_setup(struct rev_info *revs, const char *prefix) +static void bisect_rev_setup(struct rev_info *revs, const char *prefix, + const char *bad_format, const char *good_format, + int read_paths) { struct argv_array rev_argv = { NULL, 0, 0 }; int i; @@ -564,26 +566,24 @@ static void bisect_rev_setup(struct rev_info *revs, const char *prefix) /* rev_argv.argv[0] will be ignored by setup_revisions */ argv_array_push(&rev_argv, xstrdup("bisect_rev_setup")); - argv_array_push_sha1(&rev_argv, current_bad_sha1, "%s"); + argv_array_push_sha1(&rev_argv, current_bad_sha1, bad_format); for (i = 0; i < good_revs.sha1_nr; i++) - argv_array_push_sha1(&rev_argv, good_revs.sha1[i], "^%s"); + argv_array_push_sha1(&rev_argv, good_revs.sha1[i], + good_format); argv_array_push(&rev_argv, xstrdup("--")); - read_bisect_paths(&rev_argv); + if (read_paths) + read_bisect_paths(&rev_argv); argv_array_push(&rev_argv, NULL); setup_revisions(rev_argv.argv_nr, rev_argv.argv, revs, NULL); - revs->limited = 1; } -static void bisect_common(struct rev_info *revs, int *reaches, int *all) +static void bisect_common(struct rev_info *revs) { if (prepare_revision_walk(revs)) die("revision walk setup failed"); if (revs->tree_objects) mark_edges_uninteresting(revs->commits, revs, NULL); - - revs->commits = find_bisection(revs->commits, reaches, all, - !!skipped_revs.sha1_nr); } static void exit_if_skipped_commits(struct commit_list *tried, @@ -750,42 +750,31 @@ static void check_merge_bases(void) free_commit_list(result); } -/* - * This function runs the command "git rev-list $_good ^$_bad" - * and returns 1 if it produces some output, 0 otherwise. - */ -static int check_ancestors(void) +static int check_ancestors(const char *prefix) { - struct argv_array rev_argv = { NULL, 0, 0 }; - struct strbuf str = STRBUF_INIT; - int i, result = 0; - struct child_process rls; - FILE *rls_fout; + struct rev_info revs; + struct object_array pending_copy; + int i, res; - argv_array_push(&rev_argv, xstrdup("rev-list")); - argv_array_push_sha1(&rev_argv, current_bad_sha1, "^%s"); - for (i = 0; i < good_revs.sha1_nr; i++) - argv_array_push_sha1(&rev_argv, good_revs.sha1[i], "%s"); - argv_array_push(&rev_argv, NULL); + bisect_rev_setup(&revs, prefix, "^%s", "%s", 0); - memset(&rls, 0, sizeof(rls)); - rls.argv = rev_argv.argv; - rls.out = -1; - rls.git_cmd = 1; - if (start_command(&rls)) - die("Could not launch 'git rev-list' command."); - rls_fout = fdopen(rls.out, "r"); - while (strbuf_getline(&str, rls_fout, '\n') != EOF) { - strbuf_trim(&str); - if (*str.buf) { - result = 1; - break; - } + /* Save pending objects, so they can be cleaned up later. */ + memset(&pending_copy, 0, sizeof(pending_copy)); + for (i = 0; i < revs.pending.nr; i++) + add_object_array(revs.pending.objects[i].item, + revs.pending.objects[i].name, + &pending_copy); + + bisect_common(&revs); + res = (revs.commits != NULL); + + /* Clean up objects used, as they will be reused. */ + for (i = 0; i < pending_copy.nr; i++) { + struct object *o = pending_copy.objects[i].item; + unparse_commit((struct commit *)o); } - fclose(rls_fout); - finish_command(&rls); - return result; + return res; } /* @@ -813,7 +802,8 @@ static void check_good_are_ancestors_of_bad(const char *prefix) if (good_revs.sha1_nr == 0) return; - if (check_ancestors()) + /* Check if all good revs are ancestor of the bad rev. */ + if (check_ancestors(prefix)) check_merge_bases(); /* Create file BISECT_ANCESTORS_OK. */ @@ -843,10 +833,13 @@ int bisect_next_all(const char *prefix) check_good_are_ancestors_of_bad(prefix); - bisect_rev_setup(&revs, prefix); + bisect_rev_setup(&revs, prefix, "%s", "^%s", 1); + revs.limited = 1; - bisect_common(&revs, &reaches, &all); + bisect_common(&revs); + revs.commits = find_bisection(revs.commits, &reaches, &all, + !!skipped_revs.sha1_nr); revs.commits = filter_skipped(revs.commits, &tried, 0); if (!revs.commits) { @@ -316,6 +316,26 @@ int parse_commit(struct commit *item) return ret; } +static void unparse_commit_list(struct commit_list *list) +{ + for (; list; list = list->next) + unparse_commit(list->item); +} + +void unparse_commit(struct commit *item) +{ + item->object.flags = 0; + item->object.used = 0; + if (item->object.parsed) { + item->object.parsed = 0; + if (item->parents) { + unparse_commit_list(item->parents); + free_commit_list(item->parents); + item->parents = NULL; + } + } +} + struct commit_list *commit_list_insert(struct commit *item, struct commit_list **list_p) { struct commit_list *new_list = xmalloc(sizeof(struct commit_list)); @@ -40,6 +40,8 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size); int parse_commit(struct commit *item); +void unparse_commit(struct commit *item); + struct commit_list * commit_list_insert(struct commit *item, struct commit_list **list_p); unsigned commit_list_count(const struct commit_list *l); struct commit_list * insert_by_date(struct commit *item, struct commit_list **list); diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index c84d765ff9..98b9cbedc2 100755 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -150,12 +150,10 @@ __git_ps1 () fi fi - if [ -n "$b" ]; then - if [ -n "${1-}" ]; then - printf "$1" "$c${b##refs/heads/}$w$i$r" - else - printf " (%s)" "$c${b##refs/heads/}$w$i$r" - fi + if [ -n "${1-}" ]; then + printf "$1" "$c${b##refs/heads/}$w$i$r" + else + printf " (%s)" "$c${b##refs/heads/}$w$i$r" fi fi } @@ -396,7 +396,7 @@ static struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathna static struct dir_entry *dir_add_ignored(struct dir_struct *dir, const char *pathname, int len) { - if (cache_name_pos(pathname, len) >= 0) + if (!cache_name_is_other(pathname, len)) return NULL; ALLOC_GROW(dir->ignored, dir->ignored_nr+1, dir->ignored_alloc); diff --git a/git-send-email.perl b/git-send-email.perl index e793935b4f..3d6a98218a 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -538,7 +538,7 @@ if ($compose) { print C <<EOT; From $tpl_sender # This line is ignored. -GIT: Lines beginning in "GIT: " will be removed. +GIT: Lines beginning in "GIT:" will be removed. GIT: Consider including an overall diffstat or table of contents GIT: for the patch you are writing. GIT: @@ -553,8 +553,6 @@ EOT } close(C); - my $editor = $ENV{GIT_EDITOR} || Git::config(@repo, "core.editor") || $ENV{VISUAL} || $ENV{EDITOR} || "vi"; - if ($annotate) { do_edit($compose_filename, @files); } else { @@ -571,7 +569,7 @@ EOT my $in_body = 0; my $summary_empty = 1; while(<C>) { - next if m/^GIT: /; + next if m/^GIT:/; if ($in_body) { $summary_empty = 0 unless (/^\n$/); } elsif (/^\n$/) { @@ -805,6 +803,10 @@ sub sanitize_address } +# Returns 1 if the message was sent, and 0 otherwise. +# In actuality, the whole program dies when a there +# is an error sending a message. + sub send_message { my @recipients = unique_email_list(@to); @@ -873,7 +875,7 @@ X-Mailer: git-send-email $gitversion default => $ask_default); die "Send this email reply required" unless defined $_; if (/^n/i) { - return; + return 0; } elsif (/^q/i) { cleanup_compose_files(); exit(0); @@ -954,7 +956,7 @@ X-Mailer: git-send-email $gitversion $smtp->data or die $smtp->message; $smtp->datasend("$header\n$message") or die $smtp->message; $smtp->dataend() or die $smtp->message; - $smtp->ok or die "Failed to send $subject\n".$smtp->message; + $smtp->code =~ /250|200/ or die "Failed to send $subject\n".$smtp->message; } if ($quiet) { printf (($dry_run ? "Dry-" : "")."Sent %s\n", $subject); @@ -975,6 +977,8 @@ X-Mailer: git-send-email $gitversion print "Result: OK\n"; } } + + return 1; } $reply_to = $initial_reply_to; @@ -1135,10 +1139,10 @@ foreach my $t (@files) { @cc = (@initial_cc, @cc); - send_message(); + my $message_was_sent = send_message(); # set up for the next message - if ($chain_reply_to || !defined $reply_to || length($reply_to) == 0) { + if ($message_was_sent and $chain_reply_to || not defined $reply_to || length($reply_to) == 0) { $reply_to = $message_id; if (length $references > 0) { $references .= "\n $message_id"; diff --git a/http-push.c b/http-push.c index 45e8a69e2d..43e2dda2e1 100644 --- a/http-push.c +++ b/http-push.c @@ -1884,17 +1884,6 @@ static void get_dav_remote_heads(void) remote_ls("refs/", (PROCESS_FILES | PROCESS_DIRS | RECURSIVE), process_ls_ref, NULL); } -static int is_zero_sha1(const unsigned char *sha1) -{ - int i; - - for (i = 0; i < 20; i++) { - if (*sha1++) - return 0; - } - return 1; -} - static void add_remote_info_ref(struct remote_ls_ctx *ls) { struct strbuf *buf = (struct strbuf *)ls->userData; @@ -2120,13 +2109,13 @@ static int delete_remote_branch(char *pattern, int force) /* Remote HEAD must resolve to a known object */ if (symref) return error("Remote HEAD symrefs too deep"); - if (is_zero_sha1(head_sha1)) + if (is_null_sha1(head_sha1)) return error("Unable to resolve remote HEAD"); if (!has_sha1_file(head_sha1)) return error("Remote HEAD resolves to object %s\nwhich does not exist locally, perhaps you need to fetch?", sha1_to_hex(head_sha1)); /* Remote branch must resolve to a known object */ - if (is_zero_sha1(remote_ref->old_sha1)) + if (is_null_sha1(remote_ref->old_sha1)) return error("Unable to resolve remote branch %s", remote_ref->name); if (!has_sha1_file(remote_ref->old_sha1)) @@ -2334,7 +2323,7 @@ int main(int argc, char **argv) if (!ref->peer_ref) continue; - if (is_zero_sha1(ref->peer_ref->new_sha1)) { + if (is_null_sha1(ref->peer_ref->new_sha1)) { if (delete_remote_branch(ref->name, 1) == -1) { error("Could not remove %s", ref->name); rc = -4; @@ -2350,7 +2339,7 @@ int main(int argc, char **argv) } if (!force_all && - !is_zero_sha1(ref->old_sha1) && + !is_null_sha1(ref->old_sha1) && !ref->force) { if (!has_sha1_file(ref->old_sha1) || !ref_newer(ref->peer_ref->new_sha1, @@ -2400,7 +2389,7 @@ int main(int argc, char **argv) old_sha1_hex = NULL; commit_argv[1] = "--objects"; commit_argv[2] = new_sha1_hex; - if (!push_all && !is_zero_sha1(ref->old_sha1)) { + if (!push_all && !is_null_sha1(ref->old_sha1)) { old_sha1_hex = xmalloc(42); sprintf(old_sha1_hex, "^%s", sha1_to_hex(ref->old_sha1)); diff --git a/t/t3700-add.sh b/t/t3700-add.sh index 050de42ef4..6ce8256a17 100755 --- a/t/t3700-add.sh +++ b/t/t3700-add.sh @@ -230,4 +230,16 @@ test_expect_success BSLASHPSPEC "git add 'fo\\[ou\\]bar' ignores foobar" ' ! ( git ls-files foobar | grep foobar ) ' +test_expect_success 'git add to resolve conflicts on otherwise ignored path' ' + git reset --hard && + H=$(git rev-parse :1/2/a) && + ( + echo "100644 $H 1 track-this" + echo "100644 $H 3 track-this" + ) | git update-index --index-info && + echo track-this >>.gitignore && + echo resolved >track-this && + git add track-this +' + test_done diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh index 54b7ea6505..5254b23512 100755 --- a/t/t6030-bisect-porcelain.sh +++ b/t/t6030-bisect-porcelain.sh @@ -482,28 +482,17 @@ test_expect_success 'good merge bases when good and bad are siblings' ' git bisect reset ' -check_trace() { - grep "$1" "$GIT_TRACE" | grep "\^$2" | grep "$3" >/dev/null -} - test_expect_success 'optimized merge base checks' ' - GIT_TRACE="$(pwd)/trace.log" && - export GIT_TRACE && git bisect start "$HASH7" "$SIDE_HASH7" > my_bisect_log.txt && grep "merge base must be tested" my_bisect_log.txt && grep "$HASH4" my_bisect_log.txt && - check_trace "rev-list" "$HASH7" "$SIDE_HASH7" && git bisect good > my_bisect_log2.txt && test -f ".git/BISECT_ANCESTORS_OK" && test "$HASH6" = $(git rev-parse --verify HEAD) && - : > "$GIT_TRACE" && git bisect bad > my_bisect_log3.txt && - test_must_fail check_trace "rev-list" "$HASH6" "$SIDE_HASH7" && git bisect good "$A_HASH" > my_bisect_log4.txt && grep "merge base must be tested" my_bisect_log4.txt && - test_must_fail test -f ".git/BISECT_ANCESTORS_OK" && - check_trace "rev-list" "$HASH6" "$A_HASH" && - unset GIT_TRACE + test_must_fail test -f ".git/BISECT_ANCESTORS_OK" ' # This creates another side branch called "parallel" with some files |