blob: b0de0484212c7dc6cac5f17649d940e27dd6ddd8 [file] [log] [blame]
yunlian994ae3a2013-02-19 21:36:36 +00001#!/usr/bin/python
asharifec9c6242013-02-15 19:56:06 +00002#
3# Copyright 2010 Google Inc. All Rights Reserved.
4
asharif0ea89582013-02-15 21:15:11 +00005__author__ = 'asharif@google.com (Ahmad Sharif)'
asharifec9c6242013-02-15 19:56:06 +00006
Han Sheneb77c442013-03-18 13:53:52 -07007import datetime
asharifec9c6242013-02-15 19:56:06 +00008import optparse
9import os
10import re
11import socket
12import sys
13import tempfile
kbaclawski20082a02013-02-16 02:12:57 +000014
asharif0ea89582013-02-15 21:15:11 +000015from automation.clients.helper import perforce
asharifec9c6242013-02-15 19:56:06 +000016from utils import command_executer
17from utils import logger
kbaclawski20082a02013-02-16 02:12:57 +000018from utils import misc
asharifec9c6242013-02-15 19:56:06 +000019
20
asharif1b92e732013-02-15 20:51:38 +000021def GetCanonicalMappings(mappings):
22 canonical_mappings = []
23 for mapping in mappings:
24 remote_path, local_path = mapping.split()
asharif0ea89582013-02-15 21:15:11 +000025 if local_path.endswith('/') and not remote_path.endswith('/'):
asharif1b92e732013-02-15 20:51:38 +000026 local_path = os.path.join(local_path, os.path.basename(remote_path))
27 remote_path = remote_path.lstrip('/').split('/', 1)[1]
28 canonical_mappings.append(perforce.PathMapping(remote_path, local_path))
29 return canonical_mappings
30
asharif0ea89582013-02-15 21:15:11 +000031
asharif56d78bc2013-02-15 21:15:08 +000032def SplitMapping(mapping):
asharif0ea89582013-02-15 21:15:11 +000033 parts = mapping.split()
34 assert len(parts) <= 2, 'Mapping %s invalid' % mapping
35 remote_path = parts[0]
36 if len(parts) == 2:
37 local_path = parts[1]
asharif56d78bc2013-02-15 21:15:08 +000038 else:
asharif0ea89582013-02-15 21:15:11 +000039 local_path = '.'
asharif56d78bc2013-02-15 21:15:08 +000040 return remote_path, local_path
41
asharif1b92e732013-02-15 20:51:38 +000042
43class Repo(object):
Luis Lozanof2a3ef42015-12-15 13:49:30 -080044
Han Sheneb77c442013-03-18 13:53:52 -070045 def __init__(self, no_create_tmp_dir=False):
asharifec9c6242013-02-15 19:56:06 +000046 self.repo_type = None
47 self.address = None
48 self.mappings = None
49 self.revision = None
asharif0ea89582013-02-15 21:15:11 +000050 self.ignores = ['.gitignore', '.p4config', 'README.google']
Han Sheneb77c442013-03-18 13:53:52 -070051 if no_create_tmp_dir:
52 self._root_dir = None
53 else:
54 self._root_dir = tempfile.mkdtemp()
asharif56d78bc2013-02-15 21:15:08 +000055 self._ce = command_executer.GetCommandExecuter()
56 self._logger = logger.GetLogger()
asharifec9c6242013-02-15 19:56:06 +000057
asharif56d78bc2013-02-15 21:15:08 +000058 def PullSources(self):
asharif0ea89582013-02-15 21:15:11 +000059 """Pull all sources into an internal dir."""
asharifec9c6242013-02-15 19:56:06 +000060 pass
61
asharif56d78bc2013-02-15 21:15:08 +000062 def SetupForPush(self):
asharif0ea89582013-02-15 21:15:11 +000063 """Setup a repository for pushing later."""
asharif56d78bc2013-02-15 21:15:08 +000064 pass
65
asharif983c7c42013-02-16 02:13:01 +000066 def PushSources(self, commit_message=None, dry_run=False, message_file=None):
asharif0ea89582013-02-15 21:15:11 +000067 """Push to the external repo with the commit message."""
asharif56d78bc2013-02-15 21:15:08 +000068 pass
69
70 def _RsyncExcludingRepoDirs(self, source_dir, dest_dir):
ashariff6ffe502013-02-15 22:23:12 +000071 for f in os.listdir(source_dir):
Luis Lozanof2a3ef42015-12-15 13:49:30 -080072 if f in ['.git', '.svn', '.p4config']:
ashariff6ffe502013-02-15 22:23:12 +000073 continue
74 dest_file = os.path.join(dest_dir, f)
75 source_file = os.path.join(source_dir, f)
76 if os.path.exists(dest_file):
Luis Lozanof2a3ef42015-12-15 13:49:30 -080077 command = 'rm -rf %s' % dest_file
ashariff6ffe502013-02-15 22:23:12 +000078 self._ce.RunCommand(command)
Luis Lozanof2a3ef42015-12-15 13:49:30 -080079 command = 'rsync -a %s %s' % (source_file, dest_dir)
ashariff6ffe502013-02-15 22:23:12 +000080 self._ce.RunCommand(command)
81 return 0
asharif56d78bc2013-02-15 21:15:08 +000082
83 def MapSources(self, dest_dir):
84 """Copy sources from the internal dir to root_dir."""
85 return self._RsyncExcludingRepoDirs(self._root_dir, dest_dir)
86
87 def GetRoot(self):
88 return self._root_dir
89
90 def CleanupRoot(self):
asharif0ea89582013-02-15 21:15:11 +000091 command = 'rm -rf %s' % self._root_dir
asharif56d78bc2013-02-15 21:15:08 +000092 return self._ce.RunCommand(command)
asharifec9c6242013-02-15 19:56:06 +000093
94 def __str__(self):
Luis Lozanof2a3ef42015-12-15 13:49:30 -080095 return '\n'.join(str(s)
96 for s in [self.repo_type, self.address, self.mappings])
asharifec9c6242013-02-15 19:56:06 +000097
98
Han Sheneb77c442013-03-18 13:53:52 -070099# Note - this type of repo is used only for "readonly", in other words, this
100# only serves as a incoming repo.
101class FileRepo(Repo):
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800102
Han Sheneb77c442013-03-18 13:53:52 -0700103 def __init__(self, address, ignores=None):
104 Repo.__init__(self, no_create_tmp_dir=True)
105 self.repo_type = 'file'
106 self.address = address
107 self.mappings = None
108 self.branch = None
109 self.revision = '{0} (as of "{1}")'.format(address, datetime.datetime.now())
110 self.gerrit = None
111 self._root_dir = self.address
112
113 def CleanupRoot(self):
114 """Override to prevent deletion."""
115 pass
116
117
asharifec9c6242013-02-15 19:56:06 +0000118class P4Repo(Repo):
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800119
asharif6578cf82013-02-16 02:41:46 +0000120 def __init__(self, address, mappings, revision=None):
asharifec9c6242013-02-15 19:56:06 +0000121 Repo.__init__(self)
asharif0ea89582013-02-15 21:15:11 +0000122 self.repo_type = 'p4'
asharifec9c6242013-02-15 19:56:06 +0000123 self.address = address
124 self.mappings = mappings
asharif6578cf82013-02-16 02:41:46 +0000125 self.revision = revision
asharifec9c6242013-02-15 19:56:06 +0000126
asharif56d78bc2013-02-15 21:15:08 +0000127 def PullSources(self):
asharifec9c6242013-02-15 19:56:06 +0000128 client_name = socket.gethostname()
asharif0ea89582013-02-15 21:15:11 +0000129 client_name += tempfile.mkstemp()[1].replace('/', '-')
asharifec9c6242013-02-15 19:56:06 +0000130 mappings = self.mappings
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800131 p4view = perforce.View('depot2', GetCanonicalMappings(mappings))
132 p4client = perforce.CommandsFactory(self._root_dir,
133 p4view,
asharif0ea89582013-02-15 21:15:11 +0000134 name=client_name)
asharif6578cf82013-02-16 02:41:46 +0000135 command = p4client.SetupAndDo(p4client.Sync(self.revision))
asharif0ea89582013-02-15 21:15:11 +0000136 ret = self._ce.RunCommand(command)
137 assert ret == 0, 'Could not setup client.'
asharif1b92e732013-02-15 20:51:38 +0000138 command = p4client.InCheckoutDir(p4client.SaveCurrentCLNumber())
Luis Lozano036c9232015-12-10 10:47:01 -0800139 ret, o, _ = self._ce.RunCommandWOutput(command)
asharif0ea89582013-02-15 21:15:11 +0000140 assert ret == 0, 'Could not get version from client.'
141 self.revision = re.search('^\d+$', o.strip(), re.MULTILINE).group(0)
asharif1b92e732013-02-15 20:51:38 +0000142 command = p4client.InCheckoutDir(p4client.Remove())
asharif0ea89582013-02-15 21:15:11 +0000143 ret = self._ce.RunCommand(command)
144 assert ret == 0, 'Could not delete client.'
asharif1b92e732013-02-15 20:51:38 +0000145 return 0
asharifec9c6242013-02-15 19:56:06 +0000146
147
148class SvnRepo(Repo):
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800149
asharifec9c6242013-02-15 19:56:06 +0000150 def __init__(self, address, mappings):
151 Repo.__init__(self)
asharif0ea89582013-02-15 21:15:11 +0000152 self.repo_type = 'svn'
asharifec9c6242013-02-15 19:56:06 +0000153 self.address = address
154 self.mappings = mappings
155
asharif56d78bc2013-02-15 21:15:08 +0000156 def PullSources(self):
kbaclawski20082a02013-02-16 02:12:57 +0000157 with misc.WorkingDirectory(self._root_dir):
asharif56d78bc2013-02-15 21:15:08 +0000158 for mapping in self.mappings:
159 remote_path, local_path = SplitMapping(mapping)
asharif0ea89582013-02-15 21:15:11 +0000160 command = 'svn co %s/%s %s' % (self.address, remote_path, local_path)
asharif56d78bc2013-02-15 21:15:08 +0000161 ret = self._ce.RunCommand(command)
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800162 if ret:
163 return ret
asharif56d78bc2013-02-15 21:15:08 +0000164
asharif0ea89582013-02-15 21:15:11 +0000165 self.revision = ''
asharif56d78bc2013-02-15 21:15:08 +0000166 for mapping in self.mappings:
167 remote_path, local_path = SplitMapping(mapping)
asharif39f7cb22013-02-19 19:35:16 +0000168 command = 'cd %s && svnversion -c .' % (local_path)
Luis Lozano036c9232015-12-10 10:47:01 -0800169 ret, o, _ = self._ce.RunCommandWOutput(command)
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800170 self.revision += o.strip().split(':')[-1]
171 if ret:
172 return ret
asharifcdbacaf2013-02-15 20:09:23 +0000173 return 0
asharifec9c6242013-02-15 19:56:06 +0000174
175
176class GitRepo(Repo):
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800177
asharif2aeeaca2013-02-16 02:11:04 +0000178 def __init__(self, address, branch, mappings=None, ignores=None, gerrit=None):
asharifec9c6242013-02-15 19:56:06 +0000179 Repo.__init__(self)
asharif0ea89582013-02-15 21:15:11 +0000180 self.repo_type = 'git'
asharifec9c6242013-02-15 19:56:06 +0000181 self.address = address
asharif0ea89582013-02-15 21:15:11 +0000182 self.branch = branch or 'master'
asharifec9c6242013-02-15 19:56:06 +0000183 if ignores:
184 self.ignores += ignores
asharif56d78bc2013-02-15 21:15:08 +0000185 self.mappings = mappings
asharif2aeeaca2013-02-16 02:11:04 +0000186 self.gerrit = gerrit
asharifec9c6242013-02-15 19:56:06 +0000187
asharif56d78bc2013-02-15 21:15:08 +0000188 def _CloneSources(self):
kbaclawski20082a02013-02-16 02:12:57 +0000189 with misc.WorkingDirectory(self._root_dir):
asharif0ea89582013-02-15 21:15:11 +0000190 command = 'git clone %s .' % (self.address)
asharif56d78bc2013-02-15 21:15:08 +0000191 return self._ce.RunCommand(command)
asharifec9c6242013-02-15 19:56:06 +0000192
asharif56d78bc2013-02-15 21:15:08 +0000193 def PullSources(self):
kbaclawski20082a02013-02-16 02:12:57 +0000194 with misc.WorkingDirectory(self._root_dir):
asharif0ea89582013-02-15 21:15:11 +0000195 ret = self._CloneSources()
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800196 if ret:
197 return ret
asharifec9c6242013-02-15 19:56:06 +0000198
asharif0ea89582013-02-15 21:15:11 +0000199 command = 'git checkout %s' % self.branch
asharif56d78bc2013-02-15 21:15:08 +0000200 ret = self._ce.RunCommand(command)
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800201 if ret:
202 return ret
asharifec9c6242013-02-15 19:56:06 +0000203
asharif0ea89582013-02-15 21:15:11 +0000204 command = 'git describe --always'
Luis Lozano036c9232015-12-10 10:47:01 -0800205 ret, o, _ = self._ce.RunCommandWOutput(command)
asharif56d78bc2013-02-15 21:15:08 +0000206 self.revision = o.strip()
207 return ret
asharifec9c6242013-02-15 19:56:06 +0000208
asharif56d78bc2013-02-15 21:15:08 +0000209 def SetupForPush(self):
kbaclawski20082a02013-02-16 02:12:57 +0000210 with misc.WorkingDirectory(self._root_dir):
asharif56d78bc2013-02-15 21:15:08 +0000211 ret = self._CloneSources()
asharif0ea89582013-02-15 21:15:11 +0000212 logger.GetLogger().LogFatalIf(ret, 'Could not clone git repo %s.' %
asharif56d78bc2013-02-15 21:15:08 +0000213 self.address)
asharifec9c6242013-02-15 19:56:06 +0000214
asharif0ea89582013-02-15 21:15:11 +0000215 command = 'git branch -a | grep -wq %s' % self.branch
asharif56d78bc2013-02-15 21:15:08 +0000216 ret = self._ce.RunCommand(command)
asharifec9c6242013-02-15 19:56:06 +0000217
asharif56d78bc2013-02-15 21:15:08 +0000218 if ret == 0:
asharif0ea89582013-02-15 21:15:11 +0000219 if self.branch != 'master':
220 command = ('git branch --track %s remotes/origin/%s' %
221 (self.branch, self.branch))
asharif56d78bc2013-02-15 21:15:08 +0000222 else:
asharif0ea89582013-02-15 21:15:11 +0000223 command = 'pwd'
224 command += '&& git checkout %s' % self.branch
asharif56d78bc2013-02-15 21:15:08 +0000225 else:
asharif0ea89582013-02-15 21:15:11 +0000226 command = 'git symbolic-ref HEAD refs/heads/%s' % self.branch
227 command += '&& rm -rf *'
asharif56d78bc2013-02-15 21:15:08 +0000228 ret = self._ce.RunCommand(command)
229 return ret
230
Han Sheneb77c442013-03-18 13:53:52 -0700231 def CommitLocally(self, commit_message=None, message_file=None):
kbaclawski20082a02013-02-16 02:12:57 +0000232 with misc.WorkingDirectory(self._root_dir):
asharif0ea89582013-02-15 21:15:11 +0000233 command = 'pwd'
234 for ignore in self.ignores:
235 command += '&& echo \'%s\' >> .git/info/exclude' % ignore
236 command += '&& git add -Av .'
asharif983c7c42013-02-16 02:13:01 +0000237 if message_file:
238 message_arg = '-F %s' % message_file
239 elif commit_message:
240 message_arg = '-m \'%s\'' % commit_message
241 else:
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800242 raise Exception('No commit message given!')
asharif983c7c42013-02-16 02:13:01 +0000243 command += '&& git commit -v %s' % message_arg
Han Sheneb77c442013-03-18 13:53:52 -0700244 return self._ce.RunCommand(command)
245
246 def PushSources(self, commit_message=None, dry_run=False, message_file=None):
247 ret = self.CommitLocally(commit_message, message_file)
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800248 if ret:
249 return ret
Han Sheneb77c442013-03-18 13:53:52 -0700250 push_args = ''
251 if dry_run:
252 push_args += ' -n '
253 with misc.WorkingDirectory(self._root_dir):
asharif2aeeaca2013-02-16 02:11:04 +0000254 if self.gerrit:
255 label = 'somelabel'
256 command = 'git remote add %s %s' % (label, self.address)
257 command += ('&& git push %s %s HEAD:refs/for/master' %
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800258 (push_args, label))
asharif2aeeaca2013-02-16 02:11:04 +0000259 else:
260 command = 'git push -v %s origin %s:%s' % (push_args, self.branch,
261 self.branch)
262 ret = self._ce.RunCommand(command)
Han Sheneb77c442013-03-18 13:53:52 -0700263 return ret
asharif56d78bc2013-02-15 21:15:08 +0000264
265 def MapSources(self, root_dir):
266 if not self.mappings:
ashariff6ffe502013-02-15 22:23:12 +0000267 self._RsyncExcludingRepoDirs(self._root_dir, root_dir)
asharif56d78bc2013-02-15 21:15:08 +0000268 return
kbaclawski20082a02013-02-16 02:12:57 +0000269 with misc.WorkingDirectory(self._root_dir):
asharif56d78bc2013-02-15 21:15:08 +0000270 for mapping in self.mappings:
271 remote_path, local_path = SplitMapping(mapping)
asharif0ea89582013-02-15 21:15:11 +0000272 remote_path.rstrip('...')
273 local_path.rstrip('...')
ashariff6ffe502013-02-15 22:23:12 +0000274 full_local_path = os.path.join(root_dir, local_path)
275 ret = self._RsyncExcludingRepoDirs(remote_path, full_local_path)
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800276 if ret:
277 return ret
asharif56d78bc2013-02-15 21:15:08 +0000278 return 0
asharifec9c6242013-02-15 19:56:06 +0000279
280
asharif0ea89582013-02-15 21:15:11 +0000281class RepoReader(object):
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800282
asharifec9c6242013-02-15 19:56:06 +0000283 def __init__(self, filename):
284 self.filename = filename
285 self.main_dict = {}
286 self.input_repos = []
287 self.output_repos = []
288
asharifec9c6242013-02-15 19:56:06 +0000289 def ParseFile(self):
asharif0ea89582013-02-15 21:15:11 +0000290 with open(self.filename) as f:
291 self.main_dict = eval(f.read())
292 self.CreateReposFromDict(self.main_dict)
asharifec9c6242013-02-15 19:56:06 +0000293 return [self.input_repos, self.output_repos]
294
asharifec9c6242013-02-15 19:56:06 +0000295 def CreateReposFromDict(self, main_dict):
asharif0ea89582013-02-15 21:15:11 +0000296 for key, repo_list in main_dict.items():
asharifec9c6242013-02-15 19:56:06 +0000297 for repo_dict in repo_list:
298 repo = self.CreateRepoFromDict(repo_dict)
asharif0ea89582013-02-15 21:15:11 +0000299 if key == 'input':
asharifec9c6242013-02-15 19:56:06 +0000300 self.input_repos.append(repo)
asharif0ea89582013-02-15 21:15:11 +0000301 elif key == 'output':
asharifec9c6242013-02-15 19:56:06 +0000302 self.output_repos.append(repo)
303 else:
asharif0ea89582013-02-15 21:15:11 +0000304 logger.GetLogger().LogFatal('Unknown key: %s found' % key)
asharifec9c6242013-02-15 19:56:06 +0000305
asharifec9c6242013-02-15 19:56:06 +0000306 def CreateRepoFromDict(self, repo_dict):
asharif0ea89582013-02-15 21:15:11 +0000307 repo_type = repo_dict.get('type', None)
308 repo_address = repo_dict.get('address', None)
309 repo_mappings = repo_dict.get('mappings', None)
310 repo_ignores = repo_dict.get('ignores', None)
311 repo_branch = repo_dict.get('branch', None)
asharif2aeeaca2013-02-16 02:11:04 +0000312 gerrit = repo_dict.get('gerrit', None)
asharif6578cf82013-02-16 02:41:46 +0000313 revision = repo_dict.get('revision', None)
asharifec9c6242013-02-15 19:56:06 +0000314
asharif0ea89582013-02-15 21:15:11 +0000315 if repo_type == 'p4':
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800316 repo = P4Repo(repo_address, repo_mappings, revision=revision)
asharif0ea89582013-02-15 21:15:11 +0000317 elif repo_type == 'svn':
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800318 repo = SvnRepo(repo_address, repo_mappings)
asharif0ea89582013-02-15 21:15:11 +0000319 elif repo_type == 'git':
asharifec9c6242013-02-15 19:56:06 +0000320 repo = GitRepo(repo_address,
321 repo_branch,
asharif56d78bc2013-02-15 21:15:08 +0000322 mappings=repo_mappings,
asharif2aeeaca2013-02-16 02:11:04 +0000323 ignores=repo_ignores,
324 gerrit=gerrit)
Han Sheneb77c442013-03-18 13:53:52 -0700325 elif repo_type == 'file':
326 repo = FileRepo(repo_address)
asharifec9c6242013-02-15 19:56:06 +0000327 else:
asharif0ea89582013-02-15 21:15:11 +0000328 logger.GetLogger().LogFatal('Unknown repo type: %s' % repo_type)
asharifec9c6242013-02-15 19:56:06 +0000329 return repo
330
331
asharif1b92e732013-02-15 20:51:38 +0000332@logger.HandleUncaughtExceptions
asharifec9c6242013-02-15 19:56:06 +0000333def Main(argv):
asharifec9c6242013-02-15 19:56:06 +0000334 parser = optparse.OptionParser()
asharif0ea89582013-02-15 21:15:11 +0000335 parser.add_option('-i',
336 '--input_file',
337 dest='input_file',
338 help='The input file that contains repo descriptions.')
asharifec9c6242013-02-15 19:56:06 +0000339
asharif0ea89582013-02-15 21:15:11 +0000340 parser.add_option('-n',
341 '--dry_run',
342 dest='dry_run',
343 action='store_true',
asharifec9c6242013-02-15 19:56:06 +0000344 default=False,
asharif0ea89582013-02-15 21:15:11 +0000345 help='Do a dry run of the push.')
asharifec9c6242013-02-15 19:56:06 +0000346
asharif983c7c42013-02-16 02:13:01 +0000347 parser.add_option('-F',
348 '--message_file',
349 dest='message_file',
350 default=None,
351 help='Use contents of the log file as the commit message.')
352
asharifec9c6242013-02-15 19:56:06 +0000353 options = parser.parse_args(argv)[0]
354 if not options.input_file:
355 parser.print_help()
356 return 1
357 rr = RepoReader(options.input_file)
358 [input_repos, output_repos] = rr.ParseFile()
359
Han Sheneb77c442013-03-18 13:53:52 -0700360 # Make sure FileRepo is not used as output destination.
361 for output_repo in output_repos:
362 if output_repo.repo_type == 'file':
363 logger.GetLogger().LogFatal(
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800364 'FileRepo is only supported as an input repo.')
Han Sheneb77c442013-03-18 13:53:52 -0700365
asharifec9c6242013-02-15 19:56:06 +0000366 for output_repo in output_repos:
asharif56d78bc2013-02-15 21:15:08 +0000367 ret = output_repo.SetupForPush()
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800368 if ret:
369 return ret
asharifec9c6242013-02-15 19:56:06 +0000370
371 input_revisions = []
372 for input_repo in input_repos:
asharif56d78bc2013-02-15 21:15:08 +0000373 ret = input_repo.PullSources()
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800374 if ret:
375 return ret
asharifec9c6242013-02-15 19:56:06 +0000376 input_revisions.append(input_repo.revision)
377
asharif56d78bc2013-02-15 21:15:08 +0000378 for input_repo in input_repos:
379 for output_repo in output_repos:
380 ret = input_repo.MapSources(output_repo.GetRoot())
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800381 if ret:
382 return ret
asharif56d78bc2013-02-15 21:15:08 +0000383
asharif0ea89582013-02-15 21:15:11 +0000384 commit_message = 'Synced repos to: %s' % ','.join(input_revisions)
asharifec9c6242013-02-15 19:56:06 +0000385 for output_repo in output_repos:
asharif983c7c42013-02-16 02:13:01 +0000386 ret = output_repo.PushSources(commit_message=commit_message,
387 dry_run=options.dry_run,
388 message_file=options.message_file)
Luis Lozanof2a3ef42015-12-15 13:49:30 -0800389 if ret:
390 return ret
asharifcdbacaf2013-02-15 20:09:23 +0000391
392 if not options.dry_run:
asharif56d78bc2013-02-15 21:15:08 +0000393 for output_repo in output_repos:
394 output_repo.CleanupRoot()
raymes80780842013-02-15 21:59:10 +0000395 for input_repo in input_repos:
396 input_repo.CleanupRoot()
asharifcdbacaf2013-02-15 20:09:23 +0000397
398 return ret
asharifec9c6242013-02-15 19:56:06 +0000399
400
asharif0ea89582013-02-15 21:15:11 +0000401if __name__ == '__main__':
asharifec9c6242013-02-15 19:56:06 +0000402 retval = Main(sys.argv)
403 sys.exit(retval)