Repository: spack/spack

Issue:
`spack pkg` command and tests fail for git < 1.8.5
The implementation of the `spack pkg` command assumes one is working in an environment with a git >= 1.8.5, as the `-C` option is used for all invocations of the `git` command. Associated tests also fail, see `spack test cmd/pkg`:

```console
$ spack test cmd/pkg
...
E                                  ProcessError: Command exited with status 129:
E                                      '/usr/bin/git' '-C' '/tmp/pytest-of-greenc/pytest-52/mock_pkg_git_repo0/builtin.mock/packages' 'ls-tree' '--name-only' 'HEAD^^'

../util/executable.py:189: ProcessError
-------------------------------------------------------------------------- Captured stderr call ---------------------------------------------------------------------------
Unknown option: -C
usage: git [--version] [--help] [-c name=value]
           [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
           [-p|--paginate|--no-pager] [--no-replace-objects] [--bare]
           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
           <command> [<args>]
```

On a standard `Scientific7` (or `RHEL7`) system, the version of git available is `1.8.3.1`. On `RHEL6` (still in extensive use in HEP), it is `1.7.1`.

A reasonable solution might be to test for the version and fall back on a function wrapper to the git `Executable` that invokes it with the current directory corresponding to the desired `path`.


Discussion:
We can also skip the tests if an old version of git is detected. But then `spack pkg` won't work for all users... @tgamblin 

Resolving patch:
diff --git a/lib/spack/spack/cmd/pkg.py b/lib/spack/spack/cmd/pkg.py
--- a/lib/spack/spack/cmd/pkg.py
+++ b/lib/spack/spack/cmd/pkg.py
@@ -11,6 +11,7 @@
 
 import llnl.util.tty as tty
 from llnl.util.tty.colify import colify
+from llnl.util.filesystem import working_dir
 
 import spack.cmd
 import spack.paths
@@ -79,12 +80,28 @@ def packages_path():
         return spack.repo.path.get_repo('builtin').packages_path
 
 
+class GitExe:
+    # Wrapper around Executable for git to set working directory for all
+    # invocations.
+    #
+    # Not using -C as that is not supported for git < 1.8.5.
+    def __init__(self):
+        self._git_cmd = which('git', required=True)
+
+    def __call__(self, *args, **kwargs):
+        with working_dir(packages_path()):
+            return self._git_cmd(*args, **kwargs)
+
+
+_git = None
+
+
 def get_git():
     """Get a git executable that runs *within* the packages path."""
-    git = which('git', required=True)
-    git.add_default_arg('-C')
-    git.add_default_arg(packages_path())
-    return git
+    global _git
+    if _git is None:
+        _git = GitExe()
+    return _git
 
 
 def list_packages(rev):
@@ -102,13 +119,14 @@ def list_packages(rev):
 
 def pkg_add(args):
     """add a package to the git stage with `git add`"""
+    git = get_git()
+
     for pkg_name in args.packages:
         filename = spack.repo.path.filename_for_package_name(pkg_name)
         if not os.path.isfile(filename):
             tty.die("No such package: %s.  Path does not exist:" %
                     pkg_name, filename)
 
-        git = get_git()
         git('add', filename)
 
 


Test patch: