aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKonstantin Ryabitsev <mricon@kernel.org>2013-05-21 14:21:28 -0400
committerKonstantin Ryabitsev <mricon@kernel.org>2013-05-21 14:21:28 -0400
commit1108c58471e767cb0c46620fc2947864220acad6 (patch)
tree06a36650d8a01e304ca5ca04ee96e83cbc22cc1e
parentc59122a7aade7f93930d120b765a5947088cb848 (diff)
downloadgrokmirror-use-gitolite.tar.gz
Experimental branch with built-in gitolite supportuse-gitolite
Created as a response to some problems seen when interacting with gitolite-managed repositories. I'm committing this into its own branch, as I'm not entirely convinced the best plan is to go ahead with these changes and not figure out the nature of the problems seen with gitolite.
-rwxr-xr-xgrok-manifest.py66
-rw-r--r--grokmirror/__init__.py40
2 files changed, 90 insertions, 16 deletions
diff --git a/grok-manifest.py b/grok-manifest.py
index 201b0a5..10a3061 100755
--- a/grok-manifest.py
+++ b/grok-manifest.py
@@ -18,6 +18,7 @@ import os
import sys
import logging
import time
+import subprocess
import grokmirror
@@ -144,6 +145,9 @@ if __name__ == '__main__':
parser.add_option('-n', '--use-now', dest='usenow', action='store_true',
default=False,
help='Use current timestamp instead of parsing commits')
+ parser.add_option('-g', '--gitolite', dest='gitolite', action='store_true',
+ default=False,
+ help='Use gitolite tools to get repository information')
parser.add_option('-c', '--check-export-ok', dest='check_export_ok',
action='store_true', default=False,
help='Export only repositories marked as git-daemon-export-ok')
@@ -167,6 +171,11 @@ if __name__ == '__main__':
parser.error('You must provide the path to the manifest file')
if not opts.toplevel:
parser.error('You must provide the toplevel path')
+ if opts.gitolite:
+ # check for sanity to make sure $HOME/.gitolite.rc exists
+ if not os.access(os.path.join(os.environ['HOME'], '.gitolite.rc'),
+ os.R_OK):
+ parser.error('Asked to use gitolite, but no $HOME/.gitolite.rc')
logger.setLevel(logging.DEBUG)
@@ -207,7 +216,8 @@ if __name__ == '__main__':
if opts.purge or not len(args) or not len(manifest.keys()):
# We automatically purge when we do a full tree walk
- gitdirs = grokmirror.find_all_gitdirs(opts.toplevel, ignore=opts.ignore)
+ gitdirs = grokmirror.find_all_gitdirs(opts.toplevel,
+ ignore=opts.ignore, use_gitolite=opts.gitolite)
purge_manifest(manifest, opts.toplevel, gitdirs)
if len(manifest.keys()) and len(args):
@@ -219,19 +229,47 @@ if __name__ == '__main__':
symlinks = []
for gitdir in gitdirs:
# check to make sure this gitdir is ok to export
- if (opts.check_export_ok and
- not os.path.exists(os.path.join(gitdir, 'git-daemon-export-ok'))):
- # is it curently in the manifest?
- repo = gitdir.replace(opts.toplevel, '', 1)
- if repo in manifest.keys():
- logger.info('Repository %s is no longer exported, '
- 'removing from manifest' % repo)
- del manifest[repo]
-
- # XXX: need to add logic to make sure we don't break the world
- # by removing a repository used as a reference for others
- # also make sure we clean up any dangling symlinks
- continue
+ if opts.check_export_ok:
+ export_ok = False
+ if opts.gitolite:
+ # Use gitolite's access check for reliability
+ repo = gitdir.replace(opts.toplevel, '', 1)
+ # remove trailing .git
+ if repo[-4:] == '.git':
+ repo = repo[:-4]
+ repo = repo.lstrip('/')
+ args = ['/usr/bin/gitolite', 'access', repo, 'daemon', 'R',
+ 'any']
+ logger.debug('Running: %s' % ' '.join(args))
+
+ (output, error) = subprocess.Popen(args, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE).communicate()
+
+ error = error.strip()
+ output = output.strip()
+ if len(error):
+ logger.critical('Attempting to run gitolite returned:')
+ logger.critical(error)
+ sys.exit(1)
+
+ if output.find('DENIED') < 0:
+ export_ok = True
+
+ elif os.path.exists(os.path.join(gitdir, 'git-daemon-export-ok')):
+ export_ok = True
+
+ if not export_ok:
+ # is it curently in the manifest?
+ repo = gitdir.replace(opts.toplevel, '', 1)
+ if repo in manifest.keys():
+ logger.info('Repository %s is no longer exported, '
+ 'removing from manifest' % repo)
+ del manifest[repo]
+
+ # XXX: need to add logic to make sure we don't break the world
+ # by removing a repository used as a reference for others
+ # also make sure we clean up any dangling symlinks
+ continue
if os.path.islink(gitdir):
symlinks.append(gitdir)
diff --git a/grokmirror/__init__.py b/grokmirror/__init__.py
index 3173466..f4f3b6d 100644
--- a/grokmirror/__init__.py
+++ b/grokmirror/__init__.py
@@ -19,6 +19,7 @@ import sys
import json
import fnmatch
+import subprocess
import logging
@@ -51,10 +52,44 @@ def unlock_repo(fullpath):
REPO_LOCKH[fullpath].close()
del REPO_LOCKH[fullpath]
-def find_all_gitdirs(toplevel, ignore=[]):
- logger.info('Finding bare git repos in %s' % toplevel)
+def find_all_gitdirs(toplevel, ignore=[], use_gitolite=False):
logger.debug('Ignore list: %s' % ' '.join(ignore))
gitdirs = []
+
+ if use_gitolite:
+ logger.info('Using gitolite list-phy-repos')
+ args = ['/usr/bin/gitolite', 'list-phy-repos']
+ logger.debug('Running: %s' % ' '.join(args))
+
+ (output, error) = subprocess.Popen(args, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE).communicate()
+
+ error = error.strip()
+ output = output.strip()
+ if len(error):
+ logger.critical('Attempting to run gitolite returned errors:')
+ logger.critical(error)
+ sys.exit(1)
+
+ for repo in output.split('\n'):
+ gitdir = os.path.join(toplevel, repo + '.git')
+ # should we ignore this repo?
+ ignored = False
+ for ignoredir in ignore:
+ if fnmatch.fnmatch(gitdir, ignoredir):
+ ignored = True
+ logger.debug('Ignoring %s due to %s' % (name, ignoredir))
+ break
+ if ignored:
+ continue
+
+ logger.debug('Found %s' % gitdir)
+ gitdirs.append(gitdir)
+
+ return gitdirs
+
+ # No gitolite requested, walk the toplevel
+ logger.info('Finding bare git repos in %s' % toplevel)
for root, dirs, files in os.walk(toplevel, topdown=True):
if not len(dirs):
continue
@@ -66,6 +101,7 @@ def find_all_gitdirs(toplevel, ignore=[]):
for ignoredir in ignore:
if fnmatch.fnmatch(os.path.join(root, name), ignoredir):
torm.append(name)
+ logger.debug('Ignoring %s due to %s' % (name, ignoredir))
ignored = True
break
if not ignored and name.find('.git') > 0: