Commit Graph

2612 Commits

Author SHA1 Message Date
Johannes Schindelin
24e74b3a76 Merge branch 'visual-studio'
This topic branch teaches the project generator to generate a Visual
Studio solution, ready to be opened in Visual Studio 2010 or later.

The idea, of course, is to let some automatic build job generate and
commit the project files with

	make MSVC=1 vcxproj

and then (force-)push to a special-purpose branch.

The major part of this branch thicket concerns itself not only with
generating the Visual Studio project files, but making sure that the
user can then run the test suite from a regular Git Bash (i.e. *not*
requiring a Git for Windows SDK), e.g. by running

	cd t
	prove --timer --jobs 15 ./t[0-9]*.sh

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-05-09 22:44:18 +02:00
Johannes Schindelin
02783bbbe6 Vcproj.pm: urlencode '<' and '>' when generating VC projects
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-05-09 22:41:03 +02:00
Johannes Schindelin
874c142260 Vcproj.pm: do not configure VCWebServiceProxyGeneratorTool
It is not necessary, and Visual Studio 2015 no longer supports it, anyway.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-05-09 22:41:03 +02:00
Philip Oakley
33e6ee2f10 Vcproj.pm: provide more GUIDs
Needed for: test-config; t-dump-split-index; t-dump-untracked-cache;
t-fake-ssh; t-sha1-array; t-submodule-config.

Plus a few spares.

Signed-off-by: Philip Oakley <philipoakley@iee.org>
2017-05-09 22:41:03 +02:00
Philip Oakley
cc7f12e92e Vcproj.pm: list git.exe first to be startup project
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>
2017-05-09 22:41:03 +02:00
Philip Oakley
9e5e6fb625 Vcproj.pm: remove duplicate GUID
Delete the duplicated GUID from the generation code for the Visual Studio
.sln project file.

The duplicate GUID tended to be allocated to test-svn-fe, which was then
ignored by Visual Studio / MSVC, and its omission from the build never
noticed.

Signed-off-by: Philip Oakley <philipoakley@iee.org>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-05-09 22:41:02 +02:00
Johannes Schindelin
56e67fafdd contrib/buildsystems: make 'Restore NuGet Packages' work in Visual Studio
Visual Studio has this very neat feature that you can get dependencies in
the form of NuGet packages, and even further: you can specify in a project
what NuGet packages it needs. These dependencies can then be fetched via
right-clicking the solution in the Solution Explorer and clicking the
"Restore NuGet Packages" entry.

This feature is so neat, in fact, that we want to support it in Git for
Windows. The idea is that we will be able to provide developers with a
checkout of the Git sources that can be built outside of the Git for
Windows SDK, using *only* Visual Studio.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-05-09 22:41:02 +02:00
Johannes Schindelin
fefca980af contrib/buildsystems: support modern Visual Studio project definitions
The .sln/.vcproj files were used to define projects up until Visual
Studio 2008, but starting with Visual Studio 2010 the project
definitions are stored in .sln/.vcxproj files (which can also be used
by the MSBuild system).

Let's just copy-edit the generator of the .vcproj files to a new
generator that produces .vcxproj files directly, without forcing Visual
Studio to upgrade the project definitions.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-05-09 22:41:02 +02:00
Johannes Schindelin
af33598eda contrib/buildsystems: handle options starting with a slash
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>
2017-05-09 22:41:02 +02:00
Philip Oakley
9d54ac42bc contrib/buildsystems: optionally capture the dry-run in a file
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>
2017-05-09 22:41:02 +02:00
Johannes Schindelin
ba08170861 contrib/buildsystems: handle libiconv, too
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>
2017-05-09 22:41:02 +02:00
Johannes Schindelin
9f9f67ec44 contrib/buildsystems: ignore irrelevant files in Generators/
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>
2017-05-09 22:41:02 +02:00
Philip Oakley
7a7cb1ef3e contrib/buildsystems: handle the curl library option
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>
2017-05-09 22:41:02 +02:00
Philip Oakley
ae27e9beac contrib/buildsystems: redirect errors of the dry run into a log file
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>
2017-05-09 22:41:01 +02:00
Philip Oakley
07e8d321e6 contrib/buildsystems: ignore gettext stuff
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>
2017-05-09 22:41:01 +02:00
Philip Oakley
1cc155929e contrib/buildsystems: handle quoted spaces in filenames
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>
2017-05-09 22:41:01 +02:00
Philip Oakley
f94d5b1b86 contrib/buildsystems: fix misleading error message
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>
2017-05-09 22:41:01 +02:00
Johannes Schindelin
8935c5c1bd Merge pull request #552 from duncansmart/fix-vcproj-gen
Fix Visual Studio .sln/.vcproj generation.
2017-05-09 22:40:43 +02:00
Johannes Schindelin
50d9fa30a7 Merge 'msys2' into HEAD
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-05-09 22:40:35 +02:00
Philip Oakley
bcdb352122 engine.pl: ignore invalidcontinue.obj which is known to MSVC
Commit 4b623d8 (MSVC: link in invalidcontinue.obj for better
POSIX compatibility, 2014-03-29) introduced invalidcontinue.obj
into the Makefile output, which was not parsed correctly by the
buildsystem. Ignore it, as it is known to Visual Studio and,
there is no matching source file.

