Commit Graph

46589 Commits

Author SHA1 Message Date
Jeff King
ba47a3088f replace snprintf with odb_pack_name()
In several places we write the name of the pack filename
into a fixed-size buffer using snprintf(), but do not check
the return value.  As a result, a very long object directory
could cause us to quietly truncate the pack filename
(potentially leading to a corrupted repository, as a newly
written packfile could be missing its .pack extension).

We can use odb_pack_name() to do this with a strbuf (and
shorten the code, as well).

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-16 11:26:18 -07:00
Jeff King
eaeefc3276 odb_pack_keep(): stop generating keepfile name
The odb_pack_keep() function generates the name of a .keep
file and opens it. This has two problems:

  1. It requires a fixed-size buffer to create the filename
     and doesn't notice when the result is truncated.

  2. Of the two callers, one sometimes wants to open a
     filename it already has, which makes things awkward (it
     has to do so manually, and skips the leading-directory
     creation).

Instead, let's have odb_pack_keep() just open the file.
Generating the name isn't hard, and a future patch will
switch callers over to odb_pack_name() anyway.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-16 11:17:00 -07:00
Jeff King
1cec8c634f sha1_file.c: make pack-name helper globally accessible
We provide sha1_pack_name() and sha1_pack_index_name(), but
the more generic form (which takes its own strbuf and an
arbitrary extension) is only used to implement the other
two.  Let's make it available, but clean up a few things:

  1. Name it odb_pack_name(), as the original
     sha1_get_pack_name() is long but not all that
     descriptive.

  2. Switch the strbuf argument to the beginning, so that it
     matches similar path-building functions like
     git_path_buf().

  3. Clean up the out-dated docstring and move it to the
     public declaration.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-16 11:05:17 -07:00
Jeff King
82c9d6614b move odb_* declarations out of git-compat-util.h
These functions were originally conceived as wrapper
functions similar to xmkstemp(). They were later moved by
463db9b10 (wrapper: move odb_* to environment.c,
2010-11-06). The more appropriate place for a declaration is
in cache.h.

While we're at it, let's add some basic docstrings.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-16 11:04:34 -07:00
Stefan Beller
6cd5757c89 update submodules: move up prepare_submodule_repo_env
In a later patch we need to prepare the submodule environment with
another git directory, so split up the function.

Also move it up in the file such that we do not need to declare the
function later before using it.

Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-15 18:15:54 -07:00
Stefan Beller
84f8925eeb submodules: introduce check to see whether to touch a submodule
In later patches we introduce the --recurse-submodule flag for commands
that modify the working directory, e.g. git-checkout.

It is potentially expensive to check if a submodule needs an update,
because a common theme to interact with submodules is to spawn a child
process for each interaction.

So let's introduce a function that checks if a submodule needs
to be checked for an update before attempting the update.

Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-15 18:15:54 -07:00
Stefan Beller
cf055e465f update submodules: add a config option to determine if submodules are updated
In later patches we introduce the options and flag for commands
that modify the working directory, e.g. git-checkout.

Have a central place to store such settings whether we want to update
a submodule.

Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-15 18:15:54 -07:00
Stefan Beller
d601fd0957 update submodules: add submodule config parsing
Similar to b33a15b08 (push: add recurseSubmodules config option,
2015-11-17) and 027771fcb1 (submodule: allow erroneous values for the
fetchRecurseSubmodules option, 2015-08-17), we add submodule-config code
that is later used to parse whether we are interested in updating
submodules.

We need the `die_on_error` parameter to be able to call this parsing
function for the config file as well, which if incorrect lets Git die.

As we're just touching the header file, also mark all functions extern.

Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-15 18:15:54 -07:00
Stefan Beller
15cdc64776 make is_submodule_populated gently
We need the gentle version in a later patch. As we have just one caller,
migrate the caller.

Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-15 18:15:54 -07:00
Stefan Beller
259f3ee296 lib-submodule-update.sh: define tests for recursing into submodules
Currently lib-submodule-update.sh provides 2 functions
test_submodule_switch and test_submodule_forced_switch that are used by a
variety of tests to ensure that submodules behave as expected. The current
expected behavior is that submodules are not touched at all (see
42639d2317 for the exact setup).

