Add the Microsoft .manifest pattern, and do not anchor the 'Debug'
and 'Release' entries at the top-level directory, to allow for
multiple projects (one per target).
Signed-off-by: Philip Oakley <philipoakley@iee.org>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
The problem with not having, say, git-receive-pack.exe after a full
build is that the test suite will then happily use the *installed*
git-receive-pack.exe because it finds nothing else.
Absolutely not what we want. We want to have confidence that our test
covers the MSVC-built Git executables, and not some random stuff.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
The entire idea of generating the VS solution makes only sense if we
generate it via Continuous Integration; otherwise potential users would
still have to download the entire Git for Windows SDK.
So let's just add a target in the Makefile that can be used to generate
said solution; The generated files will then be committed so that they
can be pushed to a branch ready to check out by Visual Studio users.
To make things even more useful, we also generate and commit other files
that are required to run the test suite, such as templates and
bin-wrappers: with this, developers can run the test suite in a regular
Git Bash (that is part of a regular Git for Windows installation) after
building the solution in Visual Studio.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Based on the previous patch series to be able to compile Git using
Visual C++ from the command-line, this patch offers to generate project
definitions for Visual Studio, so that Git can be developed in a modern
IDE.
Based on the generator for Visual Studio versions <= 2008 (which used
.sln/.vcproj files), this patch copy-edits the generator of the .vcproj
files to a new generator that produces .vcxproj files ready for Visual
Studio 2010 and later (or MSBuild).
As the vcpkg system (which is used to build Git's dependencies) cannot
run in parallel (it does not lock, wreaking havoc with files being
accessed and written at the same time, letting the vcpkg processes
stumble over each others' toes), we make libgit the root of the project
dependency tree and initialize the vcpkg system in this project's
PreBuildEvent.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
One time too many did this developer call the `generate` script passing
a `--make-out=<PATH>` option that was happily ignored (because there
should be a space, not an equal sign, between `--make-out` and the
path).
And one time too many, this script not only ignored it but did not even
complain. Let's fix that.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
With the recent changes to allow building with MSVC=1, we now pass the
/OPT:REF option to the compiler. This confuses the parser that wants to
turn the output of a dry run into project definitions for QMake and Visual
Studio:
Unhandled link option @ line 213: /OPT:REF at [...]
Let's just extend the code that passes through options that start with a
dash, so that it passes through options that start with a slash, too.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Git's test suite shows tons of breakages unless Git is compiled
*without* NO_ICONV. That means, in turn, that we need to generate
build definitions *with* libiconv, which in turn implies that we
have to handle the -liconv option properly.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Upon seeing the '-lcurl' option, point to the libcurl.lib.
While there, fix the elsif indentation.
Signed-off-by: Philip Oakley <philipoakley@iee.org>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Add an option for capturing the output of the make dry-run used in
determining the msvc-build structure for easy debugging.
You can use the output of `--make-out <path>` in subsequent runs via the
`--in <path>` option.
Signed-off-by: Philip Oakley <philipoakley@iee.org>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Rather than swallowing the errors, it is better to have them in a file.
To make it obvious what this is about, use the file name
'msvc-build-makedryerrors.txt'.
Further, if the output is empty, simply delete that file. As we target
Git for Windows' SDK (which, unlike its predecessor msysGit, offers Perl
versions newer than 5.8), we can use the quite readable syntax `if -f -z
$ErrsFile` (available in Perl >=5.10).
Note that the file will contain the new values of the GIT_VERSION and
GITGUI_VERSION if they were generated by the make file. They are omitted
if the release is tagged and indentically defined in their respective
GIT_VERSION_GEN file DEF_VER variables.
Signed-off-by: Philip Oakley <philipoakley@iee.org>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Git's build contains steps to handle internationalization. This caused
hiccups in the parser used to generate QMake/Visual Studio project files.
As those steps are irrelevant in this context, let's just ignore them.
Signed-off-by: Philip Oakley <philipoakley@iee.org>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
The engine.pl script expects file names not to contain spaces. However,
paths with spaces are quite prevalent on Windows. Use shellwords() rather
than split() to parse them correctly.
Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Philip Oakley <philipoakley@iee.org>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
The error message talked about a "lib option", but it clearly referred
to a link option.
Signed-off-by: Philip Oakley <philipoakley@iee.org>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
The Generators/ directory can contain spurious files such as editors'
backup files. Even worse, there could be .swp files which are not even
valid Perl scripts.
Let's just ignore anything but .pm files in said directory.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Since 4b623d8 (MSVC: link in invalidcontinue.obj for better POSIX
compatibility, 2014-03-29), invalidcontinue.obj is linked in the MSVC
build, but it was not parsed correctly by the buildsystem. Ignore it, as
it is known to Visual Studio and will be handled elsewhere.
Also only substitute filenames ending with .o when generating the
source .c filename, otherwise we would start to expect .cbj files to
generate .obj files (which are not generated by our build)...
In the future there may be source files that produce .obj files
so keep the two issues (.obj files with & without source files)
separate.
Signed-off-by: Philip Oakley <philipoakley@iee.org>
Signed-off-by: Duncan Smart <duncan.smart@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Visual Studio takes the first listed application/library as the default
startup project [1].
Detect the 'git' project and place it the head of the apps list, rather
than the tail.
Export the apps list before libs list for both the projects and global
structures of the .sln file.
[1] http://stackoverflow.com/questions/1238553/
vs2008-where-is-the-startup-project-setting-stored-for-a-solution
"In the solution file, there are a list of pseudo-XML "Project"
entries. It turns out that whatever is the first one ends up as
the Startup Project, unless it’s overridden in the suo file. Argh.
I just rearranged the order in the file and it’s good."
"just moving the pseudo-xml isn't enough. You also have to move the
group of entries in the "GlobalSection(ProjectConfigurationPlatforms)
= postSolution" group that has the GUID of the project you moved to
the top. So there are two places to move lines."
Signed-off-by: Philip Oakley <philipoakley@iee.org>
We ran out GUIDs. Again. But there is no need to: we can generate them
semi-randomly from the target file name of the project.
Note: the Vcproj generator is probably only interesting for historical
reasons; nevertheless, the upcoming Vcxproj generator (to support modern
Visual Studio versions) is based on the Vcproj generator and it is
better to fix this here first.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
For regular debugging, it is pretty helpful when a debug assertion in a
running application triggers a window that offers to start the debugger.
However, when running the test suite, it is not so helpful, in
particular when the debug assertions are then suppressed anyway because
we disable the invalid parameter checking (via invalidcontinue.obj, see
the comment in config.mak.uname about that object for more information).
So let's simply disable that window in Debug Mode (it is already
disabled in Release Mode).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
With this patch, Git can be built using the Microsoft toolchain, via:
make MSVC=1 [DEBUG=1]
Third party libraries are built from source using the open source
"vcpkg" tool set. See https://github.com/Microsoft/vcpkg
On a first build, the vcpkg tools and the third party libraries are
automatically downloaded and built. DLLs for the third party libraries
are copied to the top-level (and t/helper) directory to facilitate
debugging. See compat/vcbuild/README.
A series of .bat files are invoked by the Makefile to find the location
of the installed version of Visual Studio and the associated compiler
tools (essentially replicating the environment setup performed by a
"Developer Command Prompt"). This should find the most recent VS2015 or
VS2017 installation. Output from these scripts are used by the Makefile
to define compiler and linker pathnames and -I and -L arguments.
The build produces .pdb files for both debug and release builds.
Note: This commit was squashed from an organic series of commits
developed between 2016 and 2018 in Git for Windows' `master` branch.
This combined commit eliminates the obsolete commits related to fetching
NuGet packages for third party libraries. It is difficult to use NuGet
packages for C/C++ sources because they may be built by earlier versions
of the MSVC compiler and have CRT version and linking issues.
Additionally, the C/C++ NuGet packages that were using tended to not be
updated concurrently with the sources. And in the case of cURL and
OpenSSL, this could expose us to security issues.
Helped-by: Yue Lin Ho <b8732003@student.nsysu.edu.tw>
Helped-by: Philip Oakley <philipoakley@iee.org>
Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This special-cases various signals that are not supported on Windows,
such as SIGPIPE. These cause the UCRT to throw asserts (at least in
debug mode).
Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
It is just called differently in MSVC's headers.
Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This constant is not defined in MSVC's headers.
In UCRT's fcntl.h, _O_RDONLY, _O_WRONLY and _O_RDWR are defined as 0, 1
and 2, respectively. Yes, that means that UCRT breaks with the tradition
that O_RDWR == O_RDONLY | O_WRONLY.
It is a perfectly legal way to define those constants, though, therefore
we need to take care of defining O_ACCMODE accordingly.
This is particularly important in order to keep our "open() can set
errno to EISDIR" emulation working: it tests that (flags & O_ACCMODE) is
not identical to O_RDONLY before going on to test specifically whether
the file for which open() reported EACCES is, in fact, a directory.
Signed-off-by: Philip Oakley <philipoakley@iee.org>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
The file compat/msvc.c includes compat/mingw.c, which means that we have
to recompile compat/msvc.o if compat/mingw.c changes.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This topic branch fixes a corner case that is amazingly common in this
developer's workflow: in a `git stash -p`, splitting a hunk and stashing
only part of it runs into a (known) bug where the partial hunk cannot be
applied in reverse.
It is one of those "good enough" fixes, not a full fix, though, as the
full fix would require a 3-way merge between `stash^` and the *worktree*
(not `HEAD`), with `stash` as merge base (i.e. a `git revert`, but on
top of the current worktree).
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Git for Windows has special code to retrieve the command-line parameters
(and even the environment) in UTF-16 encoding, so that they can be
converted to UTF-8. This is necessary because Git for Windows wants to
use UTF-8 encoded strings throughout its code, and the main() function
does not get the parameters in that encoding.
To do that, we used the __wgetmainargs() function, which is not even a
Win32 API function, but provided by the MINGW "runtime" instead.
Obviously, this method would not work with any other compiler than GCC,
and in preparation for compiling with Visual C++, we would like to avoid
that.
Lucky us, there is a much more elegant way: we simply implement wmain()
and link with -municode. The command-line parameters are passed to
wmain() encoded in UTF-16, as desired, and this method also works with
Visual C++ after adjusting the MSVC linker flags to force it to use
wmain().
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This is the final leg of the journey to a fully built-in `git add`: the
`git add -i` and `git add -p` modes were re-implemented in C, but they
lacked support for a couple of config settings.
The one that sticks out most is the `interactive.singleKey` setting: it
was not only particularly hard to get to work, especially on Windows. It
is also the setting that seems to be incomplete already in the Perl
version: while the name suggests that it applies to the main loop of
`git add --interactive`, or to the file selections in that command, it
does not. Only the `git add --patch` mode respects that setting.
As it is outside the purpose of the conversion of
`git-add--interactive.perl` to C, we will leave that loose end for some
future date.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
MS Visual C suggests that the construct
condition ? (int) i : (ptrdiff_t) d
is incorrect. Let's fix this by casting to ptrdiff_t also for the
positive arm of the conditional.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
At this stage on the journey to a fully built-in `git add`, we already
have everything we need, including the `--interactive` and `--patch`
options, as long as the `add.interactive.useBuiltin` setting is set to
`true` (kind of a "turned off feature flag", which it will be for a
while, until we get confident enough that the built-in version does the
job, and retire the Perl script).
However, the internal `add--interactive` helper is also used to back the
`--patch` option of `git stash`, `git reset` and `git checkout`.
This patch series brings them "online".
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
In MSVC, the DEBUG constant is set automatically whenever compiling with
debug information.
This is clearly not what was intended in cache-tree.c, so let's use a less
ambiguous constant there.
Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
When redirecting stdout/stderr to the same file, we cannot guarantee
that stdout will come first.
In fact, in this test case, it seems that an MSVC build always prints
stderr first.
In any case, this test case does not want to verify the *order* but
the *presence* of both outputs, so let's relax the test a little.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When trying to stash part of the worktree changes by splitting a hunk
and then only partially accepting the split bits and pieces, the user
is presented with a rather cryptic error:
error: patch failed: <file>:<line>
error: test: patch does not apply
Cannot remove worktree changes
and the command would fail to stash the desired parts of the worktree
changes (even if the `stash` ref was actually updated correctly).
We even have a test case demonstrating that failure, carrying it for
four years already.
The explanation: when splitting a hunk, the changed lines are no longer
separated by more than 3 lines (which is the amount of context lines
Git's diffs use by default), but less than that. So when staging only
part of the diff hunk for stashing, the resulting diff that we want to
apply to the worktree in reverse will contain those changes to be
dropped surrounded by three context lines, but since the diff is
relative to HEAD rather than to the worktree, these context lines will
not match.
Example time. Let's assume that the file README contains these lines:
We
the
people
and the worktree added some lines so that it contains these lines
instead:
We
are
the
kind
people
and the user tries to stash the line containing "are", then the command
will internally stage this line to a temporary index file and try to
revert the diff between HEAD and that index file. The diff hunk that
`git stash` tries to revert will look somewhat like this:
@@ -1776,3 +1776,4
We
+are
the
people
It is obvious, now, that the trailing context lines overlap with the
part of the original diff hunk that the user did *not* want to stash.
Keeping in mind that context lines in diffs serve the primary purpose of
finding the exact location when the diff does not apply precisely (but
when the exact line number in the file to be patched differs from the
line number indicated in the diff), we work around this by reducing the
amount of context lines: the diff was just generated.
Note: this is not a *full* fix for the issue. Just as demonstrated in
t3701's 'add -p works with pathological context lines' test case, there
are ambiguities in the diff format. It is very rare in practice, of
course, to encounter such repeated lines.
The full solution for such cases would be to replace the approach of
generating a diff from the stash and then applying it in reverse by
emulating `git revert` (i.e. doing a 3-way merge). However, in `git
stash -p` it would not apply to `HEAD` but instead to the worktree,
which makes this non-trivial to implement as long as we also maintain a
scripted version of `add -i`.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Out of all the patch series on the journey to provide `git add
--interactive` and `git add --patch` in a built-in versions, this is the
big one, as can be expected from the fact that the `git add --patch`
functionality makes up over half of the 1,800+ lines of
`git-add--interactive.perl`.
The two patches that stick out are of course the ones to implement hunk
splitting and hunk editing: these operations are fundamentally more
complicated, and less obvious, than the rest of the operations.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
While re-implementing `git add -i` and `git add -p` in C, I tried to
make sure that there is test coverage for all of the features I convert
from Perl to C, to give me some confidence in the correctness from
running the test suite both with `GIT_TEST_ADD_I_USE_BUILTIN=true` and
with `GIT_TEST_ADD_I_USE_BUILTIN=false`.
However, I discovered that there are a couple of gaps. This patch series
intends to close them.
The first patch might actually not be considered a gap by some: it
basically removes the need for the `TTY` prerequisite in the `git add
-i` tests to verify that the output is colored all right. This change is
rather crucial for me, though: on Windows, where the conversion to a
built-in shows the most obvious benefits, there are no pseudo terminals
(yet), therefore `git.exe` cannot work with them (even if the MSYS2 Perl
interpreter used by Git for Windows knows about some sort of pty
emulation). And I *really* wanted to make sure that the colors work on
Windows, as I personally get a lot out of those color cues.
The patch series ends by addressing two issues that are not exactly
covering testing gaps:
- While adding a test case, I noticed that `git add -p` exited with
*success* when it could not even generate a diff. This is so obviously
wrong that I had to fix it right away (I noticed, actually, because my
in-progress built-in `git add -p` failed, and the Perl version did
not), and I used the same test case to verify that this is fixed once
and for all.
- While working on covering those test gaps, I noticed a problem in an
early version of the built-in version of `git add -p` where the `git
apply --allow-overlap` mode failed to work properly, for little
reason, and I fixed it real quick.
It would seem that the `--allow-overlap` function is not only
purposefully under-documented, but also purposefully under-tested,
probably to discourage its use. I do not quite understand what I
perceive to be Junio's aversion to that option, but I did not feel
like I should put up a battle here, so I did not accompany this fix
with a new test script.
In the end, the built-in version of `git add -p` does not use the
`--allow-overlap` function at all, anyway. Which should make everybody
a lot happier.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This patch series implements the rest of the commands in `git add -i`'s
main loop: `update`, `revert`, `add_untracked`, `patch`, `diff`, and
`quit`. Apart from `quit`, these commands are all very similar in that
they first build a list of files, display it, let the user choose which
ones to act on, and then perform the action.
Note that the `patch` command is not actually converted to C, not
completely at least: the built-in version simply hands off to `git
add--interactive` after letting the user select which files to act on.
The reason for this omission is practicality. Out of the 1,800+ lines of
`git-add--interactive.perl`, over a thousand deal *just* with the `git
add -p` part. I did convert that functionality already (to be
contributed in a separate patch series), discovering that there is so
little overlap between the `git add --patch` part and the rest of `git
add --interactive` that I could put the former into a totally different
file: `add-patch.c`. Just a teaser ;-)
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
The first part of the long journey to a fully built-in `git add -i`.
It reflects the part that was submitted a couple of times (see
https://github.com/gitgitgadget/git/pull/103) during the Outreachy
project by Slavica Đukić that continued the journey based on an initial
patch series by Daniel Ferreira.
This part only implements the `status` and the `help` part, like
Slavica's last iteration did, in the interest of making the review
remotely more reviewable. I fear that this attempt of making it a bit
more reviewable is pretty futile, as so many things changed. So I will
ask the reviewers for forgiveness: please be kind, and give this sort of
a fresh review.
I threw in a couple of major changes on top of that iteration, though:
- The original plan was to add a helper (`git add--helper`) that takes
over more and more responsibility from the Perl script over the course
of the conversion.
This plan is no longer in effect, as I encountered a serious problem
with that: the MSYS2 runtime used by the Perl interpreter which Git
for Windows employs to run `git add -i` has a curious bug (that is
safely outside the purview of this here patch series) where it fails
to read from standard input after it spawned a non-MSYS2 program that
reads from standard input. To keep my `git add -i` in a working state,
I therefore adopted a different strategy:
Just like `git difftool` was converted by starting with a built-in
that did nothing but handing off to the scripted version, guarded by
the (opt-in) `difftool.useBuiltin` config setting, I start this patch
series by a built-in `add -i` that does nothing else but state that it
is not implemented yet, guarded by the (opt-in)
`add.interactive.useBuiltin` config setting.
In contrast to the `git difftool` situation, it is quite a bit easier
here, as we do not even have to rename the script to
`git-legacy-add--interactive.perl`: the `add--interactive` command is
an implementation detail that users are not even supposed to know
about. Therefore, we can implement that road fork between the built-in
and the scripted version in `builtin/add.c`, i.e. in the user-facing
`git add` command.
This will also naturally help with the transition to a fully built-in
`git add -i`/`git add -p`, as we saw with the built-in `git rebase`
how important it is for end users to have an escape hatch (and for
that reason, tried our best to provide the same with the built-in `git
stash`).
- The `help` command was actually not hooked up in `git add -i`, but was
only available as a special option of the `git add--helper` command.
As that command no longer exists, I kind of *had* to implement
some way to let the built-in `git add -i` show the help text.
- The main loop of `git add -i` (i.e. the thing that lets you choose
`status` or `help`) is now implemented (but only lists `status` and
`help`, of course), as it makes use of that feature that took the main
chunk of the Outreachy project: the function to determine unique
prefixes of a list of strings.
- Speaking of the unique prefixes: the functionality to determine those
is now encapsulated in the `prefix-map.c` file, and I also added a
regression test.
- Speaking of the tests: I also implemented support for the environment
variable `GIT_TEST_ADD_I_USE_BUILTIN`: by setting it, the test suite
can be forced to use the built-in, or the Perl script, version of `git
add -i`. Needless to say: by the end of this patch series, running the
test suite with `GIT_TEST_ADD_I_USE_BUILTIN=true` will still result in
a ton of test failures due to not-yet-implemented commands, but it
will also demonstrate what *already* works.
- Since the main loop starts not only by showing the status, but
refreshes the index before that, I added that, and I actually
refactored that code into a new function
(`repo_refresh_and_write_index()`), as it will be used a couple of
times by the end of the complete conversion of `git add -i` into a
built-in command.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This job runs the test suite twice, once in regular mode, and once with
a whole slew of `GIT_TEST_*` variables set.
Now that the built-in version of `git add --interactive` is
feature-complete, let's also throw `GIT_TEST_MULTI_PACK_INDEX` into that
fray.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
The scripted version of `git stash` called directly into the Perl script
`git-add--interactive.perl`, and this was faithfully converted to C.
However, we have a much better way to do this now: call `git add
--patch=<mode>`, which incidentally also respects the config setting
`add.interactive.useBuiltin`.
Let's do this.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
In 7e9e048661 (stash -p: demonstrate failure of split with mixed y/n,
2015-04-16), a regression test for a known breakage that was added to
the test script `t3904-stash-patch.sh` that demonstrated that splitting
a hunk and trying to stash only part of that split hunk fails (but
shouldn't).
As expected, it still fails, but for the wrong reason: once the bug is
fixed, we would expect stderr to show nothing, yet the regression test
expects stderr to show something.
Let's fix that by telling that regression test case to expect nothing to
be printed to stderr.
While at it, also drop the obvious left-over from debugging where the
regression test did not mind `git stash -p` to return a non-zero exit
status.
Of course, the regression test still fails, but this time for the
correct reason.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
When `interactive.singlekey = true`, we react immediately to keystrokes,
even to Escape sequences (e.g. when pressing a cursor key).
The problem with Escape sequences is that we do not really know when
they are done, and as a heuristic we poll standard input for half a
second to make sure that we got all of it.
While waiting half a second is not asking for a whole lot, it can become
quite annoying over time, therefore with this patch, we read the
terminal capabilities (if available) and extract known Escape sequences
from there, then stop polling immediately when we detected that the user
pressed a key that generated such a known sequence.
This recapitulates the remaining part of b5cc003253 (add -i: ignore
terminal escape sequences, 2011-05-17).
Note: We do *not* query the terminal capabilities directly. That would
either require a lot of platform-specific code, or it would require
linking to a library such as ncurses.
Linking to a library in the built-ins is something we try very hard to
avoid (we even kicked the libcurl dependency to a non-built-in remote
helper, just to shave off a tiny fraction of a second from Git's startup
time). And the platform-specific code would be a maintenance nightmare.
Even worse: in Git for Windows' case, we would need to query MSYS2
pseudo terminals, which `git.exe` simply cannot do (because it is
intentionally *not* an MSYS2 program).
To address this, we simply spawn `infocmp -L -1` and parse its output
(which works even in Git for Windows, because that helper is included in
the end-user facing installations).
This is done only once, as in the Perl version, but it is done only when
the first Escape sequence is encountered, not upon startup of `git add
-i`; This saves on startup time, yet makes reacting to the first Escape
sequence slightly more sluggish. But it allows us to keep the
terminal-related code encapsulated in the `compat/terminal.c` file.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
The built-in `git add -i` machinery obviously has its `the_repository`
structure initialized at the point where `cmd_commit()` calls it, and
therefore does not look at the environment variable `GIT_INDEX_FILE`.
But it has to, because the index was already locked, and we want to ask
the interactive add machinery to work on the `index.lock` file instead
of the `index` file.
Technically, we could teach `run_add_i()` (and `run_add_p()`) to look
specifically at that environment variable, but the entire idea of
passing in a parameter of type `struct repository *` is to allow working
on multiple repositories (and their index files) independently.
So let's instead override the `index_file` field of that structure
temporarily.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This recapitulates part of b5cc003253 (add -i: ignore terminal escape
sequences, 2011-05-17):
add -i: ignore terminal escape sequences
On the author's terminal, the up-arrow input sequence is ^[[A, and
thus fat-fingering an up-arrow into 'git checkout -p' is quite
dangerous: git-add--interactive.perl will ignore the ^[ and [
characters and happily treat A as "discard everything".
As a band-aid fix, use Term::Cap to get all terminal capabilities.
Then use the heuristic that any capability value that starts with ^[
(i.e., \e in perl) must be a key input sequence. Finally, given an
input that starts with ^[, read more characters until we have read a
full escape sequence, then return that to the caller. We use a
timeout of 0.5 seconds on the subsequent reads to avoid getting stuck
if the user actually input a lone ^[.
Since none of the currently recognized keys start with ^[, the net
result is that the sequence as a whole will be ignored and the help
displayed.
Note that we leave part for later which uses "Term::Cap to get all
terminal capabilities", for several reasons:
1. it is actually not really necessary, as the timeout of 0.5 seconds
should be plenty sufficient to catch Escape sequences,
2. it is cleaner to keep the change to special-case Escape sequences
separate from the change that reads all terminal capabilities to
speed things up, and
3. in practice, relying on the terminal capabilities is a bit overrated,
as the information could be incomplete, or plain wrong. For example,
in this developer's tmux sessions, the terminal capabilities claim
that the "cursor up" sequence is ^[M, but the actual sequence
produced by the "cursor up" key is ^[[A.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>