Sync with 1.7.11.6

Signed-off-by: Junio C Hamano <gitster@pobox.com>
maint
Junio C Hamano 2012-09-11 11:23:45 -07:00
commit 1c88a6d174
32 changed files with 585 additions and 408 deletions

View File

@ -4,59 +4,81 @@ Git v1.7.11.6 Release Notes
Fixes since v1.7.11.5 Fixes since v1.7.11.5
--------------------- ---------------------


This consists primarily of documentation updates and low-impact code * "ciabot" script (in contrib/) has been updated with extensive
clarification and bugfixes.

- "ciabot" script (in contrib/) has been updated with extensive
documentation. documentation.


- The "--rebase" option to "git pull" can be abbreviated to "-r", * "git foo" errored out with "Not a directory" when the user had a
but we didn't document it. non-directory on $PATH, and worse yet it masked an alias "foo" from
running.


- It was generally understood that "--long-option"s to many of our * When the user exports a non-default IFS without HT, scripts that
subcommands can be abbreviated to the unique prefix, but it was not
easy to find it described for new readers of the documentation set.

- The "--topo-order", "--date-order" (and the lack of either means
the default order) options to "rev-list" and "log" family of
commands were poorly described in the documentation.

- Older parts of the documentation described as if having a regular
file in .git/refs/ hierarchy were the only way to have branches and
tags, which is not true for quite some time.

- A utility shell function test_seq has been added as a replacement
for the 'seq' utility found on some platforms.

- Fallback 'getpass' implementation made unportable use of stdio API.

- "git commit --amend" let the user edit the log message and then
died when the human-readable committer name was given
insufficiently by getpwent(3).

- The reflog entries left by "git rebase" and "git rebase -i" were
inconsistent (the interactive one gave an abbreviated object name).

- When the user exports a non-default IFS without HT, scripts that
rely on being able to parse "ls-files -s | while read a b c..." rely on being able to parse "ls-files -s | while read a b c..."
started to fail. Protect them from such a misconfiguration. started to fail. Protect them from such a misconfiguration.


- When "git push" triggered the automatic gc on the receiving end, a * When the user gives an argument that can be taken as both a
message from "git prune" that said it was removing cruft leaked to
the standard output, breaking the communication protocol.

- "git diff" had a confusion between taking data from a path in the
working tree and taking data from an object that happens to have
name 0{40} recorded in a tree.

- "git send-email" did not unquote encoded words that appear on the
header correctly, and lost "_" from strings.

- When the user gives an argument that can be taken as both a
revision name and a pathname without disambiguating with "--", we revision name and a pathname without disambiguating with "--", we
used to give a help message "Use '--' to separate". The message used to give a help message "Use '--' to separate". The message
has been clarified to show where that '--' goes on the command has been clarified to show where that '--' goes on the command
line. line.


- "gitweb" when used with PATH_INFO failed to notice directories with * Documentation for the configuration file format had a confusing
example.

* Older parts of the documentation described as if having a regular
file in .git/refs/ hierarchy were the only way to have branches and
tags, which is not true for quite some time.

* It was generally understood that "--long-option"s to many of our
subcommands can be abbreviated to the unique prefix, but it was not
easy to find it described for new readers of the documentation set.

* The "--topo-order", "--date-order" (and the lack of either means
the default order) options to "rev-list" and "log" family of
commands were poorly described in the documentation.

* "git commit --amend" let the user edit the log message and then
died when the human-readable committer name was given
insufficiently by getpwent(3).

* The exit status code from "git config" was way overspecified while
being incorrect. The implementation has been updated to give the
documented status for a case that was documented, and introduce a
new code for "all other errors".

* The output from "git diff -B" for a file that ends with an
incomplete line did not put "\ No newline..." on a line of its own.

* "git diff" had a confusion between taking data from a path in the
working tree and taking data from an object that happens to have
name 0{40} recorded in a tree.

* The "--rebase" option to "git pull" can be abbreviated to "-r",
but we didn't document it.

* When "git push" triggered the automatic gc on the receiving end, a
message from "git prune" that said it was removing cruft leaked to
the standard output, breaking the communication protocol.

* The reflog entries left by "git rebase" and "git rebase -i" were
inconsistent (the interactive one gave an abbreviated object name).

* "git send-email" did not unquote encoded words that appear on the
header correctly, and lost "_" from strings.

* "git stash apply/pop" did not trigger "rerere" upon conflicts
unlike other mergy operations.

* "git submodule <cmd> path" did not error out when the path to the
submodule was misspelt.

* "git submodule update -f" did not update paths in the working tree
that has local changes.
(merge 01d4721 sz/submodule-force-update later to maint).

* "gitweb" when used with PATH_INFO failed to notice directories with
SP (and other characters that need URL-style quoting) in them. SP (and other characters that need URL-style quoting) in them.

* Fallback 'getpass' implementation made unportable use of stdio API.

* A utility shell function test_seq has been added as a replacement
for the 'seq' utility found on some platforms.

View File

