Merge branch 'tg/grep-no-index-fallback'
authorJunio C Hamano <gitster@pobox.com>
Wed, 20 Jan 2016 19:43:38 +0000 (11:43 -0800)
committerJunio C Hamano <gitster@pobox.com>
Wed, 20 Jan 2016 19:43:39 +0000 (11:43 -0800)
"git grep" by default does not fall back to its "--no-index"
behaviour outside a directory under Git's control (otherwise the
user may by mistake end up running a huge recursive search); with a
new configuration (set in $HOME/.gitconfig--by definition this
cannot be set in the config file per project), this safety can be
disabled.

* tg/grep-no-index-fallback:
builtin/grep: add grep.fallbackToNoIndex config
t7810: correct --no-index test

1  2 
Documentation/config.txt
Documentation/git-grep.txt
builtin/grep.c
diff --combined Documentation/config.txt
index beb18da14354a4b8b475b74113d103d404c70a7d,d41b2a61a82645755256e580cd5227b5940010b9..07f7a3b771266d488f986cd803e3fd7809533e21
@@@ -453,8 -453,6 +453,8 @@@ false), while all other repositories ar
  
  core.worktree::
        Set the path to the root of the working tree.
 +      If GIT_COMMON_DIR environment variable is set, core.worktree
 +      is ignored and not used for determining the root of working tree.
        This can be overridden by the GIT_WORK_TREE environment
        variable and the '--work-tree' command-line option.
        The value can be an absolute path or relative to the path to
@@@ -624,12 -622,6 +624,12 @@@ core.commentChar:
  If set to "auto", `git-commit` would select a character that is not
  the beginning character of any line in existing commit messages.
  
 +core.packedRefsTimeout::
 +      The length of time, in milliseconds, to retry when trying to
 +      lock the `packed-refs` file. Value 0 means not to retry at
 +      all; -1 means to try indefinitely. Default is 1000 (i.e.,
 +      retry for 1 second).
 +
  sequence.editor::
        Text editor used by `git rebase -i` for editing the rebase instruction file.
        The value is meant to be interpreted by the shell when it is used.
@@@ -769,14 -761,6 +769,14 @@@ am.keepcr:
        by giving '--no-keep-cr' from the command line.
        See linkgit:git-am[1], linkgit:git-mailsplit[1].
  
 +am.threeWay::
 +      By default, `git am` will fail if the patch does not apply cleanly. When
 +      set to true, this setting tells `git am` to fall back on 3-way merge if
 +      the patch records the identity of blobs it is supposed to apply to and
 +      we have those blobs available locally (equivalent to giving the `--3way`
 +      option from the command line). Defaults to `false`.
 +      See linkgit:git-am[1].
 +
  apply.ignoreWhitespace::
        When set to 'change', tells 'git apply' to ignore changes in
        whitespace, in the same way as the '--ignore-space-change'