In the future we want to teach all these commands to recurse
into submodules. To do that, we'll add two testing functions to
submodule-update-lib.sh: test_submodule_switch_recursing and
test_submodule_forced_switch_recursing.

These two functions behave in analogy to the already existing functions
just with a different expectation on submodule behavior. The submodule
in the working tree is expected to be updated to the recorded submodule
version. The behavior is analogous to e.g. the behavior of files in a
nested directory in the working tree, where a change to the working tree
handles any arising directory/file conflicts just fine.

Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-15 18:15:54 -07:00
Stefan Beller
03c7e2a321 lib-submodule-update.sh: replace sha1 by hash
Cleaning up code by generalising it.
Currently the mailing list discusses yet again how
to migrate away from sha1.

Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-15 18:15:53 -07:00
Stefan Beller
2f70edccb4 lib-submodule-update: teach test_submodule_content the -C <dir> flag
Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-15 18:15:53 -07:00
Stefan Beller
a70ef2dac4 lib-submodule-update.sh: do not use ./. as submodule remote
Adding the repository itself as a submodule does not make sense in the
real world. In our test suite we used to do that out of convenience in
some tests as the current repository has easiest access for setting up
'just a submodule'.

However this doesn't quite test the real world, so let's do not follow
this pattern any further and actually create an independent repository
that we can use as a submodule.

When using './.' as the remote the superproject and submodule share the
same objects, such that testing if a given sha1 is a valid commit works
in either repository.  As running commands in an unpopulated submodule
fall back to the superproject, this happens in `reset_work_tree_to`
to determine if we need to populate the submodule. Fix this bug by
checking in the actual remote now.

Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-15 18:15:53 -07:00
Stefan Beller
eb41e7feed lib-submodule-update.sh: reorder create_lib_submodule_repo
Redraw the ASCII art describing the setup using more space, such that
it is easier to understand.  The leaf commits are now ordered the same
way the actual code is ordered.

Add empty lines to the setup code separating each of the leaf commits,
each starting with a "checkout -b".

Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-15 18:15:53 -07:00
Valery Tolstov
4682085cd4 submodule--helper.c: remove duplicate code
Remove code fragment from module_clone that duplicates functionality
of connect_work_tree_and_git_dir in dir.c

Signed-off-by: Valery Tolstov <me@vtolstov.org>
Reviewed-by: Brandon Williams <bmwill@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-15 18:15:53 -07:00
Stefan Beller
365444a6a5 connect_work_tree_and_git_dir: safely create leading directories
In a later patch we'll use connect_work_tree_and_git_dir when the
directory for the gitlink file doesn't exist yet. This patch makes
connect_work_tree_and_git_dir safe to use for both cases of
either the git dir or the working dir missing.

To do so, we need to call safe_create_leading_directories[_const]
on both directories. However this has to happen before we construct
the absolute paths as real_pathdup assumes the directories to
be there already.

So for both the config file in the git dir as well as the .git link
file we need to
a) construct the name
b) call SCLD
c) get the absolute path
d) once a-c is done for both we can consume the absolute path
   to compute the relative path to each other and store those
   relative paths.

The implementation provided here puts a) and b) for both cases first,
and then performs c and d after.

One of the two users of 'connect_work_tree_and_git_dir' already checked
for the directory being there, so we can loose that check as
connect_work_tree_and_git_dir handles this functionality now.

Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-15 18:15:53 -07:00
Jeff King
ffddfc6328 rev-parse: simplify parsing of ref options
All of these options do the same thing "--foo" iterates over
the "foo" refs, and "--foo=<glob>" does the same with a
glob. We can factor this into its own function to avoid
repeating ourselves.

