mirror of
https://github.com/git/git.git
synced 2024-11-28 12:34:08 +08:00
Merge branch 'master' of github.com:git/git into git-po-master
* 'master' of github.com:git/git: (27 commits) Git 2.26-rc1 remote-curl: show progress for fetches over dumb HTTP show_one_mergetag: print non-parent in hex form. config.mak.dev: re-enable -Wformat-zero-length rebase-interactive.c: silence format-zero-length warnings mingw: workaround for hangs when sending STDIN t6020: new test with interleaved lexicographic ordering of directories t6022, t6046: test expected behavior instead of testing a proxy for it t3035: prefer test_must_fail to bash negation for git commands t6020, t6022, t6035: update merge tests to use test helper functions t602[1236], t6034: modernize test formatting merge-recursive: apply collision handling unification to recursive case completion: add diff --color-moved[-ws] t1050: replace test -f with test_path_is_file am: support --show-current-patch=diff to retrieve .git/rebase-apply/patch am: support --show-current-patch=raw as a synonym for--show-current-patch am: convert "resume" variable to a struct parse-options: convert "command mode" to a flag parse-options: add testcases for OPT_CMDMODE() stash push: support the --pathspec-from-file option ...
This commit is contained in:
commit
52b2742df8
@ -47,6 +47,18 @@ UI, Workflows & Features
|
||||
* "git clone --recurse-submodules --single-branch" now uses the same
|
||||
single-branch option when cloning the submodules.
|
||||
|
||||
* "git rm" and "git stash" learns the new "--pathspec-from-file"
|
||||
option.
|
||||
|
||||
* "git am --short-current-patch" is a way to show the piece of e-mail
|
||||
for the stopped step, which is not suitable to directly feed "git
|
||||
apply" (it is designed to be a good "git am" input). It learned a
|
||||
new option to show only the patch part.
|
||||
|
||||
* Handling of conflicting renames in merge-recursive have further
|
||||
been made consistent with how existing codepaths try to mimic what
|
||||
is done to add/add conflicts.
|
||||
|
||||
|
||||
Performance, Internal Implementation, Development Support etc.
|
||||
|
||||
@ -288,6 +300,18 @@ Fixes since v2.25
|
||||
reverted.
|
||||
(merge 0106b1d4be hi/gpg-use-check-signature later to maint).
|
||||
|
||||
* MinGW's poll() emulation has been improved.
|
||||
(merge 94f4d01932 am/mingw-poll-fix later to maint).
|
||||
|
||||
* "git show" and others gave an object name in raw format in its
|
||||
error output, which has been corrected to give it in hex.
|
||||
(merge 237a28173f hd/show-one-mergetag-fix later to maint).
|
||||
|
||||
* "git fetch" over HTTP walker protocol did not show any progress
|
||||
output. We inherently do not know how much work remains, but still
|
||||
we can show something not to bore users.
|
||||
(merge 7655b4119d rs/show-progress-in-dumb-http-fetch later to maint).
|
||||
|
||||
* Other code cleanup, docfix, build fix, etc.
|
||||
(merge 26f924d50e en/simplify-check-updates-in-unpack-trees later to maint).
|
||||
(merge d0d0a357a1 am/update-pathspec-f-f-tests later to maint).
|
||||
@ -315,3 +339,6 @@ Fixes since v2.25
|
||||
(merge 240fc04f81 ag/rebase-remove-redundant-code later to maint).
|
||||
(merge 7f487ce062 js/ci-windows-update later to maint).
|
||||
(merge d68ce906c7 rs/commit-graph-code-simplification later to maint).
|
||||
(merge a51d9e8f07 rj/t1050-use-test-path-is-file later to maint).
|
||||
(merge fd0bc17557 kk/complete-diff-color-moved later to maint).
|
||||
(merge 65bf820d0e en/test-cleanup later to maint).
|
||||
|
@ -16,7 +16,7 @@ SYNOPSIS
|
||||
[--exclude=<path>] [--include=<path>] [--reject] [-q | --quiet]
|
||||
[--[no-]scissors] [-S[<keyid>]] [--patch-format=<format>]
|
||||
[(<mbox> | <Maildir>)...]
|
||||
'git am' (--continue | --skip | --abort | --quit | --show-current-patch)
|
||||
'git am' (--continue | --skip | --abort | --quit | --show-current-patch[=(diff|raw)])
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@ -176,9 +176,11 @@ default. You can use `--no-utf8` to override this.
|
||||
Abort the patching operation but keep HEAD and the index
|
||||
untouched.
|
||||
|
||||
--show-current-patch::
|
||||
Show the entire e-mail message "git am" has stopped at, because
|
||||
of conflicts.
|
||||
--show-current-patch[=(diff|raw)]::
|
||||
Show the message at which `git am` has stopped due to
|
||||
conflicts. If `raw` is specified, show the raw contents of
|
||||
the e-mail message; if `diff`, show the diff portion only.
|
||||
Defaults to `raw`.
|
||||
|
||||
DISCUSSION
|
||||
----------
|
||||
|
@ -8,16 +8,18 @@ git-rm - Remove files from the working tree and from the index
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git rm' [-f | --force] [-n] [-r] [--cached] [--ignore-unmatch] [--quiet] [--] <file>...
|
||||
'git rm' [-f | --force] [-n] [-r] [--cached] [--ignore-unmatch]
|
||||
[--quiet] [--pathspec-from-file=<file> [--pathspec-file-nul]]
|
||||
[--] [<pathspec>...]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Remove files from the index, or from the working tree and the index.
|
||||
`git rm` will not remove a file from just your working directory.
|
||||
(There is no option to remove a file only from the working tree
|
||||
and yet keep it in the index; use `/bin/rm` if you want to do that.)
|
||||
The files being removed have to be identical to the tip of the branch,
|
||||
and no updates to their contents can be staged in the index,
|
||||
Remove files matching pathspec from the index, or from the working tree
|
||||
and the index. `git rm` will not remove a file from just your working
|
||||
directory. (There is no option to remove a file only from the working
|
||||
tree and yet keep it in the index; use `/bin/rm` if you want to do
|
||||
that.) The files being removed have to be identical to the tip of the
|
||||
branch, and no updates to their contents can be staged in the index,
|
||||
though that default behavior can be overridden with the `-f` option.
|
||||
When `--cached` is given, the staged content has to
|
||||
match either the tip of the branch or the file on disk,
|
||||
@ -26,15 +28,20 @@ allowing the file to be removed from just the index.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
<file>...::
|
||||
Files to remove. Fileglobs (e.g. `*.c`) can be given to
|
||||
remove all matching files. If you want Git to expand
|
||||
file glob characters, you may need to shell-escape them.
|
||||
A leading directory name
|
||||
(e.g. `dir` to remove `dir/file1` and `dir/file2`) can be
|
||||
given to remove all files in the directory, and recursively
|
||||
all sub-directories,
|
||||
but this requires the `-r` option to be explicitly given.
|
||||
<pathspec>...::
|
||||
Files to remove. A leading directory name (e.g. `dir` to remove
|
||||
`dir/file1` and `dir/file2`) can be given to remove all files in
|
||||
the directory, and recursively all sub-directories, but this
|
||||
requires the `-r` option to be explicitly given.
|
||||
+
|
||||
The command removes only the paths that are known to Git.
|
||||
+
|
||||
File globbing matches across directory boundaries. Thus, given two
|
||||
directories `d` and `d2`, there is a difference between using
|
||||
`git rm 'd*'` and `git rm 'd/*'`, as the former will also remove all
|
||||
of directory `d2`.
|
||||
+
|
||||
For more details, see the 'pathspec' entry in linkgit:gitglossary[7].
|
||||
|
||||
-f::
|
||||
--force::
|
||||
@ -68,19 +75,19 @@ OPTIONS
|
||||
`git rm` normally outputs one line (in the form of an `rm` command)
|
||||
for each file removed. This option suppresses that output.
|
||||
|
||||
--pathspec-from-file=<file>::
|
||||
Pathspec is passed in `<file>` instead of commandline args. If
|
||||
`<file>` is exactly `-` then standard input is used. Pathspec
|
||||
elements are separated by LF or CR/LF. Pathspec elements can be
|
||||
quoted as explained for the configuration variable `core.quotePath`
|
||||
(see linkgit:git-config[1]). See also `--pathspec-file-nul` and
|
||||
global `--literal-pathspecs`.
|
||||
|
||||
DISCUSSION
|
||||
----------
|
||||
--pathspec-file-nul::
|
||||
Only meaningful with `--pathspec-from-file`. Pathspec elements are
|
||||
separated with NUL character and all other characters are taken
|
||||
literally (including newlines and quotes).
|
||||
|
||||
The <file> list given to the command can be exact pathnames,
|
||||
file glob patterns, or leading directory names. The command
|
||||
removes only the paths that are known to Git. Giving the name of
|
||||
a file that you have not told Git about does not remove that file.
|
||||
|
||||
File globbing matches across directory boundaries. Thus, given
|
||||
two directories `d` and `d2`, there is a difference between
|
||||
using `git rm 'd*'` and `git rm 'd/*'`, as the former will
|
||||
also remove all of directory `d2`.
|
||||
|
||||
REMOVING FILES THAT HAVE DISAPPEARED FROM THE FILESYSTEM
|
||||
--------------------------------------------------------
|
||||
|
@ -15,6 +15,7 @@ SYNOPSIS
|
||||
'git stash' branch <branchname> [<stash>]
|
||||
'git stash' [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
|
||||
[-u|--include-untracked] [-a|--all] [-m|--message <message>]
|
||||
[--pathspec-from-file=<file> [--pathspec-file-nul]]
|
||||
[--] [<pathspec>...]]
|
||||
'git stash' clear
|
||||
'git stash' create [<message>]
|
||||
@ -43,10 +44,10 @@ created stash, `stash@{1}` is the one before it, `stash@{2.hours.ago}`
|
||||
is also possible). Stashes may also be referenced by specifying just the
|
||||
stash index (e.g. the integer `n` is equivalent to `stash@{n}`).
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
COMMANDS
|
||||
--------
|
||||
|
||||
push [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [-m|--message <message>] [--] [<pathspec>...]::
|
||||
push [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [-m|--message <message>] [--pathspec-from-file=<file> [--pathspec-file-nul]] [--] [<pathspec>...]::
|
||||
|
||||
Save your local modifications to a new 'stash entry' and roll them
|
||||
back to HEAD (in the working tree and in the index).
|
||||
@ -56,38 +57,13 @@ push [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q
|
||||
For quickly making a snapshot, you can omit "push". In this mode,
|
||||
non-option arguments are not allowed to prevent a misspelled
|
||||
subcommand from making an unwanted stash entry. The two exceptions to this
|
||||
are `stash -p` which acts as alias for `stash push -p` and pathspecs,
|
||||
are `stash -p` which acts as alias for `stash push -p` and pathspec elements,
|
||||
which are allowed after a double hyphen `--` for disambiguation.
|
||||
+
|
||||
When pathspec is given to 'git stash push', the new stash entry records the
|
||||
modified states only for the files that match the pathspec. The index
|
||||
entries and working tree files are then rolled back to the state in
|
||||
HEAD only for these files, too, leaving files that do not match the
|
||||
pathspec intact.
|
||||
+
|
||||
If the `--keep-index` option is used, all changes already added to the
|
||||
index are left intact.
|
||||
+
|
||||
If the `--include-untracked` option is used, all untracked files are also
|
||||
stashed and then cleaned up with `git clean`, leaving the working directory
|
||||
in a very clean state. If the `--all` option is used instead then the
|
||||
ignored files are stashed and cleaned in addition to the untracked files.
|
||||
+
|
||||
With `--patch`, you can interactively select hunks from the diff
|
||||
between HEAD and the working tree to be stashed. The stash entry is
|
||||
constructed such that its index state is the same as the index state
|
||||
of your repository, and its worktree contains only the changes you
|
||||
selected interactively. The selected changes are then rolled back
|
||||
from your worktree. See the ``Interactive Mode'' section of
|
||||
linkgit:git-add[1] to learn how to operate the `--patch` mode.
|
||||
+
|
||||
The `--patch` option implies `--keep-index`. You can use
|
||||
`--no-keep-index` to override this.
|
||||
|
||||
save [-p|--patch] [-k|--[no-]keep-index] [-u|--include-untracked] [-a|--all] [-q|--quiet] [<message>]::
|
||||
|
||||
This option is deprecated in favour of 'git stash push'. It
|
||||
differs from "stash push" in that it cannot take pathspecs.
|
||||
differs from "stash push" in that it cannot take pathspec.
|
||||
Instead, all non-option arguments are concatenated to form the stash
|
||||
message.
|
||||
|
||||
@ -111,7 +87,7 @@ show [<options>] [<stash>]::
|
||||
|
||||
Show the changes recorded in the stash entry as a diff between the
|
||||
stashed contents and the commit back when the stash entry was first
|
||||
created. When no `<stash>` is given, it shows the latest one.
|
||||
created.
|
||||
By default, the command shows the diffstat, but it will accept any
|
||||
format known to 'git diff' (e.g., `git stash show -p stash@{1}`
|
||||
to view the second most recent entry in patch form).
|
||||
@ -128,14 +104,6 @@ pop [--index] [-q|--quiet] [<stash>]::
|
||||
Applying the state can fail with conflicts; in this case, it is not
|
||||
removed from the stash list. You need to resolve the conflicts by hand
|
||||
and call `git stash drop` manually afterwards.
|
||||
+
|
||||
If the `--index` option is used, then tries to reinstate not only the working
|
||||
tree's changes, but also the index's ones. However, this can fail, when you
|
||||
have conflicts (which are stored in the index, where you therefore can no
|
||||
longer apply the changes as they were originally).
|
||||
+
|
||||
When no `<stash>` is given, `stash@{0}` is assumed, otherwise `<stash>` must
|
||||
be a reference of the form `stash@{<revision>}`.
|
||||
|
||||
apply [--index] [-q|--quiet] [<stash>]::
|
||||
|
||||
@ -149,8 +117,7 @@ branch <branchname> [<stash>]::
|
||||
the commit at which the `<stash>` was originally created, applies the
|
||||
changes recorded in `<stash>` to the new working tree and index.
|
||||
If that succeeds, and `<stash>` is a reference of the form
|
||||
`stash@{<revision>}`, it then drops the `<stash>`. When no `<stash>`
|
||||
is given, applies the latest one.
|
||||
`stash@{<revision>}`, it then drops the `<stash>`.
|
||||
+
|
||||
This is useful if the branch on which you ran `git stash push` has
|
||||
changed enough that `git stash apply` fails due to conflicts. Since
|
||||
@ -166,9 +133,6 @@ clear::
|
||||
drop [-q|--quiet] [<stash>]::
|
||||
|
||||
Remove a single stash entry from the list of stash entries.
|
||||
When no `<stash>` is given, it removes the latest one.
|
||||
i.e. `stash@{0}`, otherwise `<stash>` must be a valid stash
|
||||
log reference of the form `stash@{<revision>}`.
|
||||
|
||||
create::
|
||||
|
||||
@ -185,6 +149,98 @@ store::
|
||||
reflog. This is intended to be useful for scripts. It is
|
||||
probably not the command you want to use; see "push" above.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
-a::
|
||||
--all::
|
||||
This option is only valid for `push` and `save` commands.
|
||||
+
|
||||
All ignored and untracked files are also stashed and then cleaned
|
||||
up with `git clean`.
|
||||
|
||||
-u::
|
||||
--include-untracked::
|
||||
This option is only valid for `push` and `save` commands.
|
||||
+
|
||||
All untracked files are also stashed and then cleaned up with
|
||||
`git clean`.
|
||||
|
||||
--index::
|
||||
This option is only valid for `pop` and `apply` commands.
|
||||
+
|
||||
Tries to reinstate not only the working tree's changes, but also
|
||||
the index's ones. However, this can fail, when you have conflicts
|
||||
(which are stored in the index, where you therefore can no longer
|
||||
apply the changes as they were originally).
|
||||
|
||||
-k::
|
||||
--keep-index::
|
||||
--no-keep-index::
|
||||
This option is only valid for `push` and `save` commands.
|
||||
+
|
||||
All changes already added to the index are left intact.
|
||||
|
||||
-p::
|
||||
--patch::
|
||||
This option is only valid for `push` and `save` commands.
|
||||
+
|
||||
Interactively select hunks from the diff between HEAD and the
|
||||
working tree to be stashed. The stash entry is constructed such
|
||||
that its index state is the same as the index state of your
|
||||
repository, and its worktree contains only the changes you selected
|
||||
interactively. The selected changes are then rolled back from your
|
||||
worktree. See the ``Interactive Mode'' section of linkgit:git-add[1]
|
||||
to learn how to operate the `--patch` mode.
|
||||
+
|
||||
The `--patch` option implies `--keep-index`. You can use
|
||||
`--no-keep-index` to override this.
|
||||
|
||||
--pathspec-from-file=<file>::
|
||||
This option is only valid for `push` command.
|
||||
+
|
||||
Pathspec is passed in `<file>` instead of commandline args. If
|
||||
`<file>` is exactly `-` then standard input is used. Pathspec
|
||||
elements are separated by LF or CR/LF. Pathspec elements can be
|
||||
quoted as explained for the configuration variable `core.quotePath`
|
||||
(see linkgit:git-config[1]). See also `--pathspec-file-nul` and
|
||||
global `--literal-pathspecs`.
|
||||
|
||||
--pathspec-file-nul::
|
||||
This option is only valid for `push` command.
|
||||
+
|
||||
Only meaningful with `--pathspec-from-file`. Pathspec elements are
|
||||
separated with NUL character and all other characters are taken
|
||||
literally (including newlines and quotes).
|
||||
|
||||
-q::
|
||||
--quiet::
|
||||
This option is only valid for `apply`, `drop`, `pop`, `push`,
|
||||
`save`, `store` commands.
|
||||
+
|
||||
Quiet, suppress feedback messages.
|
||||
|
||||
\--::
|
||||
This option is only valid for `push` command.
|
||||
+
|
||||
Separates pathspec from options for disambiguation purposes.
|
||||
|
||||
<pathspec>...::
|
||||
This option is only valid for `push` command.
|
||||
+
|
||||
The new stash entry records the modified states only for the files
|
||||
that match the pathspec. The index entries and working tree files
|
||||
are then rolled back to the state in HEAD only for these files,
|
||||
too, leaving files that do not match the pathspec intact.
|
||||
+
|
||||
For more details, see the 'pathspec' entry in linkgit:gitglossary[7].
|
||||
|
||||
<stash>::
|
||||
This option is only valid for `apply`, `branch`, `drop`, `pop`,
|
||||
`show` commands.
|
||||
+
|
||||
A reference of the form `stash@{<revision>}`. When no `<stash>` is
|
||||
given, the latest stash is assumed (that is, `stash@{0}`).
|
||||
|
||||
DISCUSSION
|
||||
----------
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
GVF=GIT-VERSION-FILE
|
||||
DEF_VER=v2.26.0-rc0
|
||||
DEF_VER=v2.26.0-rc1
|
||||
|
||||
LF='
|
||||
'
|
||||
|
96
builtin/am.c
96
builtin/am.c
@ -81,6 +81,11 @@ enum signoff_type {
|
||||
SIGNOFF_EXPLICIT /* --signoff was set on the command-line */
|
||||
};
|
||||
|
||||
enum show_patch_type {
|
||||
SHOW_PATCH_RAW = 0,
|
||||
SHOW_PATCH_DIFF = 1,
|
||||
};
|
||||
|
||||
struct am_state {
|
||||
/* state directory path */
|
||||
char *dir;
|
||||
@ -1763,7 +1768,7 @@ static void am_run(struct am_state *state, int resume)
|
||||
linelen(state->msg), state->msg);
|
||||
|
||||
if (advice_amworkdir)
|
||||
advise(_("Use 'git am --show-current-patch' to see the failed patch"));
|
||||
advise(_("Use 'git am --show-current-patch=diff' to see the failed patch"));
|
||||
|
||||
die_user_resolve(state);
|
||||
}
|
||||
@ -2061,7 +2066,7 @@ static void am_abort(struct am_state *state)
|
||||
am_destroy(state);
|
||||
}
|
||||
|
||||
static int show_patch(struct am_state *state)
|
||||
static int show_patch(struct am_state *state, enum show_patch_type sub_mode)
|
||||
{
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
const char *patch_path;
|
||||
@ -2078,7 +2083,17 @@ static int show_patch(struct am_state *state)
|
||||
return ret;
|
||||
}
|
||||
|
||||
patch_path = am_path(state, msgnum(state));
|
||||
switch (sub_mode) {
|
||||
case SHOW_PATCH_RAW:
|
||||
patch_path = am_path(state, msgnum(state));
|
||||
break;
|
||||
case SHOW_PATCH_DIFF:
|
||||
patch_path = am_path(state, "patch");
|
||||
break;
|
||||
default:
|
||||
BUG("invalid mode for --show-current-patch");
|
||||
}
|
||||
|
||||
len = strbuf_read_file(&sb, patch_path, 0);
|
||||
if (len < 0)
|
||||
die_errno(_("failed to read '%s'"), patch_path);
|
||||
@ -2118,7 +2133,7 @@ static int parse_opt_patchformat(const struct option *opt, const char *arg, int
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum resume_mode {
|
||||
enum resume_type {
|
||||
RESUME_FALSE = 0,
|
||||
RESUME_APPLY,
|
||||
RESUME_RESOLVED,
|
||||
@ -2128,6 +2143,45 @@ enum resume_mode {
|
||||
RESUME_SHOW_PATCH
|
||||
};
|
||||
|
||||
struct resume_mode {
|
||||
enum resume_type mode;
|
||||
enum show_patch_type sub_mode;
|
||||
};
|
||||
|
||||
static int parse_opt_show_current_patch(const struct option *opt, const char *arg, int unset)
|
||||
{
|
||||
int *opt_value = opt->value;
|
||||
struct resume_mode *resume = container_of(opt_value, struct resume_mode, mode);
|
||||
|
||||
/*
|
||||
* Please update $__git_showcurrentpatch in git-completion.bash
|
||||
* when you add new options
|
||||
*/
|
||||
const char *valid_modes[] = {
|
||||
[SHOW_PATCH_DIFF] = "diff",
|
||||
[SHOW_PATCH_RAW] = "raw"
|
||||
};
|
||||
int new_value = SHOW_PATCH_RAW;
|
||||
|
||||
if (arg) {
|
||||
for (new_value = 0; new_value < ARRAY_SIZE(valid_modes); new_value++) {
|
||||
if (!strcmp(arg, valid_modes[new_value]))
|
||||
break;
|
||||
}
|
||||
if (new_value >= ARRAY_SIZE(valid_modes))
|
||||
return error(_("Invalid value for --show-current-patch: %s"), arg);
|
||||
}
|
||||
|
||||
if (resume->mode == RESUME_SHOW_PATCH && new_value != resume->sub_mode)
|
||||
return error(_("--show-current-patch=%s is incompatible with "
|
||||
"--show-current-patch=%s"),
|
||||
arg, valid_modes[resume->sub_mode]);
|
||||
|
||||
resume->mode = RESUME_SHOW_PATCH;
|
||||
resume->sub_mode = new_value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int git_am_config(const char *k, const char *v, void *cb)
|
||||
{
|
||||
int status;
|
||||
@ -2145,7 +2199,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
|
||||
int binary = -1;
|
||||
int keep_cr = -1;
|
||||
int patch_format = PATCH_FORMAT_UNKNOWN;
|
||||
enum resume_mode resume = RESUME_FALSE;
|
||||
struct resume_mode resume = { .mode = RESUME_FALSE };
|
||||
int in_progress;
|
||||
int ret = 0;
|
||||
|
||||
@ -2214,24 +2268,26 @@ int cmd_am(int argc, const char **argv, const char *prefix)
|
||||
PARSE_OPT_NOARG),
|
||||
OPT_STRING(0, "resolvemsg", &state.resolvemsg, NULL,
|
||||
N_("override error message when patch failure occurs")),
|
||||
OPT_CMDMODE(0, "continue", &resume,
|
||||
OPT_CMDMODE(0, "continue", &resume.mode,
|
||||
N_("continue applying patches after resolving a conflict"),
|
||||
RESUME_RESOLVED),
|
||||
OPT_CMDMODE('r', "resolved", &resume,
|
||||
OPT_CMDMODE('r', "resolved", &resume.mode,
|
||||
N_("synonyms for --continue"),
|
||||
RESUME_RESOLVED),
|
||||
OPT_CMDMODE(0, "skip", &resume,
|
||||
OPT_CMDMODE(0, "skip", &resume.mode,
|
||||
N_("skip the current patch"),
|
||||
RESUME_SKIP),
|
||||
OPT_CMDMODE(0, "abort", &resume,
|
||||
OPT_CMDMODE(0, "abort", &resume.mode,
|
||||
N_("restore the original branch and abort the patching operation."),
|
||||
RESUME_ABORT),
|
||||
OPT_CMDMODE(0, "quit", &resume,
|
||||
OPT_CMDMODE(0, "quit", &resume.mode,
|
||||
N_("abort the patching operation but keep HEAD where it is."),
|
||||
RESUME_QUIT),
|
||||
OPT_CMDMODE(0, "show-current-patch", &resume,
|
||||
N_("show the patch being applied."),
|
||||
RESUME_SHOW_PATCH),
|
||||
{ OPTION_CALLBACK, 0, "show-current-patch", &resume.mode,
|
||||
"(diff|raw)",
|
||||
N_("show the patch being applied"),
|
||||
PARSE_OPT_CMDMODE | PARSE_OPT_OPTARG | PARSE_OPT_NONEG | PARSE_OPT_LITERAL_ARGHELP,
|
||||
parse_opt_show_current_patch, RESUME_SHOW_PATCH },
|
||||
OPT_BOOL(0, "committer-date-is-author-date",
|
||||
&state.committer_date_is_author_date,
|
||||
N_("lie about committer date")),
|
||||
@ -2281,12 +2337,12 @@ int cmd_am(int argc, const char **argv, const char *prefix)
|
||||
* intend to feed us a patch but wanted to continue
|
||||
* unattended.
|
||||
*/
|
||||
if (argc || (resume == RESUME_FALSE && !isatty(0)))
|
||||
if (argc || (resume.mode == RESUME_FALSE && !isatty(0)))
|
||||
die(_("previous rebase directory %s still exists but mbox given."),
|
||||
state.dir);
|
||||
|
||||
if (resume == RESUME_FALSE)
|
||||
resume = RESUME_APPLY;
|
||||
if (resume.mode == RESUME_FALSE)
|
||||
resume.mode = RESUME_APPLY;
|
||||
|
||||
if (state.signoff == SIGNOFF_EXPLICIT)
|
||||
am_append_signoff(&state);
|
||||
@ -2300,7 +2356,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
|
||||
* stray directories.
|
||||
*/
|
||||
if (file_exists(state.dir) && !state.rebasing) {
|
||||
if (resume == RESUME_ABORT || resume == RESUME_QUIT) {
|
||||
if (resume.mode == RESUME_ABORT || resume.mode == RESUME_QUIT) {
|
||||
am_destroy(&state);
|
||||
am_state_release(&state);
|
||||
return 0;
|
||||
@ -2311,7 +2367,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
|
||||
state.dir);
|
||||
}
|
||||
|
||||
if (resume)
|
||||
if (resume.mode)
|
||||
die(_("Resolve operation not in progress, we are not resuming."));
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
@ -2329,7 +2385,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
|
||||
argv_array_clear(&paths);
|
||||
}
|
||||
|
||||
switch (resume) {
|
||||
switch (resume.mode) {
|
||||
case RESUME_FALSE:
|
||||
am_run(&state, 0);
|
||||
break;
|
||||
@ -2350,7 +2406,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
|
||||
am_destroy(&state);
|
||||
break;
|
||||
case RESUME_SHOW_PATCH:
|
||||
ret = show_patch(&state);
|
||||
ret = show_patch(&state, resume.sub_mode);
|
||||
break;
|
||||
default:
|
||||
BUG("invalid resume value");
|
||||
|
28
builtin/rm.c
28
builtin/rm.c
@ -235,7 +235,8 @@ static int check_local_mod(struct object_id *head, int index_only)
|
||||
}
|
||||
|
||||
static int show_only = 0, force = 0, index_only = 0, recursive = 0, quiet = 0;
|
||||
static int ignore_unmatch = 0;
|
||||
static int ignore_unmatch = 0, pathspec_file_nul;
|
||||
static char *pathspec_from_file;
|
||||
|
||||
static struct option builtin_rm_options[] = {
|
||||
OPT__DRY_RUN(&show_only, N_("dry run")),
|
||||
@ -245,6 +246,8 @@ static struct option builtin_rm_options[] = {
|
||||
OPT_BOOL('r', NULL, &recursive, N_("allow recursive removal")),
|
||||
OPT_BOOL( 0 , "ignore-unmatch", &ignore_unmatch,
|
||||
N_("exit with a zero status even if nothing matched")),
|
||||
OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
|
||||
OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
|
||||
OPT_END(),
|
||||
};
|
||||
|
||||
@ -259,8 +262,24 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
|
||||
|
||||
argc = parse_options(argc, argv, prefix, builtin_rm_options,
|
||||
builtin_rm_usage, 0);
|
||||
if (!argc)
|
||||
usage_with_options(builtin_rm_usage, builtin_rm_options);
|
||||
|
||||
parse_pathspec(&pathspec, 0,
|
||||
PATHSPEC_PREFER_CWD,
|
||||
prefix, argv);
|
||||
|
||||
if (pathspec_from_file) {
|
||||
if (pathspec.nr)
|
||||
die(_("--pathspec-from-file is incompatible with pathspec arguments"));
|
||||
|
||||
parse_pathspec_file(&pathspec, 0,
|
||||
PATHSPEC_PREFER_CWD,
|
||||
prefix, pathspec_from_file, pathspec_file_nul);
|
||||
} else if (pathspec_file_nul) {
|
||||
die(_("--pathspec-file-nul requires --pathspec-from-file"));
|
||||
}
|
||||
|
||||
if (!pathspec.nr)
|
||||
die(_("No pathspec was given. Which files should I remove?"));
|
||||
|
||||
if (!index_only)
|
||||
setup_work_tree();
|
||||
@ -270,9 +289,6 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
|
||||
if (read_cache() < 0)
|
||||
die(_("index file corrupt"));
|
||||
|
||||
parse_pathspec(&pathspec, 0,
|
||||
PATHSPEC_PREFER_CWD,
|
||||
prefix, argv);
|
||||
refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, &pathspec, NULL, NULL);
|
||||
|
||||
seen = xcalloc(pathspec.nr, 1);
|
||||
|
@ -27,6 +27,7 @@ static const char * const git_stash_usage[] = {
|
||||
N_("git stash clear"),
|
||||
N_("git stash [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
|
||||
" [-u|--include-untracked] [-a|--all] [-m|--message <message>]\n"
|
||||
" [--pathspec-from-file=<file> [--pathspec-file-nul]]\n"
|
||||
" [--] [<pathspec>...]]"),
|
||||
N_("git stash save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
|
||||
" [-u|--include-untracked] [-a|--all] [<message>]"),
|
||||
@ -1451,13 +1452,17 @@ done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int push_stash(int argc, const char **argv, const char *prefix)
|
||||
static int push_stash(int argc, const char **argv, const char *prefix,
|
||||
int push_assumed)
|
||||
{
|
||||
int force_assume = 0;
|
||||
int keep_index = -1;
|
||||
int patch_mode = 0;
|
||||
int include_untracked = 0;
|
||||
int quiet = 0;
|
||||
int pathspec_file_nul = 0;
|
||||
const char *stash_msg = NULL;
|
||||
const char *pathspec_from_file = NULL;
|
||||
struct pathspec ps;
|
||||
struct option options[] = {
|
||||
OPT_BOOL('k', "keep-index", &keep_index,
|
||||
@ -1471,16 +1476,45 @@ static int push_stash(int argc, const char **argv, const char *prefix)
|
||||
N_("include ignore files"), 2),
|
||||
OPT_STRING('m', "message", &stash_msg, N_("message"),
|
||||
N_("stash message")),
|
||||
OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
|
||||
OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
if (argc)
|
||||
if (argc) {
|
||||
force_assume = !strcmp(argv[0], "-p");
|
||||
argc = parse_options(argc, argv, prefix, options,
|
||||
git_stash_push_usage,
|
||||
0);
|
||||
PARSE_OPT_KEEP_DASHDASH);
|
||||
}
|
||||
|
||||
if (argc) {
|
||||
if (!strcmp(argv[0], "--")) {
|
||||
argc--;
|
||||
argv++;
|
||||
} else if (push_assumed && !force_assume) {
|
||||
die("subcommand wasn't specified; 'push' can't be assumed due to unexpected token '%s'",
|
||||
argv[0]);
|
||||
}
|
||||
}
|
||||
|
||||
parse_pathspec(&ps, 0, PATHSPEC_PREFER_FULL | PATHSPEC_PREFIX_ORIGIN,
|
||||
prefix, argv);
|
||||
|
||||
if (pathspec_from_file) {
|
||||
if (patch_mode)
|
||||
die(_("--pathspec-from-file is incompatible with --patch"));
|
||||
|
||||
if (ps.nr)
|
||||
die(_("--pathspec-from-file is incompatible with pathspec arguments"));
|
||||
|
||||
parse_pathspec_file(&ps, 0,
|
||||
PATHSPEC_PREFER_FULL | PATHSPEC_PREFIX_ORIGIN,
|
||||
prefix, pathspec_from_file, pathspec_file_nul);
|
||||
} else if (pathspec_file_nul) {
|
||||
die(_("--pathspec-file-nul requires --pathspec-from-file"));
|
||||
}
|
||||
|
||||
return do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
|
||||
include_untracked);
|
||||
}
|
||||
@ -1550,7 +1584,6 @@ static int use_builtin_stash(void)
|
||||
|
||||
int cmd_stash(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
int i = -1;
|
||||
pid_t pid = getpid();
|
||||
const char *index_file;
|
||||
struct argv_array args = ARGV_ARRAY_INIT;
|
||||
@ -1583,7 +1616,7 @@ int cmd_stash(int argc, const char **argv, const char *prefix)
|
||||
(uintmax_t)pid);
|
||||
|
||||
if (!argc)
|
||||
return !!push_stash(0, NULL, prefix);
|
||||
return !!push_stash(0, NULL, prefix, 0);
|
||||
else if (!strcmp(argv[0], "apply"))
|
||||
return !!apply_stash(argc, argv, prefix);
|
||||
else if (!strcmp(argv[0], "clear"))
|
||||
@ -1603,45 +1636,15 @@ int cmd_stash(int argc, const char **argv, const char *prefix)
|
||||
else if (!strcmp(argv[0], "create"))
|
||||
return !!create_stash(argc, argv, prefix);
|
||||
else if (!strcmp(argv[0], "push"))
|
||||
return !!push_stash(argc, argv, prefix);
|
||||
return !!push_stash(argc, argv, prefix, 0);
|
||||
else if (!strcmp(argv[0], "save"))
|
||||
return !!save_stash(argc, argv, prefix);
|
||||
else if (*argv[0] != '-')
|
||||
usage_msg_opt(xstrfmt(_("unknown subcommand: %s"), argv[0]),
|
||||
git_stash_usage, options);
|
||||
|
||||
if (strcmp(argv[0], "-p")) {
|
||||
while (++i < argc && strcmp(argv[i], "--")) {
|
||||
/*
|
||||
* `akpqu` is a string which contains all short options,
|
||||
* except `-m` which is verified separately.
|
||||
*/
|
||||
if ((strlen(argv[i]) == 2) && *argv[i] == '-' &&
|
||||
strchr("akpqu", argv[i][1]))
|
||||
continue;
|
||||
|
||||
if (!strcmp(argv[i], "--all") ||
|
||||
!strcmp(argv[i], "--keep-index") ||
|
||||
!strcmp(argv[i], "--no-keep-index") ||
|
||||
!strcmp(argv[i], "--patch") ||
|
||||
!strcmp(argv[i], "--quiet") ||
|
||||
!strcmp(argv[i], "--include-untracked"))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* `-m` and `--message=` are verified separately because
|
||||
* they need to be immediately followed by a string
|
||||
* (i.e.`-m"foobar"` or `--message="foobar"`).
|
||||
*/
|
||||
if (starts_with(argv[i], "-m") ||
|
||||
starts_with(argv[i], "--message="))
|
||||
continue;
|
||||
|
||||
usage_with_options(git_stash_usage, options);
|
||||
}
|
||||
}
|
||||
|
||||
/* Assume 'stash push' */
|
||||
argv_array_push(&args, "push");
|
||||
argv_array_pushv(&args, argv);
|
||||
return !!push_stash(args.argc, args.argv, prefix);
|
||||
return !!push_stash(args.argc, args.argv, prefix, 1);
|
||||
}
|
||||
|
@ -139,22 +139,10 @@ win32_compute_revents (HANDLE h, int *p_sought)
|
||||
INPUT_RECORD *irbuffer;
|
||||
DWORD avail, nbuffer;
|
||||
BOOL bRet;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
FILE_PIPE_LOCAL_INFORMATION fpli;
|
||||
static PNtQueryInformationFile NtQueryInformationFile;
|
||||
static BOOL once_only;
|
||||
|
||||
switch (GetFileType (h))
|
||||
{
|
||||
case FILE_TYPE_PIPE:
|
||||
if (!once_only)
|
||||
{
|
||||
NtQueryInformationFile = (PNtQueryInformationFile)(void (*)(void))
|
||||
GetProcAddress (GetModuleHandleW (L"ntdll.dll"),
|
||||
"NtQueryInformationFile");
|
||||
once_only = TRUE;
|
||||
}
|
||||
|
||||
happened = 0;
|
||||
if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
|
||||
{
|
||||
@ -166,22 +154,9 @@ win32_compute_revents (HANDLE h, int *p_sought)
|
||||
|
||||
else
|
||||
{
|
||||
/* It was the write-end of the pipe. Check if it is writable.
|
||||
If NtQueryInformationFile fails, optimistically assume the pipe is
|
||||
writable. This could happen on Win9x, where NtQueryInformationFile
|
||||
is not available, or if we inherit a pipe that doesn't permit
|
||||
FILE_READ_ATTRIBUTES access on the write end (I think this should
|
||||
not happen since WinXP SP2; WINE seems fine too). Otherwise,
|
||||
ensure that enough space is available for atomic writes. */
|
||||
memset (&iosb, 0, sizeof (iosb));
|
||||
memset (&fpli, 0, sizeof (fpli));
|
||||
|
||||
if (!NtQueryInformationFile
|
||||
|| NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
|
||||
FilePipeLocalInformation)
|
||||
|| fpli.WriteQuotaAvailable >= PIPE_BUF
|
||||
|| (fpli.OutboundQuota < PIPE_BUF &&
|
||||
fpli.WriteQuotaAvailable == fpli.OutboundQuota))
|
||||
/* It was the write-end of the pipe. Unfortunately there is no
|
||||
reliable way of knowing if it can be written without blocking.
|
||||
Just say that it's all good. */
|
||||
happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
|
||||
}
|
||||
return happened;
|
||||
|
@ -9,7 +9,6 @@ endif
|
||||
DEVELOPER_CFLAGS += -Wall
|
||||
DEVELOPER_CFLAGS += -Wdeclaration-after-statement
|
||||
DEVELOPER_CFLAGS += -Wformat-security
|
||||
DEVELOPER_CFLAGS += -Wno-format-zero-length
|
||||
DEVELOPER_CFLAGS += -Wold-style-definition
|
||||
DEVELOPER_CFLAGS += -Woverflow
|
||||
DEVELOPER_CFLAGS += -Wpointer-arith
|
||||
|
@ -1197,6 +1197,7 @@ __git_count_arguments ()
|
||||
|
||||
__git_whitespacelist="nowarn warn error error-all fix"
|
||||
__git_patchformat="mbox stgit stgit-series hg mboxrd"
|
||||
__git_showcurrentpatch="diff raw"
|
||||
__git_am_inprogress_options="--skip --continue --resolved --abort --quit --show-current-patch"
|
||||
|
||||
_git_am ()
|
||||
@ -1215,6 +1216,10 @@ _git_am ()
|
||||
__gitcomp "$__git_patchformat" "" "${cur##--patch-format=}"
|
||||
return
|
||||
;;
|
||||
--show-current-patch=*)
|
||||
__gitcomp "$__git_showcurrentpatch" "" "${cur##--show-current-patch=}"
|
||||
return
|
||||
;;
|
||||
--*)
|
||||
__gitcomp_builtin am "" \
|
||||
"$__git_am_inprogress_options"
|
||||
@ -1487,9 +1492,16 @@ __git_diff_algorithms="myers minimal patience histogram"
|
||||
|
||||
__git_diff_submodule_formats="diff log short"
|
||||
|
||||
__git_color_moved_opts="no default plain blocks zebra dimmed-zebra"
|
||||
|
||||
__git_color_moved_ws_opts="no ignore-space-at-eol ignore-space-change
|
||||
ignore-all-space allow-indentation-change"
|
||||
|
||||
__git_diff_common_options="--stat --numstat --shortstat --summary
|
||||
--patch-with-stat --name-only --name-status --color
|
||||
--no-color --color-words --no-renames --check
|
||||
--color-moved --color-moved= --no-color-moved
|
||||
--color-moved-ws= --no-color-moved-ws
|
||||
--full-index --binary --abbrev --diff-filter=
|
||||
--find-copies-harder --ignore-cr-at-eol
|
||||
--text --ignore-space-at-eol --ignore-space-change
|
||||
@ -1520,6 +1532,14 @@ _git_diff ()
|
||||
__gitcomp "$__git_diff_submodule_formats" "" "${cur##--submodule=}"
|
||||
return
|
||||
;;
|
||||
--color-moved=*)
|
||||
__gitcomp "$__git_color_moved_opts" "" "${cur##--color-moved=}"
|
||||
return
|
||||
;;
|
||||
--color-moved-ws=*)
|
||||
__gitcomp "$__git_color_moved_ws_opts" "" "${cur##--color-moved-ws=}"
|
||||
return
|
||||
;;
|
||||
--*)
|
||||
__gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
|
||||
--base --ours --theirs --no-index
|
||||
|
@ -516,7 +516,7 @@ static int show_one_mergetag(struct commit *commit,
|
||||
"merged tag '%s'\n", tag->tag);
|
||||
else if ((nth = which_parent(&tag->tagged->oid, commit)) < 0)
|
||||
strbuf_addf(&verify_message, "tag %s names a non-parent %s\n",
|
||||
tag->tag, tag->tagged->oid.hash);
|
||||
tag->tag, oid_to_hex(&tag->tagged->oid));
|
||||
else
|
||||
strbuf_addf(&verify_message,
|
||||
"parent #%d, tagged '%s'\n", nth + 1, tag->tag);
|
||||
|
@ -1560,35 +1560,6 @@ static int handle_file_collision(struct merge_options *opt,
|
||||
b, a);
|
||||
}
|
||||
|
||||
/*
|
||||
* In the recursive case, we just opt to undo renames
|
||||
*/
|
||||
if (opt->priv->call_depth && (prev_path1 || prev_path2)) {
|
||||
/* Put first file (a->oid, a->mode) in its original spot */
|
||||
if (prev_path1) {
|
||||
if (update_file(opt, 1, a, prev_path1))
|
||||
return -1;
|
||||
} else {
|
||||
if (update_file(opt, 1, a, collide_path))
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Put second file (b->oid, b->mode) in its original spot */
|
||||
if (prev_path2) {
|
||||
if (update_file(opt, 1, b, prev_path2))
|
||||
return -1;
|
||||
} else {
|
||||
if (update_file(opt, 1, b, collide_path))
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Don't leave something at collision path if unrenaming both */
|
||||
if (prev_path1 && prev_path2)
|
||||
remove_file(opt, 1, collide_path, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Remove rename sources if rename/add or rename/rename(2to1) */
|
||||
if (prev_path1)
|
||||
remove_file(opt, 1, prev_path1,
|
||||
@ -1749,85 +1720,56 @@ static int handle_rename_rename_1to2(struct merge_options *opt,
|
||||
return -1;
|
||||
free(path_desc);
|
||||
|
||||
if (opt->priv->call_depth) {
|
||||
/*
|
||||
* FIXME: For rename/add-source conflicts (if we could detect
|
||||
* such), this is wrong. We should instead find a unique
|
||||
* pathname and then either rename the add-source file to that
|
||||
* unique path, or use that unique path instead of src here.
|
||||
*/
|
||||
if (update_file(opt, 0, &mfi.blob, o->path))
|
||||
if (opt->priv->call_depth)
|
||||
remove_file_from_index(opt->repo->index, o->path);
|
||||
|
||||
/*
|
||||
* For each destination path, we need to see if there is a
|
||||
* rename/add collision. If not, we can write the file out
|
||||
* to the specified location.
|
||||
*/
|
||||
add = &ci->ren1->dst_entry->stages[flip_stage(2)];
|
||||
if (is_valid(add)) {
|
||||
add->path = mfi.blob.path = a->path;
|
||||
if (handle_file_collision(opt, a->path,
|
||||
NULL, NULL,
|
||||
ci->ren1->branch,
|
||||
ci->ren2->branch,
|
||||
&mfi.blob, add) < 0)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Above, we put the merged content at the merge-base's
|
||||
* path. Now we usually need to delete both a->path and
|
||||
* b->path. However, the rename on each side of the merge
|
||||
* could also be involved in a rename/add conflict. In
|
||||
* such cases, we should keep the added file around,
|
||||
* resolving the conflict at that path in its favor.
|
||||
*/
|
||||
add = &ci->ren1->dst_entry->stages[flip_stage(2)];
|
||||
if (is_valid(add)) {
|
||||
if (update_file(opt, 0, add, a->path))
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
remove_file_from_index(opt->repo->index, a->path);
|
||||
add = &ci->ren2->dst_entry->stages[flip_stage(3)];
|
||||
if (is_valid(add)) {
|
||||
if (update_file(opt, 0, add, b->path))
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
remove_file_from_index(opt->repo->index, b->path);
|
||||
} else {
|
||||
/*
|
||||
* For each destination path, we need to see if there is a
|
||||
* rename/add collision. If not, we can write the file out
|
||||
* to the specified location.
|
||||
*/
|
||||
add = &ci->ren1->dst_entry->stages[flip_stage(2)];
|
||||
if (is_valid(add)) {
|
||||
add->path = mfi.blob.path = a->path;
|
||||
if (handle_file_collision(opt, a->path,
|
||||
NULL, NULL,
|
||||
ci->ren1->branch,
|
||||
ci->ren2->branch,
|
||||
&mfi.blob, add) < 0)
|
||||
return -1;
|
||||
} else {
|
||||
char *new_path = find_path_for_conflict(opt, a->path,
|
||||
ci->ren1->branch,
|
||||
ci->ren2->branch);
|
||||
if (update_file(opt, 0, &mfi.blob,
|
||||
new_path ? new_path : a->path))
|
||||
return -1;
|
||||
free(new_path);
|
||||
if (update_stages(opt, a->path, NULL, a, NULL))
|
||||
return -1;
|
||||
}
|
||||
char *new_path = find_path_for_conflict(opt, a->path,
|
||||
ci->ren1->branch,
|
||||
ci->ren2->branch);
|
||||
if (update_file(opt, 0, &mfi.blob,
|
||||
new_path ? new_path : a->path))
|
||||
return -1;
|
||||
free(new_path);
|
||||
if (!opt->priv->call_depth &&
|
||||
update_stages(opt, a->path, NULL, a, NULL))
|
||||
return -1;
|
||||
}
|
||||
|
||||
add = &ci->ren2->dst_entry->stages[flip_stage(3)];
|
||||
if (is_valid(add)) {
|
||||
add->path = mfi.blob.path = b->path;
|
||||
if (handle_file_collision(opt, b->path,
|
||||
NULL, NULL,
|
||||
ci->ren1->branch,
|
||||
ci->ren2->branch,
|
||||
add, &mfi.blob) < 0)
|
||||
return -1;
|
||||
} else {
|
||||
char *new_path = find_path_for_conflict(opt, b->path,
|
||||
ci->ren2->branch,
|
||||
ci->ren1->branch);
|
||||
if (update_file(opt, 0, &mfi.blob,
|
||||
new_path ? new_path : b->path))
|
||||
return -1;
|
||||
free(new_path);
|
||||
if (update_stages(opt, b->path, NULL, NULL, b))
|
||||
return -1;
|
||||
}
|
||||
add = &ci->ren2->dst_entry->stages[flip_stage(3)];
|
||||
if (is_valid(add)) {
|
||||
add->path = mfi.blob.path = b->path;
|
||||
if (handle_file_collision(opt, b->path,
|
||||
NULL, NULL,
|
||||
ci->ren1->branch,
|
||||
ci->ren2->branch,
|
||||
add, &mfi.blob) < 0)
|
||||
return -1;
|
||||
} else {
|
||||
char *new_path = find_path_for_conflict(opt, b->path,
|
||||
ci->ren2->branch,
|
||||
ci->ren1->branch);
|
||||
if (update_file(opt, 0, &mfi.blob,
|
||||
new_path ? new_path : b->path))
|
||||
return -1;
|
||||
free(new_path);
|
||||
if (!opt->priv->call_depth &&
|
||||
update_stages(opt, b->path, NULL, NULL, b))
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -61,7 +61,7 @@ static enum parse_opt_result opt_command_mode_error(
|
||||
*/
|
||||
for (that = all_opts; that->type != OPTION_END; that++) {
|
||||
if (that == opt ||
|
||||
that->type != OPTION_CMDMODE ||
|
||||
!(that->flags & PARSE_OPT_CMDMODE) ||
|
||||
that->value != opt->value ||
|
||||
that->defval != *(int *)opt->value)
|
||||
continue;
|
||||
@ -95,6 +95,14 @@ static enum parse_opt_result get_value(struct parse_opt_ctx_t *p,
|
||||
if (!(flags & OPT_SHORT) && p->opt && (opt->flags & PARSE_OPT_NOARG))
|
||||
return error(_("%s takes no value"), optname(opt, flags));
|
||||
|
||||
/*
|
||||
* Giving the same mode option twice, although unnecessary,
|
||||
* is not a grave error, so let it pass.
|
||||
*/
|
||||
if ((opt->flags & PARSE_OPT_CMDMODE) &&
|
||||
*(int *)opt->value && *(int *)opt->value != opt->defval)
|
||||
return opt_command_mode_error(opt, all_opts, flags);
|
||||
|
||||
switch (opt->type) {
|
||||
case OPTION_LOWLEVEL_CALLBACK:
|
||||
return opt->ll_callback(p, opt, NULL, unset);
|
||||
@ -130,16 +138,6 @@ static enum parse_opt_result get_value(struct parse_opt_ctx_t *p,
|
||||
*(int *)opt->value = unset ? 0 : opt->defval;
|
||||
return 0;
|
||||
|
||||
case OPTION_CMDMODE:
|
||||
/*
|
||||
* Giving the same mode option twice, although is unnecessary,
|
||||
* is not a grave error, so let it pass.
|
||||
*/
|
||||
if (*(int *)opt->value && *(int *)opt->value != opt->defval)
|
||||
return opt_command_mode_error(opt, all_opts, flags);
|
||||
*(int *)opt->value = opt->defval;
|
||||
return 0;
|
||||
|
||||
case OPTION_STRING:
|
||||
if (unset)
|
||||
*(const char **)opt->value = NULL;
|
||||
|
@ -18,7 +18,6 @@ enum parse_opt_type {
|
||||
OPTION_BITOP,
|
||||
OPTION_COUNTUP,
|
||||
OPTION_SET_INT,
|
||||
OPTION_CMDMODE,
|
||||
/* options with arguments (usually) */
|
||||
OPTION_STRING,
|
||||
OPTION_INTEGER,
|
||||
@ -47,7 +46,8 @@ enum parse_opt_option_flags {
|
||||
PARSE_OPT_LITERAL_ARGHELP = 64,
|
||||
PARSE_OPT_SHELL_EVAL = 256,
|
||||
PARSE_OPT_NOCOMPLETE = 512,
|
||||
PARSE_OPT_COMP_ARG = 1024
|
||||
PARSE_OPT_COMP_ARG = 1024,
|
||||
PARSE_OPT_CMDMODE = 2048
|
||||
};
|
||||
|
||||
enum parse_opt_result {
|
||||
@ -168,8 +168,8 @@ struct option {
|
||||
#define OPT_BOOL(s, l, v, h) OPT_BOOL_F(s, l, v, h, 0)
|
||||
#define OPT_HIDDEN_BOOL(s, l, v, h) { OPTION_SET_INT, (s), (l), (v), NULL, \
|
||||
(h), PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, 1}
|
||||
#define OPT_CMDMODE(s, l, v, h, i) { OPTION_CMDMODE, (s), (l), (v), NULL, \
|
||||
(h), PARSE_OPT_NOARG|PARSE_OPT_NONEG, NULL, (i) }
|
||||
#define OPT_CMDMODE(s, l, v, h, i) { OPTION_SET_INT, (s), (l), (v), NULL, \
|
||||
(h), PARSE_OPT_CMDMODE|PARSE_OPT_NOARG|PARSE_OPT_NONEG, NULL, (i) }
|
||||
#define OPT_INTEGER(s, l, v, h) OPT_INTEGER_F(s, l, v, h, 0)
|
||||
#define OPT_MAGNITUDE(s, l, v, h) { OPTION_MAGNITUDE, (s), (l), (v), \
|
||||
N_("n"), (h), PARSE_OPT_NONEG }
|
||||
|
@ -129,14 +129,14 @@ int edit_todo_list(struct repository *r, struct todo_list *todo_list,
|
||||
|
||||
if (incorrect) {
|
||||
if (todo_list_check_against_backup(r, new_todo)) {
|
||||
write_file(rebase_path_dropped(), "");
|
||||
write_file(rebase_path_dropped(), "%s", "");
|
||||
return -4;
|
||||
}
|
||||
|
||||
if (incorrect > 0)
|
||||
unlink(rebase_path_dropped());
|
||||
} else if (todo_list_check(todo_list, new_todo)) {
|
||||
write_file(rebase_path_dropped(), "");
|
||||
write_file(rebase_path_dropped(), "%s", "");
|
||||
return -4;
|
||||
}
|
||||
|
||||
|
@ -1026,6 +1026,7 @@ static int fetch_dumb(int nr_heads, struct ref **to_fetch)
|
||||
|
||||
walker = get_http_walker(url.buf);
|
||||
walker->get_verbosely = options.verbosity >= 3;
|
||||
walker->get_progress = options.progress;
|
||||
walker->get_recover = 0;
|
||||
ret = walker_fetch(walker, nr_heads, targets, NULL, NULL);
|
||||
walker_free(walker);
|
||||
|
@ -121,6 +121,8 @@ int cmd__parse_options(int argc, const char **argv)
|
||||
OPT_INTEGER('j', NULL, &integer, "get a integer, too"),
|
||||
OPT_MAGNITUDE('m', "magnitude", &magnitude, "get a magnitude"),
|
||||
OPT_SET_INT(0, "set23", &integer, "set integer to 23", 23),
|
||||
OPT_CMDMODE(0, "mode1", &integer, "set integer to 1 (cmdmode option)", 1),
|
||||
OPT_CMDMODE(0, "mode2", &integer, "set integer to 2 (cmdmode option)", 2),
|
||||
OPT_CALLBACK('L', "length", &integer, "str",
|
||||
"get length of <str>", length_callback),
|
||||
OPT_FILENAME('F', "file", &file, "set file to <file>"),
|
||||
|
@ -23,6 +23,8 @@ usage: test-tool parse-options <options>
|
||||
-j <n> get a integer, too
|
||||
-m, --magnitude <n> get a magnitude
|
||||
--set23 set integer to 23
|
||||
--mode1 set integer to 1 (cmdmode option)
|
||||
--mode2 set integer to 2 (cmdmode option)
|
||||
-L, --length <str> get length of <str>
|
||||
-F, --file <file> set file to <file>
|
||||
|
||||
@ -324,6 +326,22 @@ test_expect_success 'OPT_NEGBIT() works' '
|
||||
test-tool parse-options --expect="boolean: 6" -bb --no-neg-or4
|
||||
'
|
||||
|
||||
test_expect_success 'OPT_CMDMODE() works' '
|
||||
test-tool parse-options --expect="integer: 1" --mode1
|
||||
'
|
||||
|
||||
test_expect_success 'OPT_CMDMODE() detects incompatibility' '
|
||||
test_must_fail test-tool parse-options --mode1 --mode2 >output 2>output.err &&
|
||||
test_must_be_empty output &&
|
||||
test_i18ngrep "incompatible with --mode" output.err
|
||||
'
|
||||
|
||||
test_expect_success 'OPT_CMDMODE() detects incompatibility with something else' '
|
||||
test_must_fail test-tool parse-options --set23 --mode2 >output 2>output.err &&
|
||||
test_must_be_empty output &&
|
||||
test_i18ngrep "incompatible with something else" output.err
|
||||
'
|
||||
|
||||
test_expect_success 'OPT_COUNTUP() with PARSE_OPT_NODASH works' '
|
||||
test-tool parse-options --expect="boolean: 6" + + + + + +
|
||||
'
|
||||
|
@ -53,7 +53,8 @@ test_expect_success 'add a large file or two' '
|
||||
for p in .git/objects/pack/pack-*.pack
|
||||
do
|
||||
count=$(( $count + 1 ))
|
||||
if test -f "$p" && idx=${p%.pack}.idx && test -f "$idx"
|
||||
if test_path_is_file "$p" &&
|
||||
idx=${p%.pack}.idx && test_path_is_file "$idx"
|
||||
then
|
||||
continue
|
||||
fi
|
||||
@ -65,7 +66,7 @@ test_expect_success 'add a large file or two' '
|
||||
test $cnt = 2 &&
|
||||
for l in .git/objects/??/??????????????????????????????????????
|
||||
do
|
||||
test -f "$l" || continue
|
||||
test_path_is_file "$l" || continue
|
||||
bad=t
|
||||
done &&
|
||||
test -z "$bad" &&
|
||||
@ -76,7 +77,8 @@ test_expect_success 'add a large file or two' '
|
||||
for p in .git/objects/pack/pack-*.pack
|
||||
do
|
||||
count=$(( $count + 1 ))
|
||||
if test -f "$p" && idx=${p%.pack}.idx && test -f "$idx"
|
||||
if test_path_is_file "$p" &&
|
||||
idx=${p%.pack}.idx && test_path_is_file "$idx"
|
||||
then
|
||||
continue
|
||||
fi
|
||||
@ -111,7 +113,7 @@ test_expect_success 'packsize limit' '
|
||||
count=0 &&
|
||||
for pi in .git/objects/pack/pack-*.idx
|
||||
do
|
||||
test -f "$pi" && count=$(( $count + 1 ))
|
||||
test_path_is_file "$pi" && count=$(( $count + 1 ))
|
||||
done &&
|
||||
test $count = 2 &&
|
||||
|
||||
|
@ -28,7 +28,7 @@ test_expect_success 'setup' '
|
||||
git config core.sparseCheckout true &&
|
||||
echo "/checked-out" >.git/info/sparse-checkout &&
|
||||
git reset --hard &&
|
||||
! git merge theirs
|
||||
test_must_fail git merge theirs
|
||||
'
|
||||
|
||||
test_expect_success 'reset --hard works after the conflict' '
|
||||
@ -42,7 +42,7 @@ test_expect_success 'is reset properly' '
|
||||
'
|
||||
|
||||
test_expect_success 'setup: conflict back' '
|
||||
! git merge theirs
|
||||
test_must_fail git merge theirs
|
||||
'
|
||||
|
||||
test_expect_success 'Merge abort works after the conflict' '
|
||||
|
79
t/t3601-rm-pathspec-file.sh
Executable file
79
t/t3601-rm-pathspec-file.sh
Executable file
@ -0,0 +1,79 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='rm --pathspec-from-file'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
test_tick
|
||||
|
||||
test_expect_success setup '
|
||||
echo A >fileA.t &&
|
||||
echo B >fileB.t &&
|
||||
echo C >fileC.t &&
|
||||
echo D >fileD.t &&
|
||||
git add fileA.t fileB.t fileC.t fileD.t &&
|
||||
git commit -m "files" &&
|
||||
|
||||
git tag checkpoint
|
||||
'
|
||||
|
||||
restore_checkpoint () {
|
||||
git reset --hard checkpoint
|
||||
}
|
||||
|
||||
verify_expect () {
|
||||
git status --porcelain --untracked-files=no -- fileA.t fileB.t fileC.t fileD.t >actual &&
|
||||
test_cmp expect actual
|
||||
}
|
||||
|
||||
test_expect_success 'simplest' '
|
||||
restore_checkpoint &&
|
||||
|
||||
cat >expect <<-\EOF &&
|
||||
D fileA.t
|
||||
EOF
|
||||
|
||||
echo fileA.t | git rm --pathspec-from-file=- &&
|
||||
verify_expect
|
||||
'
|
||||
|
||||
test_expect_success '--pathspec-file-nul' '
|
||||
restore_checkpoint &&
|
||||
|
||||
cat >expect <<-\EOF &&
|
||||
D fileA.t
|
||||
D fileB.t
|
||||
EOF
|
||||
|
||||
printf "fileA.t\0fileB.t\0" | git rm --pathspec-from-file=- --pathspec-file-nul &&
|
||||
verify_expect
|
||||
'
|
||||
|
||||
test_expect_success 'only touches what was listed' '
|
||||
restore_checkpoint &&
|
||||
|
||||
cat >expect <<-\EOF &&
|
||||
D fileB.t
|
||||
D fileC.t
|
||||
EOF
|
||||
|
||||
printf "fileB.t\nfileC.t\n" | git rm --pathspec-from-file=- &&
|
||||
verify_expect
|
||||
'
|
||||
|
||||
test_expect_success 'error conditions' '
|
||||
restore_checkpoint &&
|
||||
echo fileA.t >list &&
|
||||
|
||||
test_must_fail git rm --pathspec-from-file=list -- fileA.t 2>err &&
|
||||
test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
|
||||
|
||||
test_must_fail git rm --pathspec-file-nul 2>err &&
|
||||
test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err &&
|
||||
|
||||
>empty_list &&
|
||||
test_must_fail git rm --pathspec-from-file=empty_list 2>err &&
|
||||
test_i18ngrep -e "No pathspec was given. Which files should I remove?" err
|
||||
'
|
||||
|
||||
test_done
|
@ -285,6 +285,11 @@ test_expect_success 'stash --no-keep-index' '
|
||||
test bar,bar2 = $(cat file),$(cat file2)
|
||||
'
|
||||
|
||||
test_expect_success 'dont assume push with non-option args' '
|
||||
test_must_fail git stash -q drop 2>err &&
|
||||
test_i18ngrep -e "subcommand wasn'\''t specified; '\''push'\'' can'\''t be assumed due to unexpected token '\''drop'\''" err
|
||||
'
|
||||
|
||||
test_expect_success 'stash --invalid-option' '
|
||||
echo bar5 >file &&
|
||||
echo bar6 >file2 &&
|
||||
|
100
t/t3909-stash-pathspec-file.sh
Executable file
100
t/t3909-stash-pathspec-file.sh
Executable file
@ -0,0 +1,100 @@
|
||||
#!/bin/sh
|
||||
|
||||
test_description='stash --pathspec-from-file'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
test_tick
|
||||
|
||||
test_expect_success setup '
|
||||
>fileA.t &&
|
||||
>fileB.t &&
|
||||
>fileC.t &&
|
||||
>fileD.t &&
|
||||
git add fileA.t fileB.t fileC.t fileD.t &&
|
||||
git commit -m "Files" &&
|
||||
|
||||
git tag checkpoint
|
||||
'
|
||||
|
||||
restore_checkpoint () {
|
||||
git reset --hard checkpoint
|
||||
}
|
||||
|
||||
verify_expect () {
|
||||
git stash show --name-status >actual &&
|
||||
test_cmp expect actual
|
||||
}
|
||||
|
||||
test_expect_success 'simplest' '
|
||||
restore_checkpoint &&
|
||||
|
||||
# More files are written to make sure that git didnt ignore
|
||||
# --pathspec-from-file, stashing everything
|
||||
echo A >fileA.t &&
|
||||
echo B >fileB.t &&
|
||||
echo C >fileC.t &&
|
||||
echo D >fileD.t &&
|
||||
|
||||
cat >expect <<-\EOF &&
|
||||
M fileA.t
|
||||
EOF
|
||||
|
||||
echo fileA.t | git stash push --pathspec-from-file=- &&
|
||||
verify_expect
|
||||
'
|
||||
|
||||
test_expect_success '--pathspec-file-nul' '
|
||||
restore_checkpoint &&
|
||||
|
||||
# More files are written to make sure that git didnt ignore
|
||||
# --pathspec-from-file, stashing everything
|
||||
echo A >fileA.t &&
|
||||
echo B >fileB.t &&
|
||||
echo C >fileC.t &&
|
||||
echo D >fileD.t &&
|
||||
|
||||
cat >expect <<-\EOF &&
|
||||
M fileA.t
|
||||
M fileB.t
|
||||
EOF
|
||||
|
||||
printf "fileA.t\0fileB.t\0" | git stash push --pathspec-from-file=- --pathspec-file-nul &&
|
||||
verify_expect
|
||||
'
|
||||
|
||||
test_expect_success 'only touches what was listed' '
|
||||
restore_checkpoint &&
|
||||
|
||||
# More files are written to make sure that git didnt ignore
|
||||
# --pathspec-from-file, stashing everything
|
||||
echo A >fileA.t &&
|
||||
echo B >fileB.t &&
|
||||
echo C >fileC.t &&
|
||||
echo D >fileD.t &&
|
||||
|
||||
cat >expect <<-\EOF &&
|
||||
M fileB.t
|
||||
M fileC.t
|
||||
EOF
|
||||
|
||||
printf "fileB.t\nfileC.t\n" | git stash push --pathspec-from-file=- &&
|
||||
verify_expect
|
||||
'
|
||||
|
||||
test_expect_success 'error conditions' '
|
||||
restore_checkpoint &&
|
||||
echo A >fileA.t &&
|
||||
echo fileA.t >list &&
|
||||
|
||||
test_must_fail git stash push --pathspec-from-file=list --patch 2>err &&
|
||||
test_i18ngrep -e "--pathspec-from-file is incompatible with --patch" err &&
|
||||
|
||||
test_must_fail git stash push --pathspec-from-file=list -- fileA.t 2>err &&
|
||||
test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err &&
|
||||
|
||||
test_must_fail git stash push --pathspec-file-nul 2>err &&
|
||||
test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err
|
||||
'
|
||||
|
||||
test_done
|
@ -666,6 +666,26 @@ test_expect_success 'am --show-current-patch' '
|
||||
test_cmp .git/rebase-apply/0001 actual.patch
|
||||
'
|
||||
|
||||
test_expect_success 'am --show-current-patch=raw' '
|
||||
git am --show-current-patch=raw >actual.patch &&
|
||||
test_cmp .git/rebase-apply/0001 actual.patch
|
||||
'
|
||||
|
||||
test_expect_success 'am --show-current-patch=diff' '
|
||||
git am --show-current-patch=diff >actual.patch &&
|
||||
test_cmp .git/rebase-apply/patch actual.patch
|
||||
'
|
||||
|
||||
test_expect_success 'am accepts repeated --show-current-patch' '
|
||||
git am --show-current-patch --show-current-patch=raw >actual.patch &&
|
||||
test_cmp .git/rebase-apply/0001 actual.patch
|
||||
'
|
||||
|
||||
test_expect_success 'am detects incompatible --show-current-patch' '
|
||||
test_must_fail git am --show-current-patch=raw --show-current-patch=diff &&
|
||||
test_must_fail git am --show-current-patch --show-current-patch=diff
|
||||
'
|
||||
|
||||
test_expect_success 'am --skip works' '
|
||||
echo goodbye >expected &&
|
||||
git am --skip &&
|
||||
|
@ -1607,6 +1607,26 @@ test_expect_success GPG 'log --graph --show-signature for merged tag' '
|
||||
grep "^| | gpg: Good signature" actual
|
||||
'
|
||||
|
||||
test_expect_success GPG 'log --graph --show-signature for merged tag in shallow clone' '
|
||||
test_when_finished "git reset --hard && git checkout master" &&
|
||||
git checkout -b plain-shallow master &&
|
||||
echo aaa >bar &&
|
||||
git add bar &&
|
||||
git commit -m bar_commit &&
|
||||
git checkout --detach master &&
|
||||
echo bbb >baz &&
|
||||
git add baz &&
|
||||
git commit -m baz_commit &&
|
||||
git tag -s -m signed_tag_msg signed_tag_shallow &&
|
||||
hash=$(git rev-parse HEAD) &&
|
||||
git checkout plain-shallow &&
|
||||
git merge --no-ff -m msg signed_tag_shallow &&
|
||||
git clone --depth 1 --no-local . shallow &&
|
||||
test_when_finished "rm -rf shallow" &&
|
||||
git -C shallow log --graph --show-signature -n1 plain-shallow >actual &&
|
||||
grep "tag signed_tag_shallow names a non-parent $hash" actual
|
||||
'
|
||||
|
||||
test_expect_success GPGSM 'log --graph --show-signature for merged tag x509' '
|
||||
test_when_finished "git reset --hard && git checkout master" &&
|
||||
test_config gpg.format x509 &&
|
||||
|
@ -83,9 +83,9 @@ test_expect_success 'modify/delete + directory/file conflict' '
|
||||
test 4 -eq $(git ls-files -u | wc -l) &&
|
||||
test 1 -eq $(git ls-files -o | wc -l) &&
|
||||
|
||||
test -f letters/file &&
|
||||
test -f letters.txt &&
|
||||
test -f letters~modify
|
||||
test_path_is_file letters/file &&
|
||||
test_path_is_file letters.txt &&
|
||||
test_path_is_file letters~modify
|
||||
'
|
||||
|
||||
test_expect_success 'modify/delete + directory/file conflict; other way' '
|
||||
@ -99,9 +99,52 @@ test_expect_success 'modify/delete + directory/file conflict; other way' '
|
||||
test 4 -eq $(git ls-files -u | wc -l) &&
|
||||
test 1 -eq $(git ls-files -o | wc -l) &&
|
||||
|
||||
test -f letters/file &&
|
||||
test -f letters.txt &&
|
||||
test -f letters~HEAD
|
||||
test_path_is_file letters/file &&
|
||||
test_path_is_file letters.txt &&
|
||||
test_path_is_file letters~HEAD
|
||||
'
|
||||
|
||||
test_expect_success 'Simple merge in repo with interesting pathnames' '
|
||||
# Simple lexicographic ordering of files and directories would be:
|
||||
# foo
|
||||
# foo/bar
|
||||
# foo/bar-2
|
||||
# foo/bar/baz
|
||||
# foo/bar-2/baz
|
||||
# The fact that foo/bar-2 appears between foo/bar and foo/bar/baz
|
||||
# can trip up some codepaths, and is the point of this test.
|
||||
test_create_repo name-ordering &&
|
||||
(
|
||||
cd name-ordering &&
|
||||
|
||||
mkdir -p foo/bar &&
|
||||
mkdir -p foo/bar-2 &&
|
||||
>foo/bar/baz &&
|
||||
>foo/bar-2/baz &&
|
||||
git add . &&
|
||||
git commit -m initial &&
|
||||
|
||||
git branch main &&
|
||||
git branch other &&
|
||||
|
||||
git checkout other &&
|
||||
echo other >foo/bar-2/baz &&
|
||||
git add -u &&
|
||||
git commit -m other &&
|
||||
|
||||
git checkout main &&
|
||||
echo main >foo/bar/baz &&
|
||||
git add -u &&
|
||||
git commit -m main &&
|
||||
|
||||
git merge other &&
|
||||
git ls-files -s >out &&
|
||||
test_line_count = 2 out &&
|
||||
git rev-parse :0:foo/bar/baz :0:foo/bar-2/baz >actual &&
|
||||
git rev-parse HEAD~1:foo/bar/baz other:foo/bar-2/baz >expect &&
|
||||
test_cmp expect actual
|
||||
)
|
||||
|
||||
'
|
||||
|
||||
test_done
|
||||
|
@ -10,87 +10,58 @@
|
||||
test_description='Test criss-cross merge'
|
||||
. ./test-lib.sh
|
||||
|
||||
test_expect_success 'prepare repository' \
|
||||
'echo "1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9" > file &&
|
||||
git add file &&
|
||||
git commit -m "Initial commit" file &&
|
||||
git branch A &&
|
||||
git branch B &&
|
||||
git checkout A &&
|
||||
echo "1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8 changed in B8, branch A
|
||||
9" > file &&
|
||||
git commit -m "B8" file &&
|
||||
git checkout B &&
|
||||
echo "1
|
||||
2
|
||||
3 changed in C3, branch B
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
" > file &&
|
||||
git commit -m "C3" file &&
|
||||
git branch C3 &&
|
||||
git merge -m "pre E3 merge" A &&
|
||||
echo "1
|
||||
2
|
||||
3 changed in E3, branch B. New file size
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8 changed in B8, branch A
|
||||
9
|
||||
" > file &&
|
||||
git commit -m "E3" file &&
|
||||
git checkout A &&
|
||||
git merge -m "pre D8 merge" C3 &&
|
||||
echo "1
|
||||
2
|
||||
3 changed in C3, branch B
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8 changed in D8, branch A. New file size 2
|
||||
9" > file &&
|
||||
git commit -m D8 file'
|
||||
test_expect_success 'prepare repository' '
|
||||
test_write_lines 1 2 3 4 5 6 7 8 9 >file &&
|
||||
git add file &&
|
||||
git commit -m "Initial commit" file &&
|
||||
|
||||
test_expect_success 'Criss-cross merge' 'git merge -m "final merge" B'
|
||||
git branch A &&
|
||||
git branch B &&
|
||||
git checkout A &&
|
||||
|
||||
cat > file-expect <<EOF
|
||||
1
|
||||
2
|
||||
3 changed in E3, branch B. New file size
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8 changed in D8, branch A. New file size 2
|
||||
9
|
||||
EOF
|
||||
test_write_lines 1 2 3 4 5 6 7 "8 changed in B8, branch A" 9 >file &&
|
||||
git commit -m "B8" file &&
|
||||
git checkout B &&
|
||||
|
||||
test_expect_success 'Criss-cross merge result' 'cmp file file-expect'
|
||||
test_write_lines 1 2 "3 changed in C3, branch B" 4 5 6 7 8 9 >file &&
|
||||
git commit -m "C3" file &&
|
||||
git branch C3 &&
|
||||
|
||||
test_expect_success 'Criss-cross merge fails (-s resolve)' \
|
||||
'git reset --hard A^ &&
|
||||
test_must_fail git merge -s resolve -m "final merge" B'
|
||||
git merge -m "pre E3 merge" A &&
|
||||
|
||||
test_write_lines 1 2 "3 changed in E3, branch B. New file size" 4 5 6 7 "8 changed in B8, branch A" 9 >file &&
|
||||
git commit -m "E3" file &&
|
||||
|
||||
git checkout A &&
|
||||
git merge -m "pre D8 merge" C3 &&
|
||||
test_write_lines 1 2 "3 changed in C3, branch B" 4 5 6 7 "8 changed in D8, branch A. New file size 2" 9 >file &&
|
||||
|
||||
git commit -m D8 file
|
||||
'
|
||||
|
||||
test_expect_success 'Criss-cross merge' '
|
||||
git merge -m "final merge" B
|
||||
'
|
||||
|
||||
test_expect_success 'Criss-cross merge result' '
|
||||
cat <<-\EOF >file-expect &&
|
||||
1
|
||||
2
|
||||
3 changed in E3, branch B. New file size
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8 changed in D8, branch A. New file size 2
|
||||
9
|
||||
EOF
|
||||
|
||||
test_cmp file-expect file
|
||||
'
|
||||
|
||||
test_expect_success 'Criss-cross merge fails (-s resolve)' '
|
||||
git reset --hard A^ &&
|
||||
test_must_fail git merge -s resolve -m "final merge" B
|
||||
'
|
||||
|
||||
test_done
|
||||
|
@ -8,94 +8,94 @@ modify () {
|
||||
mv "$2.x" "$2"
|
||||
}
|
||||
|
||||
test_expect_success setup \
|
||||
test_expect_success 'setup' '
|
||||
cat >A <<-\EOF &&
|
||||
a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
b bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||
c cccccccccccccccccccccccccccccccccccccccccccccccc
|
||||
d dddddddddddddddddddddddddddddddddddddddddddddddd
|
||||
e eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
|
||||
f ffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
g gggggggggggggggggggggggggggggggggggggggggggggggg
|
||||
h hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
|
||||
i iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
|
||||
j jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj
|
||||
k kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
|
||||
l llllllllllllllllllllllllllllllllllllllllllllllll
|
||||
m mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
|
||||
n nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
|
||||
o oooooooooooooooooooooooooooooooooooooooooooooooo
|
||||
EOF
|
||||
|
||||
cat >M <<-\EOF &&
|
||||
A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
B BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
|
||||
C CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
||||
D DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
|
||||
E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
|
||||
F FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
|
||||
G GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
|
||||
H HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
|
||||
I IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
|
||||
J JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ
|
||||
K KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
|
||||
L LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL
|
||||
M MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
N NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
|
||||
O OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
|
||||
EOF
|
||||
|
||||
git add A M &&
|
||||
git commit -m "initial has A and M" &&
|
||||
git branch white &&
|
||||
git branch red &&
|
||||
git branch blue &&
|
||||
git branch yellow &&
|
||||
git branch change &&
|
||||
git branch change+rename &&
|
||||
|
||||
sed -e "/^g /s/.*/g : master changes a line/" <A >A+ &&
|
||||
mv A+ A &&
|
||||
git commit -a -m "master updates A" &&
|
||||
|
||||
git checkout yellow &&
|
||||
rm -f M &&
|
||||
git commit -a -m "yellow removes M" &&
|
||||
|
||||
git checkout white &&
|
||||
sed -e "/^g /s/.*/g : white changes a line/" <A >B &&
|
||||
sed -e "/^G /s/.*/G : colored branch changes a line/" <M >N &&
|
||||
rm -f A M &&
|
||||
git update-index --add --remove A B M N &&
|
||||
git commit -m "white renames A->B, M->N" &&
|
||||
|
||||
git checkout red &&
|
||||
sed -e "/^g /s/.*/g : red changes a line/" <A >B &&
|
||||
sed -e "/^G /s/.*/G : colored branch changes a line/" <M >N &&
|
||||
rm -f A M &&
|
||||
git update-index --add --remove A B M N &&
|
||||
git commit -m "red renames A->B, M->N" &&
|
||||
|
||||
git checkout blue &&
|
||||
sed -e "/^g /s/.*/g : blue changes a line/" <A >C &&
|
||||
sed -e "/^G /s/.*/G : colored branch changes a line/" <M >N &&
|
||||
rm -f A M &&
|
||||
git update-index --add --remove A C M N &&
|
||||
git commit -m "blue renames A->C, M->N" &&
|
||||
|
||||
git checkout change &&
|
||||
sed -e "/^g /s/.*/g : changed line/" <A >A+ &&
|
||||
mv A+ A &&
|
||||
git commit -q -a -m "changed" &&
|
||||
|
||||
git checkout change+rename &&
|
||||
sed -e "/^g /s/.*/g : changed line/" <A >B &&
|
||||
rm A &&
|
||||
git update-index --add B &&
|
||||
git commit -q -a -m "changed and renamed" &&
|
||||
|
||||
git checkout master
|
||||
'
|
||||
cat >A <<\EOF &&
|
||||
a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
b bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||
c cccccccccccccccccccccccccccccccccccccccccccccccc
|
||||
d dddddddddddddddddddddddddddddddddddddddddddddddd
|
||||
e eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
|
||||
f ffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
g gggggggggggggggggggggggggggggggggggggggggggggggg
|
||||
h hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
|
||||
i iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
|
||||
j jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj
|
||||
k kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
|
||||
l llllllllllllllllllllllllllllllllllllllllllllllll
|
||||
m mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
|
||||
n nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
|
||||
o oooooooooooooooooooooooooooooooooooooooooooooooo
|
||||
EOF
|
||||
|
||||
cat >M <<\EOF &&
|
||||
A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
B BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
|
||||
C CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
||||
D DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
|
||||
E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
|
||||
F FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
|
||||
G GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
|
||||
H HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
|
||||
I IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
|
||||
J JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ
|
||||
K KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
|
||||
L LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL
|
||||
M MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
N NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
|
||||
O OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
|
||||
EOF
|
||||
|
||||
git add A M &&
|
||||
git commit -m "initial has A and M" &&
|
||||
git branch white &&
|
||||
git branch red &&
|
||||
git branch blue &&
|
||||
git branch yellow &&
|
||||
git branch change &&
|
||||
git branch change+rename &&
|
||||
|
||||
sed -e "/^g /s/.*/g : master changes a line/" <A >A+ &&
|
||||
mv A+ A &&
|
||||
git commit -a -m "master updates A" &&
|
||||
|
||||
git checkout yellow &&
|
||||
rm -f M &&
|
||||
git commit -a -m "yellow removes M" &&
|
||||
|
||||
git checkout white &&
|
||||
sed -e "/^g /s/.*/g : white changes a line/" <A >B &&
|
||||
sed -e "/^G /s/.*/G : colored branch changes a line/" <M >N &&
|
||||
rm -f A M &&
|
||||
git update-index --add --remove A B M N &&
|
||||
git commit -m "white renames A->B, M->N" &&
|
||||
|
||||
git checkout red &&
|
||||
sed -e "/^g /s/.*/g : red changes a line/" <A >B &&
|
||||
sed -e "/^G /s/.*/G : colored branch changes a line/" <M >N &&
|
||||
rm -f A M &&
|
||||
git update-index --add --remove A B M N &&
|
||||
git commit -m "red renames A->B, M->N" &&
|
||||
|
||||
git checkout blue &&
|
||||
sed -e "/^g /s/.*/g : blue changes a line/" <A >C &&
|
||||
sed -e "/^G /s/.*/G : colored branch changes a line/" <M >N &&
|
||||
rm -f A M &&
|
||||
git update-index --add --remove A C M N &&
|
||||
git commit -m "blue renames A->C, M->N" &&
|
||||
|
||||
git checkout change &&
|
||||
sed -e "/^g /s/.*/g : changed line/" <A >A+ &&
|
||||
mv A+ A &&
|
||||
git commit -q -a -m "changed" &&
|
||||
|
||||
git checkout change+rename &&
|
||||
sed -e "/^g /s/.*/g : changed line/" <A >B &&
|
||||
rm A &&
|
||||
git update-index --add B &&
|
||||
git commit -q -a -m "changed and renamed" &&
|
||||
|
||||
git checkout master'
|
||||
|
||||
test_expect_success 'pull renaming branch into unrenaming one' \
|
||||
'
|
||||
@ -242,12 +242,23 @@ test_expect_success 'merge of identical changes in a renamed file' '
|
||||
rm -f A M N &&
|
||||
git reset --hard &&
|
||||
git checkout change+rename &&
|
||||
|
||||
test-tool chmtime =31337 B &&
|
||||
test-tool chmtime --get B >old-mtime &&
|
||||
GIT_MERGE_VERBOSITY=3 git merge change >out &&
|
||||
test_i18ngrep "^Skipped B" out &&
|
||||
|
||||
test-tool chmtime --get B >new-mtime &&
|
||||
test_cmp old-mtime new-mtime &&
|
||||
|
||||
git reset --hard HEAD^ &&
|
||||
git checkout change &&
|
||||
|
||||
test-tool chmtime =-1 M &&
|
||||
test-tool chmtime --get M >old-mtime &&
|
||||
GIT_MERGE_VERBOSITY=3 git merge change+rename >out &&
|
||||
test_i18ngrep ! "^Skipped B" out
|
||||
|
||||
test-tool chmtime --get B >new-mtime &&
|
||||
test $(cat old-mtime) -lt $(cat new-mtime)
|
||||
'
|
||||
|
||||
test_expect_success 'setup for rename + d/f conflicts' '
|
||||
@ -288,14 +299,15 @@ test_expect_success 'setup for rename + d/f conflicts' '
|
||||
git commit -m "Conflicting change"
|
||||
'
|
||||
|
||||
printf "1\n2\n3\n4\n5555\n6\n7\n8\n9\n10\n11\n" >expected
|
||||
|
||||
test_expect_success 'Rename+D/F conflict; renamed file merges + dir not in way' '
|
||||
git reset --hard &&
|
||||
git checkout -q renamed-file-has-no-conflicts^0 &&
|
||||
|
||||
git merge --strategy=recursive dir-not-in-way &&
|
||||
|
||||
git diff --quiet &&
|
||||
test -f dir &&
|
||||
test_path_is_file dir &&
|
||||
test_write_lines 1 2 3 4 5555 6 7 8 9 10 11 >expected &&
|
||||
test_cmp expected dir
|
||||
'
|
||||
|
||||
@ -315,8 +327,8 @@ test_expect_success 'Rename+D/F conflict; renamed file merges but dir in way' '
|
||||
test_must_fail git diff --quiet &&
|
||||
test_must_fail git diff --cached --quiet &&
|
||||
|
||||
test -f dir/file-in-the-way &&
|
||||
test -f dir~HEAD &&
|
||||
test_path_is_file dir/file-in-the-way &&
|
||||
test_path_is_file dir~HEAD &&
|
||||
test_cmp expected dir~HEAD
|
||||
'
|
||||
|
||||
@ -337,29 +349,11 @@ test_expect_success 'Same as previous, but merged other way' '
|
||||
test_must_fail git diff --quiet &&
|
||||
test_must_fail git diff --cached --quiet &&
|
||||
|
||||
test -f dir/file-in-the-way &&
|
||||
test -f dir~renamed-file-has-no-conflicts &&
|
||||
test_path_is_file dir/file-in-the-way &&
|
||||
test_path_is_file dir~renamed-file-has-no-conflicts &&
|
||||
test_cmp expected dir~renamed-file-has-no-conflicts
|
||||
'
|
||||
|
||||
cat >expected <<\EOF &&
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
<<<<<<< HEAD:dir
|
||||
12
|
||||
=======
|
||||
11
|
||||
>>>>>>> dir-not-in-way:sub/file
|
||||
EOF
|
||||
|
||||
test_expect_success 'Rename+D/F conflict; renamed file cannot merge, dir not in way' '
|
||||
git reset --hard &&
|
||||
rm -rf dir~* &&
|
||||
@ -372,7 +366,24 @@ test_expect_success 'Rename+D/F conflict; renamed file cannot merge, dir not in
|
||||
test_must_fail git diff --quiet &&
|
||||
test_must_fail git diff --cached --quiet &&
|
||||
|
||||
test -f dir &&
|
||||
test_path_is_file dir &&
|
||||
cat >expected <<-\EOF &&
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
<<<<<<< HEAD:dir
|
||||
12
|
||||
=======
|
||||
11
|
||||
>>>>>>> dir-not-in-way:sub/file
|
||||
EOF
|
||||
test_cmp expected dir
|
||||
'
|
||||
|
||||
@ -391,29 +402,11 @@ test_expect_success 'Rename+D/F conflict; renamed file cannot merge and dir in t
|
||||
test_must_fail git diff --quiet &&
|
||||
test_must_fail git diff --cached --quiet &&
|
||||
|
||||
test -f dir/file-in-the-way &&
|
||||
test -f dir~HEAD &&
|
||||
test_path_is_file dir/file-in-the-way &&
|
||||
test_path_is_file dir~HEAD &&
|
||||
test_cmp expected dir~HEAD
|
||||
'
|
||||
|
||||
cat >expected <<\EOF &&
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
<<<<<<< HEAD:sub/file
|
||||
11
|
||||
=======
|
||||
12
|
||||
>>>>>>> renamed-file-has-conflicts:dir
|
||||
EOF
|
||||
|
||||
test_expect_success 'Same as previous, but merged other way' '
|
||||
git reset --hard &&
|
||||
rm -rf dir~* &&
|
||||
@ -427,8 +420,25 @@ test_expect_success 'Same as previous, but merged other way' '
|
||||
test_must_fail git diff --quiet &&
|
||||
test_must_fail git diff --cached --quiet &&
|
||||
|
||||
test -f dir/file-in-the-way &&
|
||||
test -f dir~renamed-file-has-conflicts &&
|
||||
test_path_is_file dir/file-in-the-way &&
|
||||
test_path_is_file dir~renamed-file-has-conflicts &&
|
||||
cat >expected <<-\EOF &&
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
10
|
||||
<<<<<<< HEAD:sub/file
|
||||
11
|
||||
=======
|
||||
12
|
||||
>>>>>>> renamed-file-has-conflicts:dir
|
||||
EOF
|
||||
test_cmp expected dir~renamed-file-has-conflicts
|
||||
'
|
||||
|
||||
@ -464,9 +474,9 @@ test_expect_success 'both rename source and destination involved in D/F conflict
|
||||
|
||||
test_must_fail git diff --quiet &&
|
||||
|
||||
test -f destdir/foo &&
|
||||
test -f one &&
|
||||
test -f destdir~HEAD &&
|
||||
test_path_is_file destdir/foo &&
|
||||
test_path_is_file one &&
|
||||
test_path_is_file destdir~HEAD &&
|
||||
test "stuff" = "$(cat destdir~HEAD)"
|
||||
'
|
||||
|
||||
@ -507,9 +517,9 @@ test_expect_success 'pair rename to parent of other (D/F conflicts) w/ untracked
|
||||
|
||||
test 4 -eq $(find . | grep -v .git | wc -l) &&
|
||||
|
||||
test -d one &&
|
||||
test -f one~rename-two &&
|
||||
test -f two &&
|
||||
test_path_is_dir one &&
|
||||
test_path_is_file one~rename-two &&
|
||||
test_path_is_file two &&
|
||||
test "other" = $(cat one~rename-two) &&
|
||||
test "stuff" = $(cat two)
|
||||
'
|
||||
@ -527,8 +537,8 @@ test_expect_success 'pair rename to parent of other (D/F conflicts) w/ clean sta
|
||||
|
||||
test 3 -eq $(find . | grep -v .git | wc -l) &&
|
||||
|
||||
test -f one &&
|
||||
test -f two &&
|
||||
test_path_is_file one &&
|
||||
test_path_is_file two &&
|
||||
test "other" = $(cat one) &&
|
||||
test "stuff" = $(cat two)
|
||||
'
|
||||
@ -568,11 +578,11 @@ test_expect_success 'check handling of differently renamed file with D/F conflic
|
||||
test 1 -eq "$(git ls-files -u original | wc -l)" &&
|
||||
test 2 -eq "$(git ls-files -o | wc -l)" &&
|
||||
|
||||
test -f one/file &&
|
||||
test -f two/file &&
|
||||
test -f one~HEAD &&
|
||||
test -f two~second-rename &&
|
||||
! test -f original
|
||||
test_path_is_file one/file &&
|
||||
test_path_is_file two/file &&
|
||||
test_path_is_file one~HEAD &&
|
||||
test_path_is_file two~second-rename &&
|
||||
test_path_is_missing original
|
||||
'
|
||||
|
||||
test_expect_success 'setup rename one file to two; directories moving out of the way' '
|
||||
@ -607,9 +617,9 @@ test_expect_success 'check handling of differently renamed file with D/F conflic
|
||||
test 1 -eq "$(git ls-files -u original | wc -l)" &&
|
||||
test 0 -eq "$(git ls-files -o | wc -l)" &&
|
||||
|
||||
test -f one &&
|
||||
test -f two &&
|
||||
! test -f original
|
||||
test_path_is_file one &&
|
||||
test_path_is_file two &&
|
||||
test_path_is_missing original
|
||||
'
|
||||
|
||||
test_expect_success 'setup avoid unnecessary update, normal rename' '
|
||||
@ -810,48 +820,48 @@ test_expect_success 'setup for use of extended merge markers' '
|
||||
git commit -mC
|
||||
'
|
||||
|
||||
cat >expected <<\EOF &&
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
<<<<<<< HEAD:renamed_file
|
||||
9
|
||||
=======
|
||||
8.5
|
||||
>>>>>>> master^0:original_file
|
||||
EOF
|
||||
|
||||
test_expect_success 'merge master into rename has correct extended markers' '
|
||||
git checkout rename^0 &&
|
||||
test_must_fail git merge -s recursive master^0 &&
|
||||
|
||||
cat >expected <<-\EOF &&
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
<<<<<<< HEAD:renamed_file
|
||||
9
|
||||
=======
|
||||
8.5
|
||||
>>>>>>> master^0:original_file
|
||||
EOF
|
||||
test_cmp expected renamed_file
|
||||
'
|
||||
|
||||
cat >expected <<\EOF &&
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
<<<<<<< HEAD:original_file
|
||||
8.5
|
||||
=======
|
||||
9
|
||||
>>>>>>> rename^0:renamed_file
|
||||
EOF
|
||||
|
||||
test_expect_success 'merge rename into master has correct extended markers' '
|
||||
git reset --hard &&
|
||||
git checkout master^0 &&
|
||||
test_must_fail git merge -s recursive rename^0 &&
|
||||
|
||||
cat >expected <<-\EOF &&
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
<<<<<<< HEAD:original_file
|
||||
8.5
|
||||
=======
|
||||
9
|
||||
>>>>>>> rename^0:renamed_file
|
||||
EOF
|
||||
test_cmp expected renamed_file
|
||||
'
|
||||
|
||||
|
@ -3,56 +3,59 @@
|
||||
test_description='RCS merge replacement: merge-file'
|
||||
. ./test-lib.sh
|
||||
|
||||
cat > orig.txt << EOF
|
||||
Dominus regit me,
|
||||
et nihil mihi deerit.
|
||||
In loco pascuae ibi me collocavit,
|
||||
super aquam refectionis educavit me;
|
||||
animam meam convertit,
|
||||
deduxit me super semitas jusitiae,
|
||||
propter nomen suum.
|
||||
EOF
|
||||
test_expect_success 'setup' '
|
||||
cat >orig.txt <<-\EOF &&
|
||||
Dominus regit me,
|
||||
et nihil mihi deerit.
|
||||
In loco pascuae ibi me collocavit,
|
||||
super aquam refectionis educavit me;
|
||||
animam meam convertit,
|
||||
deduxit me super semitas jusitiae,
|
||||
propter nomen suum.
|
||||
EOF
|
||||
|
||||
cat > new1.txt << EOF
|
||||
Dominus regit me,
|
||||
et nihil mihi deerit.
|
||||
In loco pascuae ibi me collocavit,
|
||||
super aquam refectionis educavit me;
|
||||
animam meam convertit,
|
||||
deduxit me super semitas jusitiae,
|
||||
propter nomen suum.
|
||||
Nam et si ambulavero in medio umbrae mortis,
|
||||
non timebo mala, quoniam tu mecum es:
|
||||
virga tua et baculus tuus ipsa me consolata sunt.
|
||||
EOF
|
||||
cat >new1.txt <<-\EOF &&
|
||||
Dominus regit me,
|
||||
et nihil mihi deerit.
|
||||
In loco pascuae ibi me collocavit,
|
||||
super aquam refectionis educavit me;
|
||||
animam meam convertit,
|
||||
deduxit me super semitas jusitiae,
|
||||
propter nomen suum.
|
||||
Nam et si ambulavero in medio umbrae mortis,
|
||||
non timebo mala, quoniam tu mecum es:
|
||||
virga tua et baculus tuus ipsa me consolata sunt.
|
||||
EOF
|
||||
|
||||
cat > new2.txt << EOF
|
||||
Dominus regit me, et nihil mihi deerit.
|
||||
In loco pascuae ibi me collocavit,
|
||||
super aquam refectionis educavit me;
|
||||
animam meam convertit,
|
||||
deduxit me super semitas jusitiae,
|
||||
propter nomen suum.
|
||||
EOF
|
||||
cat >new2.txt <<-\EOF &&
|
||||
Dominus regit me, et nihil mihi deerit.
|
||||
In loco pascuae ibi me collocavit,
|
||||
super aquam refectionis educavit me;
|
||||
animam meam convertit,
|
||||
deduxit me super semitas jusitiae,
|
||||
propter nomen suum.
|
||||
EOF
|
||||
|
||||
cat > new3.txt << EOF
|
||||
DOMINUS regit me,
|
||||
et nihil mihi deerit.
|
||||
In loco pascuae ibi me collocavit,
|
||||
super aquam refectionis educavit me;
|
||||
animam meam convertit,
|
||||
deduxit me super semitas jusitiae,
|
||||
propter nomen suum.
|
||||
EOF
|
||||
cat >new3.txt <<-\EOF &&
|
||||
DOMINUS regit me,
|
||||
et nihil mihi deerit.
|
||||
In loco pascuae ibi me collocavit,
|
||||
super aquam refectionis educavit me;
|
||||
animam meam convertit,
|
||||
deduxit me super semitas jusitiae,
|
||||
propter nomen suum.
|
||||
EOF
|
||||
|
||||
cat > new4.txt << EOF
|
||||
Dominus regit me, et nihil mihi deerit.
|
||||
In loco pascuae ibi me collocavit,
|
||||
super aquam refectionis educavit me;
|
||||
animam meam convertit,
|
||||
deduxit me super semitas jusitiae,
|
||||
EOF
|
||||
printf "propter nomen suum." >> new4.txt
|
||||
cat >new4.txt <<-\EOF &&
|
||||
Dominus regit me, et nihil mihi deerit.
|
||||
In loco pascuae ibi me collocavit,
|
||||
super aquam refectionis educavit me;
|
||||
animam meam convertit,
|
||||
deduxit me super semitas jusitiae,
|
||||
EOF
|
||||
|
||||
printf "propter nomen suum." >>new4.txt
|
||||
'
|
||||
|
||||
test_expect_success 'merge with no changes' '
|
||||
cp orig.txt test.txt &&
|
||||
@ -60,9 +63,10 @@ test_expect_success 'merge with no changes' '
|
||||
test_cmp test.txt orig.txt
|
||||
'
|
||||
|
||||
cp new1.txt test.txt
|
||||
test_expect_success "merge without conflict" \
|
||||
"git merge-file test.txt orig.txt new2.txt"
|
||||
test_expect_success "merge without conflict" '
|
||||
cp new1.txt test.txt &&
|
||||
git merge-file test.txt orig.txt new2.txt
|
||||
'
|
||||
|
||||
test_expect_success 'works in subdirectory' '
|
||||
mkdir dir &&
|
||||
@ -73,151 +77,176 @@ test_expect_success 'works in subdirectory' '
|
||||
test_path_is_missing a.txt
|
||||
'
|
||||
|
||||
cp new1.txt test.txt
|
||||
test_expect_success "merge without conflict (--quiet)" \
|
||||
"git merge-file --quiet test.txt orig.txt new2.txt"
|
||||
test_expect_success "merge without conflict (--quiet)" '
|
||||
cp new1.txt test.txt &&
|
||||
git merge-file --quiet test.txt orig.txt new2.txt
|
||||
'
|
||||
|
||||
cp new1.txt test2.txt
|
||||
test_expect_failure "merge without conflict (missing LF at EOF)" \
|
||||
"git merge-file test2.txt orig.txt new4.txt"
|
||||
test_expect_failure "merge without conflict (missing LF at EOF)" '
|
||||
cp new1.txt test2.txt &&
|
||||
git merge-file test2.txt orig.txt new4.txt
|
||||
'
|
||||
|
||||
test_expect_failure "merge result added missing LF" \
|
||||
"test_cmp test.txt test2.txt"
|
||||
test_expect_failure "merge result added missing LF" '
|
||||
test_cmp test.txt test2.txt
|
||||
'
|
||||
|
||||
cp new4.txt test3.txt
|
||||
test_expect_success "merge without conflict (missing LF at EOF, away from change in the other file)" \
|
||||
"git merge-file --quiet test3.txt new2.txt new3.txt"
|
||||
test_expect_success "merge without conflict (missing LF at EOF, away from change in the other file)" '
|
||||
cp new4.txt test3.txt &&
|
||||
git merge-file --quiet test3.txt new2.txt new3.txt
|
||||
'
|
||||
|
||||
cat > expect.txt << EOF
|
||||
DOMINUS regit me,
|
||||
et nihil mihi deerit.
|
||||
In loco pascuae ibi me collocavit,
|
||||
super aquam refectionis educavit me;
|
||||
animam meam convertit,
|
||||
deduxit me super semitas jusitiae,
|
||||
EOF
|
||||
printf "propter nomen suum." >> expect.txt
|
||||
test_expect_success "merge does not add LF away of change" '
|
||||
cat >expect.txt <<-\EOF &&
|
||||
DOMINUS regit me,
|
||||
et nihil mihi deerit.
|
||||
In loco pascuae ibi me collocavit,
|
||||
super aquam refectionis educavit me;
|
||||
animam meam convertit,
|
||||
deduxit me super semitas jusitiae,
|
||||
EOF
|
||||
printf "propter nomen suum." >>expect.txt &&
|
||||
|
||||
test_expect_success "merge does not add LF away of change" \
|
||||
"test_cmp expect.txt test3.txt"
|
||||
test_cmp expect.txt test3.txt
|
||||
'
|
||||
|
||||
cp test.txt backup.txt
|
||||
test_expect_success "merge with conflicts" \
|
||||
"test_must_fail git merge-file test.txt orig.txt new3.txt"
|
||||
test_expect_success "merge with conflicts" '
|
||||
cp test.txt backup.txt &&
|
||||
test_must_fail git merge-file test.txt orig.txt new3.txt
|
||||
'
|
||||
|
||||
cat > expect.txt << EOF
|
||||
<<<<<<< test.txt
|
||||
Dominus regit me, et nihil mihi deerit.
|
||||
=======
|
||||
DOMINUS regit me,
|
||||
et nihil mihi deerit.
|
||||
>>>>>>> new3.txt
|
||||
In loco pascuae ibi me collocavit,
|
||||
super aquam refectionis educavit me;
|
||||
animam meam convertit,
|
||||
deduxit me super semitas jusitiae,
|
||||
propter nomen suum.
|
||||
Nam et si ambulavero in medio umbrae mortis,
|
||||
non timebo mala, quoniam tu mecum es:
|
||||
virga tua et baculus tuus ipsa me consolata sunt.
|
||||
EOF
|
||||
test_expect_success "expected conflict markers" '
|
||||
cat >expect.txt <<-\EOF &&
|
||||
<<<<<<< test.txt
|
||||
Dominus regit me, et nihil mihi deerit.
|
||||
=======
|
||||
DOMINUS regit me,
|
||||
et nihil mihi deerit.
|
||||
>>>>>>> new3.txt
|
||||
In loco pascuae ibi me collocavit,
|
||||
super aquam refectionis educavit me;
|
||||
animam meam convertit,
|
||||
deduxit me super semitas jusitiae,
|
||||
propter nomen suum.
|
||||
Nam et si ambulavero in medio umbrae mortis,
|
||||
non timebo mala, quoniam tu mecum es:
|
||||
virga tua et baculus tuus ipsa me consolata sunt.
|
||||
EOF
|
||||
|
||||
test_expect_success "expected conflict markers" "test_cmp expect.txt test.txt"
|
||||
test_cmp expect.txt test.txt
|
||||
'
|
||||
|
||||
cp backup.txt test.txt
|
||||
test_expect_success "merge conflicting with --ours" '
|
||||
cp backup.txt test.txt &&
|
||||
|
||||
cat > expect.txt << EOF
|
||||
Dominus regit me, et nihil mihi deerit.
|
||||
In loco pascuae ibi me collocavit,
|
||||
super aquam refectionis educavit me;
|
||||
animam meam convertit,
|
||||
deduxit me super semitas jusitiae,
|
||||
propter nomen suum.
|
||||
Nam et si ambulavero in medio umbrae mortis,
|
||||
non timebo mala, quoniam tu mecum es:
|
||||
virga tua et baculus tuus ipsa me consolata sunt.
|
||||
EOF
|
||||
test_expect_success "merge conflicting with --ours" \
|
||||
"git merge-file --ours test.txt orig.txt new3.txt && test_cmp expect.txt test.txt"
|
||||
cp backup.txt test.txt
|
||||
cat >expect.txt <<-\EOF &&
|
||||
Dominus regit me, et nihil mihi deerit.
|
||||
In loco pascuae ibi me collocavit,
|
||||
super aquam refectionis educavit me;
|
||||
animam meam convertit,
|
||||
deduxit me super semitas jusitiae,
|
||||
propter nomen suum.
|
||||
Nam et si ambulavero in medio umbrae mortis,
|
||||
non timebo mala, quoniam tu mecum es:
|
||||
virga tua et baculus tuus ipsa me consolata sunt.
|
||||
EOF
|
||||
|
||||
cat > expect.txt << EOF
|
||||
DOMINUS regit me,
|
||||
et nihil mihi deerit.
|
||||
In loco pascuae ibi me collocavit,
|
||||
super aquam refectionis educavit me;
|
||||
animam meam convertit,
|
||||
deduxit me super semitas jusitiae,
|
||||
propter nomen suum.
|
||||
Nam et si ambulavero in medio umbrae mortis,
|
||||
non timebo mala, quoniam tu mecum es:
|
||||
virga tua et baculus tuus ipsa me consolata sunt.
|
||||
EOF
|
||||
test_expect_success "merge conflicting with --theirs" \
|
||||
"git merge-file --theirs test.txt orig.txt new3.txt && test_cmp expect.txt test.txt"
|
||||
cp backup.txt test.txt
|
||||
git merge-file --ours test.txt orig.txt new3.txt &&
|
||||
test_cmp expect.txt test.txt
|
||||
'
|
||||
|
||||
cat > expect.txt << EOF
|
||||
Dominus regit me, et nihil mihi deerit.
|
||||
DOMINUS regit me,
|
||||
et nihil mihi deerit.
|
||||
In loco pascuae ibi me collocavit,
|
||||
super aquam refectionis educavit me;
|
||||
animam meam convertit,
|
||||
deduxit me super semitas jusitiae,
|
||||
propter nomen suum.
|
||||
Nam et si ambulavero in medio umbrae mortis,
|
||||
non timebo mala, quoniam tu mecum es:
|
||||
virga tua et baculus tuus ipsa me consolata sunt.
|
||||
EOF
|
||||
test_expect_success "merge conflicting with --union" \
|
||||
"git merge-file --union test.txt orig.txt new3.txt && test_cmp expect.txt test.txt"
|
||||
cp backup.txt test.txt
|
||||
test_expect_success "merge conflicting with --theirs" '
|
||||
cp backup.txt test.txt &&
|
||||
|
||||
test_expect_success "merge with conflicts, using -L" \
|
||||
"test_must_fail git merge-file -L 1 -L 2 test.txt orig.txt new3.txt"
|
||||
cat >expect.txt <<-\EOF &&
|
||||
DOMINUS regit me,
|
||||
et nihil mihi deerit.
|
||||
In loco pascuae ibi me collocavit,
|
||||
super aquam refectionis educavit me;
|
||||
animam meam convertit,
|
||||
deduxit me super semitas jusitiae,
|
||||
propter nomen suum.
|
||||
Nam et si ambulavero in medio umbrae mortis,
|
||||
non timebo mala, quoniam tu mecum es:
|
||||
virga tua et baculus tuus ipsa me consolata sunt.
|
||||
EOF
|
||||
|
||||
cat > expect.txt << EOF
|
||||
<<<<<<< 1
|
||||
Dominus regit me, et nihil mihi deerit.
|
||||
=======
|
||||
DOMINUS regit me,
|
||||
et nihil mihi deerit.
|
||||
>>>>>>> new3.txt
|
||||
In loco pascuae ibi me collocavit,
|
||||
super aquam refectionis educavit me;
|
||||
animam meam convertit,
|
||||
deduxit me super semitas jusitiae,
|
||||
propter nomen suum.
|
||||
Nam et si ambulavero in medio umbrae mortis,
|
||||
non timebo mala, quoniam tu mecum es:
|
||||
virga tua et baculus tuus ipsa me consolata sunt.
|
||||
EOF
|
||||
git merge-file --theirs test.txt orig.txt new3.txt &&
|
||||
test_cmp expect.txt test.txt
|
||||
'
|
||||
|
||||
test_expect_success "expected conflict markers, with -L" \
|
||||
"test_cmp expect.txt test.txt"
|
||||
test_expect_success "merge conflicting with --union" '
|
||||
cp backup.txt test.txt &&
|
||||
|
||||
sed "s/ tu / TU /" < new1.txt > new5.txt
|
||||
test_expect_success "conflict in removed tail" \
|
||||
"test_must_fail git merge-file -p orig.txt new1.txt new5.txt > out"
|
||||
cat >expect.txt <<-\EOF &&
|
||||
Dominus regit me, et nihil mihi deerit.
|
||||
DOMINUS regit me,
|
||||
et nihil mihi deerit.
|
||||
In loco pascuae ibi me collocavit,
|
||||
super aquam refectionis educavit me;
|
||||
animam meam convertit,
|
||||
deduxit me super semitas jusitiae,
|
||||
propter nomen suum.
|
||||
Nam et si ambulavero in medio umbrae mortis,
|
||||
non timebo mala, quoniam tu mecum es:
|
||||
virga tua et baculus tuus ipsa me consolata sunt.
|
||||
EOF
|
||||
|
||||
cat > expect << EOF
|
||||
Dominus regit me,
|
||||
et nihil mihi deerit.
|
||||
In loco pascuae ibi me collocavit,
|
||||
super aquam refectionis educavit me;
|
||||
animam meam convertit,
|
||||
deduxit me super semitas jusitiae,
|
||||
propter nomen suum.
|
||||
<<<<<<< orig.txt
|
||||
=======
|
||||
Nam et si ambulavero in medio umbrae mortis,
|
||||
non timebo mala, quoniam TU mecum es:
|
||||
virga tua et baculus tuus ipsa me consolata sunt.
|
||||
>>>>>>> new5.txt
|
||||
EOF
|
||||
git merge-file --union test.txt orig.txt new3.txt &&
|
||||
test_cmp expect.txt test.txt
|
||||
'
|
||||
|
||||
test_expect_success "expected conflict markers" "test_cmp expect out"
|
||||
test_expect_success "merge with conflicts, using -L" '
|
||||
cp backup.txt test.txt &&
|
||||
|
||||
test_must_fail git merge-file -L 1 -L 2 test.txt orig.txt new3.txt
|
||||
'
|
||||
|
||||
test_expect_success "expected conflict markers, with -L" '
|
||||
cat >expect.txt <<-\EOF &&
|
||||
<<<<<<< 1
|
||||
Dominus regit me, et nihil mihi deerit.
|
||||
=======
|
||||
DOMINUS regit me,
|
||||
et nihil mihi deerit.
|
||||
>>>>>>> new3.txt
|
||||
In loco pascuae ibi me collocavit,
|
||||
super aquam refectionis educavit me;
|
||||
animam meam convertit,
|
||||
deduxit me super semitas jusitiae,
|
||||
propter nomen suum.
|
||||
Nam et si ambulavero in medio umbrae mortis,
|
||||
non timebo mala, quoniam tu mecum es:
|
||||
virga tua et baculus tuus ipsa me consolata sunt.
|
||||
EOF
|
||||
|
||||
test_cmp expect.txt test.txt
|
||||
'
|
||||
|
||||
test_expect_success "conflict in removed tail" '
|
||||
sed "s/ tu / TU /" <new1.txt >new5.txt &&
|
||||
test_must_fail git merge-file -p orig.txt new1.txt new5.txt >out
|
||||
'
|
||||
|
||||
test_expect_success "expected conflict markers" '
|
||||
cat >expect <<-\EOF &&
|
||||
Dominus regit me,
|
||||
et nihil mihi deerit.
|
||||
In loco pascuae ibi me collocavit,
|
||||
super aquam refectionis educavit me;
|
||||
animam meam convertit,
|
||||
deduxit me super semitas jusitiae,
|
||||
propter nomen suum.
|
||||
<<<<<<< orig.txt
|
||||
=======
|
||||
Nam et si ambulavero in medio umbrae mortis,
|
||||
non timebo mala, quoniam TU mecum es:
|
||||
virga tua et baculus tuus ipsa me consolata sunt.
|
||||
>>>>>>> new5.txt
|
||||
EOF
|
||||
|
||||
test_cmp expect out
|
||||
'
|
||||
|
||||
test_expect_success 'binary files cannot be merged' '
|
||||
test_must_fail git merge-file -p \
|
||||
@ -225,59 +254,55 @@ test_expect_success 'binary files cannot be merged' '
|
||||
grep "Cannot merge binary files" merge.err
|
||||
'
|
||||
|
||||
sed -e "s/deerit.\$/deerit;/" -e "s/me;\$/me./" < new5.txt > new6.txt
|
||||
sed -e "s/deerit.\$/deerit,/" -e "s/me;\$/me,/" < new5.txt > new7.txt
|
||||
|
||||
test_expect_success 'MERGE_ZEALOUS simplifies non-conflicts' '
|
||||
sed -e "s/deerit.\$/deerit;/" -e "s/me;\$/me./" <new5.txt >new6.txt &&
|
||||
sed -e "s/deerit.\$/deerit,/" -e "s/me;\$/me,/" <new5.txt >new7.txt &&
|
||||
|
||||
test_must_fail git merge-file -p new6.txt new5.txt new7.txt > output &&
|
||||
test 1 = $(grep ======= < output | wc -l)
|
||||
|
||||
test 1 = $(grep ======= <output | wc -l)
|
||||
'
|
||||
|
||||
sed -e 's/deerit./&%%%%/' -e "s/locavit,/locavit;/"< new6.txt | tr '%' '\012' > new8.txt
|
||||
sed -e 's/deerit./&%%%%/' -e "s/locavit,/locavit --/" < new7.txt | tr '%' '\012' > new9.txt
|
||||
|
||||
test_expect_success 'ZEALOUS_ALNUM' '
|
||||
sed -e "s/deerit./&%%%%/" -e "s/locavit,/locavit;/" <new6.txt | tr % "\012" >new8.txt &&
|
||||
sed -e "s/deerit./&%%%%/" -e "s/locavit,/locavit --/" <new7.txt | tr % "\012" >new9.txt &&
|
||||
|
||||
test_must_fail git merge-file -p \
|
||||
new8.txt new5.txt new9.txt > merge.out &&
|
||||
test 1 = $(grep ======= < merge.out | wc -l)
|
||||
|
||||
new8.txt new5.txt new9.txt >merge.out &&
|
||||
test 1 = $(grep ======= <merge.out | wc -l)
|
||||
'
|
||||
|
||||
cat >expect <<\EOF
|
||||
Dominus regit me,
|
||||
<<<<<<< new8.txt
|
||||
et nihil mihi deerit;
|
||||
|
||||
|
||||
|
||||
|
||||
In loco pascuae ibi me collocavit;
|
||||
super aquam refectionis educavit me.
|
||||
||||||| new5.txt
|
||||
et nihil mihi deerit.
|
||||
In loco pascuae ibi me collocavit,
|
||||
super aquam refectionis educavit me;
|
||||
=======
|
||||
et nihil mihi deerit,
|
||||
|
||||
|
||||
|
||||
|
||||
In loco pascuae ibi me collocavit --
|
||||
super aquam refectionis educavit me,
|
||||
>>>>>>> new9.txt
|
||||
animam meam convertit,
|
||||
deduxit me super semitas jusitiae,
|
||||
propter nomen suum.
|
||||
Nam et si ambulavero in medio umbrae mortis,
|
||||
non timebo mala, quoniam TU mecum es:
|
||||
virga tua et baculus tuus ipsa me consolata sunt.
|
||||
EOF
|
||||
|
||||
test_expect_success '"diff3 -m" style output (1)' '
|
||||
cat >expect <<-\EOF &&
|
||||
Dominus regit me,
|
||||
<<<<<<< new8.txt
|
||||
et nihil mihi deerit;
|
||||
|
||||
|
||||
|
||||
|
||||
In loco pascuae ibi me collocavit;
|
||||
super aquam refectionis educavit me.
|
||||
||||||| new5.txt
|
||||
et nihil mihi deerit.
|
||||
In loco pascuae ibi me collocavit,
|
||||
super aquam refectionis educavit me;
|
||||
=======
|
||||
et nihil mihi deerit,
|
||||
|
||||
|
||||
|
||||
|
||||
In loco pascuae ibi me collocavit --
|
||||
super aquam refectionis educavit me,
|
||||
>>>>>>> new9.txt
|
||||
animam meam convertit,
|
||||
deduxit me super semitas jusitiae,
|
||||
propter nomen suum.
|
||||
Nam et si ambulavero in medio umbrae mortis,
|
||||
non timebo mala, quoniam TU mecum es:
|
||||
virga tua et baculus tuus ipsa me consolata sunt.
|
||||
EOF
|
||||
|
||||
test_must_fail git merge-file -p --diff3 \
|
||||
new8.txt new5.txt new9.txt >actual &&
|
||||
test_cmp expect actual
|
||||
@ -290,61 +315,64 @@ test_expect_success '"diff3 -m" style output (2)' '
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
cat >expect <<\EOF
|
||||
Dominus regit me,
|
||||
<<<<<<<<<< new8.txt
|
||||
et nihil mihi deerit;
|
||||
|
||||
|
||||
|
||||
|
||||
In loco pascuae ibi me collocavit;
|
||||
super aquam refectionis educavit me.
|
||||
|||||||||| new5.txt
|
||||
et nihil mihi deerit.
|
||||
In loco pascuae ibi me collocavit,
|
||||
super aquam refectionis educavit me;
|
||||
==========
|
||||
et nihil mihi deerit,
|
||||
|
||||
|
||||
|
||||
|
||||
In loco pascuae ibi me collocavit --
|
||||
super aquam refectionis educavit me,
|
||||
>>>>>>>>>> new9.txt
|
||||
animam meam convertit,
|
||||
deduxit me super semitas jusitiae,
|
||||
propter nomen suum.
|
||||
Nam et si ambulavero in medio umbrae mortis,
|
||||
non timebo mala, quoniam TU mecum es:
|
||||
virga tua et baculus tuus ipsa me consolata sunt.
|
||||
EOF
|
||||
|
||||
test_expect_success 'marker size' '
|
||||
cat >expect <<-\EOF &&
|
||||
Dominus regit me,
|
||||
<<<<<<<<<< new8.txt
|
||||
et nihil mihi deerit;
|
||||
|
||||
|
||||
|
||||
|
||||
In loco pascuae ibi me collocavit;
|
||||
super aquam refectionis educavit me.
|
||||
|||||||||| new5.txt
|
||||
et nihil mihi deerit.
|
||||
In loco pascuae ibi me collocavit,
|
||||
super aquam refectionis educavit me;
|
||||
==========
|
||||
et nihil mihi deerit,
|
||||
|
||||
|
||||
|
||||
|
||||
In loco pascuae ibi me collocavit --
|
||||
super aquam refectionis educavit me,
|
||||
>>>>>>>>>> new9.txt
|
||||
animam meam convertit,
|
||||
deduxit me super semitas jusitiae,
|
||||
propter nomen suum.
|
||||
Nam et si ambulavero in medio umbrae mortis,
|
||||
non timebo mala, quoniam TU mecum es:
|
||||
virga tua et baculus tuus ipsa me consolata sunt.
|
||||
EOF
|
||||
|
||||
test_must_fail git merge-file -p --marker-size=10 \
|
||||
new8.txt new5.txt new9.txt >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
printf "line1\nline2\nline3" >nolf-orig.txt
|
||||
printf "line1\nline2\nline3x" >nolf-diff1.txt
|
||||
printf "line1\nline2\nline3y" >nolf-diff2.txt
|
||||
test_expect_success 'conflict at EOF without LF resolved by --ours' '
|
||||
printf "line1\nline2\nline3" >nolf-orig.txt &&
|
||||
printf "line1\nline2\nline3x" >nolf-diff1.txt &&
|
||||
printf "line1\nline2\nline3y" >nolf-diff2.txt &&
|
||||
|
||||
test_expect_success 'conflict at EOF without LF resolved by --ours' \
|
||||
'git merge-file -p --ours nolf-diff1.txt nolf-orig.txt nolf-diff2.txt >output.txt &&
|
||||
printf "line1\nline2\nline3x" >expect.txt &&
|
||||
test_cmp expect.txt output.txt'
|
||||
git merge-file -p --ours nolf-diff1.txt nolf-orig.txt nolf-diff2.txt >output.txt &&
|
||||
printf "line1\nline2\nline3x" >expect.txt &&
|
||||
test_cmp expect.txt output.txt
|
||||
'
|
||||
|
||||
test_expect_success 'conflict at EOF without LF resolved by --theirs' \
|
||||
'git merge-file -p --theirs nolf-diff1.txt nolf-orig.txt nolf-diff2.txt >output.txt &&
|
||||
printf "line1\nline2\nline3y" >expect.txt &&
|
||||
test_cmp expect.txt output.txt'
|
||||
test_expect_success 'conflict at EOF without LF resolved by --theirs' '
|
||||
git merge-file -p --theirs nolf-diff1.txt nolf-orig.txt nolf-diff2.txt >output.txt &&
|
||||
printf "line1\nline2\nline3y" >expect.txt &&
|
||||
test_cmp expect.txt output.txt
|
||||
'
|
||||
|
||||
test_expect_success 'conflict at EOF without LF resolved by --union' \
|
||||
'git merge-file -p --union nolf-diff1.txt nolf-orig.txt nolf-diff2.txt >output.txt &&
|
||||
printf "line1\nline2\nline3x\nline3y" >expect.txt &&
|
||||
test_cmp expect.txt output.txt'
|
||||
test_expect_success 'conflict at EOF without LF resolved by --union' '
|
||||
git merge-file -p --union nolf-diff1.txt nolf-orig.txt nolf-diff2.txt >output.txt &&
|
||||
printf "line1\nline2\nline3x\nline3y" >expect.txt &&
|
||||
test_cmp expect.txt output.txt
|
||||
'
|
||||
|
||||
test_expect_success 'conflict sections match existing line endings' '
|
||||
printf "1\\r\\n2\\r\\n3" >crlf-orig.txt &&
|
||||
|
@ -32,7 +32,29 @@ test_expect_success setup '
|
||||
test_tick &&
|
||||
git commit -m Side &&
|
||||
|
||||
git tag anchor
|
||||
git tag anchor &&
|
||||
|
||||
cat >./custom-merge <<-\EOF &&
|
||||
#!/bin/sh
|
||||
|
||||
orig="$1" ours="$2" theirs="$3" exit="$4" path=$5
|
||||
(
|
||||
echo "orig is $orig"
|
||||
echo "ours is $ours"
|
||||
echo "theirs is $theirs"
|
||||
echo "path is $path"
|
||||
echo "=== orig ==="
|
||||
cat "$orig"
|
||||
echo "=== ours ==="
|
||||
cat "$ours"
|
||||
echo "=== theirs ==="
|
||||
cat "$theirs"
|
||||
) >"$ours+"
|
||||
cat "$ours+" >"$ours"
|
||||
rm -f "$ours+"
|
||||
exit "$exit"
|
||||
EOF
|
||||
chmod +x ./custom-merge
|
||||
'
|
||||
|
||||
test_expect_success merge '
|
||||
@ -82,28 +104,6 @@ test_expect_success 'retry the merge with longer context' '
|
||||
grep "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" actual
|
||||
'
|
||||
|
||||
cat >./custom-merge <<\EOF
|
||||
#!/bin/sh
|
||||
|
||||
orig="$1" ours="$2" theirs="$3" exit="$4" path=$5
|
||||
(
|
||||
echo "orig is $orig"
|
||||
echo "ours is $ours"
|
||||
echo "theirs is $theirs"
|
||||
echo "path is $path"
|
||||
echo "=== orig ==="
|
||||
cat "$orig"
|
||||
echo "=== ours ==="
|
||||
cat "$ours"
|
||||
echo "=== theirs ==="
|
||||
cat "$theirs"
|
||||
) >"$ours+"
|
||||
cat "$ours+" >"$ours"
|
||||
rm -f "$ours+"
|
||||
exit "$exit"
|
||||
EOF
|
||||
chmod +x ./custom-merge
|
||||
|
||||
test_expect_success 'custom merge backend' '
|
||||
|
||||
echo "* merge=union" >.gitattributes &&
|
||||
|
@ -3,74 +3,73 @@
|
||||
test_description='Merge-recursive merging renames'
|
||||
. ./test-lib.sh
|
||||
|
||||
test_expect_success setup \
|
||||
test_expect_success 'setup' '
|
||||
cat >A <<-\EOF &&
|
||||
a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
b bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||
c cccccccccccccccccccccccccccccccccccccccccccccccc
|
||||
d dddddddddddddddddddddddddddddddddddddddddddddddd
|
||||
e eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
|
||||
f ffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
g gggggggggggggggggggggggggggggggggggggggggggggggg
|
||||
h hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
|
||||
i iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
|
||||
j jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj
|
||||
k kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
|
||||
l llllllllllllllllllllllllllllllllllllllllllllllll
|
||||
m mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
|
||||
n nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
|
||||
o oooooooooooooooooooooooooooooooooooooooooooooooo
|
||||
EOF
|
||||
|
||||
cat >M <<-\EOF &&
|
||||
A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
B BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
|
||||
C CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
||||
D DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
|
||||
E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
|
||||
F FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
|
||||
G GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
|
||||
H HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
|
||||
I IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
|
||||
J JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ
|
||||
K KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
|
||||
L LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL
|
||||
M MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
N NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
|
||||
O OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
|
||||
EOF
|
||||
|
||||
git add A M &&
|
||||
git commit -m "initial has A and M" &&
|
||||
git branch white &&
|
||||
git branch red &&
|
||||
git branch blue &&
|
||||
|
||||
git checkout white &&
|
||||
sed -e "/^g /s/.*/g : white changes a line/" <A >B &&
|
||||
sed -e "/^G /s/.*/G : colored branch changes a line/" <M >N &&
|
||||
rm -f A M &&
|
||||
git update-index --add --remove A B M N &&
|
||||
git commit -m "white renames A->B, M->N" &&
|
||||
|
||||
git checkout red &&
|
||||
echo created by red >R &&
|
||||
git update-index --add R &&
|
||||
git commit -m "red creates R" &&
|
||||
|
||||
git checkout blue &&
|
||||
sed -e "/^o /s/.*/g : blue changes a line/" <A >B &&
|
||||
rm -f A &&
|
||||
mv B A &&
|
||||
git update-index A &&
|
||||
git commit -m "blue modify A" &&
|
||||
|
||||
git checkout master
|
||||
'
|
||||
cat >A <<\EOF &&
|
||||
a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
b bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
|
||||
c cccccccccccccccccccccccccccccccccccccccccccccccc
|
||||
d dddddddddddddddddddddddddddddddddddddddddddddddd
|
||||
e eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
|
||||
f ffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
g gggggggggggggggggggggggggggggggggggggggggggggggg
|
||||
h hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
|
||||
i iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
|
||||
j jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj
|
||||
k kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
|
||||
l llllllllllllllllllllllllllllllllllllllllllllllll
|
||||
m mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
|
||||
n nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
|
||||
o oooooooooooooooooooooooooooooooooooooooooooooooo
|
||||
EOF
|
||||
|
||||
cat >M <<\EOF &&
|
||||
A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
B BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
|
||||
C CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
|
||||
D DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
|
||||
E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
|
||||
F FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
|
||||
G GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
|
||||
H HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
|
||||
I IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
|
||||
J JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ
|
||||
K KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
|
||||
L LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL
|
||||
M MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
|
||||
N NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
|
||||
O OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
|
||||
EOF
|
||||
|
||||
git add A M &&
|
||||
git commit -m "initial has A and M" &&
|
||||
git branch white &&
|
||||
git branch red &&
|
||||
git branch blue &&
|
||||
|
||||
git checkout white &&
|
||||
sed -e "/^g /s/.*/g : white changes a line/" <A >B &&
|
||||
sed -e "/^G /s/.*/G : colored branch changes a line/" <M >N &&
|
||||
rm -f A M &&
|
||||
git update-index --add --remove A B M N &&
|
||||
git commit -m "white renames A->B, M->N" &&
|
||||
|
||||
git checkout red &&
|
||||
echo created by red >R &&
|
||||
git update-index --add R &&
|
||||
git commit -m "red creates R" &&
|
||||
|
||||
git checkout blue &&
|
||||
sed -e "/^o /s/.*/g : blue changes a line/" <A >B &&
|
||||
rm -f A &&
|
||||
mv B A &&
|
||||
git update-index A &&
|
||||
git commit -m "blue modify A" &&
|
||||
|
||||
git checkout master'
|
||||
|
||||
# This test broke in 65ac6e9c3f47807cb603af07a6a9e1a43bc119ae
|
||||
test_expect_success 'merge white into red (A->B,M->N)' \
|
||||
'
|
||||
test_expect_success 'merge white into red (A->B,M->N)' '
|
||||
git checkout -b red-white red &&
|
||||
git merge white &&
|
||||
git write-tree &&
|
||||
@ -82,8 +81,7 @@ test_expect_success 'merge white into red (A->B,M->N)' \
|
||||
'
|
||||
|
||||
# This test broke in 8371234ecaaf6e14fe3f2082a855eff1bbd79ae9
|
||||
test_expect_success 'merge blue into white (A->B, mod A, A untracked)' \
|
||||
'
|
||||
test_expect_success 'merge blue into white (A->B, mod A, A untracked)' '
|
||||
git checkout -b white-blue white &&
|
||||
echo dirty >A &&
|
||||
git merge blue &&
|
||||
|
@ -31,19 +31,19 @@ test_expect_success 'a/b-2/c/d is kept when clobbering symlink b' '
|
||||
git rm --cached a/b &&
|
||||
git commit -m "untracked symlink remains" &&
|
||||
git checkout -f start^0 &&
|
||||
test -f a/b-2/c/d
|
||||
test_path_is_file a/b-2/c/d
|
||||
'
|
||||
|
||||
test_expect_success 'checkout should not have deleted a/b-2/c/d' '
|
||||
git checkout HEAD^0 &&
|
||||
git reset --hard master &&
|
||||
git checkout start^0 &&
|
||||
test -f a/b-2/c/d
|
||||
test_path_is_file a/b-2/c/d
|
||||
'
|
||||
|
||||
test_expect_success 'setup for merge test' '
|
||||
git reset --hard &&
|
||||
test -f a/b-2/c/d &&
|
||||
test_path_is_file a/b-2/c/d &&
|
||||
echo x > a/x &&
|
||||
git add a/x &&
|
||||
git commit -m x &&
|
||||
@ -54,7 +54,7 @@ test_expect_success 'Handle D/F conflict, do not lose a/b-2/c/d in merge (resolv
|
||||
git reset --hard &&
|
||||
git checkout baseline^0 &&
|
||||
git merge -s resolve master &&
|
||||
test -f a/b-2/c/d
|
||||
test_path_is_file a/b-2/c/d
|
||||
'
|
||||
|
||||
test_expect_success SYMLINKS 'a/b was resolved as symlink' '
|
||||
@ -65,7 +65,7 @@ test_expect_success 'Handle D/F conflict, do not lose a/b-2/c/d in merge (recurs
|
||||
git reset --hard &&
|
||||
git checkout baseline^0 &&
|
||||
git merge -s recursive master &&
|
||||
test -f a/b-2/c/d
|
||||
test_path_is_file a/b-2/c/d
|
||||
'
|
||||
|
||||
test_expect_success SYMLINKS 'a/b was resolved as symlink' '
|
||||
@ -76,7 +76,7 @@ test_expect_success 'Handle F/D conflict, do not lose a/b-2/c/d in merge (resolv
|
||||
git reset --hard &&
|
||||
git checkout master^0 &&
|
||||
git merge -s resolve baseline^0 &&
|
||||
test -f a/b-2/c/d
|
||||
test_path_is_file a/b-2/c/d
|
||||
'
|
||||
|
||||
test_expect_success SYMLINKS 'a/b was resolved as symlink' '
|
||||
@ -87,7 +87,7 @@ test_expect_success 'Handle F/D conflict, do not lose a/b-2/c/d in merge (recurs
|
||||
git reset --hard &&
|
||||
git checkout master^0 &&
|
||||
git merge -s recursive baseline^0 &&
|
||||
test -f a/b-2/c/d
|
||||
test_path_is_file a/b-2/c/d
|
||||
'
|
||||
|
||||
test_expect_success SYMLINKS 'a/b was resolved as symlink' '
|
||||
@ -99,8 +99,8 @@ test_expect_failure 'do not lose untracked in merge (resolve)' '
|
||||
git checkout baseline^0 &&
|
||||
>a/b/c/e &&
|
||||
test_must_fail git merge -s resolve master &&
|
||||
test -f a/b/c/e &&
|
||||
test -f a/b-2/c/d
|
||||
test_path_is_file a/b/c/e &&
|
||||
test_path_is_file a/b-2/c/d
|
||||
'
|
||||
|
||||
test_expect_success 'do not lose untracked in merge (recursive)' '
|
||||
@ -108,8 +108,8 @@ test_expect_success 'do not lose untracked in merge (recursive)' '
|
||||
git checkout baseline^0 &&
|
||||
>a/b/c/e &&
|
||||
test_must_fail git merge -s recursive master &&
|
||||
test -f a/b/c/e &&
|
||||
test -f a/b-2/c/d
|
||||
test_path_is_file a/b/c/e &&
|
||||
test_path_is_file a/b-2/c/d
|
||||
'
|
||||
|
||||
test_expect_success 'do not lose modifications in merge (resolve)' '
|
||||
@ -140,7 +140,7 @@ test_expect_success 'merge should not have D/F conflicts (resolve)' '
|
||||
git reset --hard &&
|
||||
git checkout baseline^0 &&
|
||||
git merge -s resolve test2 &&
|
||||
test -f a/b/c/d
|
||||
test_path_is_file a/b/c/d
|
||||
'
|
||||
|
||||
test_expect_success SYMLINKS 'a/b-2 was resolved as symlink' '
|
||||
@ -151,7 +151,7 @@ test_expect_success 'merge should not have D/F conflicts (recursive)' '
|
||||
git reset --hard &&
|
||||
git checkout baseline^0 &&
|
||||
git merge -s recursive test2 &&
|
||||
test -f a/b/c/d
|
||||
test_path_is_file a/b/c/d
|
||||
'
|
||||
|
||||
test_expect_success SYMLINKS 'a/b-2 was resolved as symlink' '
|
||||
@ -162,7 +162,7 @@ test_expect_success 'merge should not have F/D conflicts (recursive)' '
|
||||
git reset --hard &&
|
||||
git checkout -b foo test2 &&
|
||||
git merge -s recursive baseline^0 &&
|
||||
test -f a/b/c/d
|
||||
test_path_is_file a/b/c/d
|
||||
'
|
||||
|
||||
test_expect_success SYMLINKS 'a/b-2 was resolved as symlink' '
|
||||
|
@ -60,9 +60,9 @@ test_expect_success 'merge simple rename+criss-cross with no modifications' '
|
||||
test_must_fail git merge -s recursive R2^0 &&
|
||||
|
||||
git ls-files -s >out &&
|
||||
test_line_count = 2 out &&
|
||||
test_line_count = 5 out &&
|
||||
git ls-files -u >out &&
|
||||
test_line_count = 2 out &&
|
||||
test_line_count = 3 out &&
|
||||
git ls-files -o >out &&
|
||||
test_line_count = 1 out &&
|
||||
|
||||
@ -133,9 +133,9 @@ test_expect_success 'merge criss-cross + rename merges with basic modification'
|
||||
test_must_fail git merge -s recursive R2^0 &&
|
||||
|
||||
git ls-files -s >out &&
|
||||
test_line_count = 2 out &&
|
||||
test_line_count = 5 out &&
|
||||
git ls-files -u >out &&
|
||||
test_line_count = 2 out &&
|
||||
test_line_count = 3 out &&
|
||||
git ls-files -o >out &&
|
||||
test_line_count = 1 out &&
|
||||
|
||||
@ -218,8 +218,18 @@ test_expect_success 'git detects differently handled merges conflict' '
|
||||
git ls-files -o >out &&
|
||||
test_line_count = 1 out &&
|
||||
|
||||
git rev-parse >expect \
|
||||
C:new_a D:new_a E:new_a &&
|
||||
git cat-file -p C:new_a >ours &&
|
||||
git cat-file -p C:a >theirs &&
|
||||
>empty &&
|
||||
test_must_fail git merge-file \
|
||||
-L "Temporary merge branch 1" \
|
||||
-L "" \
|
||||
-L "Temporary merge branch 2" \
|
||||
ours empty theirs &&
|
||||
sed -e "s/^\([<=>]\)/\1\1\1/" ours >ours-tweaked &&
|
||||
git hash-object ours-tweaked >expect &&
|
||||
git rev-parse >>expect \
|
||||
D:new_a E:new_a &&
|
||||
git rev-parse >actual \
|
||||
:1:new_a :2:new_a :3:new_a &&
|
||||
test_cmp expect actual &&
|
||||
@ -257,7 +267,8 @@ test_expect_success 'git detects differently handled merges conflict, swapped' '
|
||||
ctime=$(git log --no-walk --date=raw --format=%cd C | awk "{print \$1}") &&
|
||||
newctime=$(($btime+1)) &&
|
||||
git fast-export --no-data --all | sed -e s/$ctime/$newctime/ | git fast-import --force --quiet &&
|
||||
# End of differences; rest is copy-paste of last test
|
||||
# End of most differences; rest is copy-paste of last test,
|
||||
# other than swapping C:a and C:new_a due to order switch
|
||||
|
||||
git checkout D^0 &&
|
||||
test_must_fail git merge -s recursive E^0 &&
|
||||
@ -269,8 +280,18 @@ test_expect_success 'git detects differently handled merges conflict, swapped' '
|
||||
git ls-files -o >out &&
|
||||
test_line_count = 1 out &&
|
||||
|
||||
git rev-parse >expect \
|
||||
C:new_a D:new_a E:new_a &&
|
||||
git cat-file -p C:a >ours &&
|
||||
git cat-file -p C:new_a >theirs &&
|
||||
>empty &&
|
||||
test_must_fail git merge-file \
|
||||
-L "Temporary merge branch 1" \
|
||||
-L "" \
|
||||
-L "Temporary merge branch 2" \
|
||||
ours empty theirs &&
|
||||
sed -e "s/^\([<=>]\)/\1\1\1/" ours >ours-tweaked &&
|
||||
git hash-object ours-tweaked >expect &&
|
||||
git rev-parse >>expect \
|
||||
D:new_a E:new_a &&
|
||||
git rev-parse >actual \
|
||||
:1:new_a :2:new_a :3:new_a &&
|
||||
test_cmp expect actual &&
|
||||
|
@ -71,16 +71,16 @@ test_expect_success '1a-L: Modify(A)/Modify(B), change on B subset of A' '
|
||||
|
||||
git checkout A^0 &&
|
||||
|
||||
test-tool chmtime =31337 b &&
|
||||
test-tool chmtime -v +0 b >expected-mtime &&
|
||||
test-tool chmtime =-1 b &&
|
||||
test-tool chmtime --get b >old-mtime &&
|
||||
|
||||
GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
|
||||
|
||||
test_i18ngrep "Skipped b" out &&
|
||||
test_must_be_empty err &&
|
||||
|
||||
test-tool chmtime -v +0 b >actual-mtime &&
|
||||
test_cmp expected-mtime actual-mtime &&
|
||||
# Make sure b was NOT updated
|
||||
test-tool chmtime --get b >new-mtime &&
|
||||
test_cmp old-mtime new-mtime &&
|
||||
|
||||
git ls-files -s >index_files &&
|
||||
test_line_count = 1 index_files &&
|
||||
@ -102,9 +102,14 @@ test_expect_success '1a-R: Modify(A)/Modify(B), change on B subset of A' '
|
||||
|
||||
git checkout B^0 &&
|
||||
|
||||
test-tool chmtime =-1 b &&
|
||||
test-tool chmtime --get b >old-mtime &&
|
||||
GIT_MERGE_VERBOSITY=3 git merge -s recursive A^0 >out 2>err &&
|
||||
|
||||
test_i18ngrep "Auto-merging b" out &&
|
||||
# Make sure b WAS updated
|
||||
test-tool chmtime --get b >new-mtime &&
|
||||
test $(cat old-mtime) -lt $(cat new-mtime) &&
|
||||
|
||||
test_must_be_empty err &&
|
||||
|
||||
git ls-files -s >index_files &&
|
||||
@ -165,10 +170,10 @@ test_expect_success '2a-L: Modify/rename, merge into modify side' '
|
||||
|
||||
git checkout A^0 &&
|
||||
|
||||
test_path_is_missing c &&
|
||||
GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
|
||||
|
||||
test_i18ngrep ! "Skipped c" out &&
|
||||
test_must_be_empty err &&
|
||||
test_path_is_file c &&
|
||||
|
||||
git ls-files -s >index_files &&
|
||||
test_line_count = 1 index_files &&
|
||||
@ -193,9 +198,14 @@ test_expect_success '2a-R: Modify/rename, merge into rename side' '
|
||||
|
||||
git checkout B^0 &&
|
||||
|
||||
test-tool chmtime =-1 c &&
|
||||
test-tool chmtime --get c >old-mtime &&
|
||||
GIT_MERGE_VERBOSITY=3 git merge -s recursive A^0 >out 2>err &&
|
||||
|
||||
test_i18ngrep ! "Skipped c" out &&
|
||||
# Make sure c WAS updated
|
||||
test-tool chmtime --get c >new-mtime &&
|
||||
test $(cat old-mtime) -lt $(cat new-mtime) &&
|
||||
|
||||
test_must_be_empty err &&
|
||||
|
||||
git ls-files -s >index_files &&
|
||||
@ -256,16 +266,15 @@ test_expect_success '2b-L: Rename+Mod(A)/Mod(B), B mods subset of A' '
|
||||
|
||||
git checkout A^0 &&
|
||||
|
||||
test-tool chmtime =31337 c &&
|
||||
test-tool chmtime -v +0 c >expected-mtime &&
|
||||
|
||||
test-tool chmtime =-1 c &&
|
||||
test-tool chmtime --get c >old-mtime &&
|
||||
GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
|
||||
|
||||
test_i18ngrep "Skipped c" out &&
|
||||
test_must_be_empty err &&
|
||||
|
||||
test-tool chmtime -v +0 c >actual-mtime &&
|
||||
test_cmp expected-mtime actual-mtime &&
|
||||
# Make sure c WAS updated
|
||||
test-tool chmtime --get c >new-mtime &&
|
||||
test_cmp old-mtime new-mtime &&
|
||||
|
||||
git ls-files -s >index_files &&
|
||||
test_line_count = 1 index_files &&
|
||||
@ -290,9 +299,12 @@ test_expect_success '2b-R: Rename+Mod(A)/Mod(B), B mods subset of A' '
|
||||
|
||||
git checkout B^0 &&
|
||||
|
||||
test_path_is_missing c &&
|
||||
GIT_MERGE_VERBOSITY=3 git merge -s recursive A^0 >out 2>err &&
|
||||
|
||||
test_i18ngrep "Auto-merging c" out &&
|
||||
# Make sure c now present (and thus was updated)
|
||||
test_path_is_file c &&
|
||||
|
||||
test_must_be_empty err &&
|
||||
|
||||
git ls-files -s >index_files &&
|
||||
@ -361,13 +373,18 @@ test_expect_success '2c: Modify b & add c VS rename b->c' '
|
||||
|
||||
git checkout A^0 &&
|
||||
|
||||
test-tool chmtime =-1 c &&
|
||||
test-tool chmtime --get c >old-mtime &&
|
||||
GIT_MERGE_VERBOSITY=3 &&
|
||||
export GIT_MERGE_VERBOSITY &&
|
||||
test_must_fail git merge -s recursive B^0 >out 2>err &&
|
||||
|
||||
test_i18ngrep "CONFLICT (rename/add): Rename b->c" out &&
|
||||
test_i18ngrep ! "Skipped c" out &&
|
||||
test_must_be_empty err
|
||||
test_must_be_empty err &&
|
||||
|
||||
# Make sure c WAS updated
|
||||
test-tool chmtime --get c >new-mtime &&
|
||||
test $(cat old-mtime) -lt $(cat new-mtime)
|
||||
|
||||
# FIXME: rename/add conflicts are horribly broken right now;
|
||||
# when I get back to my patch series fixing it and
|
||||
@ -460,11 +477,13 @@ test_expect_success '3a-L: bq_1->foo/bq_2 on A, foo/->bar/ on B' '
|
||||
|
||||
git checkout A^0 &&
|
||||
|
||||
test_path_is_missing bar/bq &&
|
||||
GIT_MERGE_VERBOSITY=3 git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
|
||||
|
||||
test_i18ngrep ! "Skipped bar/bq" out &&
|
||||
test_must_be_empty err &&
|
||||
|
||||
test_path_is_file bar/bq &&
|
||||
|
||||
git ls-files -s >index_files &&
|
||||
test_line_count = 2 index_files &&
|
||||
|
||||
@ -488,11 +507,13 @@ test_expect_success '3a-R: bq_1->foo/bq_2 on A, foo/->bar/ on B' '
|
||||
|
||||
git checkout B^0 &&
|
||||
|
||||
test_path_is_missing bar/bq &&
|
||||
GIT_MERGE_VERBOSITY=3 git -c merge.directoryRenames=true merge -s recursive A^0 >out 2>err &&
|
||||
|
||||
test_i18ngrep ! "Skipped bar/bq" out &&
|
||||
test_must_be_empty err &&
|
||||
|
||||
test_path_is_file bar/bq &&
|
||||
|
||||
git ls-files -s >index_files &&
|
||||
test_line_count = 2 index_files &&
|
||||
|
||||
@ -552,11 +573,13 @@ test_expect_success '3b-L: bq_1->foo/bq_2 on A, foo/->bar/ on B' '
|
||||
|
||||
git checkout A^0 &&
|
||||
|
||||
test_path_is_missing bar/bq &&
|
||||
GIT_MERGE_VERBOSITY=3 git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
|
||||
|
||||
test_i18ngrep ! "Skipped bar/bq" out &&
|
||||
test_must_be_empty err &&
|
||||
|
||||
test_path_is_file bar/bq &&
|
||||
|
||||
git ls-files -s >index_files &&
|
||||
test_line_count = 2 index_files &&
|
||||
|
||||
@ -580,11 +603,13 @@ test_expect_success '3b-R: bq_1->foo/bq_2 on A, foo/->bar/ on B' '
|
||||
|
||||
git checkout B^0 &&
|
||||
|
||||
test_path_is_missing bar/bq &&
|
||||
GIT_MERGE_VERBOSITY=3 git -c merge.directoryRenames=true merge -s recursive A^0 >out 2>err &&
|
||||
|
||||
test_i18ngrep ! "Skipped bar/bq" out &&
|
||||
test_must_be_empty err &&
|
||||
|
||||
test_path_is_file bar/bq &&
|
||||
|
||||
git ls-files -s >index_files &&
|
||||
test_line_count = 2 index_files &&
|
||||
|
||||
@ -654,16 +679,16 @@ test_expect_failure '4a: Change on A, change on B subset of A, dirty mods presen
|
||||
git checkout A^0 &&
|
||||
echo "File rewritten" >b &&
|
||||
|
||||
test-tool chmtime =31337 b &&
|
||||
test-tool chmtime -v +0 b >expected-mtime &&
|
||||
test-tool chmtime =-1 b &&
|
||||
test-tool chmtime --get b >old-mtime &&
|
||||
|
||||
GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
|
||||
|
||||
test_i18ngrep "Skipped b" out &&
|
||||
test_must_be_empty err &&
|
||||
|
||||
test-tool chmtime -v +0 b >actual-mtime &&
|
||||
test_cmp expected-mtime actual-mtime &&
|
||||
# Make sure b was NOT updated
|
||||
test-tool chmtime --get b >new-mtime &&
|
||||
test_cmp old-mtime new-mtime &&
|
||||
|
||||
git ls-files -s >index_files &&
|
||||
test_line_count = 1 index_files &&
|
||||
@ -722,16 +747,16 @@ test_expect_success '4b: Rename+Mod(A)/Mod(B), change on B subset of A, dirty mo
|
||||
git checkout A^0 &&
|
||||
echo "File rewritten" >c &&
|
||||
|
||||
test-tool chmtime =31337 c &&
|
||||
test-tool chmtime -v +0 c >expected-mtime &&
|
||||
test-tool chmtime =-1 c &&
|
||||
test-tool chmtime --get c >old-mtime &&
|
||||
|
||||
GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
|
||||
|
||||
test_i18ngrep "Skipped c" out &&
|
||||
test_must_be_empty err &&
|
||||
|
||||
test-tool chmtime -v +0 c >actual-mtime &&
|
||||
test_cmp expected-mtime actual-mtime &&
|
||||
# Make sure c was NOT updated
|
||||
test-tool chmtime --get c >new-mtime &&
|
||||
test_cmp old-mtime new-mtime &&
|
||||
|
||||
git ls-files -s >index_files &&
|
||||
test_line_count = 1 index_files &&
|
||||
|
13
walker.c
13
walker.c
@ -8,6 +8,7 @@
|
||||
#include "tag.h"
|
||||
#include "blob.h"
|
||||
#include "refs.h"
|
||||
#include "progress.h"
|
||||
|
||||
static struct object_id current_commit_oid;
|
||||
|
||||
@ -162,6 +163,11 @@ static int process(struct walker *walker, struct object *obj)
|
||||
static int loop(struct walker *walker)
|
||||
{
|
||||
struct object_list *elem;
|
||||
struct progress *progress = NULL;
|
||||
uint64_t nr = 0;
|
||||
|
||||
if (walker->get_progress)
|
||||
progress = start_delayed_progress(_("Fetching objects"), 0);
|
||||
|
||||
while (process_queue) {
|
||||
struct object *obj = process_queue->item;
|
||||
@ -176,15 +182,20 @@ static int loop(struct walker *walker)
|
||||
*/
|
||||
if (! (obj->flags & TO_SCAN)) {
|
||||
if (walker->fetch(walker, obj->oid.hash)) {
|
||||
stop_progress(&progress);
|
||||
report_missing(obj);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (!obj->type)
|
||||
parse_object(the_repository, &obj->oid);
|
||||
if (process_object(walker, obj))
|
||||
if (process_object(walker, obj)) {
|
||||
stop_progress(&progress);
|
||||
return -1;
|
||||
}
|
||||
display_progress(progress, ++nr);
|
||||
}
|
||||
stop_progress(&progress);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user