Commit Graph

67928 Commits

Author SHA1 Message Date
Johannes Schindelin
c19aa3bb4f msvc: fix detect_msys_tty()
The ntstatus.h header is only available in MINGW.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2017-02-01 16:33:42 +01:00
Jeff Hostetler
667006afc4 msvc: define ftello()
It is just called different in MSVC's headers.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2017-02-01 16:33:42 +01:00
Jeff Hostetler
0209cfabe5 msvc: do not re-declare the timespec struct
VS2015's headers already declare that struct.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2017-02-01 16:33:42 +01:00
Johannes Schindelin
816315adf5 msvc: provide a main() wrapper similar to mingw_main()
The MINGW version of the main() wrapper gets away with declaring symbols
that were intentionally not exported. However, some of these symbols do
not actually exist in MSVC's UCRT.

So let's add an MSVC version of the main() wrapper that uses wmain() and
imports the UNICODE argv and environment. While at it, we pass our UTF-8
version of ARGV to the real main -- rather than overwriting __argv as is
done in the MINGW Version.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2017-02-01 16:33:42 +01:00
Jeff Hostetler
7907348d03 msvc: do not pretend to support all signals
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>
2017-02-01 16:33:42 +01:00
Jeff Hostetler
1fa0acbf07 msvc: mark a variable as non-const
VS2015 complains when using a const pointer in memcpy()/free().

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2017-02-01 16:33:42 +01:00
Jeff Hostetler
d34ea93776 msvc: convert environment from/to UTF-16 on the fly
This adds MSVC versions of getenv() and friends. These take UTF-8
arguments and return UTF-8 values, but use the UNICODE versions
of the CRT routines.  This avoids the need to write to __environ
(which is only visible if you statically link to the CRT).  This
also avoids the CP_ACP conversions performed inside the CRT.
It also avoids various memory leaks and problems.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
2017-02-01 16:33:41 +01:00
Philip Oakley
7f57ad55b4 msvc: fix the declaration of the _REPARSE_DATA_BUFFER structure
GCC and MSVC disagree about using the GCC extension _ANONYMOUS_UNION.
Simply skip that offending keyword when compiling with MSVC.

Signed-off-by: Philip Oakley <philipoakley@iee.org>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:33:41 +01:00
Philip Oakley
a2864226b3 msvc: define O_ACCMODE
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>
2017-02-01 16:33:38 +01:00
Johannes Schindelin
9adc2328e8 Merge 'rebase-i-extra' into HEAD 2017-02-01 16:16:39 +01:00
Johannes Schindelin
e3ea804bce Merge 'rebase--helper' into HEAD 2017-02-01 16:16:38 +01:00
Johannes Schindelin
93b54b980a Merge 'sequencer-i' into HEAD 2017-02-01 16:16:38 +01:00
Johannes Schindelin
43c33fb1b7 rebase -i: rearrange fixup/squash lines using the rebase--helper
This operation has quadratic complexity, which is especially painful
on Windows, where shell scripts are *already* slow (mainly due to the
overhead of the POSIX emulation layer).

Let's reimplement this with linear complexity (using a hash map to
match the commits' subject lines) for the common case; Sadly, the
fixup/squash feature's design neglected performance considerations,
allowing arbitrary prefixes (read: `fixup! hell` will match the
commit subject `hello world`), which means that we are stuck with
quadratic performance in the worst case.

The reimplemented logic also happens to fix a bug where commented-out
lines (representing empty patches) were dropped by the previous code.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:36 +01:00
Johannes Schindelin
9ad137a2e9 t3415: test fixup with wrapped oneline
The `git commit --fixup` command unwraps wrapped onelines when
constructing the commit message, without wrapping the result.

We need to make sure that `git rebase --autosquash` keeps handling such
cases correctly, in particular since we are about to move the autosquash
handling into the rebase--helper.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:36 +01:00
Johannes Schindelin
0c50fc7f1f rebase -i: skip unnecessary picks using the rebase--helper
In particular on Windows, where shell scripts are even more expensive
than on MacOSX or Linux, it makes sense to move a loop that forks
Git at least once for every line in the todo list into a builtin.

Note: The original code did not try to skip unnecessary picks of root
commits but punts instead (probably --root was not considered common
enough of a use case to bother optimizing). We do the same, for now.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:36 +01:00
Johannes Schindelin
e0e7ebb071 rebase -i: check for missing commits in the rebase--helper
In particular on Windows, where shell scripts are even more expensive
than on MacOSX or Linux, it makes sense to move a loop that forks
Git at least once for every line in the todo list into a builtin.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:36 +01:00
Johannes Schindelin
252bd7b1b6 t3404: relax rebase.missingCommitsCheck tests
These tests were a bit anal about the *exact* warning/error message
printed by git rebase. But those messages are intended for the *end
user*, therefore it does not make sense to test so rigidly for the
*exact* wording.