There are two subtleties to note:

  - the original called for_each_branch_ref(), etc, in the
    non-glob case. Now we will call for_each_ref_in("refs/heads/")
    which is exactly what for_each_branch_ref() did under
    the hood.

  - for --glob, we'll call for_each_glob_ref_in() with a
    NULL "prefix" argument. Which is exactly what
    for_each_glob_ref() was doing already.

So both cases should behave identically, and it seems
reasonable to assume that this will remain the same. The
functions we are calling now are the more-generic ones, and
the ones we are dropping are just convenience wrappers.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-15 14:02:36 -07:00
Jeff King
9d16ca65bb rev-parse: add helper for parsing "--foo/--foo="
We can't just use a bare skip_prefix() for these cases,
because we need to match both the "--foo" form and the
"--foo=<value>" form (and tell the difference between the
two in the caller).

We can wrap this in a simple helper which has two obvious
callsites, and will gain some more in the next patch.

Note that the error output for abbrev-ref changes slightly,
as we don't keep our original "arg" pointer. However, the
new output should hopefully be more clear:

  [before]
  fatal: unknown mode for --abbrev-ref=foo

  [after]
  fatal: unknown mode for --abbrev-ref: foo

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-15 14:01:51 -07:00
Jeff King
ef87cc79df rev-parse: use skip_prefix when parsing options
Using skip_prefix lets us avoid manually-counted offsets
into the argument string. This patch converts the simple and
obvious cases.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-15 14:00:28 -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
Jeff King
b16a991c1b cherry-pick: detect bogus arguments to --mainline
The cherry-pick and revert commands use OPT_INTEGER() to
parse --mainline. The stock parser is smart enough to reject
non-numeric nonsense, but it doesn't know that parent
counting starts at 1.

Worse, the value "0" is indistinguishable from the unset
case, so a user who assumes the counting is 0-based will get
a confusing message:

  $ git cherry-pick -m 0 $merge
  error: commit ... is a merge but no -m option was given.

Let's use a custom callback that enforces our range.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-15 12:08:36 -07:00
David Aguilar
18ec800512 difftool: handle modified symlinks in dir-diff mode
Detect the null object ID for symlinks in dir-diff so that difftool can
detect when symlinks are modified in the worktree.

Previously, a null symlink object ID would crash difftool.
Handle null object IDs as unknown content that must be read from
the worktree.

Helped-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: David Aguilar <davvid@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-15 12:08:10 -07:00
David Aguilar
98fde5e47b t7800: cleanup cruft left behind by tests
Signed-off-by: David Aguilar <davvid@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-15 11:57:29 -07:00
David Aguilar
8d8061d642 t7800: remove whitespace before redirect
Signed-off-by: David Aguilar <davvid@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-15 11:57:16 -07:00
Stefan Beller
5ea304896e submodule-config: correct error reporting for invalid ignore value
As 'var' contains the whole value we get error messages that repeat
the section and key currently:

warning: Invalid parameter 'true' for config option 'submodule.submodule.plugins/hooks.ignore.ignore'

Fix this by only giving the section name in the warning.

Signed-off-by: Stefan Beller <sbeller@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-15 11:26:08 -07:00
brian m. carlson
f18f816cb1 hash.h: move SHA-1 implementation selection into a header file
Many developers use functionality in their editors that allows for quick
syntax checks, including warning about questionable constructs.  This
functionality allows rapid development with fewer errors.  However, such
functionality generally does not allow the specification of
project-specific defines or command-line options.

Since the SHA1_HEADER include is not defined in such a case,
developers see spurious errors when using these tools.  Furthermore,
there are known implementations of "cc" whose '#include' is unhappy
with this construct.

Instead of using SHA1_HEADER, create a hash.h header and use #if
and #elif to select the desired header.  Have the Makefile pass an
appropriate option to help the header select the right implementation to
use.