@ -36,7 +36,7 @@ ifndef::git-asciidoc-no-roff[]
# v1.72 breaks with this because it replaces dots not in roff requests. # v1.72 breaks with this because it replaces dots not in roff requests.
[listingblock] [listingblock]
<example><title>{title}</title> <example><title>{title}</title>
<literallayout> <literallayout class="monospaced">
ifdef::doctype-manpage[] ifdef::doctype-manpage[]
&#10;.ft C&#10; &#10;.ft C&#10;
endif::doctype-manpage[] endif::doctype-manpage[]
@ -53,7 +53,7 @@ ifdef::doctype-manpage[]
# The following two small workarounds insert a simple paragraph after screen # The following two small workarounds insert a simple paragraph after screen
[listingblock] [listingblock]
<example><title>{title}</title> <example><title>{title}</title>
<literallayout> <literallayout class="monospaced">
| |
</literallayout><simpara></simpara> </literallayout><simpara></simpara>
{title#}</example> {title#}</example>

View File

@ -54,16 +54,16 @@ configuration file by default, and options '--system', '--global',
'--file <filename>' can be used to tell the command to write to '--file <filename>' can be used to tell the command to write to
that location (you can say '--local' but that is the default). that location (you can say '--local' but that is the default).


This command will fail (with exit code ret) if: This command will fail with non-zero status upon error. Some exit
codes are:


. The config file is invalid (ret=3), . The config file is invalid (ret=3),
. can not write to the config file (ret=4), . can not write to the config file (ret=4),
. no section or name was provided (ret=2), . no section or name was provided (ret=2),
. the section or key is invalid (ret=1), . the section or key is invalid (ret=1),
. you try to unset an option which does not exist (ret=5), . you try to unset an option which does not exist (ret=5),
. you try to unset/set an option for which multiple lines match (ret=5), . you try to unset/set an option for which multiple lines match (ret=5), or
. you try to use an invalid regexp (ret=6), or . you try to use an invalid regexp (ret=6).
. you use '--global' option without $HOME being properly set (ret=128).


On success, the command returns the exit code 0. On success, the command returns the exit code 0.


@ -267,7 +267,7 @@ Given a .git/config like this:


; Proxy settings ; Proxy settings
[core] [core]
gitproxy="proxy-command" for kernel.org gitproxy=proxy-command for kernel.org
gitproxy=default-proxy ; for all the rest gitproxy=default-proxy ; for all the rest


you can set the filemode to true with you can set the filemode to true with
@ -342,7 +342,7 @@ To actually match only values with an exclamation mark, you have to
To add a new proxy, without altering any of the existing ones, use To add a new proxy, without altering any of the existing ones, use


------------ ------------
% git config core.gitproxy '"proxy-command" for example.com' % git config --add core.gitproxy '"proxy-command" for example.com'
------------ ------------


An example to use customized color from the configuration in your An example to use customized color from the configuration in your

View File

@ -149,6 +149,11 @@ submodule with the `--init` option.
+ +
If `--recursive` is specified, this command will recurse into the If `--recursive` is specified, this command will recurse into the
registered submodules, and update any nested submodules within. registered submodules, and update any nested submodules within.
+
If `--force` is specified, the submodule will be checked out (using
`git checkout --force` if appropriate), even if the commit specified in the
index of the containing repository already matches the commit checked out in
the submodule.


summary:: summary::
Show commit summary between the given commit (defaults to HEAD) and Show commit summary between the given commit (defaults to HEAD) and
@ -210,7 +215,9 @@ OPTIONS
This option is only valid for add and update commands. This option is only valid for add and update commands.
When running add, allow adding an otherwise ignored submodule path. When running add, allow adding an otherwise ignored submodule path.
When running update, throw away local changes in submodules when When running update, throw away local changes in submodules when
switching to a different commit. switching to a different commit; and always run a checkout operation
in the submodule, even if the commit listed in the index of the
containing repository matches the commit checked out in the submodule.


--cached:: --cached::
This option is only valid for status and summary commands. These This option is only valid for status and summary commands. These

View File

@ -48,9 +48,10 @@ Documentation for older releases are available here:
* release notes for * release notes for
link:RelNotes/1.7.12.txt[1.7.12]. link:RelNotes/1.7.12.txt[1.7.12].


* link:v1.7.11.5/git.html[documentation for release 1.7.11.5] * link:v1.7.11.6/git.html[documentation for release 1.7.11.6]


* release notes for * release notes for
link:RelNotes/1.7.11.6.txt[1.7.11.6],
link:RelNotes/1.7.11.5.txt[1.7.11.5], link:RelNotes/1.7.11.5.txt[1.7.11.5],
link:RelNotes/1.7.11.4.txt[1.7.11.4], link:RelNotes/1.7.11.4.txt[1.7.11.4],
link:RelNotes/1.7.11.3.txt[1.7.11.3], link:RelNotes/1.7.11.3.txt[1.7.11.3],

View File

@ -14,7 +14,7 @@ ifdef::backend-docbook[]
# "unbreak" docbook-xsl v1.68 for manpages. v1.69 works with or without this. # "unbreak" docbook-xsl v1.68 for manpages. v1.69 works with or without this.
[listingblock] [listingblock]
<example><title>{title}</title> <example><title>{title}</title>
<literallayout> <literallayout class="monospaced">
| |
</literallayout> </literallayout>
{title#}</example> {title#}</example>

View File

@ -188,7 +188,6 @@ struct patch {
int is_new, is_delete; /* -1 = unknown, 0 = false, 1 = true */ int is_new, is_delete; /* -1 = unknown, 0 = false, 1 = true */
int rejected; int rejected;
unsigned ws_rule; unsigned ws_rule;
unsigned long deflate_origlen;
int lines_added, lines_deleted; int lines_added, lines_deleted;
int score; int score;
unsigned int is_toplevel_relative:1; unsigned int is_toplevel_relative:1;

View File

@ -407,8 +407,7 @@ static struct origin *find_origin(struct scoreboard *sb,
paths[1] = NULL; paths[1] = NULL;


diff_tree_setup_paths(paths, &diff_opts); diff_tree_setup_paths(paths, &diff_opts);
if (diff_setup_done(&diff_opts) < 0) diff_setup_done(&diff_opts);
die("diff-setup");


if (is_null_sha1(origin->commit->object.sha1)) if (is_null_sha1(origin->commit->object.sha1))
do_diff_cache(parent->tree->object.sha1, &diff_opts); do_diff_cache(parent->tree->object.sha1, &diff_opts);
@ -494,8 +493,7 @@ static struct origin *find_rename(struct scoreboard *sb,
diff_opts.single_follow = origin->path; diff_opts.single_follow = origin->path;
paths[0] = NULL; paths[0] = NULL;
diff_tree_setup_paths(paths, &diff_opts); diff_tree_setup_paths(paths, &diff_opts);
if (diff_setup_done(&diff_opts) < 0) diff_setup_done(&diff_opts);
die("diff-setup");


if (is_null_sha1(origin->commit->object.sha1)) if (is_null_sha1(origin->commit->object.sha1))
do_diff_cache(parent->tree->object.sha1, &diff_opts); do_diff_cache(parent->tree->object.sha1, &diff_opts);
@ -1075,8 +1073,7 @@ static int find_copy_in_parent(struct scoreboard *sb,


paths[0] = NULL; paths[0] = NULL;
diff_tree_setup_paths(paths, &diff_opts); diff_tree_setup_paths(paths, &diff_opts);
if (diff_setup_done(&diff_opts) < 0) diff_setup_done(&diff_opts);
die("diff-setup");


/* Try "find copies harder" on new path if requested; /* Try "find copies harder" on new path if requested;
* we do not want to use diffcore_rename() actually to * we do not want to use diffcore_rename() actually to

View File

@ -316,8 +316,7 @@ static void show_local_changes(struct object *head, struct diff_options *opts)
init_revisions(&rev, NULL); init_revisions(&rev, NULL);
rev.diffopt.flags = opts->flags; rev.diffopt.flags = opts->flags;
rev.diffopt.output_format |= DIFF_FORMAT_NAME_STATUS; rev.diffopt.output_format |= DIFF_FORMAT_NAME_STATUS;
if (diff_setup_done(&rev.diffopt) < 0) diff_setup_done(&rev.diffopt);
die(_("diff_setup_done failed"));
add_pending_object(&rev, head, NULL); add_pending_object(&rev, head, NULL);
run_diff_index(&rev, 0); run_diff_index(&rev, 0);
} }

View File

@ -160,7 +160,7 @@ static int show_config(const char *key_, const char *value_, void *cb)


static int get_value(const char *key_, const char *regex_) static int get_value(const char *key_, const char *regex_)
{ {
int ret = -1; int ret = CONFIG_GENERIC_ERROR;
char *global = NULL, *xdg = NULL, *repo_config = NULL; char *global = NULL, *xdg = NULL, *repo_config = NULL;
const char *system_wide = NULL, *local; const char *system_wide = NULL, *local;
struct config_include_data inc = CONFIG_INCLUDE_INIT; struct config_include_data inc = CONFIG_INCLUDE_INIT;
@ -196,12 +196,15 @@ static int get_value(const char *key_, const char *regex_)
if (regcomp(key_regexp, key, REG_EXTENDED)) { if (regcomp(key_regexp, key, REG_EXTENDED)) {
fprintf(stderr, "Invalid key pattern: %s\n", key_); fprintf(stderr, "Invalid key pattern: %s\n", key_);
free(key); free(key);
ret = CONFIG_INVALID_PATTERN;
goto free_strings; goto free_strings;
} }
} else { } else {
if (git_config_parse_key(key_, &key, NULL)) if (git_config_parse_key(key_, &key, NULL)) {
ret = CONFIG_INVALID_KEY;
goto free_strings; goto free_strings;
} }
}


if (regex_) { if (regex_) {
if (regex_[0] == '!') { if (regex_[0] == '!') {
@ -212,6 +215,7 @@ static int get_value(const char *key_, const char *regex_)
regexp = (regex_t*)xmalloc(sizeof(regex_t)); regexp = (regex_t*)xmalloc(sizeof(regex_t));
if (regcomp(regexp, regex_, REG_EXTENDED)) { if (regcomp(regexp, regex_, REG_EXTENDED)) {
fprintf(stderr, "Invalid pattern: %s\n", regex_); fprintf(stderr, "Invalid pattern: %s\n", regex_);
ret = CONFIG_INVALID_PATTERN;
goto free_strings; goto free_strings;
} }
} }

View File

@ -302,8 +302,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
argc = setup_revisions(argc, argv, &rev, NULL); argc = setup_revisions(argc, argv, &rev, NULL);
if (!rev.diffopt.output_format) { if (!rev.diffopt.output_format) {
rev.diffopt.output_format = DIFF_FORMAT_PATCH; rev.diffopt.output_format = DIFF_FORMAT_PATCH;
if (diff_setup_done(&rev.diffopt) < 0) diff_setup_done(&rev.diffopt);
die(_("diff_setup_done failed"));
} }


DIFF_OPT_SET(&rev.diffopt, RECURSIVE); DIFF_OPT_SET(&rev.diffopt, RECURSIVE);

View File

@ -404,8 +404,7 @@ static void finish(struct commit *head_commit,
opts.output_format |= opts.output_format |=
DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT; DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
opts.detect_rename = DIFF_DETECT_RENAME; opts.detect_rename = DIFF_DETECT_RENAME;
if (diff_setup_done(&opts) < 0) diff_setup_done(&opts);
die(_("diff_setup_done failed"));
diff_tree_sha1(head, new_head, "", &opts); diff_tree_sha1(head, new_head, "", &opts);
diffcore_std(&opts); diffcore_std(&opts);
diff_flush(&opts); diff_flush(&opts);

View File

@ -1110,6 +1110,7 @@ extern int update_server_info(int);
#define CONFIG_NO_WRITE 4 #define CONFIG_NO_WRITE 4
#define CONFIG_NOTHING_SET 5 #define CONFIG_NOTHING_SET 5
#define CONFIG_INVALID_PATTERN 6 #define CONFIG_INVALID_PATTERN 6
#define CONFIG_GENERIC_ERROR 7


typedef int (*config_fn_t)(const char *, const char *, void *); typedef int (*config_fn_t)(const char *, const char *, void *);
extern int git_default_config(const char *, const char *, void *); extern int git_default_config(const char *, const char *, void *);

View File

@ -258,8 +258,7 @@ void diff_no_index(struct rev_info *revs,
DIFF_OPT_SET(&revs->diffopt, NO_INDEX); DIFF_OPT_SET(&revs->diffopt, NO_INDEX);


revs->max_count = -2; revs->max_count = -2;
if (diff_setup_done(&revs->diffopt) < 0) diff_setup_done(&revs->diffopt);
die("diff_setup_done failed");


setup_diff_pager(&revs->diffopt); setup_diff_pager(&revs->diffopt);
DIFF_OPT_SET(&revs->diffopt, EXIT_WITH_STATUS); DIFF_OPT_SET(&revs->diffopt, EXIT_WITH_STATUS);

5
diff.c
View File

@ -574,6 +574,7 @@ static void emit_rewrite_lines(struct emit_callback *ecb,
if (!endp) { if (!endp) {
const char *plain = diff_get_color(ecb->color_diff, const char *plain = diff_get_color(ecb->color_diff,
DIFF_PLAIN); DIFF_PLAIN);
putc('\n', ecb->opt->file);
emit_line_0(ecb->opt, plain, reset, '\\', emit_line_0(ecb->opt, plain, reset, '\\',
nneof, strlen(nneof)); nneof, strlen(nneof));
} }
@ -3187,7 +3188,7 @@ void diff_setup(struct diff_options *options)
} }
} }


int diff_setup_done(struct diff_options *options) void diff_setup_done(struct diff_options *options)
{ {
int count = 0; int count = 0;


@ -3286,8 +3287,6 @@ int diff_setup_done(struct diff_options *options)
options->output_format = DIFF_FORMAT_NO_OUTPUT; options->output_format = DIFF_FORMAT_NO_OUTPUT;
DIFF_OPT_SET(options, EXIT_WITH_STATUS); DIFF_OPT_SET(options, EXIT_WITH_STATUS);
} }

return 0;
} }


static int opt_arg(const char *arg, int arg_short, const char *arg_long, int *val) static int opt_arg(const char *arg, int arg_short, const char *arg_long, int *val)

2
diff.h
View File

@ -246,7 +246,7 @@ extern int git_diff_ui_config(const char *var, const char *value, void *cb);
extern int diff_use_color_default; extern int diff_use_color_default;
extern void diff_setup(struct diff_options *); extern void diff_setup(struct diff_options *);
extern int diff_opt_parse(struct diff_options *, const char **, int); extern int diff_opt_parse(struct diff_options *, const char **, int);
extern int diff_setup_done(struct diff_options *); extern void diff_setup_done(struct diff_options *);


#define DIFF_DETECT_RENAME 1 #define DIFF_DETECT_RENAME 1
#define DIFF_DETECT_COPY 2 #define DIFF_DETECT_COPY 2

View File

@ -38,7 +38,8 @@ base_present () {
} }


cleanup_temp_files () { cleanup_temp_files () {
if test "$1" = --save-backup ; then if test "$1" = --save-backup
then
rm -rf -- "$MERGED.orig" rm -rf -- "$MERGED.orig"
test -e "$BACKUP" && mv -- "$BACKUP" "$MERGED.orig" test -e "$BACKUP" && mv -- "$BACKUP" "$MERGED.orig"
rm -f -- "$LOCAL" "$REMOTE" "$BASE" rm -f -- "$LOCAL" "$REMOTE" "$BASE"
@ -53,24 +54,26 @@ describe_file () {
file="$3" file="$3"


printf " {%s}: " "$branch" printf " {%s}: " "$branch"
if test -z "$mode"; then if test -z "$mode"
then
echo "deleted" echo "deleted"
elif is_symlink "$mode" ; then elif is_symlink "$mode"
then
echo "a symbolic link -> '$(cat "$file")'" echo "a symbolic link -> '$(cat "$file")'"
elif is_submodule "$mode" ; then elif is_submodule "$mode"
then
echo "submodule commit $file" echo "submodule commit $file"
else elif base_present
if base_present; then then
echo "modified file" echo "modified file"
else else
echo "created file" echo "created file"
fi fi
fi
} }



resolve_symlink_merge () { resolve_symlink_merge () {
while true; do while true
do
printf "Use (l)ocal or (r)emote, or (a)bort? " printf "Use (l)ocal or (r)emote, or (a)bort? "
read ans || return 1 read ans || return 1
case "$ans" in case "$ans" in
@ -94,8 +97,10 @@ resolve_symlink_merge () {
} }


resolve_deleted_merge () { resolve_deleted_merge () {
while true; do while true
if base_present; then do
if base_present
then
printf "Use (m)odified or (d)eleted file, or (a)bort? " printf "Use (m)odified or (d)eleted file, or (a)bort? "
else else
printf "Use (c)reated or (d)eleted file, or (a)bort? " printf "Use (c)reated or (d)eleted file, or (a)bort? "
@ -120,21 +125,26 @@ resolve_deleted_merge () {
} }


resolve_submodule_merge () { resolve_submodule_merge () {
while true; do while true
do
printf "Use (l)ocal or (r)emote, or (a)bort? " printf "Use (l)ocal or (r)emote, or (a)bort? "
read ans || return 1 read ans || return 1
case "$ans" in case "$ans" in
[lL]*) [lL]*)
if ! local_present; then if ! local_present
if test -n "$(git ls-tree HEAD -- "$MERGED")"; then then
if test -n "$(git ls-tree HEAD -- "$MERGED")"
then
# Local isn't present, but it's a subdirectory # Local isn't present, but it's a subdirectory
git ls-tree --full-name -r HEAD -- "$MERGED" | git update-index --index-info || exit $? git ls-tree --full-name -r HEAD -- "$MERGED" |
git update-index --index-info || exit $?
else else
test -e "$MERGED" && mv -- "$MERGED" "$BACKUP" test -e "$MERGED" && mv -- "$MERGED" "$BACKUP"
git update-index --force-remove "$MERGED" git update-index --force-remove "$MERGED"
cleanup_temp_files --save-backup cleanup_temp_files --save-backup
fi fi
elif is_submodule "$local_mode"; then elif is_submodule "$local_mode"
then
stage_submodule "$MERGED" "$local_sha1" stage_submodule "$MERGED" "$local_sha1"
else else
git checkout-index -f --stage=2 -- "$MERGED" git checkout-index -f --stage=2 -- "$MERGED"
@ -143,16 +153,22 @@ resolve_submodule_merge () {
return 0 return 0
;; ;;
[rR]*) [rR]*)
if ! remote_present; then if ! remote_present
if test -n "$(git ls-tree MERGE_HEAD -- "$MERGED")"; then then
if test -n "$(git ls-tree MERGE_HEAD -- "$MERGED")"
then
# Remote isn't present, but it's a subdirectory # Remote isn't present, but it's a subdirectory
git ls-tree --full-name -r MERGE_HEAD -- "$MERGED" | git update-index --index-info || exit $? git ls-tree --full-name -r MERGE_HEAD -- "$MERGED" |
git update-index --index-info || exit $?
else else
test -e "$MERGED" && mv -- "$MERGED" "$BACKUP" test -e "$MERGED" && mv -- "$MERGED" "$BACKUP"
git update-index --force-remove "$MERGED" git update-index --force-remove "$MERGED"
fi fi
elif is_submodule "$remote_mode"; then elif is_submodule "$remote_mode"
! is_submodule "$local_mode" && test -e "$MERGED" && mv -- "$MERGED" "$BACKUP" then
! is_submodule "$local_mode" &&
test -e "$MERGED" &&
mv -- "$MERGED" "$BACKUP"
stage_submodule "$MERGED" "$remote_sha1" stage_submodule "$MERGED" "$remote_sha1"
else else
test -e "$MERGED" && mv -- "$MERGED" "$BACKUP" test -e "$MERGED" && mv -- "$MERGED" "$BACKUP"
@ -172,11 +188,15 @@ resolve_submodule_merge () {
stage_submodule () { stage_submodule () {
path="$1" path="$1"
submodule_sha1="$2" submodule_sha1="$2"
mkdir -p "$path" || die "fatal: unable to create directory for module at $path" mkdir -p "$path" ||
die "fatal: unable to create directory for module at $path"
# Find $path relative to work tree # Find $path relative to work tree
work_tree_root=$(cd_to_toplevel && pwd) work_tree_root=$(cd_to_toplevel && pwd)
work_rel_path=$(cd "$path" && GIT_WORK_TREE="${work_tree_root}" git rev-parse --show-prefix) work_rel_path=$(cd "$path" &&
test -n "$work_rel_path" || die "fatal: unable to get path of module $path relative to work tree" GIT_WORK_TREE="${work_tree_root}" git rev-parse --show-prefix
)
test -n "$work_rel_path" ||
die "fatal: unable to get path of module $path relative to work tree"
git update-index --add --replace --cacheinfo 160000 "$submodule_sha1" "${work_rel_path%/}" || die git update-index --add --replace --cacheinfo 160000 "$submodule_sha1" "${work_rel_path%/}" || die
} }


@ -185,7 +205,8 @@ checkout_staged_file () {
"$(git checkout-index --temp --stage="$1" "$2" 2>/dev/null)" \ "$(git checkout-index --temp --stage="$1" "$2" 2>/dev/null)" \
: '\([^ ]*\) ') : '\([^ ]*\) ')


if test $? -eq 0 -a -n "$tmpfile" ; then if test $? -eq 0 -a -n "$tmpfile"
then
mv -- "$(git rev-parse --show-cdup)$tmpfile" "$3" mv -- "$(git rev-parse --show-cdup)$tmpfile" "$3"
else else
>"$3" >"$3"
@ -196,8 +217,10 @@ merge_file () {
MERGED="$1" MERGED="$1"


f=$(git ls-files -u -- "$MERGED") f=$(git ls-files -u -- "$MERGED")
if test -z "$f" ; then if test -z "$f"
if test ! -f "$MERGED" ; then then
if test ! -f "$MERGED"
then
echo "$MERGED: file not found" echo "$MERGED: file not found"
else else
echo "$MERGED: file does not need merging" echo "$MERGED: file does not need merging"
@ -215,7 +238,8 @@ merge_file () {
local_mode=$(git ls-files -u -- "$MERGED" | awk '{if ($3==2) print $1;}') local_mode=$(git ls-files -u -- "$MERGED" | awk '{if ($3==2) print $1;}')
remote_mode=$(git ls-files -u -- "$MERGED" | awk '{if ($3==3) print $1;}') remote_mode=$(git ls-files -u -- "$MERGED" | awk '{if ($3==3) print $1;}')


if is_submodule "$local_mode" || is_submodule "$remote_mode"; then if is_submodule "$local_mode" || is_submodule "$remote_mode"
then
echo "Submodule merge conflict for '$MERGED':" echo "Submodule merge conflict for '$MERGED':"
local_sha1=$(git ls-files -u -- "$MERGED" | awk '{if ($3==2) print $2;}') local_sha1=$(git ls-files -u -- "$MERGED" | awk '{if ($3==2) print $2;}')
remote_sha1=$(git ls-files -u -- "$MERGED" | awk '{if ($3==3) print $2;}') remote_sha1=$(git ls-files -u -- "$MERGED" | awk '{if ($3==3) print $2;}')
@ -232,7 +256,8 @@ merge_file () {
checkout_staged_file 2 "$MERGED" "$LOCAL" checkout_staged_file 2 "$MERGED" "$LOCAL"
checkout_staged_file 3 "$MERGED" "$REMOTE" checkout_staged_file 3 "$MERGED" "$REMOTE"


if test -z "$local_mode" -o -z "$remote_mode"; then if test -z "$local_mode" -o -z "$remote_mode"
then
echo "Deleted merge conflict for '$MERGED':" echo "Deleted merge conflict for '$MERGED':"
describe_file "$local_mode" "local" "$LOCAL" describe_file "$local_mode" "local" "$LOCAL"
describe_file "$remote_mode" "remote" "$REMOTE" describe_file "$remote_mode" "remote" "$REMOTE"
@ -240,7 +265,8 @@ merge_file () {
return return
fi fi


if is_symlink "$local_mode" || is_symlink "$remote_mode"; then if is_symlink "$local_mode" || is_symlink "$remote_mode"
then
echo "Symbolic link merge conflict for '$MERGED':" echo "Symbolic link merge conflict for '$MERGED':"
describe_file "$local_mode" "local" "$LOCAL" describe_file "$local_mode" "local" "$LOCAL"
describe_file "$remote_mode" "remote" "$REMOTE" describe_file "$remote_mode" "remote" "$REMOTE"
@ -251,29 +277,34 @@ merge_file () {
echo "Normal merge conflict for '$MERGED':" echo "Normal merge conflict for '$MERGED':"
describe_file "$local_mode" "local" "$LOCAL" describe_file "$local_mode" "local" "$LOCAL"
describe_file "$remote_mode" "remote" "$REMOTE" describe_file "$remote_mode" "remote" "$REMOTE"
if "$prompt" = true; then if "$prompt" = true
then
printf "Hit return to start merge resolution tool (%s): " "$merge_tool" printf "Hit return to start merge resolution tool (%s): " "$merge_tool"
read ans || return 1 read ans || return 1
fi fi


if base_present; then if base_present
then
present=true present=true
else else
present=false present=false
fi fi


if ! run_merge_tool "$merge_tool" "$present"; then if ! run_merge_tool "$merge_tool" "$present"
then
echo "merge of $MERGED failed" 1>&2 echo "merge of $MERGED failed" 1>&2
mv -- "$BACKUP" "$MERGED" mv -- "$BACKUP" "$MERGED"


if test "$merge_keep_temporaries" = "false"; then if test "$merge_keep_temporaries" = "false"
then
cleanup_temp_files cleanup_temp_files
fi fi


return 1 return 1
fi fi


if test "$merge_keep_backup" = "true"; then if test "$merge_keep_backup" = "true"
then
mv -- "$BACKUP" "$MERGED.orig" mv -- "$BACKUP" "$MERGED.orig"
else else
rm -- "$BACKUP" rm -- "$BACKUP"
@ -361,16 +392,15 @@ do
shift shift
done done


prompt_after_failed_merge() { prompt_after_failed_merge () {
while true; do while true
do
printf "Continue merging other unresolved paths (y/n) ? " printf "Continue merging other unresolved paths (y/n) ? "
read ans || return 1 read ans || return 1
case "$ans" in case "$ans" in

[yY]*) [yY]*)
return 0 return 0
;; ;;

[nN]*) [nN]*)
return 1 return 1
;; ;;
@ -378,7 +408,8 @@ prompt_after_failed_merge() {
done done
} }


if test -z "$merge_tool"; then if test -z "$merge_tool"
then
merge_tool=$(get_merge_tool "$merge_tool") || exit merge_tool=$(get_merge_tool "$merge_tool") || exit
fi fi
merge_keep_backup="$(git config --bool mergetool.keepBackup || echo true)" merge_keep_backup="$(git config --bool mergetool.keepBackup || echo true)"
@ -388,7 +419,8 @@ last_status=0
rollup_status=0 rollup_status=0
files= files=


if test $# -eq 0 ; then if test $# -eq 0
then
cd_to_toplevel cd_to_toplevel


if test -e "$GIT_DIR/MERGE_RR" if test -e "$GIT_DIR/MERGE_RR"
@ -401,7 +433,8 @@ else
files=$(git ls-files -u -- "$@" | sed -e 's/^[^ ]* //' | sort -u) files=$(git ls-files -u -- "$@" | sed -e 's/^[^ ]* //' | sort -u)
fi fi


if test -z "$files" ; then if test -z "$files"
then
echo "No files need merging" echo "No files need merging"
exit 0 exit 0
fi fi
@ -413,13 +446,15 @@ IFS='
' '
for i in $files for i in $files
do do
if test $last_status -ne 0; then if test $last_status -ne 0
then
prompt_after_failed_merge || exit 1 prompt_after_failed_merge || exit 1
fi fi
printf "\n" printf "\n"
merge_file "$i" merge_file "$i"
last_status=$? last_status=$?
if test $last_status -ne 0; then if test $last_status -ne 0
then
rollup_status=1 rollup_status=1
fi fi
done done

View File

@ -469,6 +469,7 @@ apply_stash () {
else else
# Merge conflict; keep the exit status from merge-recursive # Merge conflict; keep the exit status from merge-recursive
status=$? status=$?
git rerere
if test -n "$INDEX_OPTION" if test -n "$INDEX_OPTION"
then then
gettextln "Index was not unstashed." >&2 gettextln "Index was not unstashed." >&2

View File

@ -109,26 +109,48 @@ resolve_relative_url ()
# #
module_list() module_list()
{ {
git ls-files --error-unmatch --stage -- "$@" | (
git ls-files --error-unmatch --stage -- "$@" ||
echo "unmatched pathspec exists"
) |
perl -e ' perl -e '
my %unmerged = (); my %unmerged = ();
my ($null_sha1) = ("0" x 40); my ($null_sha1) = ("0" x 40);
my @out = ();
my $unmatched = 0;
while (<STDIN>) { while (<STDIN>) {
if (/^unmatched pathspec/) {
$unmatched = 1;
next;
}
chomp; chomp;
my ($mode, $sha1, $stage, $path) = my ($mode, $sha1, $stage, $path) =
/^([0-7]+) ([0-9a-f]{40}) ([0-3])\t(.*)$/; /^([0-7]+) ([0-9a-f]{40}) ([0-3])\t(.*)$/;
next unless $mode eq "160000"; next unless $mode eq "160000";
if ($stage ne "0") { if ($stage ne "0") {
if (!$unmerged{$path}++) { if (!$unmerged{$path}++) {
print "$mode $null_sha1 U\t$path\n"; push @out, "$mode $null_sha1 U\t$path\n";
} }
next; next;
} }
print "$_\n"; push @out, "$_\n";
}
if ($unmatched) {
print "#unmatched\n";
} else {
print for (@out);
} }
' '
} }


die_if_unmatched ()
{
if test "$1" = "#unmatched"
then
exit 1
fi
}

# #
# Map submodule path to submodule name # Map submodule path to submodule name
# #
@ -385,6 +407,7 @@ cmd_foreach()
module_list | module_list |
while read mode sha1 stage sm_path while read mode sha1 stage sm_path
do do
die_if_unmatched "$mode"
if test -e "$sm_path"/.git if test -e "$sm_path"/.git
then then
say "$(eval_gettext "Entering '\$prefix\$sm_path'")" say "$(eval_gettext "Entering '\$prefix\$sm_path'")"
@ -437,6 +460,7 @@ cmd_init()
module_list "$@" | module_list "$@" |
while read mode sha1 stage sm_path while read mode sha1 stage sm_path
do do
die_if_unmatched "$mode"
name=$(module_name "$sm_path") || exit name=$(module_name "$sm_path") || exit


# Copy url setting when it is not set yet # Copy url setting when it is not set yet
@ -537,6 +561,7 @@ cmd_update()
err= err=
while read mode sha1 stage sm_path while read mode sha1 stage sm_path
do do
die_if_unmatched "$mode"
if test "$stage" = U if test "$stage" = U
then then
echo >&2 "Skipping unmerged submodule $sm_path" echo >&2 "Skipping unmerged submodule $sm_path"
@ -578,7 +603,7 @@ Maybe you want to use 'update --init'?")"
die "$(eval_gettext "Unable to find current revision in submodule path '\$sm_path'")" die "$(eval_gettext "Unable to find current revision in submodule path '\$sm_path'")"
fi fi


if test "$subsha1" != "$sha1" if test "$subsha1" != "$sha1" -o -n "$force"
then then
subforce=$force subforce=$force
# If we don't already have a -f flag and the submodule has never been checked out # If we don't already have a -f flag and the submodule has never been checked out
@ -932,6 +957,7 @@ cmd_status()
module_list "$@" | module_list "$@" |
while read mode sha1 stage sm_path while read mode sha1 stage sm_path
do do
die_if_unmatched "$mode"
name=$(module_name "$sm_path") || exit name=$(module_name "$sm_path") || exit
url=$(git config submodule."$name".url) url=$(git config submodule."$name".url)
displaypath="$prefix$sm_path" displaypath="$prefix$sm_path"
@ -1000,6 +1026,7 @@ cmd_sync()
module_list "$@" | module_list "$@" |
while read mode sha1 stage sm_path while read mode sha1 stage sm_path
do do
die_if_unmatched "$mode"
name=$(module_name "$sm_path") name=$(module_name "$sm_path")
url=$(git config -f .gitmodules --get submodule."$name".url) url=$(git config -f .gitmodules --get submodule."$name".url)



View File

@ -493,8 +493,7 @@ static struct string_list *get_renames(struct merge_options *o,
opts.rename_score = o->rename_score; opts.rename_score = o->rename_score;
opts.show_rename_progress = o->show_rename_progress; opts.show_rename_progress = o->show_rename_progress;
opts.output_format = DIFF_FORMAT_NO_OUTPUT; opts.output_format = DIFF_FORMAT_NO_OUTPUT;
if (diff_setup_done(&opts) < 0) diff_setup_done(&opts);
die(_("diff setup failed"));
diff_tree_sha1(o_tree->object.sha1, tree->object.sha1, "", &opts); diff_tree_sha1(o_tree->object.sha1, tree->object.sha1, "", &opts);
diffcore_std(&opts); diffcore_std(&opts);
if (opts.needed_rename_limit > o->needed_rename_limit) if (opts.needed_rename_limit > o->needed_rename_limit)
@ -614,23 +613,6 @@ static char *unique_path(struct merge_options *o, const char *path, const char *
return newpath; return newpath;
} }


static void flush_buffer(int fd, const char *buf, unsigned long size)
{
while (size > 0) {
long ret = write_in_full(fd, buf, size);
if (ret < 0) {
/* Ignore epipe */
if (errno == EPIPE)
break;
die_errno("merge-recursive");
} else if (!ret) {
die(_("merge-recursive: disk full?"));
}
size -= ret;
buf += ret;
}
}

static int dir_in_way(const char *path, int check_working_copy) static int dir_in_way(const char *path, int check_working_copy)
{ {
int pos, pathlen = strlen(path); int pos, pathlen = strlen(path);
@ -789,7 +771,7 @@ static void update_file_flags(struct merge_options *o,
fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, mode); fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, mode);
if (fd < 0) if (fd < 0)
die_errno(_("failed to open '%s'"), path); die_errno(_("failed to open '%s'"), path);
flush_buffer(fd, buf, size); write_in_full(fd, buf, size);
close(fd); close(fd);
} else if (S_ISLNK(mode)) { } else if (S_ISLNK(mode)) {
char *lnk = xmemdupz(buf, size); char *lnk = xmemdupz(buf, size);

View File

@ -126,8 +126,7 @@ static struct notes_merge_pair *diff_tree_remote(struct notes_merge_options *o,
diff_setup(&opt); diff_setup(&opt);
DIFF_OPT_SET(&opt, RECURSIVE); DIFF_OPT_SET(&opt, RECURSIVE);
opt.output_format = DIFF_FORMAT_NO_OUTPUT; opt.output_format = DIFF_FORMAT_NO_OUTPUT;
if (diff_setup_done(&opt) < 0) diff_setup_done(&opt);
die("diff_setup_done failed");
diff_tree_sha1(base, remote, "", &opt); diff_tree_sha1(base, remote, "", &opt);
diffcore_std(&opt); diffcore_std(&opt);


@ -190,8 +189,7 @@ static void diff_tree_local(struct notes_merge_options *o,
diff_setup(&opt); diff_setup(&opt);
DIFF_OPT_SET(&opt, RECURSIVE); DIFF_OPT_SET(&opt, RECURSIVE);
opt.output_format = DIFF_FORMAT_NO_OUTPUT; opt.output_format = DIFF_FORMAT_NO_OUTPUT;
if (diff_setup_done(&opt) < 0) diff_setup_done(&opt);
die("diff_setup_done failed");
diff_tree_sha1(base, local, "", &opt); diff_tree_sha1(base, local, "", &opt);
diffcore_std(&opt); diffcore_std(&opt);



View File

@ -39,8 +39,7 @@ int init_patch_ids(struct patch_ids *ids)
memset(ids, 0, sizeof(*ids)); memset(ids, 0, sizeof(*ids));
diff_setup(&ids->diffopts); diff_setup(&ids->diffopts);
DIFF_OPT_SET(&ids->diffopts, RECURSIVE); DIFF_OPT_SET(&ids->diffopts, RECURSIVE);
if (diff_setup_done(&ids->diffopts) < 0) diff_setup_done(&ids->diffopts);
return error("diff_setup_done failed");
return 0; return 0;
} }



View File

@ -1414,11 +1414,9 @@ int read_index_from(struct index_state *istate, const char *path)
size_t mmap_size; size_t mmap_size;
struct strbuf previous_name_buf = STRBUF_INIT, *previous_name; struct strbuf previous_name_buf = STRBUF_INIT, *previous_name;


errno = EBUSY;
if (istate->initialized) if (istate->initialized)
return istate->cache_nr; return istate->cache_nr;


errno = ENOENT;
istate->timestamp.sec = 0; istate->timestamp.sec = 0;
istate->timestamp.nsec = 0; istate->timestamp.nsec = 0;
fd = open(path, O_RDONLY); fd = open(path, O_RDONLY);
@ -1431,15 +1429,14 @@ int read_index_from(struct index_state *istate, const char *path)
if (fstat(fd, &st)) if (fstat(fd, &st))
die_errno("cannot stat the open index"); die_errno("cannot stat the open index");


errno = EINVAL;
mmap_size = xsize_t(st.st_size); mmap_size = xsize_t(st.st_size);
if (mmap_size < sizeof(struct cache_header) + 20) if (mmap_size < sizeof(struct cache_header) + 20)
die("index file smaller than expected"); die("index file smaller than expected");


mmap = xmmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); mmap = xmmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
close(fd);
if (mmap == MAP_FAILED) if (mmap == MAP_FAILED)
die_errno("unable to map index file"); die_errno("unable to map index file");
close(fd);


hdr = mmap; hdr = mmap;
if (verify_hdr(hdr, mmap_size) < 0) if (verify_hdr(hdr, mmap_size) < 0)
@ -1495,7 +1492,6 @@ int read_index_from(struct index_state *istate, const char *path)


unmap: unmap:
munmap(mmap, mmap_size); munmap(mmap, mmap_size);
errno = EINVAL;
die("index file corrupt"); die("index file corrupt");
} }



View File

@ -1863,8 +1863,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct s
if (revs->combine_merges) if (revs->combine_merges)
revs->ignore_merges = 0; revs->ignore_merges = 0;
revs->diffopt.abbrev = revs->abbrev; revs->diffopt.abbrev = revs->abbrev;
if (diff_setup_done(&revs->diffopt) < 0) diff_setup_done(&revs->diffopt);
die("diff_setup_done failed");


compile_grep_patterns(&revs->grep_filter); compile_grep_patterns(&revs->grep_filter);



View File

@ -139,6 +139,8 @@ int sane_execvp(const char *file, char * const argv[])
*/ */
if (errno == EACCES && !strchr(file, '/')) if (errno == EACCES && !strchr(file, '/'))
errno = exists_in_PATH(file) ? EACCES : ENOENT; errno = exists_in_PATH(file) ? EACCES : ENOENT;
else if (errno == ENOTDIR && !strchr(file, '/'))
errno = ENOENT;
return -1; return -1;
} }