In the following, we will reimplement the missing commits check in
the sequencer, with slightly different words.

So let's just test for the parts in the warning/error message that
we *really* care about, nothing more, nothing less.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:36 +01:00
Johannes Schindelin
5cb3d57be7 rebase -i: also expand/collapse the SHA-1s via the rebase--helper
This is crucial to improve performance on Windows, as the speed is now
mostly dominated by the SHA-1 transformation (because it spawns a new
rev-parse process for *every* line, and spawning processes is pretty
slow from Git for Windows' MSYS2 Bash).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:36 +01:00
Johannes Schindelin
e0092f4748 rebase -i: do not invent onelines when expanding/collapsing SHA-1s
To avoid problems with short SHA-1s that become non-unique during the
rebase, we rewrite the todo script with short/long SHA-1s before and
after letting the user edit the script. Since SHA-1s are not intuitive
for humans, rebase -i also provides the onelines (commit message
subjects) in the script, purely for the user's convenience.

It is very possible to generate a todo script via different means than
rebase -i and then to let rebase -i run with it; In this case, these
onelines are not required.

And this is where the expand/collapse machinery has a bug: it *expects*
that oneline, and failing to find one reuses the previous SHA-1 as
"oneline".

It was most likely an oversight, and made implementation in the (quite
limiting) shell script language less convoluted. However, we are about
to reimplement performance-critical parts in C (and due to spawning a
git.exe process for every single line of the todo script, the
expansion/collapsing of the SHA-1s *is* performance-hampering on
Windows), therefore let's fix this bug to make cross-validation with the
C version of that functionality possible.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:35 +01:00
Johannes Schindelin
0d0700577b rebase -i: remove useless indentation
The commands used to be indented, and it is nice to look at, but when we
transform the SHA-1s, the indentation is removed. So let's do away with it.

For the moment, at least: when we will use the upcoming rebase--helper
to transform the SHA-1s, we *will* keep the indentation and can
reintroduce it. Yet, to be able to validate the rebase--helper against
the output of the current shell script version, we need to remove the
extra indentation.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:35 +01:00
Johannes Schindelin
3bb63949a2 rebase -i: generate the script via rebase--helper
The first step of an interactive rebase is to generate the so-called "todo
script", to be stored in the state directory as "git-rebase-todo" and to
be edited by the user.

Originally, we adjusted the output of `git log <options>` using a simple
sed script. Over the course of the years, the code became more
complicated. We now use shell scripting to edit the output of `git log`
conditionally, depending whether to keep "empty" commits (i.e. commits
that do not change any files).

On platforms where shell scripting is not native, this can be a serious
drag. And it opens the door for incompatibilities between platforms when
it comes to shell scripting or to Unix-y commands.

Let's just re-implement the todo script generation in plain C, using the
revision machinery directly.

This is substantially faster, improving the speed relative to the
shell script version of the interactive rebase from 2x to 3x on Windows.

Note that the rearrange_squash() function in git-rebase--interactive
relied on the fact that we set the "format" variable to the config setting
rebase.instructionFormat. Relying on a side effect like this is no good,
hence we explicitly perform that assignment (possibly again) in
rearrange_squash().

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:35 +01:00
Johannes Schindelin
e71d6a7190 rebase -i: use the rebase--helper builtin
Now that the sequencer learned to process a "normal" interactive rebase,
we use it. The original shell script is still used for "non-normal"
interactive rebases, i.e. when --root or --preserve-merges was passed.

Please note that the --root option (via the $squash_onto variable) needs
special handling only for the very first command, hence it is still okay
to use the helper upon continue/skip.

Also please note that the --no-ff setting is volatile, i.e. when the
interactive rebase is interrupted at any stage, there is no record of
it. Therefore, we have to pass it from the shell script to the
rebase--helper.

Note: the test t3404 had to be adjusted because the the error messages
produced by the sequencer comply with our current convention to start with
a lower-case letter.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:34 +01:00
Johannes Schindelin
fd6fcc5c31 Add a builtin helper for interactive rebases
Git's interactive rebase is still implemented as a shell script, despite
its complexity. This implies that it suffers from the portability point
of view, from lack of expressibility, and of course also from
performance. The latter issue is particularly serious on Windows, where
we pay a hefty price for relying so much on POSIX.

Unfortunately, being such a huge shell script also means that we missed
the train when it would have been relatively easy to port it to C, and
instead piled feature upon feature onto that poor script that originally
never intended to be more than a slightly pimped cherry-pick in a loop.

To open the road toward better performance (in addition to all the other
benefits of C over shell scripts), let's just start *somewhere*.

The approach taken here is to add a builtin helper that at first intends
to take care of the parts of the interactive rebase that are most
affected by the performance penalties mentioned above.

In particular, after we spent all those efforts on preparing the sequencer
to process rebase -i's git-rebase-todo scripts, we implement the `git
rebase -i --continue` functionality as a new builtin, git-rebase--helper.

Once that is in place, we can work gradually on tackling the rest of the
technical debt.

Note that the rebase--helper needs to learn about the transient
--ff/--no-ff options of git-rebase, as the corresponding flag is not
persisted to, and re-read from, the state directory.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:34 +01:00
Johannes Schindelin
4bcaae5065 sequencer (rebase -i): write out the final message
The shell script version of the interactive rebase has a very specific
final message. Teach the sequencer to print the same.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:33 +01:00
Johannes Schindelin
e71d16634c sequencer (rebase -i): write the progress into files
For the benefit of e.g. the shell prompt, the interactive rebase not
only displays the progress for the user to see, but also writes it into
the msgnum/end files in the state directory.

Teach the sequencer this new trick.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:33 +01:00
Johannes Schindelin
48dc2fe45a sequencer (rebase -i): show the progress
The interactive rebase keeps the user informed about its progress.
If the sequencer wants to do the grunt work of the interactive
rebase, it also needs to show that progress.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:33 +01:00
Johannes Schindelin
c42e28a8cc sequencer (rebase -i): suggest --edit-todo upon unknown command
This is the same behavior as known from `git rebase -i`.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:33 +01:00
Johannes Schindelin
d136853252 sequencer (rebase -i): show only failed cherry-picks' output
This is the behavior of the shell script version of the interactive
rebase, by using the `output` function defined in `git-rebase.sh`.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:33 +01:00
Johannes Schindelin
26ce9a496e sequencer (rebase -i): show only failed git commit's output
This is the behavior of the shell script version of the interactive
rebase, by using the `output` function defined in `git-rebase.sh`.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:33 +01:00
Johannes Schindelin
16ab51eb91 sequencer: use run_command() directly
Instead of using the convenience function run_command_v_opt_cd_env(), we
now use the run_command() function. The former function is simply a
wrapper of the latter, trying to make it more convenient to use.

However, we already have to construct the argv and the env parameters,
and we will need even finer control e.g. over the output of the command,
so let's just stop using the convenience function.

Based on patches and suggestions by Johannes Sixt and Jeff King.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:33 +01:00
Johannes Schindelin
e76d9d461c sequencer: make reading author-script more elegant
Rather than abusing a strbuf to come up with an environment block, let's
just use the argv_array structure which serves the same purpose much
better.

While at it, rename the function to reflect the fact that it does not
really care exactly what environment variables are defined in said file.

Suggested-by: Jeff King <peff@peff.net>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:33 +01:00
Johannes Schindelin
7e3439a9d5 sequencer (rebase -i): differentiate between comments and 'noop'
In the upcoming patch, we will support rebase -i's progress
reporting. The progress skips comments but counts 'noop's.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:32 +01:00
Johannes Schindelin
9f23c411ec sequencer (rebase -i): implement the 'drop' command
The parsing part of a 'drop' command is almost identical to parsing a
'pick', while the operation is the same as that of a 'noop'.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:32 +01:00
Johannes Schindelin
995f9215bf sequencer (rebase -i): allow rescheduling commands
The interactive rebase has the very special magic that a cherry-pick
that exits with a status different from 0 and 1 signifies a failure to
even record that a cherry-pick was started.

This can happen e.g. when a fast-forward fails because it would
overwrite untracked files.

In that case, we must reschedule the command that we thought we already
had at least started successfully.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:32 +01:00
Johannes Schindelin
ece313bfe5 sequencer (rebase -i): respect strategy/strategy_opts settings
The sequencer already has an idea about using different merge
strategies. We just piggy-back on top of that, using rebase -i's
own settings, when running the sequencer in interactive rebase mode.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:32 +01:00
Johannes Schindelin
bffc405fe8 sequencer (rebase -i): respect the rebase.autostash setting
Git's `rebase` command inspects the `rebase.autostash` config setting
to determine whether it should stash any uncommitted changes before
rebasing and re-apply them afterwards.

As we introduce more bits and pieces to let the sequencer act as
interactive rebase's backend, here is the part that adds support for
the autostash feature.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:32 +01:00
Johannes Schindelin
d1fb1c7e37 sequencer (rebase -i): run the post-rewrite hook, if needed
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:32 +01:00
Johannes Schindelin
33b9ae304e sequencer (rebase -i): record interrupted commits in rewritten, too
When continuing after a `pick` command failed, we want that commit
to show up in the rewritten-list (and its notes to be rewritten), too.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:32 +01:00
Johannes Schindelin
b1d5ca0761 sequencer (rebase -i): copy commit notes at end
When rebasing commits that have commit notes attached, the interactive
rebase rewrites those notes faithfully at the end. The sequencer must
do this, too, if it wishes to do interactive rebase's job.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:32 +01:00
Johannes Schindelin
c8427ddc72 sequencer (rebase -i): set the reflog message consistently
We already used the same reflog message as the scripted version of rebase
-i when finishing. With this commit, we do that also for all the commands
before that.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:32 +01:00
Johannes Schindelin
040e42ce97 sequencer (rebase -i): refactor setting the reflog message
This makes the code DRYer, with the obvious benefit that we can enhance
the code further in a single place.

We can also reuse the functionality elsewhere by calling this new
function.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:31 +01:00
Johannes Schindelin
95d0e33f09 sequencer (rebase -i): allow fast-forwarding for edit/reword
The sequencer already knew how to fast-forward instead of
cherry-picking, if possible.

We want to continue to do this, of course, but in case of the 'reword'
command, we will need to call `git commit` after fast-forwarding.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:31 +01:00
Johannes Schindelin
e7ab15805e sequencer (rebase -i): implement the 'reword' command
This is now trivial, as all the building blocks are in place: all we need
to do is to flip the "edit" switch when committing.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:31 +01:00
Johannes Schindelin
4b5ba841e8 sequencer (rebase -i): leave a patch upon error
When doing an interactive rebase, we want to leave a 'patch' file for
further inspection by the user (even if we never tried to actually apply
that patch, since we're cherry-picking instead).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:31 +01:00
Johannes Schindelin
ff9462c780 sequencer (rebase -i): update refs after a successful rebase
An interactive rebase operates on a detached HEAD (to keep the reflog
of the original branch relatively clean), and updates the branch only
at the end.

Now that the sequencer learns to perform interactive rebases, it also
needs to learn the trick to update the branch before removing the
directory containing the state of the interactive rebase.

We introduce a new head_ref variable in a wider scope than necessary at
the moment, to allow for a later patch that prints out "Successfully
rebased and updated <ref>".

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:31 +01:00
Johannes Schindelin
6ea60067ac sequencer (rebase -i): the todo can be empty when continuing
When the last command of an interactive rebase fails, the user needs to
resolve the problem and then continue the interactive rebase. Naturally,
the todo script is empty by then. So let's not complain about that!

To that end, let's move that test out of the function that parses the
todo script, and into the more high-level function read_populate_todo().
This is also necessary by now because the lower-level parse_insn_buffer()
has no idea whether we are performing an interactive rebase or not.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:31 +01:00
Johannes Schindelin
342c5eb157 sequencer (rebase -i): skip some revert/cherry-pick specific code path
When a cherry-pick continues without a "todo script", the intention is
simply to pick a single commit.

However, when an interactive rebase is continued without a "todo
script", it means that the last command has been completed and that we
now need to clean up.

This commit guards the revert/cherry-pick specific steps so that they
are not executed in rebase -i mode.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:31 +01:00
Johannes Schindelin
a30bda887f sequencer (rebase -i): remove CHERRY_PICK_HEAD when no longer needed
The scripted version of the interactive rebase already does that.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:31 +01:00
Johannes Schindelin
7049b78624 sequencer (rebase -i): allow continuing with staged changes
When an interactive rebase is interrupted, the user may stage changes
before continuing, and we need to commit those changes in that case.

Please note that the nested "if" added to the sequencer_continue() is
not combined into a single "if" because it will be extended with an
"else" clause in a later patch in this patch series.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:31 +01:00
Johannes Schindelin
216891b2bd sequencer (rebase -i): write an author-script file
When the interactive rebase aborts, it writes out an author-script file
to record the author information for the current commit. As we are about
to teach the sequencer how to perform the actions behind an interactive
rebase, it needs to write those author-script files, too.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-02-01 16:16:30 +01:00