[jc: make BLK_SHA1 the fallback default as discussed on list,
e.g. <20170314201424.vccij5z2ortq4a4o@sigill.intra.peff.net>; also
remove SHA1_HEADER and SHA1_HEADER_SQ that are no longer used].

Signed-off-by: brian m. carlson <sandals@crustytoothpaste.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Reviewed-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-15 11:00:09 -07:00
Junio C Hamano
4a9b9b32d4 Fourth batch after 2.12
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-14 15:29:40 -07:00
Junio C Hamano
0737780171 Merge branch 'kn/ref-filter-branch-list'
"git branch --list" takes the "--abbrev" and "--no-abbrev" options
to control the output of the object name in its "-v"(erbose)
output, but a recent update started ignoring them; this fixes it
before the breakage reaches to any released version.

* kn/ref-filter-branch-list:
  branch: honor --abbrev/--no-abbrev in --list mode
2017-03-14 15:23:20 -07:00
Junio C Hamano
d6857a831c Merge branch 'jk/push-deadlock-regression-fix'
"git push" had a handful of codepaths that could lead to a deadlock
when unexpected error happened, which has been fixed.

* jk/push-deadlock-regression-fix:
  send-pack: report signal death of pack-objects
  send-pack: read "unpack" status even on pack-objects failure
  send-pack: improve unpack-status error messages
  send-pack: use skip_prefix for parsing unpack status
  send-pack: extract parsing of "unpack" response
  receive-pack: fix deadlock when we cannot create tmpdir
2017-03-14 15:23:20 -07:00
Junio C Hamano
130b664e44 Merge branch 'js/travis-32bit-linux'
Add 32-bit Linux variant to the set of platforms to be tested with
Travis CI.

* js/travis-32bit-linux:
  Travis: also test on 32-bit Linux
2017-03-14 15:23:20 -07:00
Junio C Hamano
519592bcc6 Merge branch 'ew/http-alternates-as-redirects-warning'
Recent versions of Git treats http alternates (used in dumb http
transport) just like HTTP redirects and requires the client to
enable following it, due to security concerns.  But we forgot to
give a warning when we decide not to honor the alternates.

* ew/http-alternates-as-redirects-warning:
  http: release strbuf on disabled alternates
  http: inform about alternates-as-redirects behavior
2017-03-14 15:23:19 -07:00
Junio C Hamano
5296357386 Merge branch 'dp/filter-branch-prune-empty'
"git filter-branch --prune-empty" drops a single-parent commit that
becomes a no-op, but did not drop a root commit whose tree is empty.

* dp/filter-branch-prune-empty:
  p7000: add test for filter-branch with --prune-empty
  filter-branch: fix --prune-empty on parentless commits
  t7003: ensure --prune-empty removes entire branch when applicable
  t7003: ensure --prune-empty can prune root commit
2017-03-14 15:23:19 -07:00
Junio C Hamano
228b78752d Merge branch 'jt/perf-updates'
The t/perf performance test suite was not prepared to test not so
old versions of Git, but now it covers versions of Git that are not
so ancient.

* jt/perf-updates:
  t/perf: add fallback for pre-bin-wrappers versions of git
  t/perf: use $MODERN_GIT for all repo-copying steps
  t/perf: export variable used in other blocks
2017-03-14 15:23:19 -07:00
Junio C Hamano
07198afbd1 Merge branch 'mm/fetch-show-error-message-on-unadvertised-object'
"git fetch" that requests a commit by object name, when the other
side does not allow such an request, failed without much
explanation.

* mm/fetch-show-error-message-on-unadvertised-object:
  fetch-pack: add specific error for fetching an unadvertised object
  fetch_refs_via_pack: call report_unmatched_refs
  fetch-pack: move code to report unmatched refs to a function
2017-03-14 15:23:18 -07:00
Junio C Hamano
c809496c97 Merge branch 'jk/interpret-branch-name'
"git branch @" created refs/heads/@ as a branch, and in general the
code that handled @{-1} and @{upstream} was a bit too loose in
disambiguating.

