7 from collections import namedtuple
8 import xml.etree.ElementTree as ET
10 # Disallow git prompting for a username/password
11 os.environ['GIT_TERMINAL_PROMPT'] = '0'
12 def git(*args, repository_path='.'):
13 return subprocess.check_output(["git"] + list(args), cwd=repository_path).decode()
15 class Manifest(object):
17 Parse and store the content of a manifest file
22 default_remote = 'origin'
23 default_revision = 'refs/heads/master'
25 def __init__(self, manifest_path):
26 self.manifest_path = manifest_path
30 tree = ET.parse(self.manifest_path)
31 except Exception as ex:
32 raise Exception("Error loading manifest %s in file %s" % (self.manifest_path, ex))
37 if child.tag == 'remote':
38 self.remotes[child.attrib['name']] = child.attrib['fetch']
39 if child.tag == 'default':
40 self.default_remote = child.attrib['remote'] or self.default_remote
41 self.default_revision = child.attrib['revision'] or self.default_revision
42 if child.tag == 'project':
43 project = namedtuple('Project', ['name', 'remote',
44 'revision', 'fetch_uri'])
46 project.name = child.attrib['name']
47 if project.name.endswith('.git'):
48 project.name = project.name[:-4]
49 project.remote = child.attrib.get('remote') or self.default_remote
50 project.revision = child.attrib.get('revision') or self.default_revision
51 project.fetch_uri = self.remotes[project.remote] + project.name + '.git'
53 self.projects[project.name] = project
55 def find_project(self, name):
57 return self.projects[name]
58 except KeyError as ex:
59 raise Exception("Could not find project %s in manifest %s" % (name, self.manifest_path))
61 def get_fetch_uri(self, project, remote):
62 fetch = self.remotes[remote]
63 return fetch + project.name + '.git'
65 if __name__ == "__main__":
66 parser = argparse.ArgumentParser()
67 parser.add_argument("--project", action="store", type=str)
68 parser.add_argument("--destination", action="store", type=str, default='.')
69 parser.add_argument("--manifest", action="store", type=str)
70 parser.add_argument("--fetch", action="store_true", default=False)
71 options = parser.parse_args()
73 if not options.project:
74 raise ValueError("--project argument not provided")
75 if not options.manifest:
76 raise ValueError("--manifest argument not provided")
78 manifest = Manifest(options.manifest)
80 project = manifest.find_project(options.project)
82 dest = options.destination
84 dest = os.path.join (os.getcwd(), project.name)
87 assert os.path.exists(dest) == True
88 git('fetch', project.fetch_uri, project.revision, repository_path=dest)
90 git('clone', project.fetch_uri, dest)
92 git('checkout', '--detach', project.revision, repository_path=dest)