@@@ -866,9 -850,9 +866,9 @@@ branch.<name>.rebase:
        "git pull" is run. See "pull.rebase" for doing this in a non
        branch-specific manner.
  +
 -      When preserve, also pass `--preserve-merges` along to 'git rebase'
 -      so that locally committed merge commits will not be flattened
 -      by running 'git pull'.
 +When preserve, also pass `--preserve-merges` along to 'git rebase'
 +so that locally committed merge commits will not be flattened
 +by running 'git pull'.
  +
  *NOTE*: this is a possibly dangerous operation; do *not* use
  it unless you understand the implications (see linkgit:git-rebase[1]
@@@ -1122,9 -1106,6 +1122,9 @@@ credential.<url>.*:
        example.com. See linkgit:gitcredentials[7] for details on how URLs are
        matched.
  
 +credentialCache.ignoreSIGHUP::
 +      Tell git-credential-cache--daemon to ignore SIGHUP, instead of quitting.
 +
  include::diff-config.txt[]
  
  difftool.<tool>.path::
@@@ -1253,25 -1234,6 +1253,25 @@@ filter.<driver>.smudge:
        object to a worktree file upon checkout.  See
        linkgit:gitattributes[5] for details.
  
 +fsck.<msg-id>::
 +      Allows overriding the message type (error, warn or ignore) of a
 +      specific message ID such as `missingEmail`.
 ++
 +For convenience, fsck prefixes the error/warning with the message ID,
 +e.g.  "missingEmail: invalid author/committer line - missing email" means
 +that setting `fsck.missingEmail = ignore` will hide that issue.
 ++
 +This feature is intended to support working with legacy repositories
 +which cannot be repaired without disruptive changes.
 +
 +fsck.skipList::
 +      The path to a sorted list of object names (i.e. one SHA-1 per
 +      line) that are known to be broken in a non-fatal way and should
 +      be ignored. This feature is useful when an established project
 +      should be accepted despite early commits containing errors that
 +      can be safely ignored such as invalid committer email addresses.
 +      Note: corrupt objects cannot be skipped with this setting.
 +
  gc.aggressiveDepth::
        The depth parameter used in the delta compression
        algorithm used by 'git gc --aggressive'.  This defaults
@@@ -1310,34 -1272,21 +1310,34 @@@ gc.packRefs:
  gc.pruneExpire::
        When 'git gc' is run, it will call 'prune --expire 2.weeks.ago'.
        Override the grace period with this config variable.  The value
 -      "now" may be used to disable this  grace period and always prune
 -      unreachable objects immediately.
 +      "now" may be used to disable this grace period and always prune
 +      unreachable objects immediately, or "never" may be used to
 +      suppress pruning.
 +
 +gc.worktreePruneExpire::
 +      When 'git gc' is run, it calls
 +      'git worktree prune --expire 3.months.ago'.
 +      This config variable can be used to set a different grace
 +      period. The value "now" may be used to disable the grace
 +      period and prune $GIT_DIR/worktrees immediately, or "never"
 +      may be used to suppress pruning.
  
  gc.reflogExpire::
  gc.<pattern>.reflogExpire::
        'git reflog expire' removes reflog entries older than
 -      this time; defaults to 90 days.  With "<pattern>" (e.g.
 +      this time; defaults to 90 days. The value "now" expires all
 +      entries immediately, and "never" suppresses expiration
 +      altogether. With "<pattern>" (e.g.
        "refs/stash") in the middle the setting applies only to
        the refs that match the <pattern>.
  
  gc.reflogExpireUnreachable::
 -gc.<ref>.reflogExpireUnreachable::
 +gc.<pattern>.reflogExpireUnreachable::
        'git reflog expire' removes reflog entries older than
        this time and are not reachable from the current tip;
 -      defaults to 30 days.  With "<pattern>" (e.g. "refs/stash")
 +      defaults to 30 days. The value "now" expires all entries
 +      immediately, and "never" suppresses expiration altogether.
 +      With "<pattern>" (e.g. "refs/stash")
        in the middle, the setting applies only to the refs that
        match the <pattern>.
  
@@@ -1450,10 -1399,10 +1450,14 @@@ grep.extendedRegexp:
        option is ignored when the 'grep.patternType' option is set to a value
        other than 'default'.
  
 +grep.threads::
 +      Number of grep worker threads to use.
 +      See `grep.threads` in linkgit:git-grep[1] for more information.
 +
+ grep.fallbackToNoIndex::
+       If set to true, fall back to git grep --no-index if git grep
+       is executed outside of a git repository.  Defaults to false.
  gpg.program::
        Use this custom program instead of "gpg" found on $PATH when
        making or verifying a PGP signature. The program must support the
@@@ -1616,42 -1565,6 +1620,42 @@@ http.saveCookies:
        If set, store cookies received during requests to the file specified by
        http.cookieFile. Has no effect if http.cookieFile is unset.
  
 +http.sslVersion::
 +      The SSL version to use when negotiating an SSL connection, if you
 +      want to force the default.  The available and default version
 +      depend on whether libcurl was built against NSS or OpenSSL and the
 +      particular configuration of the crypto library in use. Internally
 +      this sets the 'CURLOPT_SSL_VERSION' option; see the libcurl
 +      documentation for more details on the format of this option and
 +      for the ssl version supported. Actually the possible values of
 +      this option are:
 +
 +      - sslv2
 +      - sslv3
 +      - tlsv1
 +      - tlsv1.0
 +      - tlsv1.1
 +      - tlsv1.2
 +
 ++
 +Can be overridden by the 'GIT_SSL_VERSION' environment variable.
 +To force git to use libcurl's default ssl version and ignore any
 +explicit http.sslversion option, set 'GIT_SSL_VERSION' to the
 +empty string.
 +
 +http.sslCipherList::
 +  A list of SSL ciphers to use when negotiating an SSL connection.
 +  The available ciphers depend on whether libcurl was built against
 +  NSS or OpenSSL and the particular configuration of the crypto
 +  library in use.  Internally this sets the 'CURLOPT_SSL_CIPHER_LIST'
 +  option; see the libcurl documentation for more details on the format
 +  of this list.
 ++
 +Can be overridden by the 'GIT_SSL_CIPHER_LIST' environment variable.
 +To force git to use libcurl's default cipher list and ignore any
 +explicit http.sslCipherList option, set 'GIT_SSL_CIPHER_LIST' to the
 +empty string.
 +
  http.sslVerify::
        Whether to verify the SSL certificate when fetching or pushing
        over HTTPS. Can be overridden by the 'GIT_SSL_NO_VERIFY' environment
@@@ -1836,7 -1749,9 +1840,7 @@@ log.abbrevCommit:
  log.date::
        Set the default date-time mode for the 'log' command.
        Setting a value for log.date is similar to using 'git log''s
 -      `--date` option.  Possible values are `relative`, `local`,
 -      `default`, `iso`, `rfc`, and `short`; see linkgit:git-log[1]
 -      for details.
 +      `--date` option.  See linkgit:git-log[1] for details.
  
  log.decorate::
        Print out the ref names of any commits that are shown by the log
        specified, the full ref name (including prefix) will be printed.
        This is the same as the log commands '--decorate' option.
  
 +log.follow::
 +      If `true`, `git log` will act as if the `--follow` option was used when
 +      a single <path> is given.  This has the same limitations as `--follow`,
 +      i.e. it cannot be used to follow multiple files and does not work well
 +      on non-linear history.
 +
  log.showRoot::
        If true, the initial commit will be shown as a big creation event.
        This is equivalent to a diff against an empty tree.
@@@ -1953,18 -1862,6 +1957,18 @@@ mergetool.writeToTemp:
  mergetool.prompt::
        Prompt before each invocation of the merge resolution program.
  
 +notes.mergeStrategy::
 +      Which merge strategy to choose by default when resolving notes
 +      conflicts.  Must be one of `manual`, `ours`, `theirs`, `union`, or
 +      `cat_sort_uniq`.  Defaults to `manual`.  See "NOTES MERGE STRATEGIES"
 +      section of linkgit:git-notes[1] for more information on each strategy.
 +
 +notes.<name>.mergeStrategy::
 +      Which merge strategy to choose when doing a notes merge into
 +      refs/notes/<name>.  This overrides the more general
 +      "notes.mergeStrategy".  See the "NOTES MERGE STRATEGIES" section in
 +      linkgit:git-notes[1] for more information on the available strategies.
 +
  notes.displayRef::
        The (fully qualified) refname from which to show notes when
        showing commit messages.  The value of this variable can be set
@@@ -1993,8 -1890,8 +1997,8 @@@ notes.rewriteMode:
        When copying notes during a rewrite (see the
        "notes.rewrite.<command>" option), determines what to do if
        the target commit already has a note.  Must be one of
 -      `overwrite`, `concatenate`, or `ignore`.  Defaults to
 -      `concatenate`.
 +      `overwrite`, `concatenate`, `cat_sort_uniq`, or `ignore`.
 +      Defaults to `concatenate`.
  +
  This setting can be overridden with the `GIT_NOTES_REWRITE_MODE`
  environment variable.
@@@ -2149,9 -2046,9 +2153,9 @@@ pull.rebase:
        pull" is run. See "branch.<name>.rebase" for setting this on a
        per-branch basis.
  +
 -      When preserve, also pass `--preserve-merges` along to 'git rebase'
 -      so that locally committed merge commits will not be flattened
 -      by running 'git pull'.
 +When preserve, also pass `--preserve-merges` along to 'git rebase'
 +so that locally committed merge commits will not be flattened
 +by running 'git pull'.
  +
  *NOTE*: this is a possibly dangerous operation; do *not* use
  it unless you understand the implications (see linkgit:git-rebase[1]
@@@ -2224,28 -2121,6 +2228,28 @@@ push.followTags:
        may override this configuration at time of push by specifying
        '--no-follow-tags'.
  
 +push.gpgSign::
 +      May be set to a boolean value, or the string 'if-asked'. A true
 +      value causes all pushes to be GPG signed, as if '--signed' is
 +      passed to linkgit:git-push[1]. The string 'if-asked' causes
 +      pushes to be signed if the server supports it, as if
 +      '--signed=if-asked' is passed to 'git push'. A false value may
 +      override a value from a lower-priority config file. An explicit
 +      command-line flag always overrides this config option.
 +
 +push.recurseSubmodules::
 +      Make sure all submodule commits used by the revisions to be pushed
 +      are available on a remote-tracking branch. If the value is 'check'
 +      then Git will verify that all submodule commits that changed in the
 +      revisions to be pushed are available on at least one remote of the
 +      submodule. If any commits are missing, the push will be aborted and
 +      exit with non-zero status. If the value is 'on-demand' then all
 +      submodules that changed in the revisions to be pushed will be
 +      pushed. If on-demand was not able to push all necessary revisions
 +      it will also be aborted and exit with non-zero status. If the value
 +      is 'no' then default behavior of ignoring submodules when pushing
 +      is retained. You may override this configuration at time of push by
 +      specifying '--recurse-submodules=check|on-demand|no'.
  
  rebase.stat::
        Whether to show a diffstat of what changed upstream since the last
@@@ -2262,22 -2137,6 +2266,22 @@@ rebase.autoStash:
        successful rebase might result in non-trivial conflicts.
        Defaults to false.
  
 +rebase.missingCommitsCheck::
 +      If set to "warn", git rebase -i will print a warning if some
 +      commits are removed (e.g. a line was deleted), however the
 +      rebase will still proceed. If set to "error", it will print
 +      the previous warning and stop the rebase, 'git rebase
 +      --edit-todo' can then be used to correct the error. If set to
 +      "ignore", no checking is done.
 +      To drop a commit without warning or error, use the `drop`
 +      command in the todo-list.
 +      Defaults to "ignore".
 +
 +rebase.instructionFormat
 +      A format string, as specified in linkgit:git-log[1], to be used for
 +      the instruction list during an interactive rebase.  The format will automatically
 +      have the long commit hash prepended to the format.
 +
  receive.advertiseAtomic::
        By default, git-receive-pack will advertise the atomic push
        capability to its clients. If you don't want to this capability
@@@ -2314,28 -2173,6 +2318,28 @@@ receive.fsckObjects:
        Defaults to false. If not set, the value of `transfer.fsckObjects`
        is used instead.
  
 +receive.fsck.<msg-id>::
 +      When `receive.fsckObjects` is set to true, errors can be switched
 +      to warnings and vice versa by configuring the `receive.fsck.<msg-id>`
 +      setting where the `<msg-id>` is the fsck message ID and the value
 +      is one of `error`, `warn` or `ignore`. For convenience, fsck prefixes
 +      the error/warning with the message ID, e.g. "missingEmail: invalid
 +      author/committer line - missing email" means that setting
 +      `receive.fsck.missingEmail = ignore` will hide that issue.
 ++
 +This feature is intended to support working with legacy repositories
 +which would not pass pushing when `receive.fsckObjects = true`, allowing
 +the host to accept repositories with certain known issues but still catch
 +other issues.
 +
 +receive.fsck.skipList::
 +      The path to a sorted list of object names (i.e. one SHA-1 per
 +      line) that are known to be broken in a non-fatal way and should
 +      be ignored. This feature is useful when an established project
 +      should be accepted despite early commits containing errors that
 +      can be safely ignored such as invalid committer email addresses.
 +      Note: corrupt objects cannot be skipped with this setting.
 +
  receive.unpackLimit::
        If the number of objects received in a push is below this
        limit then the objects will be unpacked into loose object
@@@ -2381,10 -2218,13 +2385,10 @@@ receive.denyNonFastForwards:
        set when initializing a shared repository.
  
  receive.hideRefs::
 -      String(s) `receive-pack` uses to decide which refs to omit
 -      from its initial advertisement.  Use more than one
 -      definitions to specify multiple prefix strings. A ref that
 -      are under the hierarchies listed on the value of this
 -      variable is excluded, and is hidden when responding to `git
 -      push`, and an attempt to update or delete a hidden ref by
 -      `git push` is rejected.
 +      This variable is the same as `transfer.hideRefs`, but applies
 +      only to `receive-pack` (and so affects pushes, but not fetches).
 +      An attempt to update or delete a hidden ref by `git push` is
 +      rejected.
  
  receive.updateServerInfo::
        If set to true, git-receive-pack will run git-update-server-info
@@@ -2612,16 -2452,6 +2616,16 @@@ status.submoduleSummary:
        submodule summary' command, which shows a similar output but does
        not honor these settings.
  
 +stash.showPatch::
 +      If this is set to true, the `git stash show` command without an
 +      option will show the stash in patch form.  Defaults to false.
 +      See description of 'show' command in linkgit:git-stash[1].
 +
 +stash.showStat::
 +      If this is set to true, the `git stash show` command without an
 +      option will show diffstat of the stash.  Defaults to true.
 +      See description of 'show' command in linkgit:git-stash[1].
 +
  submodule.<name>.path::
  submodule.<name>.url::
        The path within this project and URL for a submodule. These
@@@ -2682,27 -2512,9 +2686,27 @@@ transfer.fsckObjects:
        Defaults to false.
  
  transfer.hideRefs::
 -      This variable can be used to set both `receive.hideRefs`
 -      and `uploadpack.hideRefs` at the same time to the same
 -      values.  See entries for these other variables.
 +      String(s) `receive-pack` and `upload-pack` use to decide which
 +      refs to omit from their initial advertisements.  Use more than
 +      one definition to specify multiple prefix strings. A ref that is
 +      under the hierarchies listed in the value of this variable is
 +      excluded, and is hidden when responding to `git push` or `git
 +      fetch`.  See `receive.hideRefs` and `uploadpack.hideRefs` for
 +      program-specific versions of this config.
 ++
 +You may also include a `!` in front of the ref name to negate the entry,
 +explicitly exposing it, even if an earlier entry marked it as hidden.
 +If you have multiple hideRefs values, later entries override earlier ones
 +(and entries in more-specific config files override less-specific ones).
 ++
 +If a namespace is in use, the namespace prefix is stripped from each
 +reference before it is matched against `transfer.hiderefs` patterns.
 +For example, if `refs/heads/master` is specified in `transfer.hideRefs` and
 +the current namespace is `foo`, then `refs/namespaces/foo/refs/heads/master`
 +is omitted from the advertisements but `refs/heads/master` and
 +`refs/namespaces/bar/refs/heads/master` are still advertised as so-called
 +"have" lines. In order to match refs before stripping, add a `^` in front of
 +the ref name. If you combine `!` and `^`, `!` must be specified first.
  
  transfer.unpackLimit::
        When `fetch.unpackLimit` or `receive.unpackLimit` are
@@@ -2717,23 -2529,20 +2721,23 @@@ uploadarchive.allowUnreachable:
        `false`.
  
  uploadpack.hideRefs::
 -      String(s) `upload-pack` uses to decide which refs to omit
 -      from its initial advertisement.  Use more than one
 -      definitions to specify multiple prefix strings. A ref that
 -      are under the hierarchies listed on the value of this
 -      variable is excluded, and is hidden from `git ls-remote`,
 -      `git fetch`, etc.  An attempt to fetch a hidden ref by `git
 -      fetch` will fail.  See also `uploadpack.allowtipsha1inwant`.
 -
 -uploadpack.allowtipsha1inwant::
 +      This variable is the same as `transfer.hideRefs`, but applies
 +      only to `upload-pack` (and so affects only fetches, not pushes).
 +      An attempt to fetch a hidden ref by `git fetch` will fail.  See
 +      also `uploadpack.allowTipSHA1InWant`.
 +
 +uploadpack.allowTipSHA1InWant::
        When `uploadpack.hideRefs` is in effect, allow `upload-pack`
        to accept a fetch request that asks for an object at the tip
        of a hidden ref (by default, such a request is rejected).
        see also `uploadpack.hideRefs`.
  
 +uploadpack.allowReachableSHA1InWant::
 +      Allow `upload-pack` to accept a fetch request that asks for an
 +      object that is reachable from any ref tip. However, note that
 +      calculating object reachability is computationally expensive.
 +      Defaults to `false`.
 +
  uploadpack.keepAlive::
        When `upload-pack` has started `pack-objects`, there may be a
        quiet period while `pack-objects` prepares the pack. Normally
index 35aada1447d5276910393b7a29a7ef10ab2d0c3e,1090ebcd2afd2de6193f23225ecca1146496d1a0..cb0f6cf6782c87d7a5b08e2b75de5b4ecb2969f9
@@@ -23,7 -23,6 +23,7 @@@ SYNOPSI
           [--break] [--heading] [-p | --show-function]
           [-A <post-context>] [-B <pre-context>] [-C <context>]
           [-W | --function-context]
 +         [--threads <num>]
           [-f <file>] [-e] <pattern>
           [--and|--or|--not|(|)|-e <pattern>...]
           [ [--[no-]exclude-standard] [--cached | --no-index | --untracked] | <tree>...]
@@@ -54,13 -53,13 +54,17 @@@ grep.extendedRegexp:
        option is ignored when the 'grep.patternType' option is set to a value
        other than 'default'.
  
 +grep.threads::
 +      Number of grep worker threads to use.  If unset (or set to 0),
 +      8 threads are used by default (for now).
 +
  grep.fullName::
        If set to true, enable '--full-name' option by default.
  
+ grep.fallbackToNoIndex::
+       If set to true, fall back to git grep --no-index if git grep
+       is executed outside of a git repository.  Defaults to false.
  
  OPTIONS
  -------
        For better compatibility with 'git diff', `--name-only` is a
        synonym for `--files-with-matches`.
  
 --O [<pager>]::
 ---open-files-in-pager [<pager>]::
 +-O[<pager>]::
 +--open-files-in-pager[=<pager>]::
        Open the matching files in the pager (not the output of 'grep').
        If the pager happens to be "less" or "vi", and the user
        specified only one pattern, the first file is positioned at
 -      the first match automatically.
 +      the first match automatically. The `pager` argument is
 +      optional; if specified, it must be stuck to the option
 +      without a space. If `pager` is unspecified, the default pager
 +      will be used (see `core.pager` in linkgit:git-config[1]).
  
  -z::
  --null::
        effectively showing the whole function in which the match was
        found.
  
 +--threads <num>::
 +      Number of grep worker threads to use.
 +      See `grep.threads` in 'CONFIGURATION' for more information.
 +
  -f <file>::
        Read patterns from <file>, one per line.
  
diff --combined builtin/grep.c
index 06ab68223a13b35612e2cb283d778a9c904b5528,f8ed4f4182a87134513888719c30a0d32efee135..5526fd705657ff80db630ec4f29554893b6c09ad
@@@ -24,11 -24,11 +24,11 @@@ static char const * const grep_usage[] 
        NULL
  };
  
 -static int use_threads = 1;
 +#define GREP_NUM_THREADS_DEFAULT 8
 +static int num_threads;
  
  #ifndef NO_PTHREADS
 -#define THREADS 8
 -static pthread_t threads[THREADS];
 +static pthread_t *threads;
  
  /* We use one producer thread and THREADS consumer
   * threads. The producer adds struct work_items to 'todo' and the
@@@ -63,13 -63,13 +63,13 @@@ static pthread_mutex_t grep_mutex
  
  static inline void grep_lock(void)
  {
 -      if (use_threads)
 +      if (num_threads)
                pthread_mutex_lock(&grep_mutex);
  }
  
  static inline void grep_unlock(void)
  {
 -      if (use_threads)
 +      if (num_threads)
                pthread_mutex_unlock(&grep_mutex);
  }
  
@@@ -206,8 -206,7 +206,8 @@@ static void start_threads(struct grep_o
                strbuf_init(&todo[i].out, 0);
        }
  
 -      for (i = 0; i < ARRAY_SIZE(threads); i++) {
 +      threads = xcalloc(num_threads, sizeof(*threads));
 +      for (i = 0; i < num_threads; i++) {
                int err;
                struct grep_opt *o = grep_opt_dup(opt);
                o->output = strbuf_out;
@@@ -239,14 -238,12 +239,14 @@@ static int wait_all(void
        pthread_cond_broadcast(&cond_add);
        grep_unlock();
  
 -      for (i = 0; i < ARRAY_SIZE(threads); i++) {
 +      for (i = 0; i < num_threads; i++) {
                void *h;
                pthread_join(threads[i], &h);
                hit |= (int) (intptr_t) h;
        }
  
 +      free(threads);
 +
        pthread_mutex_destroy(&grep_mutex);
        pthread_mutex_destroy(&grep_read_mutex);
        pthread_mutex_destroy(&grep_attr_mutex);
@@@ -270,14 -267,6 +270,14 @@@ static int grep_cmd_config(const char *
        int st = grep_config(var, value, cb);
        if (git_color_default_config(var, value, cb) < 0)
                st = -1;
 +
 +      if (!strcmp(var, "grep.threads")) {
 +              num_threads = git_config_int(var, value);
 +              if (num_threads < 0)
 +                      die(_("invalid number of threads specified (%d) for %s"),
 +                          num_threads, var);
 +      }
 +
        return st;
  }
  
@@@ -305,7 -294,7 +305,7 @@@ static int grep_sha1(struct grep_opt *o
        }
  
  #ifndef NO_PTHREADS
 -      if (use_threads) {
 +      if (num_threads) {
                add_work(opt, GREP_SOURCE_SHA1, pathbuf.buf, path, sha1);
                strbuf_release(&pathbuf);
                return 0;
@@@ -334,7 -323,7 +334,7 @@@ static int grep_file(struct grep_opt *o
                strbuf_addstr(&buf, filename);
  
  #ifndef NO_PTHREADS
 -      if (use_threads) {
 +      if (num_threads) {
                add_work(opt, GREP_SOURCE_FILE, buf.buf, filename, filename);
                strbuf_release(&buf);
                return 0;
@@@ -386,7 -375,7 +386,7 @@@ static int grep_cache(struct grep_opt *
  
        for (nr = 0; nr < active_nr; nr++) {
                const struct cache_entry *ce = active_cache[nr];
 -              if (!S_ISREG(ce->ce_mode))
 +              if (!S_ISREG(ce->ce_mode) || ce_intent_to_add(ce))
                        continue;
                if (!ce_path_match(ce, pathspec, NULL))
                        continue;
@@@ -470,7 -459,7 +470,7 @@@ static int grep_object(struct grep_opt 
                       struct object *obj, const char *name, const char *path)
  {
        if (obj->type == OBJ_BLOB)
 -              return grep_sha1(opt, obj->sha1, name, 0, path);
 +              return grep_sha1(opt, obj->oid.hash, name, 0, path);
        if (obj->type == OBJ_COMMIT || obj->type == OBJ_TREE) {
                struct tree_desc tree;
                void *data;
                int hit, len;
  
                grep_read_lock();
 -              data = read_object_with_reference(obj->sha1, tree_type,
 +              data = read_object_with_reference(obj->oid.hash, tree_type,
                                                  &size, NULL);
                grep_read_unlock();
  
                if (!data)
 -                      die(_("unable to read tree (%s)"), sha1_to_hex(obj->sha1));
 +                      die(_("unable to read tree (%s)"), oid_to_hex(&obj->oid));
  
                len = name ? strlen(name) : 0;
                strbuf_init(&base, PATH_MAX + len + 1);
@@@ -623,6 -612,11 +623,6 @@@ static int pattern_callback(const struc
        return 0;
  }
  
 -static int help_callback(const struct option *opt, const char *arg, int unset)
 -{
 -      return -1;
 -}
 -
  int cmd_grep(int argc, const char **argv, const char *prefix)
  {
        int hit = 0;
                        N_("show <n> context lines before matches")),
                OPT_INTEGER('A', "after-context", &opt.post_context,
                        N_("show <n> context lines after matches")),
 +              OPT_INTEGER(0, "threads", &num_threads,
 +                      N_("use <n> worker threads")),
                OPT_NUMBER_CALLBACK(&opt, N_("shortcut for -C NUM"),
                        context_callback),
                OPT_BOOL('p', "show-function", &opt.funcname,
                        PARSE_OPT_OPTARG, NULL, (intptr_t)default_pager },
                OPT_BOOL(0, "ext-grep", &external_grep_allowed__ignored,
                         N_("allow calling of grep(1) (ignored by this build)")),
 -              { OPTION_CALLBACK, 0, "help-all", NULL, NULL, N_("show usage"),
 -                PARSE_OPT_HIDDEN | PARSE_OPT_NOARG, help_callback },
                OPT_END()
        };
  
 -      /*
 -       * 'git grep -h', unlike 'git grep -h <pattern>', is a request
 -       * to show usage information and exit.
 -       */
 -      if (argc == 2 && !strcmp(argv[1], "-h"))
 -              usage_with_options(grep_usage, options);
 -
        init_grep_defaults();
        git_config(grep_cmd_config, NULL);
        grep_init(&opt, prefix);
         */
        argc = parse_options(argc, argv, prefix, options, grep_usage,
                             PARSE_OPT_KEEP_DASHDASH |
 -                           PARSE_OPT_STOP_AT_NON_OPTION |
 -                           PARSE_OPT_NO_INTERNAL_HELP);
 +                           PARSE_OPT_STOP_AT_NON_OPTION);
        grep_commit_pattern_type(pattern_type_arg, &opt);
  
-       if (use_index && !startup_info->have_repository)
-               /* die the same way as if we did it at the beginning */
-               setup_git_directory();
+       if (use_index && !startup_info->have_repository) {
+               int fallback = 0;
+               git_config_get_bool("grep.fallbacktonoindex", &fallback);
+               if (fallback)
+                       use_index = 0;
+               else
+                       /* die the same way as if we did it at the beginning */
+                       setup_git_directory();
+       }
  
        /*
         * skip a -- separator; we know it cannot be
                opt.output_priv = &path_list;
                opt.output = append_path;
                string_list_append(&path_list, show_in_pager);
 -              use_threads = 0;
        }
  
        if (!opt.pattern_list)
        }
  
  #ifndef NO_PTHREADS
 -      if (list.nr || cached || online_cpus() == 1)
 -              use_threads = 0;
 +      if (list.nr || cached || show_in_pager)
 +              num_threads = 0;
 +      else if (num_threads == 0)
 +              num_threads = GREP_NUM_THREADS_DEFAULT;
 +      else if (num_threads < 0)
 +              die(_("invalid number of threads specified (%d)"), num_threads);
  #else
 -      use_threads = 0;
 +      num_threads = 0;
  #endif
  
  #ifndef NO_PTHREADS
 -      if (use_threads) {
 +      if (num_threads) {
                if (!(opt.name_only || opt.unmatch_name_only || opt.count)
                    && (opt.pre_context || opt.post_context ||
                        opt.file_break || opt.funcbody))
                hit = grep_objects(&opt, &pathspec, &list);
        }
  
 -      if (use_threads)
 +      if (num_threads)
                hit |= wait_all();
        if (hit && show_in_pager)
                run_pager(&opt, prefix);