* jk/interpret-branch-name:
  checkout: restrict @-expansions when finding branch
  strbuf_check_ref_format(): expand only local branches
  branch: restrict @-expansions when deleting
  t3204: test git-branch @-expansion corner cases
  interpret_branch_name: allow callers to restrict expansions
  strbuf_branchname: add docstring
  strbuf_branchname: drop return value
  interpret_branch_name: move docstring to header file
  interpret_branch_name(): handle auto-namelen for @{-1}
2017-03-14 15:23:18 -07:00
Junio C Hamano
7c3b2034ed Merge branch 'ab/cond-skip-tests'
A few tests were run conditionally under (rare) conditions where
they cannot be run (like running cvs tests under 'root' account).

* ab/cond-skip-tests:
  gitweb tests: skip tests when we don't have Time::HiRes
  gitweb tests: change confusing "skip_all" phrasing
  cvs tests: skip tests that call "cvs commit" when running as root
2017-03-14 15:23:17 -07:00
Johannes Schindelin
5c4003ca3f setup.c: mention unresolved problems
During the review of the `early-config` patch series, two issues
have been identified that have been with us forever.  Mark the
identified problems for later so that we do not forget them.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-14 14:24:16 -07:00
Johannes Schindelin
751d3b9415 t1309: document cases where we would want early config not to die()
Jeff King came up with a couple examples that demonstrate how the new
read_early_config() that looks harder for the current .git/ directory
could die() in an undesirable way.

Let's add those cases to the test script, to document what we would like
to happen when early config encounters problems.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-14 14:24:16 -07:00
Johannes Schindelin
01017dce54 setup_git_directory_gently_1(): avoid die()ing
This function now has a new caller in addition to setup_git_directory():
the newly introduced discover_git_directory(). That function wants to
discover the current .git/ directory, and in case of a corrupted one
simply pretend that there is none to be found.

Example: if a stale .git file exists in the parent directory, and the
user calls `git -p init`, we want Git to simply *not* read any
repository config for the pager (instead of aborting with a message that
the .git file is corrupt).

Let's actually pretend that there was no GIT_DIR to be found in that case
when being called from discover_git_directory(), but keep the previous
behavior (i.e. to die()) for the setup_git_directory() case.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-14 14:24:16 -07:00
Johannes Schindelin
1a6ec1eb38 t1309: test read_early_config()
So far, we had no explicit tests of that function.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-14 14:24:16 -07:00
Johannes Schindelin
1a27409ae8 read_early_config(): really discover .git/
Earlier, we punted and simply assumed that we are in the top-level
directory of the project, and that there is no .git file but a .git/
directory so that we can read directly from .git/config.

However, that is not necessarily true. We may be in a subdirectory. Or
.git may be a gitfile. Or the environment variable GIT_DIR may be set.

To remedy this situation, we just refactored the way
setup_git_directory() discovers the .git/ directory, to make it
reusable, and more importantly, to leave all global variables and the
current working directory alone.

Let's discover the .git/ directory correctly in read_early_config() by
using that new function.

This fixes 4 known breakages in t7006.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-14 14:24:16 -07:00
Johannes Schindelin
267b4538c0 read_early_config(): avoid .git/config hack when unneeded
So far, we only look whether the startup_info claims to have seen a
git_dir.

