Commit Graph

98402 Commits

Author SHA1 Message Date
Johannes Schindelin
345be1b134 built-in add -i: start implementing the patch functionality in C
In the previous steps, we re-implemented the main loop of `git add -i`
in C, and most of the commands.

Notably, we left out the actual functionality of `patch`, as the
relevant code makes up more than half of `git-add--interactive.perl`,
and is actually pretty independent of the rest of the commands.

With this commit, we start to tackle that `patch` part. For better
separation of concerns, we keep the code in a separate file,
`add-patch.c`. The new code is still guarded behind the
`add.interactive.useBuiltin` config setting, and for the moment,
it can only be called via `git add -p`.

The actual functionality follows the original implementation of
5cde71d64a (git-add --interactive, 2006-12-10), but not too closely
(for example, we use string offsets rather than copying strings around,
and we also remember which previous/next hunk was undecided, rather than
looking again when the user asked to jump there).

As a further deviation from that commit, We also use a comma instead of
a slash to separate the available commands in the prompt, as the current
version of the Perl script does this, and we also add a line about the
question mark ("print help") to the help text.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 23:01:40 +02:00
Johannes Schindelin
cfd029e13d apply --allow-overlap: fix a corner case
Yes, yes, this is supposed to be only a band-aid option for `git add -p`
not Doing The Right Thing. But as long as we carry the `--allow-overlap`
option, we might just as well get it right.

This fixes the case where one hunk inserts a line before the first one,
and a hunk whose context overlaps with the first one's appends a line at
the end.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 23:01:40 +02:00
Johannes Schindelin
5ffcb49c6d git add -p: use non-zero exit code when the diff generation failed
The first thing `git add -p` does is to generate a diff. If this diff
cannot be generated, `git add -p` should not continue as if nothing
happened, but instead fail.

What we *actually* do here is much broader: we now verify for *every*
`run_cmd_pipe()` call that the spawned process actually succeeded.

Note that we have to change two callers in this patch, as we need to
store the spawned process' output in a local variable, which means that
the callers can no longer decide whether to interpret the `return <$fh>`
in array or in scalar context.

This bug was noticed while writing a test case for the diff.algorithm
feature, and we let that test case double as a regression test for this
fixed bug, too.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 23:01:39 +02:00
Johannes Schindelin
ec81a5486c t3701: verify that the diff.algorithm config setting is handled
Without this patch, there is actually no test in Git's test suite that
covers the diff.algorithm feature. Let's add one.

We do this by passing a bogus value and then expecting `git diff-files`
to produce the appropriate error message.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 23:01:39 +02:00
Johannes Schindelin
53a2c9daa0 t3701: verify the shown messages when nothing can be added
In preparation for re-implementing `git add -p` in pure C (where we will
purposefully keep the implementation of `git add -p` separate from the
implementation of `git add -i`), let's verify that the user is told the
same things as in the Perl version when the diff file is either empty or
contains only entries about binary files.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 23:01:39 +02:00
Johannes Schindelin
54cdf43705 t3701: add a test for the different add -p prompts
The `git add -p` command offers different prompts for regular diff hunks
vs mode change pseudo hunks vs diffs deleting files.

Let's cover this in the regresion test suite, in preparation for
re-implementing `git add -p` in C.

For the mode change prompt, we use a trick that lets this test case pass
even on systems without executable bit, i.e. where `core.filemode =
false` (such as Windows): we first add the file to the index with `git
add --chmod=+x`, and then call `git add -p` with `core.filemode` forced
to `true`. The file on disk has no executable bit set, therefore we will
see a mode change.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 23:01:39 +02:00
Johannes Schindelin
007f58c880 t3701: avoid depending on the TTY prerequisite
The TTY prerequisite is a rather heavy one: it not only requires Perl to
work, but also the IO/Pty.pm module (with native support, and it
requires pseudo terminals, too).

In particular, test cases marked with the TTY prerequisite would be
skipped in Git for Windows' SDK.

In the case of `git add -p`, we do not actually need that big a hammer,
as we do not want to test any functionality that requires a pseudo
terminal; all we want is to talk the interactive add command to use
color, even when being called from within the test suite.