View File

@ -574,8 +574,7 @@ static void calculate_changed_submodule_paths(void)
DIFF_OPT_SET(&diff_opts, RECURSIVE); DIFF_OPT_SET(&diff_opts, RECURSIVE);
diff_opts.output_format |= DIFF_FORMAT_CALLBACK; diff_opts.output_format |= DIFF_FORMAT_CALLBACK;
diff_opts.format_callback = submodule_collect_changed_cb; diff_opts.format_callback = submodule_collect_changed_cb;
if (diff_setup_done(&diff_opts) < 0) diff_setup_done(&diff_opts);
die("diff_setup_done failed");
diff_tree_sha1(parent->item->object.sha1, commit->object.sha1, "", &diff_opts); diff_tree_sha1(parent->item->object.sha1, commit->object.sha1, "", &diff_opts);
diffcore_std(&diff_opts); diffcore_std(&diff_opts);
diff_flush(&diff_opts); diff_flush(&diff_opts);

View File

@ -47,7 +47,23 @@ test_expect_success 'rebase ignores empty commit' '
git commit --allow-empty -m empty && git commit --allow-empty -m empty &&
test_commit D && test_commit D &&
git rebase C && git rebase C &&
test $(git log --format=%s C..) = "D" test "$(git log --format=%s C..)" = "D"
'

