git » git-arr » commit ba3b213

Improve the way we find repo paths

author Alberto Bertogli
2012-11-11 13:39:41 UTC
committer Alberto Bertogli
2012-11-11 13:43:02 UTC
parent 1c729578b2c503b84a1cb78aefc4fda4845c672b

Improve the way we find repo paths

This patch improves the way we find the path to the repositories, both in the
recursive and in the non-recursive cases.

We now support specifying non-bare repositories directly, and also recursing
on them.

Signed-off-by: Alberto Bertogli <albertito@blitiri.com.ar>

git-arr +34 -8
git.py +9 -3

diff --git a/git-arr b/git-arr
index 8e8ae1f..8688c12 100755
--- a/git-arr
+++ b/git-arr
@@ -49,14 +49,10 @@ def load_config(path):
 
     # Do a first pass for general sanity checking and recursive expansion.
     for s in config.sections():
-        if not config.has_option(s, 'path'):
-            raise configparser.NoOptionError(
-                    '%s is missing the mandatory path' % s)
-
         if config.getboolean(s, 'recursive'):
             for path in os.listdir(config.get(s, 'path')):
-                fullpath = config.get(s, 'path') + '/' + path
-                if not os.path.exists(fullpath + '/HEAD'):
+                fullpath = find_git_dir(config.get(s, 'path') + '/' + path)
+                if not fullpath:
                     continue
 
                 if os.path.exists(fullpath + '/disable_gitweb'):
@@ -76,7 +72,13 @@ def load_config(path):
             config.remove_section(s)
 
     for s in config.sections():
-        fullpath = config.get(s, 'path')
+        fullpath = find_git_dir(config.get(s, 'path'))
+        if not fullpath:
+            raise ValueError(
+                    '%s: path %s is not a valid git repository' % (
+                        s, config.get(s, 'path')))
+
+        config.set(s, 'path', fullpath)
         config.set(s, 'name', s)
 
         desc = config.get(s, 'desc')
@@ -102,6 +104,29 @@ def load_config(path):
 
         repos[r.name] = r
 
+def find_git_dir(path):
+    """Returns the path to the git directory for the given repository.
+
+    This function takes a path to a git repository, and returns the path to
+    its git directory. If the repo is bare, it will be the same path;
+    otherwise it will be path + '.git/'.
+
+    An empty string is returned if the given path is not a valid repository.
+    """
+    def check(p):
+        """A dirty check for whether this is a git dir or not."""
+        # Note silent stderr because we expect this to fail and don't want the
+        # noise; and also we strip the final \n from the output.
+        return git.run_git(p,
+                ['rev-parse', '--git-dir'],
+                silent_stderr = True).read()[:-1]
+
+    for p in [ path, path + '/.git' ]:
+        if check(p):
+            return p
+
+    return ''
+
 
 def repo_filter(unused_conf):
     """Bottle route filter for repos."""
@@ -367,8 +392,9 @@ def main():
 
     try:
         load_config(opts.config)
-    except configparser.NoOptionError as e:
+    except (configparser.NoOptionError, ValueError) as e:
         print('Error parsing config:', e)
+        return
 
     if not args:
         parser.error('Must specify an action (serve|generate)')
diff --git a/git.py b/git.py
index 023f1a6..d005b13 100644
--- a/git.py
+++ b/git.py
@@ -41,7 +41,7 @@ class EncodeWrapper:
         return s.decode(self.encoding, errors = self.errors)
 
 
-def run_git(repo_path, params, stdin = None):
+def run_git(repo_path, params, stdin = None, silent_stderr = False):
     """Invokes git with the given parameters.
 
     This function invokes git with the given parameters, and returns a
@@ -49,11 +49,17 @@ def run_git(repo_path, params, stdin = None):
     """
     params = [GIT_BIN, '--git-dir=%s' % repo_path] + list(params)
 
+    stderr = None
+    if silent_stderr:
+        stderr = subprocess.PIPE
+
     if not stdin:
-        p = subprocess.Popen(params, stdin = None, stdout = subprocess.PIPE)
+        p = subprocess.Popen(params,
+                stdin = None, stdout = subprocess.PIPE, stderr = stderr)
     else:
         p = subprocess.Popen(params,
-                stdin = subprocess.PIPE, stdout = subprocess.PIPE)
+                stdin = subprocess.PIPE, stdout = subprocess.PIPE,
+                stderr = stderr)
         p.stdin.write(stdin)
         p.stdin.close()