Only substitute filenames ending with .o when generating the
source .c filename, otherwise a .cbj file may be expected.

Split the .o and .obj processing; 'make' does not produce .obj
files.

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>

(cherry picked from commit d01d71fe1aed67f4e3a5ab80eeadeaf525ad0846)
2017-05-09 22:40:25 +02:00
Johannes Schindelin
31a8f5cabe mingw: load system libraries the recommended way
When we access IPv6-related functions, we load the corresponding system
library using the `LoadLibrary()` function, which is not the recommended
way to load system libraries.

In practice, it does not make a difference: the `ws2_32.dll` library
containing the IPv6 functions is already loaded into memory, so
LoadLibrary() simply reuses the already-loaded library.

Still, recommended way is recommended way, so let's use that instead.

While at it, also adjust the code in contrib/ that loads system libraries.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2017-05-09 22:38:52 +02:00
Jakub Bereżański
f043bbaef7 wincred: handle empty username/password correctly
Empty (length 0) usernames and/or passwords, when saved in the Windows
Credential Manager, come back as null when reading the credential.

One use case for such empty credentials is with NTLM authentication, where
empty username and password instruct libcurl to authenticate using the
credentials of the currently logged-on user (single sign-on).

When locating the relevant credentials, make empty username match null.
When outputting the credentials, handle nulls correctly.

Signed-off-by: Jakub Bereżański <kuba@berezanscy.pl>
2017-05-09 22:38:42 +02:00
Junio C Hamano
b439747bc1 Merge branch 'jk/complete-checkout-sans-dwim-remote'
Completion for "git checkout <branch>" that auto-creates the branch
out of a remote tracking branch can now be disabled, as this
completion often gets in the way when completing to checkout an
existing local branch that happens to share the same prefix with
bunch of remote tracking branches.

* jk/complete-checkout-sans-dwim-remote:
  completion: optionally disable checkout DWIM
2017-05-01 14:14:41 +09:00
Jeff King
60e71bbcea completion: optionally disable checkout DWIM
When we complete branch names for "git checkout", we also
complete remote branch names that could trigger the DWIM
behavior. Depending on your workflow and project, this can
be either convenient or annoying.

For instance, my clone of gitster.git contains 74 local
"jk/*" branches, but origin contains another 147. When I
want to checkout a local branch but can't quite remember the
name, tab completion shows me 251 entries. And worse, for a
topic that has been picked up for pu, the upstream branch
name is likely to be similar to mine, leading to a high
probability that I pick the wrong one and accidentally
create a new branch.

This patch adds a way for the user to tell the completion
code not to include DWIM suggestions for checkout. This can
already be done by typing:

  git checkout --no-guess jk/<TAB>