test_expect_success 'rebase --keep-empty' '
git reset --hard D &&
git rebase --keep-empty C &&
test "$(git log --format=%s C..)" = "D
empty"
'

test_expect_success 'rebase --keep-empty keeps empty even if already in upstream' '
git reset --hard A &&
git commit --allow-empty -m also-empty &&
git rebase --keep-empty D &&
test "$(git log --format=%s A..)" = "also-empty
D
empty"
' '


test_done test_done

View File

@ -66,5 +66,35 @@ test_expect_success 'suppress deletion diff with -B -D' '
grep -v "Linus Torvalds" actual grep -v "Linus Torvalds" actual
' '


test_expect_success 'prepare a file that ends with an incomplete line' '
test_seq 1 99 >seq &&
printf 100 >>seq &&
git add seq &&
git commit seq -m seq
'

test_expect_success 'rewrite the middle 90% of sequence file and terminate with newline' '
test_seq 1 5 >seq &&
test_seq 9331 9420 >>seq &&
test_seq 96 100 >>seq
'

test_expect_success 'confirm that sequence file is considered a rewrite' '
git diff -B seq >res &&
grep "dissimilarity index" res
'

test_expect_success 'no newline at eof is on its own line without -B' '
git diff seq >res &&
grep "^\\\\ " res &&
! grep "^..*\\\\ " res
'