However, do_git_config_sequence() (and consequently the
git_config_with_options() call used by read_early_config() asks the
have_git_dir() function whether we have a .git/ directory, which in turn
also looks at git_dir and at the environment variable GIT_DIR. And when
this is the case, the repository config is handled already, so we do not
have to do that again explicitly.

Let's just use the same function, have_git_dir(), to determine whether we
have to handle .git/config explicitly.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-14 14:24:16 -07:00
Johannes Schindelin
0654aa57f3 setup: make read_early_config() reusable
The pager configuration needs to be read early, possibly before
discovering any .git/ directory.

Let's not hide this function in pager.c, but make it available to other
callers.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-14 14:24:16 -07:00
Johannes Schindelin
16ac8b8db6 setup: introduce the discover_git_directory() function
We modified the setup_git_directory_gently_1() function earlier to make
it possible to discover the GIT_DIR without changing global state.

However, it is still a bit cumbersome to use if you only need to figure
out the (possibly absolute) path of the .git/ directory. Let's just
provide a convenient wrapper function with an easier signature that
*just* discovers the .git/ directory.

We will use it in a subsequent patch to fix the early config.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-14 14:24:16 -07:00
Johannes Schindelin
ce9b8aab5d setup_git_directory_1(): avoid changing global state
For historical reasons, Git searches for the .git/ directory (or the
.git file) by changing the working directory successively to the parent
directory of the current directory, until either anything was found or
until a ceiling or a mount point is hit.

Further global state may be changed in case a .git/ directory was found.

We do have a use case, though, where we would like to find the .git/
directory without having any global state touched, though: when we read
the early config e.g. for the pager or for alias expansion.

Let's just move all of code that changes any global state out of the
function `setup_git_directory_gently_1()` into
`setup_git_directory_gently()`.

In subsequent patches, we will use the _1() function in a new
`discover_git_directory()` function that we will then use for the early
config code.

Note: the new loop is a *little* tricky, as we have to handle the root
directory specially: we cannot simply strip away the last component
including the slash, as the root directory only has that slash. To remedy
that, we introduce the `min_offset` variable that holds the minimal length
of an absolute path, and using that to special-case the root directory,
including an early exit before trying to find the parent of the root
directory.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-14 14:24:16 -07:00
Johannes Schindelin
df380d58ec setup: prepare setup_discovered_git_dir() for the root directory
Currently, the offset parameter (indicating what part of the cwd
parameter corresponds to the current directory after discovering the
.git/ directory) is set to 0 when we are running in the root directory.

However, in the next patches we will avoid changing the current working
directory while searching for the .git/ directory, meaning that the
offset corresponding to the root directory will have to be 1 to reflect
that this directory is characterized by the path "/" (and not "").

So let's make sure that setup_discovered_git_directory() only tries to
append the trailing slash to non-root directories.

Note: the setup_bare_git_directory() does not need a corresponding
change, as it does not want to return a prefix.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-14 14:24:04 -07:00
Jeff King
7288e12cce add--interactive: do not expand pathspecs with ls-files
When we want to get the list of modified files, we first
expand any user-provided pathspecs with "ls-files", and then
feed the resulting list of paths as arguments to
"diff-index" and "diff-files". If your pathspec expands into
a large number of paths, you may run into one of two
problems:

  1. The OS may complain about the size of the argument
     list, and refuse to run. For example:

       $ (ulimit -s 128 && git add -p drivers)
       Can't exec "git": Argument list too long at .../git-add--interactive line 177.
       Died at .../git-add--interactive line 177.

     That's on the linux.git repository, which has about 20K
     files in the "drivers" directory (none of them modified
     in this case). The "ulimit -s" trick is necessary to
     show the problem on Linux even for such a gigantic set
     of paths. Other operating systems have much smaller
     limits (e.g., a real-world case was seen with only 5K
     files on OS X).

  2. Even when it does work, it's really slow. The pathspec
     code is not optimized for huge numbers of paths. Here's
     the same case without the ulimit:

       $ time git add -p drivers
       No changes.

       real	0m16.559s
       user	0m53.140s
       sys	0m0.220s

We can improve this by skipping "ls-files" completely, and
just feeding the original pathspecs to the diff commands.
This solution was discussed in 2010:

  http://public-inbox.org/git/20100105041438.GB12574@coredump.intra.peff.net/

but at the time the diff code's pathspecs were more
primitive than those used by ls-files (e.g., they did not
support globs). Making the change would have caused a
user-visible regression, so we didn't.

Since then, the pathspec code has been unified, and the diff
commands natively understand pathspecs like '*.c'.

This patch implements that solution. That skips the
argument-list limits, and the result runs much faster:

  $ time git add -p drivers
  No changes.

  real	0m0.149s
  user	0m0.116s
  sys	0m0.080s

There are two new tests. The first just exercises the
globbing behavior to confirm that we are not causing a
regression there. The second checks the actual argument
behavior using GIT_TRACE. We _could_ do it with the "ulimit
-s" trick, as above. But that would mean the test could only
run where "ulimit -s" works. And tests of that sort are
expensive, because we have to come up with enough files to
actually bust the limit (we can't just shrink the "128" down
infinitely, since it is also the in-program stack size).

Finally, two caveats and possibilities for future work:

  a. This fixes one argument-list expansion, but there may
     be others. In fact, it's very likely that if you run
     "git add -i" and select a large number of modified
     files that the script would try to feed them all to a
     single git command.

     In practice this is probably fine. The real issue here
     is that the argument list was growing with the _total_
     number of files, not the number of modified or selected
     files.

  b. If the repository contains filenames with literal wildcard
     characters (e.g., "foo*"), the original code expanded
     them via "ls-files" and then fed those wildcard names
     to "diff-index", which would have treated them as
     wildcards. This was a bug, which is now fixed (though
     unless you really go through some contortions with
     ":(literal)", it's likely that your original pathspec
     would match whatever the accidentally-expanded wildcard
     would anyway).

     So this takes us one step closer to working correctly
     with files whose names contain wildcard characters, but
     it's likely that others remain (e.g., if "git add -i"
     feeds the selected paths to "git add").