And we found exactly such a trick earlier already: when we added a test
case to verify that the main loop of `git add -i` is colored
appropriately. Let's use that trick instead of the TTY prerequisite.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 23:01:39 +02:00
Johannes Schindelin
53a7243a0c t3701: add a test for advanced split-hunk editing
In this developer's workflows, it often happens that a hunk needs to be
edited in a way that adds lines, and even reduces the context

Let's add a regression test for this.

Note that just like the preceding test case, the new test case is *not*
handled gracefully by the current `git add -p`. It will be handled
correctly by the upcoming built-in `git add -p`, though.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 23:01:39 +02:00
Johannes Schindelin
0f8e505773 built-in add -i: offer the quit command
We do not really want to `exit()` here, of course, as this is safely
libified code.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 23:01:39 +02:00
Johannes Schindelin
d3ac7398db built-in add -i: re-implement the diff command
It is not only laziness that we simply spawn `git diff -p --cached`
here: this command needs to use the pager, and the pager needs to exit
when the diff is done. Currently we do not have any way to make that
happen if we run the diff in-process. So let's just spawn.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 23:01:38 +02:00
Johannes Schindelin
2b0bdda9b6 built-in add -i: implement the patch command
Well, it is not a full implementation yet. In the interest of making
this easy to review (and easy to keep bugs out), we still hand off to
the Perl script to do the actual work.

The `patch` functionality actually makes up for more than half of the
1,800+ lines of `git-add--interactive.perl`. It will be ported from Perl
to C incrementally, later.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 23:01:38 +02:00
Johannes Schindelin
64a51b70c6 built-in add -i: re-implement add-untracked in C
This is yet another command, ported to C. It builds nicely on the
support functions introduced for other commands, with the notable
difference that only names are displayed for untracked files, no
file type or diff summary.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 23:01:38 +02:00
Johannes Schindelin
c877ae8dbf built-in add -i: re-implement revert in C
This is a relatively straight-forward port from the Perl version, with
the notable exception that we imitate `git reset -- <paths>` in the C
version rather than the convoluted `git ls-tree HEAD -- <paths> | git
update-index --index-info` followed by `git update-index --force-remove
-- <paths>` for the missed ones.

While at it, we fix the pretty obvious bug where the `revert` command
offers to unstage files that do not have staged changes.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 23:01:38 +02:00
Johannes Schindelin
84e1b94aac built-in add -i: implement the update command
After `status` and `help`, it is now turn to port the `update` command
to C, the second command that is shown in the main loop menu of `git add
-i`.

This `git add -i` command is the first one which lets the user choose a
subset of a list of files, and as such, this patch lays the groundwork
for the other commands of that category:

- It teaches the `print_file_item()` function to show a unique prefix
  if we found any (the code to find it had been added already in the
  previous patch where we colored the unique prefixes of the main loop
  commands, but that patch uses the `print_command_item()` function to
  display the menu items).

- This patch also adds the help text that is shown when the user input
  to select items from the shown list could not be parsed.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 23:01:38 +02:00
Johannes Schindelin
5c8497fbfd built-in add -i: prepare for multi-selection commands
The `upgrade`, `revert` and `add-untracked` commands allow selecting
multiple entries. Let's extend the `list_and_choose()` function to
accommodate those use cases.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 23:01:38 +02:00
Johannes Schindelin
fc8c637600 built-in add -i: allow filtering the modified files list
In `update` command of `git add -i`, we are primarily interested in the
list of modified files that have worktree (i.e. unstaged) changes.

The Perl script version of `git add -i` has a parameter of the
`list_modified()` function for that matter. In C, we can be a lot more
precise, using an `enum`.

The C implementation of the filter also has an easier time to avoid
unnecessary work, simply by using an adaptive order of the `diff-index`
and `diff-files` calls, and then not adding unnecessary entries in the
first place.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 23:01:38 +02:00
Johannes Schindelin
e29f0db6ce built-in add -i: implement the help command
This imitates the code to show the help text from the Perl script
`git-add--interactive.perl` in the built-in version.

To make sure that it renders exactly like the Perl version of `git add
-i`, we also add a test case for that to `t3701-add-interactive.sh`.

Signed-off-by: Slavica Djukic <slawica92@hotmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 23:01:38 +02:00
Slavica Djukic
665f4b8a0f built-in add -i: use color in the main loop
The error messages as well as the unique prefixes are colored in `git
add -i` by default; We need to do the same in the built-in version.