test_expect_success 'no newline at eof is on its own line with -B' '
git diff -B seq >res &&
grep "^\\\\ " res &&
! grep "^..*\\\\ " res
'

test_done test_done



View File

@ -258,6 +258,27 @@ test_expect_success 'init should register submodule url in .git/config' '
test_cmp expect url test_cmp expect url
' '


test_failure_with_unknown_submodule () {
test_must_fail git submodule $1 no-such-submodule 2>output.err &&
grep "^error: .*no-such-submodule" output.err
}

test_expect_success 'init should fail with unknown submodule' '
test_failure_with_unknown_submodule init
'

test_expect_success 'update should fail with unknown submodule' '
test_failure_with_unknown_submodule update
'

test_expect_success 'status should fail with unknown submodule' '
test_failure_with_unknown_submodule status
'

test_expect_success 'sync should fail with unknown submodule' '
test_failure_with_unknown_submodule sync
'

test_expect_success 'update should fail when path is used by a file' ' test_expect_success 'update should fail when path is used by a file' '
echo hello >expect && echo hello >expect &&


@ -418,10 +439,7 @@ test_expect_success 'moving to a commit without submodule does not leave empty d
' '


test_expect_success 'submodule <invalid-path> warns' ' test_expect_success 'submodule <invalid-path> warns' '

