Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 144 lines (107 sloc) 3.69 KB
#!/usr/bin/env python
import argparse
import subprocess
import sys
import os
class ScriptError(Exception):
pass
def run(*args, **kwargs):
show_cmd = kwargs.get('show_cmd', False)
shell = kwargs.get('shell', False)
if shell:
command = ' '.join(['"' + x + '"' for x in args])
else:
command = args
if show_cmd:
print ' '.join(args)
check_ret = kwargs.get('check_ret', True)
p = subprocess.Popen(
command, shell=shell,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output = p.communicate()
retcode = p.poll()
if check_ret and retcode:
raise ScriptError("Error executing: %r (%d, %s)" % (command, retcode, output))
return output[0]
def run_git(*args, **kwargs):
path = kwargs.get('path', None)
if path is not None:
if path.endswith('.git'):
args = ['--git-dir=%s' % path] + list(args)
else:
args = ['--git-dir=%s/.git' % path, '--work-tree=%s' % path] + list(args)
command = ['git'] + list(args)
return run(*command, **kwargs).strip()
def get_current_branch():
return run_git('symbolic-ref', 'HEAD').replace('refs/heads/', '')
def get_local_ref(name):
return run_git('show-ref', 'heads/' + name,
check_ret=False)
def get_remote_ref(remote, name):
return run_git('show-ref', 'remotes/%s/%s' % (remote, name),
check_ret=False)
def get_remote_config(local_branch):
return run_git('config', 'branch.%s.merge' % local_branch,
check_ret=False)
def get_remote_url(repository):
return run_git('config', 'remote.%s.url' % repository,
check_ret=False)
def find_git_repos(path, max_depth, current_depth=0):
"""Finds git repos that are no more than max_depth
from the provided path
Arguments:
- `path`:
- `max_depth`:
"""
git_repos = []
entries = set(os.listdir(path))
if '.git' in entries:
entries.remove('.git')
git_repos.append(path)
elif path.endswith('.git'):
# Bare repository...
git_repos.append(path)
entries.clear()
entries = [os.path.join(path, e) for e in entries]
dirs = set([e for e in entries if os.path.isdir(e)])
if max_depth < 0 or current_depth < max_depth:
for d in dirs:
git_repos.extend(
find_git_repos(d, max_depth, current_depth+1))
return sorted(git_repos)
def main():
parser = argparse.ArgumentParser(
prog='git-fetch-all',
description=
"A simple tool to help fetch new revisions across a directory tree."
)
parser.add_argument(
'--max-depth', dest='max_depth', action='store',
default=1, type=int,
help='The maximum depth to look for git repos.')
parser.add_argument(
'-n', '--dry-run', dest='dry_run', action='store_true',
default=False,
help="Don't actually fetch anything from the remotes.")
parser.add_argument(
'paths', nargs='*', default=['.'],
help='The paths to search for git repos.')
args = parser.parse_args()
repos = []
for p in args.paths:
repos.extend(find_git_repos(p, args.max_depth))
for r in repos:
if not args.dry_run:
print "Fetching %s..." % r
try:
run_git('ffwd', path=r, show_cmd=True)
except ScriptError as e:
print >>sys.stderr, \
"WARNING: Couldn't fetch %r. " \
"Probably because we can't reach the repo.\n%s" % (r, e)
if __name__ == '__main__':
try:
main()
except ScriptError, e:
print >>sys.stderr, "ERROR: %s" % str(e)
sys.exit(1)