Signed-off-by: Slavica Djukic <slawica92@hotmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 23:01:37 +02:00
Johannes Schindelin
daed62e58e built-in add -i: support ? (prompt help)
With this change, we print out the same colored help text that the
Perl-based `git add -i` prints in the main loop when question mark is
entered.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 23:01:37 +02:00
Slavica Djukic
88896d3482 built-in add -i: show unique prefixes of the commands
Just like in the Perl script `git-add--interactive.perl`, for each
command a unique prefix is determined (if there exists any within the
given parameters), and shown in the list, and accepted as a shortcut for
the command.

We use the prefix map implementation that we just added in the previous
commit for that purpose.

Signed-off-by: Slavica Djukic <slawica92@hotmail.com>
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
2019-05-13 23:01:37 +02:00
Slavica Djukic
dd3c03253f Add a function to determine unique prefixes for a list of strings
In the `git add -i` command, we show unique prefixes of the commands and
files, to give an indication what prefix would select them.

Naturally, the C implementation looks a lot different than the Perl
implementation: in Perl, a trie is much easier implemented, while we
already have a pretty neat hashmap implementation in C that we use for
the purpose of storing (not necessarily unique) prefixes.

The idea: for each item that we add, we generate prefixes starting with
the first letter, then the first two letters, then three, etc, until we
find a prefix that is unique (or until the prefix length would be
longer than we want). If we encounter a previously-unique prefix on the
way, we adjust that item's prefix to make it unique again (or we mark it
as having no unique prefix if we failed to find one). These partial
prefixes are stored in a hash map (for quick lookup times).

To make sure that this function works as expected, we add a test using a
special-purpose test helper that was added for that purpose.

Note: We expect the list of prefix items to be passed in as a list of
pointers rather than as regular list to avoid having to copy information
(the actual items will most likely contain more information than just
the name and the length of the unique prefix, but passing in `struct
prefix_item *` would not allow for that).

Signed-off-by: Slavica Djukic <slawica92@hotmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 23:01:37 +02:00
Johannes Schindelin
2831e368aa built-in add -i: implement the main loop
The reason why we did not start with the main loop to begin with is that
it is the first user of `list_and_choose()`, which uses the `list()`
function that we conveniently introduced for use by the `status`
command.

Apart from the "and choose" part, there are more differences between the
way the `status` command calls the `list_and_choose()` function in the
Perl version of `git add -i` compared to the other callers of said
function. The most important ones:

- The list is not only shown, but the user is also asked to make a
  choice, possibly selecting multiple entries.

- The list of items is prefixed with a marker indicating what items have
  been selected, if multi-selection is allowed.

- Initially, for each item a unique prefix (if there exists any within
  the given parameters) is determined, and shown in the list, and
  accepted as a shortcut for the selection.

These features will be implemented later, except the part where the user
can choose a command. At this stage, though, the built-in `git add -i`
still only supports the `status` command, with the remaining commands to
follow over the course of the next commits.

In addition, we also modify `list()` to support displaying the commands
in columns, even if there is currently only one.

The Perl script `git-add--interactive.perl` mixed the purposes of the
"list" and the "and choose" part into the same function. In the C
version, we will keep them separate instead, calling the `list()`
function from the `list_and_choose()` function.

Note that we only have a prompt ending in a single ">" at this stage;
later commits will add commands that display a double ">>" to indicate
that the user is in a different loop than the main one.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 23:01:37 +02:00
Johannes Schindelin
fb229024cf built-in add -i: color the header in the status command
For simplicity, we only implemented the `status` command without colors.
This patch starts adding color, matching what the Perl script
`git-add--interactive.perl` does.

Original-Patch-By: Daniel Ferreira <bnmvco@gmail.com>
Signed-off-by: Slavica Djukic <slawica92@hotmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 23:01:37 +02:00
Johannes Schindelin
e270e97ceb built-in add -i: refresh the index before running status
This is what the Perl version does, and therefore it is what the
built-in version should do, too.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 23:01:37 +02:00
Daniel Ferreira
b0107351c4 built-in add -i: implement the status command
This implements the `status` command of `git add -i`. The data
structures introduced in this commit will be extended as needed later.

At this point, we re-implement only part of the `list_and_choose()`
function of the Perl script `git-add--interactive.perl` and call it
`list()`. It does not yet color anything, or do columns, or allow user
input.