test_failure_with_unknown_submodule
git submodule no-such-submodule 2> output.err &&
grep "^error: .*no-such-submodule" output.err

' '


test_expect_success 'add submodules without specifying an explicit path' ' test_expect_success 'add submodules without specifying an explicit path' '

View File

@ -123,6 +123,18 @@ test_expect_success 'submodule update should throw away changes with --force ' '
) )
' '


test_expect_success 'submodule update --force forcibly checks out submodules' '
(cd super &&
(cd submodule &&
rm -f file
) &&
git submodule update --force submodule &&
(cd submodule &&
test "$(git status -s file)" = ""
)
)
'

test_expect_success 'submodule update --rebase staying on master' ' test_expect_success 'submodule update --rebase staying on master' '
(cd super/submodule && (cd super/submodule &&
git checkout master git checkout master
@ -367,7 +379,7 @@ test_expect_success 'submodule update continues after checkout error' '
git submodule init && git submodule init &&
git commit -am "new_submodule" && git commit -am "new_submodule" &&
(cd submodule2 && (cd submodule2 &&
git rev-parse --max-count=1 HEAD > ../expect git rev-parse --verify HEAD >../expect
) && ) &&
(cd submodule && (cd submodule &&
test_commit "update_submodule" file test_commit "update_submodule" file
@ -384,7 +396,7 @@ test_expect_success 'submodule update continues after checkout error' '
git checkout HEAD^ && git checkout HEAD^ &&
test_must_fail git submodule update && test_must_fail git submodule update &&
(cd submodule2 && (cd submodule2 &&
git rev-parse --max-count=1 HEAD > ../actual git rev-parse --verify HEAD >../actual
) && ) &&
test_cmp expect actual test_cmp expect actual
) )
@ -413,7 +425,7 @@ test_expect_success 'submodule update continues after recursive checkout error'
test_commit "update_submodule_again_again" file test_commit "update_submodule_again_again" file
) && ) &&
(cd submodule2 && (cd submodule2 &&
git rev-parse --max-count=1 HEAD > ../expect && git rev-parse --verify HEAD >../expect &&
test_commit "update_submodule2_again" file test_commit "update_submodule2_again" file
) && ) &&
git add submodule && git add submodule &&
@ -428,7 +440,7 @@ test_expect_success 'submodule update continues after recursive checkout error'
) && ) &&
test_must_fail git submodule update --recursive && test_must_fail git submodule update --recursive &&
(cd submodule2 && (cd submodule2 &&
git rev-parse --max-count=1 HEAD > ../actual git rev-parse --verify HEAD >../actual
) && ) &&
test_cmp expect actual test_cmp expect actual
) )
@ -460,12 +472,12 @@ test_expect_success 'submodule update exit immediately in case of merge conflict
) && ) &&
git checkout HEAD^ && git checkout HEAD^ &&
(cd submodule2 && (cd submodule2 &&
git rev-parse --max-count=1 HEAD > ../expect git rev-parse --verify HEAD >../expect
) && ) &&
git config submodule.submodule.update merge && git config submodule.submodule.update merge &&
test_must_fail git submodule update && test_must_fail git submodule update &&
(cd submodule2 && (cd submodule2 &&
git rev-parse --max-count=1 HEAD > ../actual git rev-parse --verify HEAD >../actual
) && ) &&
test_cmp expect actual test_cmp expect actual
) )
@ -495,12 +507,12 @@ test_expect_success 'submodule update exit immediately after recursive rebase er
) && ) &&
git checkout HEAD^ && git checkout HEAD^ &&
(cd submodule2 && (cd submodule2 &&
git rev-parse --max-count=1 HEAD > ../expect git rev-parse --verify HEAD >../expect
) && ) &&
git config submodule.submodule.update rebase && git config submodule.submodule.update rebase &&
test_must_fail git submodule update && test_must_fail git submodule update &&
(cd submodule2 && (cd submodule2 &&
git rev-parse --max-count=1 HEAD > ../actual git rev-parse --verify HEAD >../actual
) && ) &&
test_cmp expect actual test_cmp expect actual
) )