but that's rather cumbersome. The downside, of course, is
that you no longer get completion support when you _do_ want
to invoke the DWIM behavior. But depending on your workflow,
that may not be a big loss (for instance, in git.git I am
much more likely to want to detach, so I'd type "git
checkout origin/jk/<TAB>" anyway).

Signed-off-by: Jeff King <peff@peff.net>
Reviewed-by: SZEDER Gábor <szeder.dev@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-04-23 17:46:31 -07:00
Ævar Arnfjörð Bjarmason
723c1d526f completion: expand "push --delete <remote> <ref>" for refs on that <remote>
Change the completion of "push --delete <remote> <ref>" to complete
refs on that <remote>, not all refs.

Before this cloning git.git and doing "git push --delete origin
p<TAB>" will complete nothing, since a fresh clone of git.git will
have no "pu" branch, whereas origin/p<TAB> will uselessly complete
origin/pu, but fully qualified references aren't accepted by
"--delete".

Now p<TAB> will complete as "pu". The completion of giving --delete
later, e.g. "git push origin --delete p<TAB>" remains unchanged, this
is a bug, but is a general existing limitation of the bash completion,
and not how git-push is documented, so I'm not fixing that case, but
adding a failing TODO test for it.

The testing code was supplied by SZEDER Gábor in
<20170421122832.24617-1-szeder.dev@gmail.com> with minor setup
modifications on my part.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Reviewed-by: SZEDER Gábor <szeder.dev@gmail.com>
Test-code-by: SZEDER Gábor <szeder.dev@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-04-23 17:30:59 -07:00
Junio C Hamano
3c833cae44 Merge branch 'jc/bs-t-is-not-a-tab-for-sed'
Code cleanup.

* jc/bs-t-is-not-a-tab-for-sed:
  contrib/git-resurrect.sh: do not write \t for HT in sed scripts
2017-04-16 23:29:29 -07:00
Junio C Hamano
d1d3d46146 Merge branch 'ab/ref-filter-no-contains'
"git tag/branch/for-each-ref" family of commands long allowed to
filter the refs by "--contains X" (show only the refs that are
descendants of X), "--merged X" (show only the refs that are
ancestors of X), "--no-merged X" (show only the refs that are not
ancestors of X).  One curious omission, "--no-contains X" (show
only the refs that are not descendants of X) has been added to
them.

* ab/ref-filter-no-contains:
  tag: add tests for --with and --without
  ref-filter: reflow recently changed branch/tag/for-each-ref docs
  ref-filter: add --no-contains option to tag/branch/for-each-ref
  tag: change --point-at to default to HEAD
  tag: implicitly supply --list given another list-like option
  tag: change misleading --list <pattern> documentation
  parse-options: add OPT_NONEG to the "contains" option
  tag: add more incompatibles mode tests
  for-each-ref: partly change <object> to <commit> in help
  tag tests: fix a typo in a test description
  tag: remove a TODO item from the test suite
  ref-filter: add test for --contains on a non-commit
  ref-filter: make combining --merged & --no-merged an error
  tag doc: reword --[no-]merged to talk about commits, not tips
  tag doc: split up the --[no-]merged documentation
  tag doc: move the description of --[no-]merged earlier
2017-04-11 00:21:50 -07:00
Junio C Hamano
fba275dc93 contrib/git-resurrect.sh: do not write \t for HT in sed scripts
Just like we did in 0d1d6e50 ("t/t7003: replace \t with literal tab
in sed expression", 2010-08-12), avoid writing "\t" for HT in sed
scripts, which is not portable.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-31 21:08:30 -07:00
Junio C Hamano
ccf680dea3 Merge branch 'sg/completion-ctags'
Command line completion updates.

* sg/completion-ctags:
  completion: offer ctags symbol names for 'git log -S', '-G' and '-L:'
  completion: extract completing ctags symbol names into helper function
  completion: put matching ctags symbol names directly into COMPREPLY
2017-03-30 14:07:15 -07:00
Junio C Hamano
bf650608be Merge branch 'sg/completion-refs-speedup'
The refs completion for large number of refs has been sped up,
partly by giving up disambiguating ambiguous refs and partly by
eliminating most of the shell processing between 'git for-each-ref'
and 'ls-remote' and Bash's completion facility.

* sg/completion-refs-speedup:
  completion: speed up branch and tag completion
  completion: fill COMPREPLY directly when completing fetch refspecs
  completion: fill COMPREPLY directly when completing refs
  completion: let 'for-each-ref' sort remote branches for 'checkout' DWIMery
  completion: let 'for-each-ref' filter remote branches for 'checkout' DWIMery
  completion: let 'for-each-ref' strip the remote name from remote branches
  completion: let 'for-each-ref' and 'ls-remote' filter matching refs
  completion: don't disambiguate short refs
  completion: don't disambiguate tags and branches
  completion: support excluding full refs
  completion: support completing fully qualified non-fast-forward refspecs
  completion: support completing full refs after '--option=refs/<TAB>'
  completion: wrap __git_refs() for better option parsing
  completion: remove redundant __gitcomp_nl() options from _git_commit()
2017-03-30 14:07:14 -07:00
Ævar Arnfjörð Bjarmason
ac3f5a3468 ref-filter: add --no-contains option to tag/branch/for-each-ref
Change the tag, branch & for-each-ref commands to have a --no-contains
option in addition to their longstanding --contains options.

This allows for finding the last-good rollout tag given a known-bad
<commit>. Given a hypothetically bad commit cf5c7253e0, the git
version to revert to can be found with this hacky two-liner:

    (git tag -l 'v[0-9]*'; git tag -l --contains cf5c7253e0 'v[0-9]*') |
        sort | uniq -c | grep -E '^ *1 ' | awk '{print $2}' | tail -n 10

With this new --no-contains option the same can be achieved with:

    git tag -l --no-contains cf5c7253e0 'v[0-9]*' | sort | tail -n 10

As the filtering machinery is shared between the tag, branch &
for-each-ref commands, implement this for those commands too. A
practical use for this with "branch" is e.g. finding branches which
were branched off between v2.8.0 and v2.10.0:

    git branch --contains v2.8.0 --no-contains v2.10.0

The "describe" command also has a --contains option, but its semantics
are unrelated to what tag/branch/for-each-ref use --contains for. A
--no-contains option for "describe" wouldn't make any sense, other
than being exactly equivalent to not supplying --contains at all,
which would be confusing at best.

Add a --without option to "tag" as an alias for --no-contains, for
consistency with --with and --contains.  The --with option is
undocumented, and possibly the only user of it is
Junio (<xmqqefy71iej.fsf@gitster.mtv.corp.google.com>). But it's
trivial to support, so let's do that.

The additions to the the test suite are inverse copies of the
corresponding --contains tests. With this change --no-contains for
tag, branch & for-each-ref is just as well tested as the existing
--contains option.

In addition to those tests, add a test for "tag" which asserts that
--no-contains won't find tree/blob tags, which is slightly
unintuitive, but consistent with how --contains works & is documented.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-24 12:15:26 -07:00
SZEDER Gábor
41d2716cdc completion: offer ctags symbol names for 'git log -S', '-G' and '-L:'
Just like in the case of search patterns for 'git grep', see 29eec71f2
(completion: match ctags symbol names in grep patterns, 2011-10-21)),
a common thing to look for using 'git log -S', '-G' and '-L:' is the
name of a symbol.

Teach the completion for 'git log' to offer ctags symbol names after
these options, both in stuck and in unstuck forms.

Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-23 13:31:24 -07:00
SZEDER Gábor
2f779f9176 completion: extract completing ctags symbol names into helper function
The previous commit doubled the number of __git_match_ctag()'s
positional parameters, and, to keep the position of existing
parameters for the sake of backwards compatibility, the prefix,
current word and suffix parameters ended up in different order than in
other functions accepting the same parameters.  Then there is a
condition checking the existence of the tag file before invoking this
function.

We could still live with this if there were only a single callsite,
but the next commit will add a few more, so it's worth providing a
cleaner interface.

Add the wrapper function __git_complete_symbol(), which encompasses
the condition for checking the presence of the tag file and filling
COMPREPLY, and accepts '--opt=val'-style options with default values
that keep callsites simpler.

Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-23 13:31:24 -07:00
SZEDER Gábor
7826a7865c completion: put matching ctags symbol names directly into COMPREPLY
The one-liner awk script in __git_match_ctag() listing ctags symbol
names for 'git grep <TAB>' is already smart enough to list only symbol
names matching the current word to be completed.

Extend this helper function to accept prefix and suffix parameters to
be prepended and appended, respectively, to each listed symbol name in
the awk script, so its output won't require any additional processing
or filtering in the completion script before being handed over to
Bash.  Use the faster __gitcomp_direct() helper instead of
__gitcomp_nl() to fill the fully processed matching symbol names into
Bash's COMPREPLY array.

Right after 'git grep <TAB>' in current git.git with 14k+ symbol names
in the tag file, best of five:

  Before:

    $ time __gitcomp_nl "$(__git_match_ctag "" tags)"

    real    0m0.178s
    user    0m0.176s
    sys     0m0.000s

  After:

    $ time __gitcomp_direct "$(__git_match_ctag "" tags "" " ")"

    real    0m0.058s
    user    0m0.048s
    sys     0m0.008s

Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-23 13:31:24 -07:00
SZEDER Gábor
227307a639 completion: speed up branch and tag completion
Modify __git_heads() and __git_tags() and the few callsites they have,
so we can let 'git for-each-ref' do all the hard work and these
functions' output won't need any further processing or filtering
before being handed over to Bash, resulting in faster branch and tag
completion.  These are some of the same tricks used in the previous
commits to speed up refs completion, namely:

  - Extend both functions to accept prefix, current word and suffix
    positional parameters, all optional and all empty by default to
    keep the parameterless behavior unaltered.

  - Specify appropriate globbing patterns to 'git for-each-ref' to
    list only branches or tags matching the given current word
    parameter.

  - Modify the 'git for-each-ref --format=<...>' to include the given
    prefix and suffix.

  - Adjust all callsites to specify the proper prefix, current word
    and suffix parameters, and to fill COMPREPLY using
    __gitcomp_direct().

Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-23 11:18:23 -07:00
SZEDER Gábor
745d655dc9 completion: fill COMPREPLY directly when completing fetch refspecs
The __git_complete_fetch_refspecs() has to iterate over __git_refs()'s
output anyway to turn the listed matching refs into refspecs, and it
knows about the prefix and suffix that has to be added to each
refspec.

Modify this function to add the prefix and suffix to each refspec
while iterating and feed the result, since it doesn't need further
processing, to the new __gitcomp_direct() helper added in the previous
commit, because it should be faster when there are a lot of refspecs
to list.

Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-23 11:18:22 -07:00
SZEDER Gábor
fef56eb006 completion: fill COMPREPLY directly when completing refs
__gitcomp_nl() iterates over all the possible completion words it gets
as argument

  - filtering matching words,
  - appending a trailing space to each matching word (in all but two
    cases),
  - prepending a prefix to each matching word (when completing words
    after e.g. '--option=<TAB>' or 'master..<TAB>'), and
  - adding each matching word to the COMPREPLY array.

This takes a while when a lot of refs are passed to __gitcomp_nl().

The previous changes in this series ensure that __git_refs() lists
only refs matching the current word to be completed, making a second
filtering in __gitcomp_nl() redundant.

Adding the necessary prefix and suffix could be done in __git_refs()
as well:

  - When refs come from 'git for-each-ref', then that prefix and
    suffix could be added much more efficiently using a 'git
    for-each-ref' format containing said prefix and suffix.  Care
    should be taken, though, because that prefix might contain
    'for-each-ref' format specifiers as part of the left hand side of
    a '..' range or '...' symmetric difference notation or
    fetch/push/etc. refspec, e.g. 'git log "evil-%(refname)..br<TAB>'.
    Doubling every '%' in the prefix will prevent 'git for-each-ref'
    from interpolating any of those contained specifiers.
  - When refs come from 'git ls-remote', then that prefix and suffix
    can be added in the shell loop that has to process 'git
    ls-remote's output anyway.
  - Finally, the prefix and suffix can be added to that handful of
    potentially matching symbolic and pseudo refs right away in the
    shell loop listing them.

And then all what is still left to do is to assign a bunch of
newline-separated words to a shell array, which can be done without a
shell loop iterating over each word, basically making all of
__gitcomp_nl() unnecessary for refs completion.

Add the helper function __gitcomp_direct() to fill the COMPREPLY array
with prefiltered and preprocessed words without any additional
processing, without a shell loop, with just one single compound
assignment.  Modify __git_refs() to accept prefix and suffix
parameters and add them to each and every listed ref as described
above.  Modify __git_complete_refs() to pass the prefix and suffix
parameters to __git_refs() and to feed __git_refs()'s output to
__gitcomp_direct() instead of __gitcomp_nl().

This speeds up refs completion when there are a lot of refs matching
the current word to be completed.  Listing all branches for completion
in a repo with 100k local branches, all packed, best of five:

  On Linux, near the beginning of this series, for reference:

    $ time __git_complete_refs

    real    0m2.028s
    user    0m1.692s
    sys     0m0.344s

  Before this patch:

    real    0m1.135s
    user    0m1.112s
    sys     0m0.024s

  After:

    real    0m0.367s
    user    0m0.352s
    sys     0m0.020s

  On Windows, near the beginning:

    real    0m13.078s
    user    0m1.609s
    sys     0m0.060s

  Before this patch:

    real    0m2.093s
    user    0m1.641s
    sys     0m0.060s

  After:

    real    0m0.683s
    user    0m0.203s
    sys     0m0.076s

Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-23 11:18:22 -07:00
SZEDER Gábor
400a7553c4 completion: let 'for-each-ref' sort remote branches for 'checkout' DWIMery
When listing unique remote branches for 'git checkout's tracking
DWIMery, __git_refs() runs the classic '... |sort |uniq -u' pattern to
filter out duplicate remote branches.

Let 'git for-each-ref' do the sorting, sparing the overhead of
fork()+exec()ing 'sort' and a stage in the pipeline where potentially
relatively large amount of data can be passed between two subsequent
pipeline stages.

This speeds up refs completion for 'git checkout' a bit when a lot of
remote branches match the current word to be completed.  Listing a
single local and 100k remote branches, all packed, best of five:

  On Linux, before:

    $ time __git_complete_refs --track

    real    0m1.856s
    user    0m1.816s
    sys     0m0.060s

  After:

    real    0m1.550s
    user    0m1.512s
    sys     0m0.060s

  On Windows, before:

    real    0m3.128s
    user    0m2.155s
    sys     0m0.183s

  After:

    real    0m2.781s
    user    0m1.826s
    sys     0m0.136s

Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-23 11:18:22 -07:00
SZEDER Gábor
824388d54b completion: let 'for-each-ref' filter remote branches for 'checkout' DWIMery
The code listing unique remote branches for 'git checkout's tracking
DWIMery outputs only remote branches that match the current word to be
completed, but the filtering is done in a shell loop iterating over
all remote refs.

Let 'git for-each-ref' do the filtering, as it can do so much more
efficiently and we can remove that shell loop entirely.

This speeds up refs completion for 'git checkout' considerably when
there are a lot of non-matching remote refs to be filtered out.
Uniquely completing a branch in a repository with 100k remote
branches, all packed, best of five:

  On Linux, before:

    $ time __git_complete_refs --cur=maste --track

    real    0m1.993s
    user    0m1.740s
    sys     0m0.304s

  After:

    real    0m0.266s
    user    0m0.248s
    sys     0m0.012s

  On Windows, before:

    real    0m6.187s
    user    0m3.358s
    sys     0m2.121s

  After:

    real    0m0.750s
    user    0m0.015s
    sys     0m0.090s

Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-23 11:18:22 -07:00
SZEDER Gábor
e8cb023433 completion: let 'for-each-ref' strip the remote name from remote branches
The code listing unique remote branches for 'git checkout's tracking
DWIMery uses a shell parameter expansion in a loop iterating over each
listed ref to remove the remote's name from the remote branches, i.e.
the leading path component from the short ref.  When listing refs from
a configured remote repository, '| sed s///' is used for the same
purpose.

Let 'git for-each-ref' strip one more leading path component from the
refs, i.e. use the format 'refname:strip=3' instead of '=2', making
that parameter expansion and 'sed' execution unnecessary.

This speeds up refs completion for 'git checkout'.  Uniquely
completing a branch for 'git checkout maste<TAB>' in a repo with 100k
remote branches, all packed, best of five:

  On Linux, near the beginning of this series, for reference:

    $ time __git_complete_refs --cur=maste --track

    real    0m8.185s
    user    0m6.896s
    sys     0m1.616s

  Before this patch:

    real    0m2.714s
    user    0m2.344s
    sys     0m0.436s

  After:

    real    0m1.993s
    user    0m1.740s
    sys     0m0.304s

  On Windows, near the beginning:

    real    1m8.421s
    user    0m7.591s
    sys     0m3.557s

  Before this patch:

    real    0m8.191s
    user    0m4.638s
    sys     0m2.918s

  After:

    real    0m6.187s
    user    0m3.358s
    sys     0m2.121s

Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-23 11:18:22 -07:00
SZEDER Gábor
e896369beb completion: let 'for-each-ref' and 'ls-remote' filter matching refs
When completing refs, several __git_refs() code paths list all the
refs from the refs/{heads,tags,remotes}/ hierarchy and then
__gitcomp_nl() iterates over those refs in a shell loop to filter out
refs not matching the current ref to be completed.  This comes with a
considerable performance penalty when a repository contains a lot of
refs but the current ref can be uniquely completed or when only a
handful of refs match the current ref.

Reduce the number of iterations in __gitcomp_nl() from the number of
refs to the number of matching refs by specifying appropriate globbing
patterns to 'git for-each-ref' and 'git ls-remote' to list only those
refs that match the current ref to be completed.  However, do so only
when the ref to match is explicitly given as parameter, because the
current word on the command line might contain a prefix like
'--option=' or 'branch..'.  The __git_complete_refs() and
__git_complete_fetch_refspecs() helpers introduced previously in this
patch series already call __git_refs() specifying this current ref
parameter, so all their callsites, i.e. all places in the completion
script doing refs completion, can benefit from this optimization.

Furthermore, list only those symbolic and pseudo refs that match the
current ref to be completed.  Though it doesn't matter at all in
itself performance-wise, it will allow us further significant
optimizations later in this series.

This speeds up refs completion considerably when there are a lot of
non-matching refs to be filtered out.  Uniquely completing a branch in
a repository with 100k local branches, all packed, best of five:

  On Linux, before:

    $ time __git_complete_refs --cur=maste

    real    0m0.831s
    user    0m0.808s
    sys     0m0.028s

  After:

    real    0m0.119s
    user    0m0.104s
    sys     0m0.008s

  On Windows, before:

    real    0m1.480s
    user    0m1.031s
    sys     0m0.060s

  After:

    real    0m0.377s
    user    0m0.015s
    sys     0m0.030s

Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-23 11:18:22 -07:00
SZEDER Gábor
b2b6811451 completion: don't disambiguate short refs
When the completion script lists short refs it does so using the 'git
for-each-ref' format 'refname:short', which makes sure that all listed
refs are unambiguous.  While disambiguating refs is technically
correct in this case, as opposed to the cases discussed in the
previous patch, this disambiguation involves several stat() syscalls
for each ref, thus, unfortunately, comes at a steep cost especially on
Windows and/or when there are a lot of refs to be listed.  A user of
Git for Windows reported[1] 'git checkout <TAB>' taking ~11 seconds in
a repository with just about 4000 refs.

However, it's questionable whether ambiguous refs are really that bad
to justify that much extra cost:

  - Ambiguous refs are not that common,
  - even if a repository contains ambiguous refs, they only hurt when
    the user actually happens to want to do something with one of the
    ambiguous refs, and
  - the issue can be easily circumvented by renaming those ambiguous
    refs.

  - On the other hand, apparently not that many refs are needed to
    make refs completion unacceptably slow on Windows,
  - and this slowness bites each and every time the user attempts refs
    completion, even when the repository doesn't contain any ambiguous
    refs.
  - Furthermore, circumventing the issue might not be possible or
    might be considerably more difficult and requires various
    trade-offs (e.g. working in a repository with only a few selected
    important refs while keeping a separate repository with all refs
    for reference).

Arguably, in this case the benefits of technical correctness are
rather minor compared to the price we pay for it, and we are better
off opting for performance over correctness.

Use the 'git for-each-ref' format 'refname:strip=2' to list short refs
to spare the substantial cost of disambiguating.

This speeds up refs completion considerably.  Uniquely completing a
branch in a repository with 100k local branches, all packed, best of
five:

  On Linux, before:

    $ time __git_complete_refs --cur=maste

    real    0m1.662s
    user    0m1.368s
    sys     0m0.296s

  After:

    real    0m0.831s
    user    0m0.808s
    sys     0m0.028s

  On Windows, before:

    real    0m12.457s
    user    0m1.016s
    sys     0m0.092s

  After:

    real    0m1.480s
    user    0m1.031s
    sys     0m0.060s

[1] - https://github.com/git-for-windows/git/issues/524

Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-23 11:18:22 -07:00
SZEDER Gábor
3ad8ea7ccc completion: don't disambiguate tags and branches
When the completion script has to list only tags or only branches, it
uses the 'git for-each-ref' format 'refname:short', which makes sure
that all listed tags and branches are unambiguous.  However,
disambiguating tags and branches in these cases is wrong, because:

  - __git_tags(), the helper function listing possible tagname
    arguments for 'git tag', lists an ambiguous tag
    'refs/tags/ambiguous' as 'tags/ambiguous'.  Its only consumer,
    'git tag' expects its tagname argument to be under 'refs/tags/',
    thus it interprets that abgiguous tag as
    'refs/tags/tags/ambiguous'.  Clearly wrong.

  - __git_heads() lists possible branchname arguments for 'git branch'
    and possible 'branch.<branchname>' configuration subsections.
    Both of these expect branchnames to be under 'refs/heads/' and
    misinterpret a disambiguated branchname like 'heads/ambiguous'.

Furthermore, disambiguation involves several stat() syscalls for each
tag or branch, thus comes at a steep cost especially on Windows and/or
when there are a lot of tags or branches to be listed.

Use the 'git for-each-ref' format 'refname:strip=2' instead of
'refname:short' to avoid harmful disambiguation of tags and branches
in __git_tags() and __git_heads().

Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-23 11:18:22 -07:00
SZEDER Gábor
aed3881359 completion: support excluding full refs
Commit 49416ad22 (completion: support excluding refs, 2016-08-24) made
possible to complete short refs with a '^' prefix.

Extend the support to full refs to make completing '^refs/...' work.

Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-23 11:18:22 -07:00
SZEDER Gábor
aa0644f74f completion: support completing fully qualified non-fast-forward refspecs
After 'git fetch <remote> <TAB>' our completion script offers refspecs
that will fetch to a local branch with the same name as in the remote
repository, e.g. 'master:master'.  This also completes
non-fast-forward refspecs, i.e. after a '+' prefix like
'+master:master', and fully qualified refspecs, e.g.
'refs/heads/master:refs/heads/master'.  However, it does not complete
non-fast-forward fully qualified refspecs (or fully qualified refspecs
following any other prefix, e.g. '--option=', though currently no git
command supports such an option, but third party git commands might).

These refspecs are listed by the __git_refs2() function, which is just
a thin wrapper iterating over __git_refs()'s output, turning each
listed ref into a refspec.  Now, it's certainly possible to modify
__git_refs2() and its callsite to pass an extra parameter containing
only the ref part of the current word to be completed (to follow suit
of the previous commit) to deal with prefixed fully qualified refspecs
as well.  Unfortunately, keeping the current behavior unchanged in the
"no extra parameter" case brings in a bit of subtlety, which makes the
resulting code ugly and compelled me to write a 8-line long comment in
the proof of concept.  Not good.  However, since the callsite has to
be modified for proper functioning anyway, we might as well leave
__git_refs2() as is and introduce a new helper function without
backwards compatibility concerns.

Add the new function __git_complete_fetch_refspecs() that has all the
necessary parameters to do the right thing in all cases mentioned
above, including non-fast-forward fully qualified refspecs.  This new
function can also easier benefit from optimizations coming later in
this patch series.

Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-23 11:18:22 -07:00
SZEDER Gábor
2ea328a119 completion: support completing full refs after '--option=refs/<TAB>'
Completing full refs currently only works when the full ref stands on
in its own on the command line, but doesn't work when the current word
to be completed contains a prefix before the full ref, e.g.
'--option=refs/<TAB>' or 'master..refs/bis<TAB>'.

The reason is that __git_refs() looks at the current word to be
completed ($cur) as a whole to decide whether it has to list full (if
it starts with 'refs/') or short refs (otherwise).  However, $cur also
holds said '--option=' or 'master..' prefixes, which of course throw
off this decision.  Luckily, the default action is to list short refs,
that's why completing short refs happens to work even after a
'master..<TAB>' prefix and similar cases.

Pass only the ref part of the current word to be completed to
__git_refs() as a new positional parameter, so it can make the right
decision even if the whole current word contains some kind of a
prefix.

Make this new parameter the 4. positional parameter and leave the 3.
as an ignored placeholder for now (it will be used later in this patch
series).

Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-23 11:18:22 -07:00
SZEDER Gábor
15b4a16395 completion: wrap __git_refs() for better option parsing
__git_refs() currently accepts two optional positional parameters: a
remote and a flag for 'git checkout's tracking DWIMery.  To fix a
minor bug, and, more importantly, for faster refs completion, this
series will add three more parameters: a prefix, the current word to
be completed and a suffix, i.e. the options accepted by __gitcomp() &
friends, and will change __git_refs() to list only refs matching that
given current word and to add that given prefix and suffix to the
listed refs.

However, __git_refs() is the helper function that is most likely used
in users' custom completion scriptlets for their own git commands, and
we don't want to break those, so

  - we can't change __git_refs()'s default output format, i.e. we
    can't by default append a trailing space to every listed ref,
    meaning that the suffix parameter containing the default trailing
    space would have to be specified on every invocation, and

  - we can't change the position of existing positional parameters
    either, so there would have to be plenty of set-but-empty
    placeholder positional parameters all over the completion script.

Furthermore, with five positional parameters it would be really hard
to remember which position means what.

To keep callsites simple, add the new wrapper function
__git_complete_refs() around __git_refs(), which:

  - instead of positional parameters accepts real '--opt=val'-style
    options and with minimalistic option parsing translates them to
    __git_refs()'s and __gitcomp_nl()'s positional parameters, and

  - includes the '__gitcomp_nl "$(__git_refs ...)" ...' command
    substitution to make its behavior match its name and the behavior
    of other __git_complete_* functions, and to limit future changes
    in this series to __git_refs() and this new wrapper function.

Call this wrapper function instead of __git_refs() wherever possible
throughout the completion script, i.e. when __git_refs()'s output is
fed to __gitcomp_nl() right away without further processing, which
means all callsites except a single one in the __git_refs2() helper.

Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-23 11:18:22 -07:00
Junio C Hamano
cbfbf443b0 Merge branch 'mg/prompt-describe-tags'
The command line prompt (in contrib/) learned a new 'tag' style
that can be specified with GIT_PS1_DESCRIBE_STYLE, to describe a
detached HEAD with "git describe --tags".

* mg/prompt-describe-tags:
  git-prompt: add a describe style for any tags
2017-03-21 15:07:17 -07:00
Michael J Gruber
9f0b4dd0b8 git-prompt: add a describe style for any tags
git-prompt has various describe styles, among them "describe" (by
annotated tags) and "default" (by exact match with any tag).

Add a mode "tag" that describes by any tag, annotated or not.

Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-15 13:19:41 -07:00
Junio C Hamano
271513cd54 Merge branch 'ss/remote-bzr-hg-placeholder-wo-python'
There is no need for Python only to give a few messages to the
standard error stream, but we somehow did.

* ss/remote-bzr-hg-placeholder-wo-python:
  contrib: git-remote-{bzr,hg} placeholders don't need Python
2017-03-12 23:21:34 -07:00