Over the course of the next commits, we will introduce a
`list_and_choose()` function that uses `list()` to display the list of
options and let the user choose one or more of the displayed items. This
will be used to implement the main loop of the built-in `git add -i`, at
which point the new `status` command can actually be used.

Note that we pass the list of items as a `struct item **` as opposed to
a `struct item *`, to allow for the actual items to contain much more
information than merely the name.

Signed-off-by: Daniel Ferreira <bnmvco@gmail.com>
Signed-off-by: Slavica Djukic <slawica92@hotmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 23:01:36 +02:00
Daniel Ferreira
979afd7901 diff: export diffstat interface
Make the diffstat interface (namely, the diffstat_t struct and
compute_diffstat) no longer be internal to diff.c and allow it to be used
by other parts of git.

This is helpful for code that may want to easily extract information
from files using the diff machinery, while flushing it differently from
how the show_* functions used by diff_flush() do it. One example is the
builtin implementation of git-add--interactive's status.

Signed-off-by: Daniel Ferreira <bnmvco@gmail.com>
Signed-off-by: Slavica Djukic <slawica92@hotmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 23:01:36 +02:00
Johannes Schindelin
52985d455b Start to implement a built-in version of git add --interactive
This is hardly the first conversion of a Git command that is implemented
as a script to a built-in. So far, the most successful strategy for such
conversions has been to add a built-in helper and call that for more and
more functionality from the script, as more and more parts are
converted.

With the interactive add, we choose a different strategy. The sole
reason for this is that on Windows (where such a conversion has the most
benefits in terms of speed and robustness) we face the very specific
problem that a `system()` call in Perl seems to close `stdin` in the
parent process when the spawned process consumes even one character from
`stdin`. And that just does not work for us here, as it would stop the
main loop as soon as any interactive command was performed by the
helper. Which is almost all of the commands in `git add -i`.

It is almost as if Perl told us once again that it does not want us to
use it on Windows.

Instead, we follow the opposite route where we start with a bare-bones
version of the built-in interactive add, guarded by the new
`add.interactive.useBuiltin` config variable, and then add more and more
functionality to it, until it is feature complete.

At this point, the built-in version of `git add -i` only states that it
cannot do anything yet ;-)

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 23:01:36 +02:00
Johannes Schindelin
a7130b1979 tests: add a special setup where stash.useBuiltin is off
Add a GIT_TEST_STASH_USE_BUILTIN=false test mode which is equivalent
to running with stash.useBuiltin=false. This is needed to spot that
we're not introducing any regressions in the legacy stash version
while we're carrying both it and the new built-in version.

This imitates the equivalent treatment for the built-in rebase in
62c23938fa (tests: add a special setup where rebase.useBuiltin is off,
2018-11-14).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Thomas Gummerer <t.gummerer@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2019-05-13 23:01:24 +02:00
Johannes Schindelin
b350563db2 Start the merging-rebase to v2.22.0-rc0
This commit starts the rebase of 08f5629871 to 41b129245a
2019-05-13 22:58:21 +02:00
Johannes Schindelin
898cf2707e Merge 'readme' into HEAD
Add a README.md for GitHub goodness.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 22:57:10 +02:00
Johannes Schindelin
a507c15da9 Merge pull request #1354 from dscho/phase-out-show-ignored-directory-gracefully
Phase out `--show-ignored-directory` gracefully
2019-05-13 22:57:10 +02:00
Johannes Schindelin
996333c849 Merge branch 'status-no-lock-index'
This branch allows third-party tools to call `git status
--no-lock-index` to avoid lock contention with the interactive Git usage
of the actual human user.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 22:57:09 +02:00
Johannes Schindelin
28841cea9a Merge pull request #2149 from dscho/gcc-8-gfw
Make Git for Windows compile with GCC 8.x
2019-05-13 22:57:07 +02:00
Jameson Miller
52e73bac2a Merge 'builtin-stash-rebase-v3'
To avoid having to play tricks as in earlier rounds, we bit the sour
apple and rebased the `builtin-stash-rebase-v3` branch thicket onto the
commit starting Git for Windows' merging-rebase.