View File

@ -55,6 +55,16 @@ test_expect_success 'setup' '
git rm file12 && git rm file12 &&
git commit -m "branch1 changes" && git commit -m "branch1 changes" &&


git checkout -b stash1 master &&
echo stash1 change file11 >file11 &&
git add file11 &&
git commit -m "stash1 changes" &&

git checkout -b stash2 master &&
echo stash2 change file11 >file11 &&
git add file11 &&
git commit -m "stash2 changes" &&

git checkout master && git checkout master &&
git submodule update -N && git submodule update -N &&
echo master updated >file1 && echo master updated >file1 &&
@ -193,7 +203,35 @@ test_expect_success 'mergetool skips resolved paths when rerere is active' '
git reset --hard git reset --hard
' '


test_expect_success 'conflicted stash sets up rerere' '
git config rerere.enabled true &&
git checkout stash1 &&
echo "Conflicting stash content" >file11 &&
git stash &&

git checkout --detach stash2 &&
test_must_fail git stash apply &&

test -n "$(git ls-files -u)" &&
conflicts="$(git rerere remaining)" &&
test "$conflicts" = "file11" &&
output="$(git mergetool --no-prompt)" &&
test "$output" != "No files need merging" &&

git commit -am "save the stash resolution" &&

git reset --hard stash2 &&
test_must_fail git stash apply &&

