зеркало из https://github.com/microsoft/git.git
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:
Коммит
52b2742df8
|
@ -47,6 +47,18 @@ UI, Workflows & Features
|
||||||
* "git clone --recurse-submodules --single-branch" now uses the same
|
* "git clone --recurse-submodules --single-branch" now uses the same
|
||||||
single-branch option when cloning the submodules.
|
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.
|
Performance, Internal Implementation, Development Support etc.
|
||||||
|
|
||||||
|
@ -288,6 +300,18 @@ Fixes since v2.25
|
||||||
reverted.
|
reverted.
|
||||||
(merge 0106b1d4be hi/gpg-use-check-signature later to maint).
|
(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.
|
* Other code cleanup, docfix, build fix, etc.
|
||||||
(merge 26f924d50e en/simplify-check-updates-in-unpack-trees later to maint).
|
(merge 26f924d50e en/simplify-check-updates-in-unpack-trees later to maint).
|
||||||
(merge d0d0a357a1 am/update-pathspec-f-f-tests 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 240fc04f81 ag/rebase-remove-redundant-code later to maint).
|
||||||
(merge 7f487ce062 js/ci-windows-update later to maint).
|
(merge 7f487ce062 js/ci-windows-update later to maint).
|
||||||
(merge d68ce906c7 rs/commit-graph-code-simplification 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]
|
[--exclude=<path>] [--include=<path>] [--reject] [-q | --quiet]
|
||||||
[--[no-]scissors] [-S[<keyid>]] [--patch-format=<format>]
|
[--[no-]scissors] [-S[<keyid>]] [--patch-format=<format>]
|
||||||
[(<mbox> | <Maildir>)...]
|
[(<mbox> | <Maildir>)...]
|
||||||
'git am' (--continue | --skip | --abort | --quit | --show-current-patch)
|
'git am' (--continue | --skip | --abort | --quit | --show-current-patch[=(diff|raw)])
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
|
@ -176,9 +176,11 @@ default. You can use `--no-utf8` to override this.
|
||||||
Abort the patching operation but keep HEAD and the index
|
Abort the patching operation but keep HEAD and the index
|
||||||
untouched.
|
untouched.
|
||||||
|
|
||||||
--show-current-patch::
|
--show-current-patch[=(diff|raw)]::
|
||||||
Show the entire e-mail message "git am" has stopped at, because
|
Show the message at which `git am` has stopped due to
|
||||||
of conflicts.
|
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
|
DISCUSSION
|
||||||
----------
|
----------
|
||||||
|
|
|
@ -8,16 +8,18 @@ git-rm - Remove files from the working tree and from the index
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
[verse]
|
[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
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
Remove files from the index, or from the working tree and the index.
|
Remove files matching pathspec from the index, or from the working tree
|
||||||
`git rm` will not remove a file from just your working directory.
|
and the index. `git rm` will not remove a file from just your working
|
||||||
(There is no option to remove a file only from the working tree
|
directory. (There is no option to remove a file only from the working
|
||||||
and yet keep it in the index; use `/bin/rm` if you want to do that.)
|
tree and yet keep it in the index; use `/bin/rm` if you want to do
|
||||||
The files being removed have to be identical to the tip of the branch,
|
that.) The files being removed have to be identical to the tip of the
|
||||||
and no updates to their contents can be staged in the index,
|
branch, and no updates to their contents can be staged in the index,
|
||||||
though that default behavior can be overridden with the `-f` option.
|
though that default behavior can be overridden with the `-f` option.
|
||||||
When `--cached` is given, the staged content has to
|
When `--cached` is given, the staged content has to
|
||||||
match either the tip of the branch or the file on disk,
|
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
|
OPTIONS
|
||||||
-------
|
-------
|
||||||
<file>...::
|
<pathspec>...::
|
||||||
Files to remove. Fileglobs (e.g. `*.c`) can be given to
|
Files to remove. A leading directory name (e.g. `dir` to remove
|
||||||
remove all matching files. If you want Git to expand
|
`dir/file1` and `dir/file2`) can be given to remove all files in
|
||||||
file glob characters, you may need to shell-escape them.
|
the directory, and recursively all sub-directories, but this
|
||||||
A leading directory name
|
requires the `-r` option to be explicitly given.
|
||||||
(e.g. `dir` to remove `dir/file1` and `dir/file2`) can be
|
+
|
||||||
given to remove all files in the directory, and recursively
|
The command removes only the paths that are known to Git.
|
||||||
all sub-directories,
|
+
|
||||||
but this requires the `-r` option to be explicitly given.
|
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::
|
-f::
|
||||||
--force::
|
--force::
|
||||||
|
@ -68,19 +75,19 @@ OPTIONS
|
||||||
`git rm` normally outputs one line (in the form of an `rm` command)
|
`git rm` normally outputs one line (in the form of an `rm` command)
|
||||||
for each file removed. This option suppresses that output.
|
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
|
REMOVING FILES THAT HAVE DISAPPEARED FROM THE FILESYSTEM
|
||||||
--------------------------------------------------------
|
--------------------------------------------------------
|
||||||
|
|
|
@ -15,6 +15,7 @@ SYNOPSIS
|
||||||
'git stash' branch <branchname> [<stash>]
|
'git stash' branch <branchname> [<stash>]
|
||||||
'git stash' [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
|
'git stash' [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
|
||||||
[-u|--include-untracked] [-a|--all] [-m|--message <message>]
|
[-u|--include-untracked] [-a|--all] [-m|--message <message>]
|
||||||
|
[--pathspec-from-file=<file> [--pathspec-file-nul]]
|
||||||
[--] [<pathspec>...]]
|
[--] [<pathspec>...]]
|
||||||
'git stash' clear
|
'git stash' clear
|
||||||
'git stash' create [<message>]
|
'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
|
is also possible). Stashes may also be referenced by specifying just the
|
||||||
stash index (e.g. the integer `n` is equivalent to `stash@{n}`).
|
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
|
Save your local modifications to a new 'stash entry' and roll them
|
||||||
back to HEAD (in the working tree and in the index).
|
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,
|
For quickly making a snapshot, you can omit "push". In this mode,
|
||||||
non-option arguments are not allowed to prevent a misspelled
|
non-option arguments are not allowed to prevent a misspelled
|
||||||
subcommand from making an unwanted stash entry. The two exceptions to this
|
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.
|
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>]::
|
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
|
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
|
Instead, all non-option arguments are concatenated to form the stash
|
||||||
message.
|
message.
|
||||||
|
|
||||||
|
@ -111,7 +87,7 @@ show [<options>] [<stash>]::
|
||||||
|
|
||||||
Show the changes recorded in the stash entry as a diff between the
|
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
|
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
|
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}`
|
format known to 'git diff' (e.g., `git stash show -p stash@{1}`
|
||||||
to view the second most recent entry in patch form).
|
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
|
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
|
removed from the stash list. You need to resolve the conflicts by hand
|
||||||
and call `git stash drop` manually afterwards.
|
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>]::
|
apply [--index] [-q|--quiet] [<stash>]::
|
||||||
|
|
||||||
|
@ -149,8 +117,7 @@ branch <branchname> [<stash>]::
|
||||||
the commit at which the `<stash>` was originally created, applies the
|
the commit at which the `<stash>` was originally created, applies the
|
||||||
changes recorded in `<stash>` to the new working tree and index.
|
changes recorded in `<stash>` to the new working tree and index.
|
||||||
If that succeeds, and `<stash>` is a reference of the form
|
If that succeeds, and `<stash>` is a reference of the form
|
||||||
`stash@{<revision>}`, it then drops the `<stash>`. When no `<stash>`
|
`stash@{<revision>}`, it then drops the `<stash>`.
|
||||||
is given, applies the latest one.
|
|
||||||
+
|
+
|
||||||
This is useful if the branch on which you ran `git stash push` has
|
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
|
changed enough that `git stash apply` fails due to conflicts. Since
|
||||||
|
@ -166,9 +133,6 @@ clear::
|
||||||
drop [-q|--quiet] [<stash>]::
|
drop [-q|--quiet] [<stash>]::
|
||||||
|
|
||||||
Remove a single stash entry from the list of stash entries.
|
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::
|
create::
|
||||||
|
|
||||||
|
@ -185,6 +149,98 @@ store::
|
||||||
reflog. This is intended to be useful for scripts. It is
|
reflog. This is intended to be useful for scripts. It is
|
||||||
probably not the command you want to use; see "push" above.
|
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
|
DISCUSSION
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
GVF=GIT-VERSION-FILE
|
GVF=GIT-VERSION-FILE
|
||||||
DEF_VER=v2.26.0-rc0
|
DEF_VER=v2.26.0-rc1
|
||||||
|
|
||||||
LF='
|
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 */
|
SIGNOFF_EXPLICIT /* --signoff was set on the command-line */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum show_patch_type {
|
||||||
|
SHOW_PATCH_RAW = 0,
|
||||||
|
SHOW_PATCH_DIFF = 1,
|
||||||
|
};
|
||||||
|
|
||||||
struct am_state {
|
struct am_state {
|
||||||
/* state directory path */
|
/* state directory path */
|
||||||
char *dir;
|
char *dir;
|
||||||
|
@ -1763,7 +1768,7 @@ static void am_run(struct am_state *state, int resume)
|
||||||
linelen(state->msg), state->msg);
|
linelen(state->msg), state->msg);
|
||||||
|
|
||||||
if (advice_amworkdir)
|
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);
|
die_user_resolve(state);
|
||||||
}
|
}
|
||||||
|
@ -2061,7 +2066,7 @@ static void am_abort(struct am_state *state)
|
||||||
am_destroy(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;
|
struct strbuf sb = STRBUF_INIT;
|
||||||
const char *patch_path;
|
const char *patch_path;
|
||||||
|
@ -2078,7 +2083,17 @@ static int show_patch(struct am_state *state)
|
||||||
return ret;
|
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);
|
len = strbuf_read_file(&sb, patch_path, 0);
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
die_errno(_("failed to read '%s'"), patch_path);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum resume_mode {
|
enum resume_type {
|
||||||
RESUME_FALSE = 0,
|
RESUME_FALSE = 0,
|
||||||
RESUME_APPLY,
|
RESUME_APPLY,
|
||||||
RESUME_RESOLVED,
|
RESUME_RESOLVED,
|
||||||
|
@ -2128,6 +2143,45 @@ enum resume_mode {
|
||||||
RESUME_SHOW_PATCH
|
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)
|
static int git_am_config(const char *k, const char *v, void *cb)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
|
@ -2145,7 +2199,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
|
||||||
int binary = -1;
|
int binary = -1;
|
||||||
int keep_cr = -1;
|
int keep_cr = -1;
|
||||||
int patch_format = PATCH_FORMAT_UNKNOWN;
|
int patch_format = PATCH_FORMAT_UNKNOWN;
|
||||||
enum resume_mode resume = RESUME_FALSE;
|
struct resume_mode resume = { .mode = RESUME_FALSE };
|
||||||
int in_progress;
|
int in_progress;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
@ -2214,24 +2268,26 @@ int cmd_am(int argc, const char **argv, const char *prefix)
|
||||||
PARSE_OPT_NOARG),
|
PARSE_OPT_NOARG),
|
||||||
OPT_STRING(0, "resolvemsg", &state.resolvemsg, NULL,
|
OPT_STRING(0, "resolvemsg", &state.resolvemsg, NULL,
|
||||||
N_("override error message when patch failure occurs")),
|
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"),
|
N_("continue applying patches after resolving a conflict"),
|
||||||
RESUME_RESOLVED),
|
RESUME_RESOLVED),
|
||||||
OPT_CMDMODE('r', "resolved", &resume,
|
OPT_CMDMODE('r', "resolved", &resume.mode,
|
||||||
N_("synonyms for --continue"),
|
N_("synonyms for --continue"),
|
||||||
RESUME_RESOLVED),
|
RESUME_RESOLVED),
|
||||||
OPT_CMDMODE(0, "skip", &resume,
|
OPT_CMDMODE(0, "skip", &resume.mode,
|
||||||
N_("skip the current patch"),
|
N_("skip the current patch"),
|
||||||
RESUME_SKIP),
|
RESUME_SKIP),
|
||||||
OPT_CMDMODE(0, "abort", &resume,
|
OPT_CMDMODE(0, "abort", &resume.mode,
|
||||||
N_("restore the original branch and abort the patching operation."),
|
N_("restore the original branch and abort the patching operation."),
|
||||||
RESUME_ABORT),
|
RESUME_ABORT),
|
||||||
OPT_CMDMODE(0, "quit", &resume,
|
OPT_CMDMODE(0, "quit", &resume.mode,
|
||||||
N_("abort the patching operation but keep HEAD where it is."),
|
N_("abort the patching operation but keep HEAD where it is."),
|
||||||
RESUME_QUIT),
|
RESUME_QUIT),
|
||||||
OPT_CMDMODE(0, "show-current-patch", &resume,
|
{ OPTION_CALLBACK, 0, "show-current-patch", &resume.mode,
|
||||||
N_("show the patch being applied."),
|
"(diff|raw)",
|
||||||
RESUME_SHOW_PATCH),
|
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",
|
OPT_BOOL(0, "committer-date-is-author-date",
|
||||||
&state.committer_date_is_author_date,
|
&state.committer_date_is_author_date,
|
||||||
N_("lie about committer 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
|
* intend to feed us a patch but wanted to continue
|
||||||
* unattended.
|
* 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."),
|
die(_("previous rebase directory %s still exists but mbox given."),
|
||||||
state.dir);
|
state.dir);
|
||||||
|
|
||||||
if (resume == RESUME_FALSE)
|
if (resume.mode == RESUME_FALSE)
|
||||||
resume = RESUME_APPLY;
|
resume.mode = RESUME_APPLY;
|
||||||
|
|
||||||
if (state.signoff == SIGNOFF_EXPLICIT)
|
if (state.signoff == SIGNOFF_EXPLICIT)
|
||||||
am_append_signoff(&state);
|
am_append_signoff(&state);
|
||||||
|
@ -2300,7 +2356,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
|
||||||
* stray directories.
|
* stray directories.
|
||||||
*/
|
*/
|
||||||
if (file_exists(state.dir) && !state.rebasing) {
|
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_destroy(&state);
|
||||||
am_state_release(&state);
|
am_state_release(&state);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2311,7 +2367,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
|
||||||
state.dir);
|
state.dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resume)
|
if (resume.mode)
|
||||||
die(_("Resolve operation not in progress, we are not resuming."));
|
die(_("Resolve operation not in progress, we are not resuming."));
|
||||||
|
|
||||||
for (i = 0; i < argc; i++) {
|
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);
|
argv_array_clear(&paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (resume) {
|
switch (resume.mode) {
|
||||||
case RESUME_FALSE:
|
case RESUME_FALSE:
|
||||||
am_run(&state, 0);
|
am_run(&state, 0);
|
||||||
break;
|
break;
|
||||||
|
@ -2350,7 +2406,7 @@ int cmd_am(int argc, const char **argv, const char *prefix)
|
||||||
am_destroy(&state);
|
am_destroy(&state);
|
||||||
break;
|
break;
|
||||||
case RESUME_SHOW_PATCH:
|
case RESUME_SHOW_PATCH:
|
||||||
ret = show_patch(&state);
|
ret = show_patch(&state, resume.sub_mode);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
BUG("invalid resume value");
|
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 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[] = {
|
static struct option builtin_rm_options[] = {
|
||||||
OPT__DRY_RUN(&show_only, N_("dry run")),
|
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('r', NULL, &recursive, N_("allow recursive removal")),
|
||||||
OPT_BOOL( 0 , "ignore-unmatch", &ignore_unmatch,
|
OPT_BOOL( 0 , "ignore-unmatch", &ignore_unmatch,
|
||||||
N_("exit with a zero status even if nothing matched")),
|
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(),
|
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,
|
argc = parse_options(argc, argv, prefix, builtin_rm_options,
|
||||||
builtin_rm_usage, 0);
|
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)
|
if (!index_only)
|
||||||
setup_work_tree();
|
setup_work_tree();
|
||||||
|
@ -270,9 +289,6 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
|
||||||
if (read_cache() < 0)
|
if (read_cache() < 0)
|
||||||
die(_("index file corrupt"));
|
die(_("index file corrupt"));
|
||||||
|
|
||||||
parse_pathspec(&pathspec, 0,
|
|
||||||
PATHSPEC_PREFER_CWD,
|
|
||||||
prefix, argv);
|
|
||||||
refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, &pathspec, NULL, NULL);
|
refresh_index(&the_index, REFRESH_QUIET|REFRESH_UNMERGED, &pathspec, NULL, NULL);
|
||||||
|
|
||||||
seen = xcalloc(pathspec.nr, 1);
|
seen = xcalloc(pathspec.nr, 1);
|
||||||
|
|
|
@ -27,6 +27,7 @@ static const char * const git_stash_usage[] = {
|
||||||
N_("git stash clear"),
|
N_("git stash clear"),
|
||||||
N_("git stash [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
|
N_("git stash [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
|
||||||
" [-u|--include-untracked] [-a|--all] [-m|--message <message>]\n"
|
" [-u|--include-untracked] [-a|--all] [-m|--message <message>]\n"
|
||||||
|
" [--pathspec-from-file=<file> [--pathspec-file-nul]]\n"
|
||||||
" [--] [<pathspec>...]]"),
|
" [--] [<pathspec>...]]"),
|
||||||
N_("git stash save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
|
N_("git stash save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]\n"
|
||||||
" [-u|--include-untracked] [-a|--all] [<message>]"),
|
" [-u|--include-untracked] [-a|--all] [<message>]"),
|
||||||
|
@ -1451,13 +1452,17 @@ done:
|
||||||
return ret;
|
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 keep_index = -1;
|
||||||
int patch_mode = 0;
|
int patch_mode = 0;
|
||||||
int include_untracked = 0;
|
int include_untracked = 0;
|
||||||
int quiet = 0;
|
int quiet = 0;
|
||||||
|
int pathspec_file_nul = 0;
|
||||||
const char *stash_msg = NULL;
|
const char *stash_msg = NULL;
|
||||||
|
const char *pathspec_from_file = NULL;
|
||||||
struct pathspec ps;
|
struct pathspec ps;
|
||||||
struct option options[] = {
|
struct option options[] = {
|
||||||
OPT_BOOL('k', "keep-index", &keep_index,
|
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),
|
N_("include ignore files"), 2),
|
||||||
OPT_STRING('m', "message", &stash_msg, N_("message"),
|
OPT_STRING('m', "message", &stash_msg, N_("message"),
|
||||||
N_("stash message")),
|
N_("stash message")),
|
||||||
|
OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
|
||||||
|
OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
|
||||||
OPT_END()
|
OPT_END()
|
||||||
};
|
};
|
||||||
|
|
||||||
if (argc)
|
if (argc) {
|
||||||
|
force_assume = !strcmp(argv[0], "-p");
|
||||||
argc = parse_options(argc, argv, prefix, options,
|
argc = parse_options(argc, argv, prefix, options,
|
||||||
git_stash_push_usage,
|
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,
|
parse_pathspec(&ps, 0, PATHSPEC_PREFER_FULL | PATHSPEC_PREFIX_ORIGIN,
|
||||||
prefix, argv);
|
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,
|
return do_push_stash(&ps, stash_msg, quiet, keep_index, patch_mode,
|
||||||
include_untracked);
|
include_untracked);
|
||||||
}
|
}
|
||||||
|
@ -1550,7 +1584,6 @@ static int use_builtin_stash(void)
|
||||||
|
|
||||||
int cmd_stash(int argc, const char **argv, const char *prefix)
|
int cmd_stash(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
int i = -1;
|
|
||||||
pid_t pid = getpid();
|
pid_t pid = getpid();
|
||||||
const char *index_file;
|
const char *index_file;
|
||||||
struct argv_array args = ARGV_ARRAY_INIT;
|
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);
|
(uintmax_t)pid);
|
||||||
|
|
||||||
if (!argc)
|
if (!argc)
|
||||||
return !!push_stash(0, NULL, prefix);
|
return !!push_stash(0, NULL, prefix, 0);
|
||||||
else if (!strcmp(argv[0], "apply"))
|
else if (!strcmp(argv[0], "apply"))
|
||||||
return !!apply_stash(argc, argv, prefix);
|
return !!apply_stash(argc, argv, prefix);
|
||||||
else if (!strcmp(argv[0], "clear"))
|
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"))
|
else if (!strcmp(argv[0], "create"))
|
||||||
return !!create_stash(argc, argv, prefix);
|
return !!create_stash(argc, argv, prefix);
|
||||||
else if (!strcmp(argv[0], "push"))
|
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"))
|
else if (!strcmp(argv[0], "save"))
|
||||||
return !!save_stash(argc, argv, prefix);
|
return !!save_stash(argc, argv, prefix);
|
||||||
else if (*argv[0] != '-')
|
else if (*argv[0] != '-')
|
||||||
usage_msg_opt(xstrfmt(_("unknown subcommand: %s"), argv[0]),
|
usage_msg_opt(xstrfmt(_("unknown subcommand: %s"), argv[0]),
|
||||||
git_stash_usage, options);
|
git_stash_usage, options);
|
||||||
|
|
||||||
if (strcmp(argv[0], "-p")) {
|
/* Assume 'stash push' */
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
argv_array_push(&args, "push");
|
argv_array_push(&args, "push");
|
||||||
argv_array_pushv(&args, argv);
|
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;
|
INPUT_RECORD *irbuffer;
|
||||||
DWORD avail, nbuffer;
|
DWORD avail, nbuffer;
|
||||||
BOOL bRet;
|
BOOL bRet;
|
||||||
IO_STATUS_BLOCK iosb;
|
|
||||||
FILE_PIPE_LOCAL_INFORMATION fpli;
|
|
||||||
static PNtQueryInformationFile NtQueryInformationFile;
|
|
||||||
static BOOL once_only;
|
|
||||||
|
|
||||||
switch (GetFileType (h))
|
switch (GetFileType (h))
|
||||||
{
|
{
|
||||||
case FILE_TYPE_PIPE:
|
case FILE_TYPE_PIPE:
|
||||||
if (!once_only)
|
|
||||||
{
|
|
||||||
NtQueryInformationFile = (PNtQueryInformationFile)(void (*)(void))
|
|
||||||
GetProcAddress (GetModuleHandleW (L"ntdll.dll"),
|
|
||||||
"NtQueryInformationFile");
|
|
||||||
once_only = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
happened = 0;
|
happened = 0;
|
||||||
if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
|
if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
|
||||||
{
|
{
|
||||||
|
@ -166,22 +154,9 @@ win32_compute_revents (HANDLE h, int *p_sought)
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* It was the write-end of the pipe. Check if it is writable.
|
/* It was the write-end of the pipe. Unfortunately there is no
|
||||||
If NtQueryInformationFile fails, optimistically assume the pipe is
|
reliable way of knowing if it can be written without blocking.
|
||||||
writable. This could happen on Win9x, where NtQueryInformationFile
|
Just say that it's all good. */
|
||||||
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))
|
|
||||||
happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
|
happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);
|
||||||
}
|
}
|
||||||
return happened;
|
return happened;
|
||||||
|
|
|
@ -9,7 +9,6 @@ endif
|
||||||
DEVELOPER_CFLAGS += -Wall
|
DEVELOPER_CFLAGS += -Wall
|
||||||
DEVELOPER_CFLAGS += -Wdeclaration-after-statement
|
DEVELOPER_CFLAGS += -Wdeclaration-after-statement
|
||||||
DEVELOPER_CFLAGS += -Wformat-security
|
DEVELOPER_CFLAGS += -Wformat-security
|
||||||
DEVELOPER_CFLAGS += -Wno-format-zero-length
|
|
||||||
DEVELOPER_CFLAGS += -Wold-style-definition
|
DEVELOPER_CFLAGS += -Wold-style-definition
|
||||||
DEVELOPER_CFLAGS += -Woverflow
|
DEVELOPER_CFLAGS += -Woverflow
|
||||||
DEVELOPER_CFLAGS += -Wpointer-arith
|
DEVELOPER_CFLAGS += -Wpointer-arith
|
||||||
|
|
|
@ -1197,6 +1197,7 @@ __git_count_arguments ()
|
||||||
|
|
||||||
__git_whitespacelist="nowarn warn error error-all fix"
|
__git_whitespacelist="nowarn warn error error-all fix"
|
||||||
__git_patchformat="mbox stgit stgit-series hg mboxrd"
|
__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_inprogress_options="--skip --continue --resolved --abort --quit --show-current-patch"
|
||||||
|
|
||||||
_git_am ()
|
_git_am ()
|
||||||
|
@ -1215,6 +1216,10 @@ _git_am ()
|
||||||
__gitcomp "$__git_patchformat" "" "${cur##--patch-format=}"
|
__gitcomp "$__git_patchformat" "" "${cur##--patch-format=}"
|
||||||
return
|
return
|
||||||
;;
|
;;
|
||||||
|
--show-current-patch=*)
|
||||||
|
__gitcomp "$__git_showcurrentpatch" "" "${cur##--show-current-patch=}"
|
||||||
|
return
|
||||||
|
;;
|
||||||
--*)
|
--*)
|
||||||
__gitcomp_builtin am "" \
|
__gitcomp_builtin am "" \
|
||||||
"$__git_am_inprogress_options"
|
"$__git_am_inprogress_options"
|
||||||
|
@ -1487,9 +1492,16 @@ __git_diff_algorithms="myers minimal patience histogram"
|
||||||
|
|
||||||
__git_diff_submodule_formats="diff log short"
|
__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
|
__git_diff_common_options="--stat --numstat --shortstat --summary
|
||||||
--patch-with-stat --name-only --name-status --color
|
--patch-with-stat --name-only --name-status --color
|
||||||
--no-color --color-words --no-renames --check
|
--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=
|
--full-index --binary --abbrev --diff-filter=
|
||||||
--find-copies-harder --ignore-cr-at-eol
|
--find-copies-harder --ignore-cr-at-eol
|
||||||
--text --ignore-space-at-eol --ignore-space-change
|
--text --ignore-space-at-eol --ignore-space-change
|
||||||
|
@ -1520,6 +1532,14 @@ _git_diff ()
|
||||||
__gitcomp "$__git_diff_submodule_formats" "" "${cur##--submodule=}"
|
__gitcomp "$__git_diff_submodule_formats" "" "${cur##--submodule=}"
|
||||||
return
|
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
|
__gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
|
||||||
--base --ours --theirs --no-index
|
--base --ours --theirs --no-index
|
||||||
|
|
|
@ -516,7 +516,7 @@ static int show_one_mergetag(struct commit *commit,
|
||||||
"merged tag '%s'\n", tag->tag);
|
"merged tag '%s'\n", tag->tag);
|
||||||
else if ((nth = which_parent(&tag->tagged->oid, commit)) < 0)
|
else if ((nth = which_parent(&tag->tagged->oid, commit)) < 0)
|
||||||
strbuf_addf(&verify_message, "tag %s names a non-parent %s\n",
|
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
|
else
|
||||||
strbuf_addf(&verify_message,
|
strbuf_addf(&verify_message,
|
||||||
"parent #%d, tagged '%s'\n", nth + 1, tag->tag);
|
"parent #%d, tagged '%s'\n", nth + 1, tag->tag);
|
||||||
|
|
|
@ -1560,35 +1560,6 @@ static int handle_file_collision(struct merge_options *opt,
|
||||||
b, a);
|
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) */
|
/* Remove rename sources if rename/add or rename/rename(2to1) */
|
||||||
if (prev_path1)
|
if (prev_path1)
|
||||||
remove_file(opt, 1, prev_path1,
|
remove_file(opt, 1, prev_path1,
|
||||||
|
@ -1749,85 +1720,56 @@ static int handle_rename_rename_1to2(struct merge_options *opt,
|
||||||
return -1;
|
return -1;
|
||||||
free(path_desc);
|
free(path_desc);
|
||||||
|
|
||||||
if (opt->priv->call_depth) {
|
if (opt->priv->call_depth)
|
||||||
/*
|
remove_file_from_index(opt->repo->index, o->path);
|
||||||
* 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
|
* For each destination path, we need to see if there is a
|
||||||
* unique path, or use that unique path instead of src here.
|
* rename/add collision. If not, we can write the file out
|
||||||
*/
|
* to the specified location.
|
||||||
if (update_file(opt, 0, &mfi.blob, o->path))
|
*/
|
||||||
|
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;
|
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 {
|
} else {
|
||||||
/*
|
char *new_path = find_path_for_conflict(opt, a->path,
|
||||||
* For each destination path, we need to see if there is a
|
ci->ren1->branch,
|
||||||
* rename/add collision. If not, we can write the file out
|
ci->ren2->branch);
|
||||||
* to the specified location.
|
if (update_file(opt, 0, &mfi.blob,
|
||||||
*/
|
new_path ? new_path : a->path))
|
||||||
add = &ci->ren1->dst_entry->stages[flip_stage(2)];
|
return -1;
|
||||||
if (is_valid(add)) {
|
free(new_path);
|
||||||
add->path = mfi.blob.path = a->path;
|
if (!opt->priv->call_depth &&
|
||||||
if (handle_file_collision(opt, a->path,
|
update_stages(opt, a->path, NULL, a, NULL))
|
||||||
NULL, NULL,
|
return -1;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
add = &ci->ren2->dst_entry->stages[flip_stage(3)];
|
add = &ci->ren2->dst_entry->stages[flip_stage(3)];
|
||||||
if (is_valid(add)) {
|
if (is_valid(add)) {
|
||||||
add->path = mfi.blob.path = b->path;
|
add->path = mfi.blob.path = b->path;
|
||||||
if (handle_file_collision(opt, b->path,
|
if (handle_file_collision(opt, b->path,
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
ci->ren1->branch,
|
ci->ren1->branch,
|
||||||
ci->ren2->branch,
|
ci->ren2->branch,
|
||||||
add, &mfi.blob) < 0)
|
add, &mfi.blob) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
char *new_path = find_path_for_conflict(opt, b->path,
|
char *new_path = find_path_for_conflict(opt, b->path,
|
||||||
ci->ren2->branch,
|
ci->ren2->branch,
|
||||||
ci->ren1->branch);
|
ci->ren1->branch);
|
||||||
if (update_file(opt, 0, &mfi.blob,
|
if (update_file(opt, 0, &mfi.blob,
|
||||||
new_path ? new_path : b->path))
|
new_path ? new_path : b->path))
|
||||||
return -1;
|
return -1;
|
||||||
free(new_path);
|
free(new_path);
|
||||||
if (update_stages(opt, b->path, NULL, NULL, b))
|
if (!opt->priv->call_depth &&
|
||||||
return -1;
|
update_stages(opt, b->path, NULL, NULL, b))
|
||||||
}
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -61,7 +61,7 @@ static enum parse_opt_result opt_command_mode_error(
|
||||||
*/
|
*/
|
||||||
for (that = all_opts; that->type != OPTION_END; that++) {
|
for (that = all_opts; that->type != OPTION_END; that++) {
|
||||||
if (that == opt ||
|
if (that == opt ||
|
||||||
that->type != OPTION_CMDMODE ||
|
!(that->flags & PARSE_OPT_CMDMODE) ||
|
||||||
that->value != opt->value ||
|
that->value != opt->value ||
|
||||||
that->defval != *(int *)opt->value)
|
that->defval != *(int *)opt->value)
|
||||||
continue;
|
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))
|
if (!(flags & OPT_SHORT) && p->opt && (opt->flags & PARSE_OPT_NOARG))
|
||||||
return error(_("%s takes no value"), optname(opt, flags));
|
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) {
|
switch (opt->type) {
|
||||||
case OPTION_LOWLEVEL_CALLBACK:
|
case OPTION_LOWLEVEL_CALLBACK:
|
||||||
return opt->ll_callback(p, opt, NULL, unset);
|
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;
|
*(int *)opt->value = unset ? 0 : opt->defval;
|
||||||
return 0;
|
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:
|
case OPTION_STRING:
|
||||||
if (unset)
|
if (unset)
|
||||||
*(const char **)opt->value = NULL;
|
*(const char **)opt->value = NULL;
|
||||||
|
|
|
@ -18,7 +18,6 @@ enum parse_opt_type {
|
||||||
OPTION_BITOP,
|
OPTION_BITOP,
|
||||||
OPTION_COUNTUP,
|
OPTION_COUNTUP,
|
||||||
OPTION_SET_INT,
|
OPTION_SET_INT,
|
||||||
OPTION_CMDMODE,
|
|
||||||
/* options with arguments (usually) */
|
/* options with arguments (usually) */
|
||||||
OPTION_STRING,
|
OPTION_STRING,
|
||||||
OPTION_INTEGER,
|
OPTION_INTEGER,
|
||||||
|
@ -47,7 +46,8 @@ enum parse_opt_option_flags {
|
||||||
PARSE_OPT_LITERAL_ARGHELP = 64,
|
PARSE_OPT_LITERAL_ARGHELP = 64,
|
||||||
PARSE_OPT_SHELL_EVAL = 256,
|
PARSE_OPT_SHELL_EVAL = 256,
|
||||||
PARSE_OPT_NOCOMPLETE = 512,
|
PARSE_OPT_NOCOMPLETE = 512,
|
||||||
PARSE_OPT_COMP_ARG = 1024
|
PARSE_OPT_COMP_ARG = 1024,
|
||||||
|
PARSE_OPT_CMDMODE = 2048
|
||||||
};
|
};
|
||||||
|
|
||||||
enum parse_opt_result {
|
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_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, \
|
#define OPT_HIDDEN_BOOL(s, l, v, h) { OPTION_SET_INT, (s), (l), (v), NULL, \
|
||||||
(h), PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, 1}
|
(h), PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, 1}
|
||||||
#define OPT_CMDMODE(s, l, v, h, i) { OPTION_CMDMODE, (s), (l), (v), NULL, \
|
#define OPT_CMDMODE(s, l, v, h, i) { OPTION_SET_INT, (s), (l), (v), NULL, \
|
||||||
(h), PARSE_OPT_NOARG|PARSE_OPT_NONEG, NULL, (i) }
|
(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_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), \
|
#define OPT_MAGNITUDE(s, l, v, h) { OPTION_MAGNITUDE, (s), (l), (v), \
|
||||||
N_("n"), (h), PARSE_OPT_NONEG }
|
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 (incorrect) {
|
||||||
if (todo_list_check_against_backup(r, new_todo)) {
|
if (todo_list_check_against_backup(r, new_todo)) {
|
||||||
write_file(rebase_path_dropped(), "");
|
write_file(rebase_path_dropped(), "%s", "");
|
||||||
return -4;
|
return -4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (incorrect > 0)
|
if (incorrect > 0)
|
||||||
unlink(rebase_path_dropped());
|
unlink(rebase_path_dropped());
|
||||||
} else if (todo_list_check(todo_list, new_todo)) {
|
} else if (todo_list_check(todo_list, new_todo)) {
|
||||||
write_file(rebase_path_dropped(), "");
|
write_file(rebase_path_dropped(), "%s", "");
|
||||||
return -4;
|
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_http_walker(url.buf);
|
||||||
walker->get_verbosely = options.verbosity >= 3;
|
walker->get_verbosely = options.verbosity >= 3;
|
||||||
|
walker->get_progress = options.progress;
|
||||||
walker->get_recover = 0;
|
walker->get_recover = 0;
|
||||||
ret = walker_fetch(walker, nr_heads, targets, NULL, NULL);
|
ret = walker_fetch(walker, nr_heads, targets, NULL, NULL);
|
||||||
walker_free(walker);
|
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_INTEGER('j', NULL, &integer, "get a integer, too"),
|
||||||
OPT_MAGNITUDE('m', "magnitude", &magnitude, "get a magnitude"),
|
OPT_MAGNITUDE('m', "magnitude", &magnitude, "get a magnitude"),
|
||||||
OPT_SET_INT(0, "set23", &integer, "set integer to 23", 23),
|
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",
|
OPT_CALLBACK('L', "length", &integer, "str",
|
||||||
"get length of <str>", length_callback),
|
"get length of <str>", length_callback),
|
||||||
OPT_FILENAME('F', "file", &file, "set file to <file>"),
|
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
|
-j <n> get a integer, too
|
||||||
-m, --magnitude <n> get a magnitude
|
-m, --magnitude <n> get a magnitude
|
||||||
--set23 set integer to 23
|
--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>
|
-L, --length <str> get length of <str>
|
||||||
-F, --file <file> set file to <file>
|
-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-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_expect_success 'OPT_COUNTUP() with PARSE_OPT_NODASH works' '
|
||||||
test-tool parse-options --expect="boolean: 6" + + + + + +
|
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
|
for p in .git/objects/pack/pack-*.pack
|
||||||
do
|
do
|
||||||
count=$(( $count + 1 ))
|
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
|
then
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
@ -65,7 +66,7 @@ test_expect_success 'add a large file or two' '
|
||||||
test $cnt = 2 &&
|
test $cnt = 2 &&
|
||||||
for l in .git/objects/??/??????????????????????????????????????
|
for l in .git/objects/??/??????????????????????????????????????
|
||||||
do
|
do
|
||||||
test -f "$l" || continue
|
test_path_is_file "$l" || continue
|
||||||
bad=t
|
bad=t
|
||||||
done &&
|
done &&
|
||||||
test -z "$bad" &&
|
test -z "$bad" &&
|
||||||
|
@ -76,7 +77,8 @@ test_expect_success 'add a large file or two' '
|
||||||
for p in .git/objects/pack/pack-*.pack
|
for p in .git/objects/pack/pack-*.pack
|
||||||
do
|
do
|
||||||
count=$(( $count + 1 ))
|
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
|
then
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
@ -111,7 +113,7 @@ test_expect_success 'packsize limit' '
|
||||||
count=0 &&
|
count=0 &&
|
||||||
for pi in .git/objects/pack/pack-*.idx
|
for pi in .git/objects/pack/pack-*.idx
|
||||||
do
|
do
|
||||||
test -f "$pi" && count=$(( $count + 1 ))
|
test_path_is_file "$pi" && count=$(( $count + 1 ))
|
||||||
done &&
|
done &&
|
||||||
test $count = 2 &&
|
test $count = 2 &&
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ test_expect_success 'setup' '
|
||||||
git config core.sparseCheckout true &&
|
git config core.sparseCheckout true &&
|
||||||
echo "/checked-out" >.git/info/sparse-checkout &&
|
echo "/checked-out" >.git/info/sparse-checkout &&
|
||||||
git reset --hard &&
|
git reset --hard &&
|
||||||
! git merge theirs
|
test_must_fail git merge theirs
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'reset --hard works after the conflict' '
|
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' '
|
test_expect_success 'setup: conflict back' '
|
||||||
! git merge theirs
|
test_must_fail git merge theirs
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'Merge abort works after the conflict' '
|
test_expect_success 'Merge abort works after the conflict' '
|
||||||
|
|
|
@ -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 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' '
|
test_expect_success 'stash --invalid-option' '
|
||||||
echo bar5 >file &&
|
echo bar5 >file &&
|
||||||
echo bar6 >file2 &&
|
echo bar6 >file2 &&
|
||||||
|
|
|
@ -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_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' '
|
test_expect_success 'am --skip works' '
|
||||||
echo goodbye >expected &&
|
echo goodbye >expected &&
|
||||||
git am --skip &&
|
git am --skip &&
|
||||||
|
|
|
@ -1607,6 +1607,26 @@ test_expect_success GPG 'log --graph --show-signature for merged tag' '
|
||||||
grep "^| | gpg: Good signature" actual
|
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_expect_success GPGSM 'log --graph --show-signature for merged tag x509' '
|
||||||
test_when_finished "git reset --hard && git checkout master" &&
|
test_when_finished "git reset --hard && git checkout master" &&
|
||||||
test_config gpg.format x509 &&
|
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 4 -eq $(git ls-files -u | wc -l) &&
|
||||||
test 1 -eq $(git ls-files -o | wc -l) &&
|
test 1 -eq $(git ls-files -o | wc -l) &&
|
||||||
|
|
||||||
test -f letters/file &&
|
test_path_is_file letters/file &&
|
||||||
test -f letters.txt &&
|
test_path_is_file letters.txt &&
|
||||||
test -f letters~modify
|
test_path_is_file letters~modify
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'modify/delete + directory/file conflict; other way' '
|
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 4 -eq $(git ls-files -u | wc -l) &&
|
||||||
test 1 -eq $(git ls-files -o | wc -l) &&
|
test 1 -eq $(git ls-files -o | wc -l) &&
|
||||||
|
|
||||||
test -f letters/file &&
|
test_path_is_file letters/file &&
|
||||||
test -f letters.txt &&
|
test_path_is_file letters.txt &&
|
||||||
test -f letters~HEAD
|
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
|
test_done
|
||||||
|
|
|
@ -10,87 +10,58 @@
|
||||||
test_description='Test criss-cross merge'
|
test_description='Test criss-cross merge'
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
|
|
||||||
test_expect_success 'prepare repository' \
|
test_expect_success 'prepare repository' '
|
||||||
'echo "1
|
test_write_lines 1 2 3 4 5 6 7 8 9 >file &&
|
||||||
2
|
git add file &&
|
||||||
3
|
git commit -m "Initial commit" file &&
|
||||||
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 'Criss-cross merge' 'git merge -m "final merge" B'
|
git branch A &&
|
||||||
|
git branch B &&
|
||||||
|
git checkout A &&
|
||||||
|
|
||||||
cat > file-expect <<EOF
|
test_write_lines 1 2 3 4 5 6 7 "8 changed in B8, branch A" 9 >file &&
|
||||||
1
|
git commit -m "B8" file &&
|
||||||
2
|
git checkout B &&
|
||||||
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_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 merge -m "pre E3 merge" A &&
|
||||||
'git reset --hard A^ &&
|
|
||||||
test_must_fail git merge -s resolve -m "final merge" B'
|
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
|
test_done
|
||||||
|
|
|
@ -8,94 +8,94 @@ modify () {
|
||||||
mv "$2.x" "$2"
|
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' \
|
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 &&
|
rm -f A M N &&
|
||||||
git reset --hard &&
|
git reset --hard &&
|
||||||
git checkout change+rename &&
|
git checkout change+rename &&
|
||||||
|
|
||||||
|
test-tool chmtime =31337 B &&
|
||||||
|
test-tool chmtime --get B >old-mtime &&
|
||||||
GIT_MERGE_VERBOSITY=3 git merge change >out &&
|
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 reset --hard HEAD^ &&
|
||||||
git checkout change &&
|
git checkout change &&
|
||||||
|
|
||||||
|
test-tool chmtime =-1 M &&
|
||||||
|
test-tool chmtime --get M >old-mtime &&
|
||||||
GIT_MERGE_VERBOSITY=3 git merge change+rename >out &&
|
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' '
|
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"
|
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' '
|
test_expect_success 'Rename+D/F conflict; renamed file merges + dir not in way' '
|
||||||
git reset --hard &&
|
git reset --hard &&
|
||||||
git checkout -q renamed-file-has-no-conflicts^0 &&
|
git checkout -q renamed-file-has-no-conflicts^0 &&
|
||||||
|
|
||||||
git merge --strategy=recursive dir-not-in-way &&
|
git merge --strategy=recursive dir-not-in-way &&
|
||||||
|
|
||||||
git diff --quiet &&
|
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
|
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 --quiet &&
|
||||||
test_must_fail git diff --cached --quiet &&
|
test_must_fail git diff --cached --quiet &&
|
||||||
|
|
||||||
test -f dir/file-in-the-way &&
|
test_path_is_file dir/file-in-the-way &&
|
||||||
test -f dir~HEAD &&
|
test_path_is_file dir~HEAD &&
|
||||||
test_cmp expected 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 --quiet &&
|
||||||
test_must_fail git diff --cached --quiet &&
|
test_must_fail git diff --cached --quiet &&
|
||||||
|
|
||||||
test -f dir/file-in-the-way &&
|
test_path_is_file dir/file-in-the-way &&
|
||||||
test -f dir~renamed-file-has-no-conflicts &&
|
test_path_is_file dir~renamed-file-has-no-conflicts &&
|
||||||
test_cmp expected 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' '
|
test_expect_success 'Rename+D/F conflict; renamed file cannot merge, dir not in way' '
|
||||||
git reset --hard &&
|
git reset --hard &&
|
||||||
rm -rf dir~* &&
|
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 --quiet &&
|
||||||
test_must_fail git diff --cached --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
|
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 --quiet &&
|
||||||
test_must_fail git diff --cached --quiet &&
|
test_must_fail git diff --cached --quiet &&
|
||||||
|
|
||||||
test -f dir/file-in-the-way &&
|
test_path_is_file dir/file-in-the-way &&
|
||||||
test -f dir~HEAD &&
|
test_path_is_file dir~HEAD &&
|
||||||
test_cmp expected 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' '
|
test_expect_success 'Same as previous, but merged other way' '
|
||||||
git reset --hard &&
|
git reset --hard &&
|
||||||
rm -rf dir~* &&
|
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 --quiet &&
|
||||||
test_must_fail git diff --cached --quiet &&
|
test_must_fail git diff --cached --quiet &&
|
||||||
|
|
||||||
test -f dir/file-in-the-way &&
|
test_path_is_file dir/file-in-the-way &&
|
||||||
test -f dir~renamed-file-has-conflicts &&
|
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
|
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_must_fail git diff --quiet &&
|
||||||
|
|
||||||
test -f destdir/foo &&
|
test_path_is_file destdir/foo &&
|
||||||
test -f one &&
|
test_path_is_file one &&
|
||||||
test -f destdir~HEAD &&
|
test_path_is_file destdir~HEAD &&
|
||||||
test "stuff" = "$(cat 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 4 -eq $(find . | grep -v .git | wc -l) &&
|
||||||
|
|
||||||
test -d one &&
|
test_path_is_dir one &&
|
||||||
test -f one~rename-two &&
|
test_path_is_file one~rename-two &&
|
||||||
test -f two &&
|
test_path_is_file two &&
|
||||||
test "other" = $(cat one~rename-two) &&
|
test "other" = $(cat one~rename-two) &&
|
||||||
test "stuff" = $(cat 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 3 -eq $(find . | grep -v .git | wc -l) &&
|
||||||
|
|
||||||
test -f one &&
|
test_path_is_file one &&
|
||||||
test -f two &&
|
test_path_is_file two &&
|
||||||
test "other" = $(cat one) &&
|
test "other" = $(cat one) &&
|
||||||
test "stuff" = $(cat two)
|
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 1 -eq "$(git ls-files -u original | wc -l)" &&
|
||||||
test 2 -eq "$(git ls-files -o | wc -l)" &&
|
test 2 -eq "$(git ls-files -o | wc -l)" &&
|
||||||
|
|
||||||
test -f one/file &&
|
test_path_is_file one/file &&
|
||||||
test -f two/file &&
|
test_path_is_file two/file &&
|
||||||
test -f one~HEAD &&
|
test_path_is_file one~HEAD &&
|
||||||
test -f two~second-rename &&
|
test_path_is_file two~second-rename &&
|
||||||
! test -f original
|
test_path_is_missing original
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'setup rename one file to two; directories moving out of the way' '
|
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 1 -eq "$(git ls-files -u original | wc -l)" &&
|
||||||
test 0 -eq "$(git ls-files -o | wc -l)" &&
|
test 0 -eq "$(git ls-files -o | wc -l)" &&
|
||||||
|
|
||||||
test -f one &&
|
test_path_is_file one &&
|
||||||
test -f two &&
|
test_path_is_file two &&
|
||||||
! test -f original
|
test_path_is_missing original
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'setup avoid unnecessary update, normal rename' '
|
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
|
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' '
|
test_expect_success 'merge master into rename has correct extended markers' '
|
||||||
git checkout rename^0 &&
|
git checkout rename^0 &&
|
||||||
test_must_fail git merge -s recursive master^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
|
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' '
|
test_expect_success 'merge rename into master has correct extended markers' '
|
||||||
git reset --hard &&
|
git reset --hard &&
|
||||||
git checkout master^0 &&
|
git checkout master^0 &&
|
||||||
test_must_fail git merge -s recursive rename^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
|
test_cmp expected renamed_file
|
||||||
'
|
'
|
||||||
|
|
||||||
|
|
|
@ -3,56 +3,59 @@
|
||||||
test_description='RCS merge replacement: merge-file'
|
test_description='RCS merge replacement: merge-file'
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
|
|
||||||
cat > orig.txt << EOF
|
test_expect_success 'setup' '
|
||||||
Dominus regit me,
|
cat >orig.txt <<-\EOF &&
|
||||||
et nihil mihi deerit.
|
Dominus regit me,
|
||||||
In loco pascuae ibi me collocavit,
|
et nihil mihi deerit.
|
||||||
super aquam refectionis educavit me;
|
In loco pascuae ibi me collocavit,
|
||||||
animam meam convertit,
|
super aquam refectionis educavit me;
|
||||||
deduxit me super semitas jusitiae,
|
animam meam convertit,
|
||||||
propter nomen suum.
|
deduxit me super semitas jusitiae,
|
||||||
EOF
|
propter nomen suum.
|
||||||
|
EOF
|
||||||
|
|
||||||
cat > new1.txt << EOF
|
cat >new1.txt <<-\EOF &&
|
||||||
Dominus regit me,
|
Dominus regit me,
|
||||||
et nihil mihi deerit.
|
et nihil mihi deerit.
|
||||||
In loco pascuae ibi me collocavit,
|
In loco pascuae ibi me collocavit,
|
||||||
super aquam refectionis educavit me;
|
super aquam refectionis educavit me;
|
||||||
animam meam convertit,
|
animam meam convertit,
|
||||||
deduxit me super semitas jusitiae,
|
deduxit me super semitas jusitiae,
|
||||||
propter nomen suum.
|
propter nomen suum.
|
||||||
Nam et si ambulavero in medio umbrae mortis,
|
Nam et si ambulavero in medio umbrae mortis,
|
||||||
non timebo mala, quoniam tu mecum es:
|
non timebo mala, quoniam tu mecum es:
|
||||||
virga tua et baculus tuus ipsa me consolata sunt.
|
virga tua et baculus tuus ipsa me consolata sunt.
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
cat > new2.txt << EOF
|
cat >new2.txt <<-\EOF &&
|
||||||
Dominus regit me, et nihil mihi deerit.
|
Dominus regit me, et nihil mihi deerit.
|
||||||
In loco pascuae ibi me collocavit,
|
In loco pascuae ibi me collocavit,
|
||||||
super aquam refectionis educavit me;
|
super aquam refectionis educavit me;
|
||||||
animam meam convertit,
|
animam meam convertit,
|
||||||
deduxit me super semitas jusitiae,
|
deduxit me super semitas jusitiae,
|
||||||
propter nomen suum.
|
propter nomen suum.
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
cat > new3.txt << EOF
|
cat >new3.txt <<-\EOF &&
|
||||||
DOMINUS regit me,
|
DOMINUS regit me,
|
||||||
et nihil mihi deerit.
|
et nihil mihi deerit.
|
||||||
In loco pascuae ibi me collocavit,
|
In loco pascuae ibi me collocavit,
|
||||||
super aquam refectionis educavit me;
|
super aquam refectionis educavit me;
|
||||||
animam meam convertit,
|
animam meam convertit,
|
||||||
deduxit me super semitas jusitiae,
|
deduxit me super semitas jusitiae,
|
||||||
propter nomen suum.
|
propter nomen suum.
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
cat > new4.txt << EOF
|
cat >new4.txt <<-\EOF &&
|
||||||
Dominus regit me, et nihil mihi deerit.
|
Dominus regit me, et nihil mihi deerit.
|
||||||
In loco pascuae ibi me collocavit,
|
In loco pascuae ibi me collocavit,
|
||||||
super aquam refectionis educavit me;
|
super aquam refectionis educavit me;
|
||||||
animam meam convertit,
|
animam meam convertit,
|
||||||
deduxit me super semitas jusitiae,
|
deduxit me super semitas jusitiae,
|
||||||
EOF
|
EOF
|
||||||
printf "propter nomen suum." >> new4.txt
|
|
||||||
|
printf "propter nomen suum." >>new4.txt
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'merge with no changes' '
|
test_expect_success 'merge with no changes' '
|
||||||
cp orig.txt test.txt &&
|
cp orig.txt test.txt &&
|
||||||
|
@ -60,9 +63,10 @@ test_expect_success 'merge with no changes' '
|
||||||
test_cmp test.txt orig.txt
|
test_cmp test.txt orig.txt
|
||||||
'
|
'
|
||||||
|
|
||||||
cp new1.txt test.txt
|
test_expect_success "merge without conflict" '
|
||||||
test_expect_success "merge without conflict" \
|
cp new1.txt test.txt &&
|
||||||
"git merge-file test.txt orig.txt new2.txt"
|
git merge-file test.txt orig.txt new2.txt
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'works in subdirectory' '
|
test_expect_success 'works in subdirectory' '
|
||||||
mkdir dir &&
|
mkdir dir &&
|
||||||
|
@ -73,151 +77,176 @@ test_expect_success 'works in subdirectory' '
|
||||||
test_path_is_missing a.txt
|
test_path_is_missing a.txt
|
||||||
'
|
'
|
||||||
|
|
||||||
cp new1.txt test.txt
|
test_expect_success "merge without conflict (--quiet)" '
|
||||||
test_expect_success "merge without conflict (--quiet)" \
|
cp new1.txt test.txt &&
|
||||||
"git merge-file --quiet test.txt orig.txt new2.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)" '
|
||||||
test_expect_failure "merge without conflict (missing LF at EOF)" \
|
cp new1.txt test2.txt &&
|
||||||
"git merge-file test2.txt orig.txt new4.txt"
|
git merge-file test2.txt orig.txt new4.txt
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_failure "merge result added missing LF" \
|
test_expect_failure "merge result added missing LF" '
|
||||||
"test_cmp test.txt test2.txt"
|
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)" '
|
||||||
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"
|
git merge-file --quiet test3.txt new2.txt new3.txt
|
||||||
|
'
|
||||||
|
|
||||||
cat > expect.txt << EOF
|
test_expect_success "merge does not add LF away of change" '
|
||||||
DOMINUS regit me,
|
cat >expect.txt <<-\EOF &&
|
||||||
et nihil mihi deerit.
|
DOMINUS regit me,
|
||||||
In loco pascuae ibi me collocavit,
|
et nihil mihi deerit.
|
||||||
super aquam refectionis educavit me;
|
In loco pascuae ibi me collocavit,
|
||||||
animam meam convertit,
|
super aquam refectionis educavit me;
|
||||||
deduxit me super semitas jusitiae,
|
animam meam convertit,
|
||||||
EOF
|
deduxit me super semitas jusitiae,
|
||||||
printf "propter nomen suum." >> expect.txt
|
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_expect_success "merge with conflicts" \
|
cp test.txt backup.txt &&
|
||||||
"test_must_fail git merge-file test.txt orig.txt new3.txt"
|
test_must_fail git merge-file test.txt orig.txt new3.txt
|
||||||
|
'
|
||||||
|
|
||||||
cat > expect.txt << EOF
|
test_expect_success "expected conflict markers" '
|
||||||
<<<<<<< test.txt
|
cat >expect.txt <<-\EOF &&
|
||||||
Dominus regit me, et nihil mihi deerit.
|
<<<<<<< test.txt
|
||||||
=======
|
Dominus regit me, et nihil mihi deerit.
|
||||||
DOMINUS regit me,
|
=======
|
||||||
et nihil mihi deerit.
|
DOMINUS regit me,
|
||||||
>>>>>>> new3.txt
|
et nihil mihi deerit.
|
||||||
In loco pascuae ibi me collocavit,
|
>>>>>>> new3.txt
|
||||||
super aquam refectionis educavit me;
|
In loco pascuae ibi me collocavit,
|
||||||
animam meam convertit,
|
super aquam refectionis educavit me;
|
||||||
deduxit me super semitas jusitiae,
|
animam meam convertit,
|
||||||
propter nomen suum.
|
deduxit me super semitas jusitiae,
|
||||||
Nam et si ambulavero in medio umbrae mortis,
|
propter nomen suum.
|
||||||
non timebo mala, quoniam tu mecum es:
|
Nam et si ambulavero in medio umbrae mortis,
|
||||||
virga tua et baculus tuus ipsa me consolata sunt.
|
non timebo mala, quoniam tu mecum es:
|
||||||
EOF
|
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
|
cat >expect.txt <<-\EOF &&
|
||||||
Dominus regit me, et nihil mihi deerit.
|
Dominus regit me, et nihil mihi deerit.
|
||||||
In loco pascuae ibi me collocavit,
|
In loco pascuae ibi me collocavit,
|
||||||
super aquam refectionis educavit me;
|
super aquam refectionis educavit me;
|
||||||
animam meam convertit,
|
animam meam convertit,
|
||||||
deduxit me super semitas jusitiae,
|
deduxit me super semitas jusitiae,
|
||||||
propter nomen suum.
|
propter nomen suum.
|
||||||
Nam et si ambulavero in medio umbrae mortis,
|
Nam et si ambulavero in medio umbrae mortis,
|
||||||
non timebo mala, quoniam tu mecum es:
|
non timebo mala, quoniam tu mecum es:
|
||||||
virga tua et baculus tuus ipsa me consolata sunt.
|
virga tua et baculus tuus ipsa me consolata sunt.
|
||||||
EOF
|
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
|
git merge-file --ours test.txt orig.txt new3.txt &&
|
||||||
DOMINUS regit me,
|
test_cmp expect.txt test.txt
|
||||||
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
|
|
||||||
|
|
||||||
cat > expect.txt << EOF
|
test_expect_success "merge conflicting with --theirs" '
|
||||||
Dominus regit me, et nihil mihi deerit.
|
cp backup.txt test.txt &&
|
||||||
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 with conflicts, using -L" \
|
cat >expect.txt <<-\EOF &&
|
||||||
"test_must_fail git merge-file -L 1 -L 2 test.txt orig.txt new3.txt"
|
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
|
git merge-file --theirs test.txt orig.txt new3.txt &&
|
||||||
<<<<<<< 1
|
test_cmp expect.txt 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, with -L" \
|
test_expect_success "merge conflicting with --union" '
|
||||||
"test_cmp expect.txt test.txt"
|
cp backup.txt test.txt &&
|
||||||
|
|
||||||
sed "s/ tu / TU /" < new1.txt > new5.txt
|
cat >expect.txt <<-\EOF &&
|
||||||
test_expect_success "conflict in removed tail" \
|
Dominus regit me, et nihil mihi deerit.
|
||||||
"test_must_fail git merge-file -p orig.txt new1.txt new5.txt > out"
|
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
|
git merge-file --union test.txt orig.txt new3.txt &&
|
||||||
Dominus regit me,
|
test_cmp expect.txt test.txt
|
||||||
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_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_expect_success 'binary files cannot be merged' '
|
||||||
test_must_fail git merge-file -p \
|
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
|
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' '
|
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_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' '
|
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 \
|
test_must_fail git merge-file -p \
|
||||||
new8.txt new5.txt new9.txt > merge.out &&
|
new8.txt new5.txt new9.txt >merge.out &&
|
||||||
test 1 = $(grep ======= < merge.out | wc -l)
|
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)' '
|
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 \
|
test_must_fail git merge-file -p --diff3 \
|
||||||
new8.txt new5.txt new9.txt >actual &&
|
new8.txt new5.txt new9.txt >actual &&
|
||||||
test_cmp expect actual
|
test_cmp expect actual
|
||||||
|
@ -290,61 +315,64 @@ test_expect_success '"diff3 -m" style output (2)' '
|
||||||
test_cmp expect actual
|
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' '
|
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 \
|
test_must_fail git merge-file -p --marker-size=10 \
|
||||||
new8.txt new5.txt new9.txt >actual &&
|
new8.txt new5.txt new9.txt >actual &&
|
||||||
test_cmp expect actual
|
test_cmp expect actual
|
||||||
'
|
'
|
||||||
|
|
||||||
printf "line1\nline2\nline3" >nolf-orig.txt
|
test_expect_success 'conflict at EOF without LF resolved by --ours' '
|
||||||
printf "line1\nline2\nline3x" >nolf-diff1.txt
|
printf "line1\nline2\nline3" >nolf-orig.txt &&
|
||||||
printf "line1\nline2\nline3y" >nolf-diff2.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 &&
|
||||||
'git merge-file -p --ours nolf-diff1.txt nolf-orig.txt nolf-diff2.txt >output.txt &&
|
printf "line1\nline2\nline3x" >expect.txt &&
|
||||||
printf "line1\nline2\nline3x" >expect.txt &&
|
test_cmp expect.txt output.txt
|
||||||
test_cmp expect.txt output.txt'
|
'
|
||||||
|
|
||||||
test_expect_success 'conflict at EOF without LF resolved by --theirs' \
|
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 &&
|
git merge-file -p --theirs nolf-diff1.txt nolf-orig.txt nolf-diff2.txt >output.txt &&
|
||||||
printf "line1\nline2\nline3y" >expect.txt &&
|
printf "line1\nline2\nline3y" >expect.txt &&
|
||||||
test_cmp expect.txt output.txt'
|
test_cmp expect.txt output.txt
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'conflict at EOF without LF resolved by --union' \
|
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 &&
|
git merge-file -p --union nolf-diff1.txt nolf-orig.txt nolf-diff2.txt >output.txt &&
|
||||||
printf "line1\nline2\nline3x\nline3y" >expect.txt &&
|
printf "line1\nline2\nline3x\nline3y" >expect.txt &&
|
||||||
test_cmp expect.txt output.txt'
|
test_cmp expect.txt output.txt
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'conflict sections match existing line endings' '
|
test_expect_success 'conflict sections match existing line endings' '
|
||||||
printf "1\\r\\n2\\r\\n3" >crlf-orig.txt &&
|
printf "1\\r\\n2\\r\\n3" >crlf-orig.txt &&
|
||||||
|
|
|
@ -32,7 +32,29 @@ test_expect_success setup '
|
||||||
test_tick &&
|
test_tick &&
|
||||||
git commit -m Side &&
|
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 '
|
test_expect_success merge '
|
||||||
|
@ -82,28 +104,6 @@ test_expect_success 'retry the merge with longer context' '
|
||||||
grep "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" actual
|
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' '
|
test_expect_success 'custom merge backend' '
|
||||||
|
|
||||||
echo "* merge=union" >.gitattributes &&
|
echo "* merge=union" >.gitattributes &&
|
||||||
|
|
|
@ -3,74 +3,73 @@
|
||||||
test_description='Merge-recursive merging renames'
|
test_description='Merge-recursive merging renames'
|
||||||
. ./test-lib.sh
|
. ./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
|
# 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 checkout -b red-white red &&
|
||||||
git merge white &&
|
git merge white &&
|
||||||
git write-tree &&
|
git write-tree &&
|
||||||
|
@ -82,8 +81,7 @@ test_expect_success 'merge white into red (A->B,M->N)' \
|
||||||
'
|
'
|
||||||
|
|
||||||
# This test broke in 8371234ecaaf6e14fe3f2082a855eff1bbd79ae9
|
# 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 &&
|
git checkout -b white-blue white &&
|
||||||
echo dirty >A &&
|
echo dirty >A &&
|
||||||
git merge blue &&
|
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 rm --cached a/b &&
|
||||||
git commit -m "untracked symlink remains" &&
|
git commit -m "untracked symlink remains" &&
|
||||||
git checkout -f start^0 &&
|
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' '
|
test_expect_success 'checkout should not have deleted a/b-2/c/d' '
|
||||||
git checkout HEAD^0 &&
|
git checkout HEAD^0 &&
|
||||||
git reset --hard master &&
|
git reset --hard master &&
|
||||||
git checkout start^0 &&
|
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' '
|
test_expect_success 'setup for merge test' '
|
||||||
git reset --hard &&
|
git reset --hard &&
|
||||||
test -f a/b-2/c/d &&
|
test_path_is_file a/b-2/c/d &&
|
||||||
echo x > a/x &&
|
echo x > a/x &&
|
||||||
git add a/x &&
|
git add a/x &&
|
||||||
git commit -m 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 reset --hard &&
|
||||||
git checkout baseline^0 &&
|
git checkout baseline^0 &&
|
||||||
git merge -s resolve master &&
|
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' '
|
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 reset --hard &&
|
||||||
git checkout baseline^0 &&
|
git checkout baseline^0 &&
|
||||||
git merge -s recursive master &&
|
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' '
|
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 reset --hard &&
|
||||||
git checkout master^0 &&
|
git checkout master^0 &&
|
||||||
git merge -s resolve baseline^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' '
|
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 reset --hard &&
|
||||||
git checkout master^0 &&
|
git checkout master^0 &&
|
||||||
git merge -s recursive baseline^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' '
|
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 &&
|
git checkout baseline^0 &&
|
||||||
>a/b/c/e &&
|
>a/b/c/e &&
|
||||||
test_must_fail git merge -s resolve master &&
|
test_must_fail git merge -s resolve master &&
|
||||||
test -f a/b/c/e &&
|
test_path_is_file a/b/c/e &&
|
||||||
test -f a/b-2/c/d
|
test_path_is_file a/b-2/c/d
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'do not lose untracked in merge (recursive)' '
|
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 &&
|
git checkout baseline^0 &&
|
||||||
>a/b/c/e &&
|
>a/b/c/e &&
|
||||||
test_must_fail git merge -s recursive master &&
|
test_must_fail git merge -s recursive master &&
|
||||||
test -f a/b/c/e &&
|
test_path_is_file a/b/c/e &&
|
||||||
test -f a/b-2/c/d
|
test_path_is_file a/b-2/c/d
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'do not lose modifications in merge (resolve)' '
|
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 reset --hard &&
|
||||||
git checkout baseline^0 &&
|
git checkout baseline^0 &&
|
||||||
git merge -s resolve test2 &&
|
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' '
|
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 reset --hard &&
|
||||||
git checkout baseline^0 &&
|
git checkout baseline^0 &&
|
||||||
git merge -s recursive test2 &&
|
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' '
|
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 reset --hard &&
|
||||||
git checkout -b foo test2 &&
|
git checkout -b foo test2 &&
|
||||||
git merge -s recursive baseline^0 &&
|
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' '
|
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 &&
|
test_must_fail git merge -s recursive R2^0 &&
|
||||||
|
|
||||||
git ls-files -s >out &&
|
git ls-files -s >out &&
|
||||||
test_line_count = 2 out &&
|
test_line_count = 5 out &&
|
||||||
git ls-files -u >out &&
|
git ls-files -u >out &&
|
||||||
test_line_count = 2 out &&
|
test_line_count = 3 out &&
|
||||||
git ls-files -o >out &&
|
git ls-files -o >out &&
|
||||||
test_line_count = 1 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 &&
|
test_must_fail git merge -s recursive R2^0 &&
|
||||||
|
|
||||||
git ls-files -s >out &&
|
git ls-files -s >out &&
|
||||||
test_line_count = 2 out &&
|
test_line_count = 5 out &&
|
||||||
git ls-files -u >out &&
|
git ls-files -u >out &&
|
||||||
test_line_count = 2 out &&
|
test_line_count = 3 out &&
|
||||||
git ls-files -o >out &&
|
git ls-files -o >out &&
|
||||||
test_line_count = 1 out &&
|
test_line_count = 1 out &&
|
||||||
|
|
||||||
|
@ -218,8 +218,18 @@ test_expect_success 'git detects differently handled merges conflict' '
|
||||||
git ls-files -o >out &&
|
git ls-files -o >out &&
|
||||||
test_line_count = 1 out &&
|
test_line_count = 1 out &&
|
||||||
|
|
||||||
git rev-parse >expect \
|
git cat-file -p C:new_a >ours &&
|
||||||
C:new_a D:new_a E:new_a &&
|
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 \
|
git rev-parse >actual \
|
||||||
:1:new_a :2:new_a :3:new_a &&
|
:1:new_a :2:new_a :3:new_a &&
|
||||||
test_cmp expect actual &&
|
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}") &&
|
ctime=$(git log --no-walk --date=raw --format=%cd C | awk "{print \$1}") &&
|
||||||
newctime=$(($btime+1)) &&
|
newctime=$(($btime+1)) &&
|
||||||
git fast-export --no-data --all | sed -e s/$ctime/$newctime/ | git fast-import --force --quiet &&
|
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 &&
|
git checkout D^0 &&
|
||||||
test_must_fail git merge -s recursive E^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 &&
|
git ls-files -o >out &&
|
||||||
test_line_count = 1 out &&
|
test_line_count = 1 out &&
|
||||||
|
|
||||||
git rev-parse >expect \
|
git cat-file -p C:a >ours &&
|
||||||
C:new_a D:new_a E:new_a &&
|
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 \
|
git rev-parse >actual \
|
||||||
:1:new_a :2:new_a :3:new_a &&
|
:1:new_a :2:new_a :3:new_a &&
|
||||||
test_cmp expect actual &&
|
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 &&
|
git checkout A^0 &&
|
||||||
|
|
||||||
test-tool chmtime =31337 b &&
|
test-tool chmtime =-1 b &&
|
||||||
test-tool chmtime -v +0 b >expected-mtime &&
|
test-tool chmtime --get b >old-mtime &&
|
||||||
|
|
||||||
GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
|
GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
|
||||||
|
|
||||||
test_i18ngrep "Skipped b" out &&
|
|
||||||
test_must_be_empty err &&
|
test_must_be_empty err &&
|
||||||
|
|
||||||
test-tool chmtime -v +0 b >actual-mtime &&
|
# Make sure b was NOT updated
|
||||||
test_cmp expected-mtime actual-mtime &&
|
test-tool chmtime --get b >new-mtime &&
|
||||||
|
test_cmp old-mtime new-mtime &&
|
||||||
|
|
||||||
git ls-files -s >index_files &&
|
git ls-files -s >index_files &&
|
||||||
test_line_count = 1 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 &&
|
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 &&
|
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 &&
|
test_must_be_empty err &&
|
||||||
|
|
||||||
git ls-files -s >index_files &&
|
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 &&
|
git checkout A^0 &&
|
||||||
|
|
||||||
|
test_path_is_missing c &&
|
||||||
GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
|
GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
|
||||||
|
|
||||||
test_i18ngrep ! "Skipped c" out &&
|
test_path_is_file c &&
|
||||||
test_must_be_empty err &&
|
|
||||||
|
|
||||||
git ls-files -s >index_files &&
|
git ls-files -s >index_files &&
|
||||||
test_line_count = 1 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 &&
|
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 &&
|
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 &&
|
test_must_be_empty err &&
|
||||||
|
|
||||||
git ls-files -s >index_files &&
|
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 &&
|
git checkout A^0 &&
|
||||||
|
|
||||||
test-tool chmtime =31337 c &&
|
test-tool chmtime =-1 c &&
|
||||||
test-tool chmtime -v +0 c >expected-mtime &&
|
test-tool chmtime --get c >old-mtime &&
|
||||||
|
|
||||||
GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
|
GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
|
||||||
|
|
||||||
test_i18ngrep "Skipped c" out &&
|
|
||||||
test_must_be_empty err &&
|
test_must_be_empty err &&
|
||||||
|
|
||||||
test-tool chmtime -v +0 c >actual-mtime &&
|
# Make sure c WAS updated
|
||||||
test_cmp expected-mtime actual-mtime &&
|
test-tool chmtime --get c >new-mtime &&
|
||||||
|
test_cmp old-mtime new-mtime &&
|
||||||
|
|
||||||
git ls-files -s >index_files &&
|
git ls-files -s >index_files &&
|
||||||
test_line_count = 1 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 &&
|
git checkout B^0 &&
|
||||||
|
|
||||||
|
test_path_is_missing c &&
|
||||||
GIT_MERGE_VERBOSITY=3 git merge -s recursive A^0 >out 2>err &&
|
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 &&
|
test_must_be_empty err &&
|
||||||
|
|
||||||
git ls-files -s >index_files &&
|
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 &&
|
git checkout A^0 &&
|
||||||
|
|
||||||
|
test-tool chmtime =-1 c &&
|
||||||
|
test-tool chmtime --get c >old-mtime &&
|
||||||
GIT_MERGE_VERBOSITY=3 &&
|
GIT_MERGE_VERBOSITY=3 &&
|
||||||
export GIT_MERGE_VERBOSITY &&
|
export GIT_MERGE_VERBOSITY &&
|
||||||
test_must_fail git merge -s recursive B^0 >out 2>err &&
|
test_must_fail git merge -s recursive B^0 >out 2>err &&
|
||||||
|
|
||||||
test_i18ngrep "CONFLICT (rename/add): Rename b->c" out &&
|
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;
|
# FIXME: rename/add conflicts are horribly broken right now;
|
||||||
# when I get back to my patch series fixing it and
|
# 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 &&
|
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 &&
|
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_must_be_empty err &&
|
||||||
|
|
||||||
|
test_path_is_file bar/bq &&
|
||||||
|
|
||||||
git ls-files -s >index_files &&
|
git ls-files -s >index_files &&
|
||||||
test_line_count = 2 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 &&
|
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 &&
|
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_must_be_empty err &&
|
||||||
|
|
||||||
|
test_path_is_file bar/bq &&
|
||||||
|
|
||||||
git ls-files -s >index_files &&
|
git ls-files -s >index_files &&
|
||||||
test_line_count = 2 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 &&
|
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 &&
|
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_must_be_empty err &&
|
||||||
|
|
||||||
|
test_path_is_file bar/bq &&
|
||||||
|
|
||||||
git ls-files -s >index_files &&
|
git ls-files -s >index_files &&
|
||||||
test_line_count = 2 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 &&
|
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 &&
|
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_must_be_empty err &&
|
||||||
|
|
||||||
|
test_path_is_file bar/bq &&
|
||||||
|
|
||||||
git ls-files -s >index_files &&
|
git ls-files -s >index_files &&
|
||||||
test_line_count = 2 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 &&
|
git checkout A^0 &&
|
||||||
echo "File rewritten" >b &&
|
echo "File rewritten" >b &&
|
||||||
|
|
||||||
test-tool chmtime =31337 b &&
|
test-tool chmtime =-1 b &&
|
||||||
test-tool chmtime -v +0 b >expected-mtime &&
|
test-tool chmtime --get b >old-mtime &&
|
||||||
|
|
||||||
GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
|
GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
|
||||||
|
|
||||||
test_i18ngrep "Skipped b" out &&
|
|
||||||
test_must_be_empty err &&
|
test_must_be_empty err &&
|
||||||
|
|
||||||
test-tool chmtime -v +0 b >actual-mtime &&
|
# Make sure b was NOT updated
|
||||||
test_cmp expected-mtime actual-mtime &&
|
test-tool chmtime --get b >new-mtime &&
|
||||||
|
test_cmp old-mtime new-mtime &&
|
||||||
|
|
||||||
git ls-files -s >index_files &&
|
git ls-files -s >index_files &&
|
||||||
test_line_count = 1 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 &&
|
git checkout A^0 &&
|
||||||
echo "File rewritten" >c &&
|
echo "File rewritten" >c &&
|
||||||
|
|
||||||
test-tool chmtime =31337 c &&
|
test-tool chmtime =-1 c &&
|
||||||
test-tool chmtime -v +0 c >expected-mtime &&
|
test-tool chmtime --get c >old-mtime &&
|
||||||
|
|
||||||
GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
|
GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
|
||||||
|
|
||||||
test_i18ngrep "Skipped c" out &&
|
|
||||||
test_must_be_empty err &&
|
test_must_be_empty err &&
|
||||||
|
|
||||||
test-tool chmtime -v +0 c >actual-mtime &&
|
# Make sure c was NOT updated
|
||||||
test_cmp expected-mtime actual-mtime &&
|
test-tool chmtime --get c >new-mtime &&
|
||||||
|
test_cmp old-mtime new-mtime &&
|
||||||
|
|
||||||
git ls-files -s >index_files &&
|
git ls-files -s >index_files &&
|
||||||
test_line_count = 1 index_files &&
|
test_line_count = 1 index_files &&
|
||||||
|
|
13
walker.c
13
walker.c
|
@ -8,6 +8,7 @@
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
#include "blob.h"
|
#include "blob.h"
|
||||||
#include "refs.h"
|
#include "refs.h"
|
||||||
|
#include "progress.h"
|
||||||
|
|
||||||
static struct object_id current_commit_oid;
|
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)
|
static int loop(struct walker *walker)
|
||||||
{
|
{
|
||||||
struct object_list *elem;
|
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) {
|
while (process_queue) {
|
||||||
struct object *obj = process_queue->item;
|
struct object *obj = process_queue->item;
|
||||||
|
@ -176,15 +182,20 @@ static int loop(struct walker *walker)
|
||||||
*/
|
*/
|
||||||
if (! (obj->flags & TO_SCAN)) {
|
if (! (obj->flags & TO_SCAN)) {
|
||||||
if (walker->fetch(walker, obj->oid.hash)) {
|
if (walker->fetch(walker, obj->oid.hash)) {
|
||||||
|
stop_progress(&progress);
|
||||||
report_missing(obj);
|
report_missing(obj);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!obj->type)
|
if (!obj->type)
|
||||||
parse_object(the_repository, &obj->oid);
|
parse_object(the_repository, &obj->oid);
|
||||||
if (process_object(walker, obj))
|
if (process_object(walker, obj)) {
|
||||||
|
stop_progress(&progress);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
display_progress(progress, ++nr);
|
||||||
}
|
}
|
||||||
|
stop_progress(&progress);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1
walker.h
1
walker.h
|
@ -10,6 +10,7 @@ struct walker {
|
||||||
int (*fetch)(struct walker *, unsigned char *sha1);
|
int (*fetch)(struct walker *, unsigned char *sha1);
|
||||||
void (*cleanup)(struct walker *);
|
void (*cleanup)(struct walker *);
|
||||||
int get_verbosely;
|
int get_verbosely;
|
||||||
|
int get_progress;
|
||||||
int get_recover;
|
int get_recover;
|
||||||
|
|
||||||
int corrupt_object_found;
|
int corrupt_object_found;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче