diff options
author | Konstantin Ryabitsev <mricon@kernel.org> | 2013-05-21 14:21:28 -0400 |
---|---|---|
committer | Konstantin Ryabitsev <mricon@kernel.org> | 2013-05-21 14:21:28 -0400 |
commit | 1108c58471e767cb0c46620fc2947864220acad6 (patch) | |
tree | 06a36650d8a01e304ca5ca04ee96e83cbc22cc1e | |
parent | c59122a7aade7f93930d120b765a5947088cb848 (diff) | |
download | grokmirror-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-x | grok-manifest.py | 66 | ||||
-rw-r--r-- | grokmirror/__init__.py | 40 |
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: |