test -n "$(git ls-files -u)" &&
conflicts="$(git rerere remaining)" &&
test -z "$conflicts" &&
output="$(git mergetool --no-prompt)" &&
test "$output" = "No files need merging"
'

test_expect_success 'mergetool takes partial path' ' test_expect_success 'mergetool takes partial path' '
git reset --hard
git config rerere.enabled false && git config rerere.enabled false &&
git checkout -b test12 branch1 && git checkout -b test12 branch1 &&
git submodule update -N && git submodule update -N &&

View File

@ -212,8 +212,7 @@ static void try_to_follow_renames(struct tree_desc *t1, struct tree_desc *t2, co
diff_opts.rename_score = opt->rename_score; diff_opts.rename_score = opt->rename_score;
paths[0] = NULL; paths[0] = NULL;
diff_tree_setup_paths(paths, &diff_opts); diff_tree_setup_paths(paths, &diff_opts);
if (diff_setup_done(&diff_opts) < 0) diff_setup_done(&diff_opts);
die("unable to set up diff options to follow renames");
diff_tree(t1, t2, base, &diff_opts); diff_tree(t1, t2, base, &diff_opts);
diffcore_std(&diff_opts); diffcore_std(&diff_opts);
diff_tree_release_paths(&diff_opts); diff_tree_release_paths(&diff_opts);