(The merging-rebase pulls in the previous branch thicket via a "fake
merge", i.e. a merge commit that does not actually apply any changes
from the merged commit history. This has the unfortunate side effect of
confusing `merge` into thinking that any branch that was merged into an
earlier round does not need to be merged again.)

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 22:57:06 +02:00
Johannes Schindelin
b43d1c3278 kwset: allow building with GCC 8
The kwset functionality makes use of the obstack code, which expects to
be handed a function that can allocate large chunks of data. It expects
that function to accept a `size` parameter of type `long`.

This upsets GCC 8 on Windows, because `long` does not have the same
bit size as `size_t` there.

Now, the proper thing to do would be to switch to `size_t`. But this
would make us deviate from the "upstream" code even further, making it
hard to synchronize with newer versions, and also it would be quite
involved because that `long` type is so invasive in that code.

Let's punt, and instead provide a super small wrapper around
`xmalloc()`.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 22:57:06 +02:00
Johannes Schindelin
040a0e7bc4 Merge branch 'fix-terminal-prompt'
This fixes the issue identified in

	https://github.com/git-for-windows/git/issues/1498

where Git would not fall back to reading credentials from a Win32
Console when the credentials could not be read from the terminal via the
Bash hack (that is necessary to support running in a MinTTY).

Tested in a Powershell window.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 22:57:06 +02:00
Johannes Schindelin
49de226562 mingw: allow compiling with GCC 8 and DEVELOPER=1
The return type of the `GetProcAddress()` function is `FARPROC` which
evaluates to `long long int (*)()`, i.e. it cannot be cast to the
correct function signature by GCC 8.

To work around that, we first cast to `void *` and go on with our merry
lives.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 22:57:06 +02:00
Johannes Schindelin
998036dce6 Merge pull request #1170 from dscho/mingw-kill-process
Handle Ctrl+C in Git Bash nicely

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 22:57:06 +02:00
Johannes Schindelin
0efbf40d86 Merge pull request #1937 from benpeart/fscache-NtQueryDirectoryFile-gfw
fscache: teach fscache to use NtQueryDirectoryFile
2019-05-13 22:57:05 +02:00
Johannes Schindelin
ab8bfeeba2 Merge pull request #1934 from benpeart/fscache-thread-safe-enable-gfw
fscache: make fscache_enable() thread safe
2019-05-13 22:57:05 +02:00
Johannes Schindelin
06d3217ac6 Merge remote-tracking branch 'benpeart/fscache-per-thread-gfw'
This brings substantial wins in performance because the FSCache is now
per-thread, being merged to the primary thread only at the end, so we do
not have to lock (except while merging).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 22:57:05 +02:00
Johannes Schindelin
d3cee078d4 Merge pull request #1910 from benpeart/fscache_statistics-gfw
fscache: add fscache hit statistics
2019-05-13 22:57:04 +02:00
Johannes Schindelin
6e5f7f81b3 Merge pull request #1914 from benpeart/free-fscache-after-add-gfw
At the end of the add command, disable and free the fscache
2019-05-13 22:57:03 +02:00
Johannes Schindelin
3009f8a1f1 Merge pull request #1911 from benpeart/git_test_fscache-gfw
fscache: add GIT_TEST_FSCACHE support
2019-05-13 22:57:03 +02:00
Johannes Schindelin
b97ee24586 Merge pull request #1909 from benpeart/free-fscache-after-status-gfw
status: disable and free fscache at the end of the status command
2019-05-13 22:57:03 +02:00
Johannes Schindelin
b4e55c6f4d Merge pull request #1908 from benpeart/FindFirstFileEx-gfw
fscache: use FindFirstFileExW to avoid retrieving the short name
2019-05-13 22:57:03 +02:00
Johannes Schindelin
a2396dc1a1 Merge pull request #1827 from benpeart/fscache_refresh_index
Enable the filesystem cache (fscache) in refresh_index().
2019-05-13 22:57:03 +02:00
Johannes Schindelin
a01dc7a753 Merge pull request #1468 from atetubou/fscache_checkout_flush
checkout.c: enable fscache for checkout again

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2019-05-13 22:57:02 +02:00
Johannes Schindelin
2aad8d9011 Merge pull request #1426 from atetubou/fetch_pack
fetch-pack.c: enable fscache for stats under .git/objects
2019-05-13 22:57:02 +02:00
Johannes Schindelin
176d05126b Merge pull request #1344 from jeffhostetler/perf_add_excludes_with_fscache
dir.c: make add_excludes aware of fscache during status
2019-05-13 22:57:02 +02:00