Reported-by: Wincent Colaiuta <win@wincent.com>
Reported-by: Mislav Marohnić <mislav.marohnic@gmail.com>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-14 13:27:23 -07:00
Michael J Gruber
b9e2bc560a git-status: make porcelain more robust
git status provides a porcelain mode for porcelain writers with a
supposedly stable (plumbing) interface.
7a76c28ff2 ("status: disable translation when --porcelain is used", 2014-03-20)
made sure that ahead/behind info is not translated (i.e. is stable).

Make sure that the remaining two strings (initial commit, detached head)
are stable, too.

These changes are for the v1 porcelain interface. While we do have a perfectly
stable v2 porcelain interface now, some tools (such as
powerline-gitstatus) are written against v1 and profit from fixing v1
without any changes on their side.

Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-14 13:15:18 -07:00
Brandon Williams
c5af19f9ab pathspec: allow escaped query values
In our own .gitattributes file we have attributes such as:

    *.[ch] whitespace=indent,trail,space

When querying for attributes we want to be able to ask for the exact
value, i.e.

    git ls-files :(attr:whitespace=indent,trail,space)

should work, but the commas are used in the attr magic to introduce
the next attr, such that this query currently fails with

fatal: Invalid pathspec magic 'trail' in ':(attr:whitespace=indent,trail,space)'

This change allows escaping characters by a backslash, such that the query

    git ls-files :(attr:whitespace=indent\,trail\,space)

will match all path that have the value "indent,trail,space" for the
whitespace attribute. To accomplish this, we need to modify two places.
First `parse_long_magic` needs to not stop early upon seeing a comma or
closing paren that is escaped. As a second step we need to remove any
escaping from the attr value.

Based on a patch by Stefan Beller <sbeller@google.com>

Signed-off-by: Brandon Williams <bmwill@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-13 15:28:56 -07:00
Brandon Williams
b0db704652 pathspec: allow querying for attributes
The pathspec mechanism is extended via the new
":(attr:eol=input)pattern/to/match" syntax to filter paths so that it
requires paths to not just match the given pattern but also have the
specified attrs attached for them to be chosen.

Based on a patch by Stefan Beller <sbeller@google.com>
Signed-off-by: Brandon Williams <bmwill@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2017-03-13 15:28:54 -07:00