blob: 7ab0b1fb620521aec12a64c2142da463e715ab39 [file] [log] [blame]
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -07001#
2# Copyright (C) 2008 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
Shawn O. Pearce2a1ccb22009-04-10 16:51:53 -070016from optparse import SUPPRESS_HELP
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070017import os
18import re
Jaikumar Ganesh4f2517f2009-06-01 21:10:33 -070019import shutil
Nico Sallembiena1bfd2c2010-04-06 10:40:01 -070020import socket
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070021import subprocess
22import sys
Shawn O. Pearcef6906872009-04-18 10:49:00 -070023import time
Nico Sallembiena1bfd2c2010-04-06 10:40:01 -070024import xmlrpclib
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070025
Roy Lee18afd7f2010-05-09 04:32:08 +080026try:
27 import threading as _threading
28except ImportError:
29 import dummy_threading as _threading
30
Shawn O. Pearce97d2b2f2011-09-22 17:23:41 -070031try:
32 import resource
33 def _rlimit_nofile():
34 return resource.getrlimit(resource.RLIMIT_NOFILE)
35except ImportError:
36 def _rlimit_nofile():
37 return (256, 256)
38
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070039from git_command import GIT
Nico Sallembien5732e472010-04-26 11:17:29 -070040from git_refs import R_HEADS
Shawn O. Pearcee756c412009-04-13 11:51:15 -070041from project import HEAD
Jaikumar Ganesh4f2517f2009-06-01 21:10:33 -070042from project import Project
43from project import RemoteSpec
Shawn O. Pearcec95583b2009-03-03 17:47:06 -080044from command import Command, MirrorSafeCommand
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070045from error import RepoChangedException, GitError
46from project import R_HEADS
Shawn O. Pearce350cde42009-04-16 11:21:18 -070047from project import SyncBuffer
Shawn O. Pearce68194f42009-04-10 16:48:52 -070048from progress import Progress
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070049
Doug Andersonfc06ced2011-03-16 15:49:18 -070050class _FetchError(Exception):
51 """Internal error thrown in _FetchHelper() when we don't want stack trace."""
52 pass
53
Shawn O. Pearcec95583b2009-03-03 17:47:06 -080054class Sync(Command, MirrorSafeCommand):
Roy Lee18afd7f2010-05-09 04:32:08 +080055 jobs = 1
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070056 common = True
57 helpSummary = "Update working tree to the latest revision"
58 helpUsage = """
59%prog [<project>...]
60"""
61 helpDescription = """
62The '%prog' command synchronizes local project directories
63with the remote repositories specified in the manifest. If a local
64project does not yet exist, it will clone a new local directory from
65the remote repository and set up tracking branches as specified in
66the manifest. If the local project already exists, '%prog'
67will update the remote branches and rebase any new local changes
68on top of the new remote changes.
69
70'%prog' will synchronize all projects listed at the command
71line. Projects can be specified either by name, or by a relative
72or absolute path to the project's local directory. If no projects
73are specified, '%prog' will synchronize all projects listed in
74the manifest.
Shawn O. Pearce3e768c92009-04-10 16:59:36 -070075
76The -d/--detach option can be used to switch specified projects
77back to the manifest revision. This option is especially helpful
78if the project is currently on a topic branch, but the manifest
79revision is temporarily needed.
Shawn O. Pearceeb7af872009-04-21 08:02:04 -070080
Nico Sallembiena1bfd2c2010-04-06 10:40:01 -070081The -s/--smart-sync option can be used to sync to a known good
82build as specified by the manifest-server element in the current
Victor Boivie08c880d2011-04-19 10:32:52 +020083manifest. The -t/--smart-tag option is similar and allows you to
84specify a custom tag/label.
Nico Sallembiena1bfd2c2010-04-06 10:40:01 -070085
Andrei Warkentin5df6de02010-07-02 17:58:31 -050086The -f/--force-broken option can be used to proceed with syncing
87other projects if a project sync fails.
88
Shawn O. Pearceeb7af872009-04-21 08:02:04 -070089SSH Connections
90---------------
91
92If at least one project remote URL uses an SSH connection (ssh://,
93git+ssh://, or user@host:path syntax) repo will automatically
94enable the SSH ControlMaster option when connecting to that host.
95This feature permits other projects in the same '%prog' session to
96reuse the same SSH tunnel, saving connection setup overheads.
97
98To disable this behavior on UNIX platforms, set the GIT_SSH
99environment variable to 'ssh'. For example:
100
101 export GIT_SSH=ssh
102 %prog
103
104Compatibility
105~~~~~~~~~~~~~
106
107This feature is automatically disabled on Windows, due to the lack
108of UNIX domain socket support.
109
110This feature is not compatible with url.insteadof rewrites in the
111user's ~/.gitconfig. '%prog' is currently not able to perform the
112rewrite early enough to establish the ControlMaster tunnel.
113
114If the remote SSH daemon is Gerrit Code Review, version 2.0.10 or
115later is required to fix a server side protocol bug.
116
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700117"""
118
Nico Sallembien6623b212010-05-11 12:57:01 -0700119 def _Options(self, p, show_smart=True):
Shawn O. Pearce6392c872011-09-22 17:44:31 -0700120 self.jobs = self.manifest.default.sync_j
121
Andrei Warkentin5df6de02010-07-02 17:58:31 -0500122 p.add_option('-f', '--force-broken',
123 dest='force_broken', action='store_true',
124 help="continue sync even if a project fails to sync")
Shawn O. Pearceb1562fa2009-04-10 17:04:08 -0700125 p.add_option('-l','--local-only',
126 dest='local_only', action='store_true',
127 help="only update working tree, don't fetch")
Shawn O. Pearce96fdcef2009-04-10 16:29:20 -0700128 p.add_option('-n','--network-only',
129 dest='network_only', action='store_true',
130 help="fetch only, don't update working tree")
Shawn O. Pearce3e768c92009-04-10 16:59:36 -0700131 p.add_option('-d','--detach',
132 dest='detach_head', action='store_true',
133 help='detach projects back to manifest revision')
Shawn O. Pearce16614f82010-10-29 12:05:43 -0700134 p.add_option('-q','--quiet',
135 dest='quiet', action='store_true',
136 help='be more quiet')
Roy Lee18afd7f2010-05-09 04:32:08 +0800137 p.add_option('-j','--jobs',
138 dest='jobs', action='store', type='int',
Shawn O. Pearce6392c872011-09-22 17:44:31 -0700139 default=self.jobs,
140 help="projects to fetch simultaneously (default %d)" % self.jobs)
Nico Sallembien6623b212010-05-11 12:57:01 -0700141 if show_smart:
142 p.add_option('-s', '--smart-sync',
143 dest='smart_sync', action='store_true',
144 help='smart sync using manifest from a known good build')
Victor Boivie08c880d2011-04-19 10:32:52 +0200145 p.add_option('-t', '--smart-tag',
146 dest='smart_tag', action='store',
147 help='smart sync using manifest from a known tag')
Shawn O. Pearce3e768c92009-04-10 16:59:36 -0700148
Shawn O. Pearcefd89b672009-04-18 11:28:57 -0700149 g = p.add_option_group('repo Version options')
150 g.add_option('--no-repo-verify',
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700151 dest='no_repo_verify', action='store_true',
152 help='do not verify repo source code')
Shawn O. Pearcefd89b672009-04-18 11:28:57 -0700153 g.add_option('--repo-upgraded',
Shawn O. Pearcec9ef7442008-11-03 10:32:09 -0800154 dest='repo_upgraded', action='store_true',
Shawn O. Pearce2a1ccb22009-04-10 16:51:53 -0700155 help=SUPPRESS_HELP)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700156
Doug Andersonfc06ced2011-03-16 15:49:18 -0700157 def _FetchHelper(self, opt, project, lock, fetched, pm, sem, err_event):
158 """Main function of the fetch threads when jobs are > 1.
159
160 Args:
161 opt: Program options returned from optparse. See _Options().
162 project: Project object for the project to fetch.
163 lock: Lock for accessing objects that are shared amongst multiple
164 _FetchHelper() threads.
165 fetched: set object that we will add project.gitdir to when we're done
166 (with our lock held).
167 pm: Instance of a Project object. We will call pm.update() (with our
168 lock held).
169 sem: We'll release() this semaphore when we exit so that another thread
170 can be started up.
171 err_event: We'll set this event in the case of an error (after printing
172 out info about the error).
173 """
174 # We'll set to true once we've locked the lock.
175 did_lock = False
176
177 # Encapsulate everything in a try/except/finally so that:
178 # - We always set err_event in the case of an exception.
179 # - We always make sure we call sem.release().
180 # - We always make sure we unlock the lock if we locked it.
181 try:
Shawn O. Pearcee6a0eeb2011-03-22 19:04:47 -0700182 try:
183 success = project.Sync_NetworkHalf(quiet=opt.quiet)
Doug Andersonfc06ced2011-03-16 15:49:18 -0700184
Shawn O. Pearcee6a0eeb2011-03-22 19:04:47 -0700185 # Lock around all the rest of the code, since printing, updating a set
186 # and Progress.update() are not thread safe.
187 lock.acquire()
188 did_lock = True
Doug Andersonfc06ced2011-03-16 15:49:18 -0700189
Shawn O. Pearcee6a0eeb2011-03-22 19:04:47 -0700190 if not success:
191 print >>sys.stderr, 'error: Cannot fetch %s' % project.name
192 if opt.force_broken:
193 print >>sys.stderr, 'warn: --force-broken, continuing to sync'
194 else:
195 raise _FetchError()
Roy Lee18afd7f2010-05-09 04:32:08 +0800196
Shawn O. Pearcee6a0eeb2011-03-22 19:04:47 -0700197 fetched.add(project.gitdir)
198 pm.update()
199 except BaseException, e:
200 # Notify the _Fetch() function about all errors.
201 err_event.set()
Doug Andersonfc06ced2011-03-16 15:49:18 -0700202
Shawn O. Pearcee6a0eeb2011-03-22 19:04:47 -0700203 # If we got our own _FetchError, we don't want a stack trace.
204 # However, if we got something else (something in Sync_NetworkHalf?),
205 # we'd like one (so re-raise after we've set err_event).
206 if not isinstance(e, _FetchError):
207 raise
Doug Andersonfc06ced2011-03-16 15:49:18 -0700208 finally:
209 if did_lock:
210 lock.release()
211 sem.release()
Roy Lee18afd7f2010-05-09 04:32:08 +0800212
Shawn O. Pearce16614f82010-10-29 12:05:43 -0700213 def _Fetch(self, projects, opt):
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700214 fetched = set()
Shawn O. Pearce68194f42009-04-10 16:48:52 -0700215 pm = Progress('Fetching projects', len(projects))
Roy Lee18afd7f2010-05-09 04:32:08 +0800216
217 if self.jobs == 1:
218 for project in projects:
219 pm.update()
Shawn O. Pearce16614f82010-10-29 12:05:43 -0700220 if project.Sync_NetworkHalf(quiet=opt.quiet):
Roy Lee18afd7f2010-05-09 04:32:08 +0800221 fetched.add(project.gitdir)
222 else:
223 print >>sys.stderr, 'error: Cannot fetch %s' % project.name
Andrei Warkentin5df6de02010-07-02 17:58:31 -0500224 if opt.force_broken:
225 print >>sys.stderr, 'warn: --force-broken, continuing to sync'
226 else:
227 sys.exit(1)
Roy Lee18afd7f2010-05-09 04:32:08 +0800228 else:
229 threads = set()
230 lock = _threading.Lock()
231 sem = _threading.Semaphore(self.jobs)
Doug Andersonfc06ced2011-03-16 15:49:18 -0700232 err_event = _threading.Event()
Roy Lee18afd7f2010-05-09 04:32:08 +0800233 for project in projects:
Doug Andersonfc06ced2011-03-16 15:49:18 -0700234 # Check for any errors before starting any new threads.
235 # ...we'll let existing threads finish, though.
Daniel Sandler723c5dc2011-04-04 11:15:17 -0400236 if err_event.isSet():
Doug Andersonfc06ced2011-03-16 15:49:18 -0700237 break
238
Roy Lee18afd7f2010-05-09 04:32:08 +0800239 sem.acquire()
240 t = _threading.Thread(target = self._FetchHelper,
Shawn O. Pearce16614f82010-10-29 12:05:43 -0700241 args = (opt,
242 project,
243 lock,
244 fetched,
245 pm,
Doug Andersonfc06ced2011-03-16 15:49:18 -0700246 sem,
247 err_event))
Roy Lee18afd7f2010-05-09 04:32:08 +0800248 threads.add(t)
249 t.start()
250
251 for t in threads:
252 t.join()
253
Doug Andersonfc06ced2011-03-16 15:49:18 -0700254 # If we saw an error, exit with code 1 so that other scripts can check.
Daniel Sandler723c5dc2011-04-04 11:15:17 -0400255 if err_event.isSet():
Doug Andersonfc06ced2011-03-16 15:49:18 -0700256 print >>sys.stderr, '\nerror: Exited sync due to fetch errors'
257 sys.exit(1)
258
Shawn O. Pearce68194f42009-04-10 16:48:52 -0700259 pm.end()
Shawn O. Pearce0d2b61f2009-07-03 15:22:49 -0700260 for project in projects:
261 project.bare_git.gc('--auto')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700262 return fetched
263
Jaikumar Ganesh4f2517f2009-06-01 21:10:33 -0700264 def UpdateProjectList(self):
265 new_project_paths = []
266 for project in self.manifest.projects.values():
Shawn O. Pearce3a68bb42009-06-04 16:18:09 -0700267 if project.relpath:
268 new_project_paths.append(project.relpath)
Jaikumar Ganesh4f2517f2009-06-01 21:10:33 -0700269 file_name = 'project.list'
270 file_path = os.path.join(self.manifest.repodir, file_name)
271 old_project_paths = []
272
273 if os.path.exists(file_path):
274 fd = open(file_path, 'r')
275 try:
276 old_project_paths = fd.read().split('\n')
277 finally:
278 fd.close()
279 for path in old_project_paths:
Shawn O. Pearce3a68bb42009-06-04 16:18:09 -0700280 if not path:
281 continue
Jaikumar Ganesh4f2517f2009-06-01 21:10:33 -0700282 if path not in new_project_paths:
Anthonyf3fdf822009-09-26 13:38:52 -0400283 """If the path has already been deleted, we don't need to do it
284 """
285 if os.path.exists(self.manifest.topdir + '/' + path):
286 project = Project(
287 manifest = self.manifest,
288 name = path,
289 remote = RemoteSpec('origin'),
290 gitdir = os.path.join(self.manifest.topdir,
291 path, '.git'),
292 worktree = os.path.join(self.manifest.topdir, path),
293 relpath = path,
294 revisionExpr = 'HEAD',
295 revisionId = None)
296
297 if project.IsDirty():
298 print >>sys.stderr, 'error: Cannot remove project "%s": \
Jaikumar Ganesh4f2517f2009-06-01 21:10:33 -0700299uncommitted changes are present' % project.relpath
Anthonyf3fdf822009-09-26 13:38:52 -0400300 print >>sys.stderr, ' commit changes, then run sync again'
301 return -1
302 else:
303 print >>sys.stderr, 'Deleting obsolete path %s' % project.worktree
304 shutil.rmtree(project.worktree)
305 # Try deleting parent subdirs if they are empty
306 dir = os.path.dirname(project.worktree)
307 while dir != self.manifest.topdir:
308 try:
309 os.rmdir(dir)
310 except OSError:
311 break
312 dir = os.path.dirname(dir)
Jaikumar Ganesh4f2517f2009-06-01 21:10:33 -0700313
Shawn O. Pearce9fb29ce2009-06-04 20:41:02 -0700314 new_project_paths.sort()
Jaikumar Ganesh4f2517f2009-06-01 21:10:33 -0700315 fd = open(file_path, 'w')
316 try:
317 fd.write('\n'.join(new_project_paths))
Shawn O. Pearce3a68bb42009-06-04 16:18:09 -0700318 fd.write('\n')
Jaikumar Ganesh4f2517f2009-06-01 21:10:33 -0700319 finally:
320 fd.close()
321 return 0
322
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700323 def Execute(self, opt, args):
Roy Lee18afd7f2010-05-09 04:32:08 +0800324 if opt.jobs:
325 self.jobs = opt.jobs
Shawn O. Pearce97d2b2f2011-09-22 17:23:41 -0700326 if self.jobs > 1:
327 soft_limit, _ = _rlimit_nofile()
328 self.jobs = min(self.jobs, (soft_limit - 5) / 3)
329
Shawn O. Pearce3e768c92009-04-10 16:59:36 -0700330 if opt.network_only and opt.detach_head:
331 print >>sys.stderr, 'error: cannot combine -n and -d'
332 sys.exit(1)
Shawn O. Pearceb1562fa2009-04-10 17:04:08 -0700333 if opt.network_only and opt.local_only:
334 print >>sys.stderr, 'error: cannot combine -n and -l'
335 sys.exit(1)
Shawn O. Pearce3e768c92009-04-10 16:59:36 -0700336
Victor Boivie08c880d2011-04-19 10:32:52 +0200337 if opt.smart_sync or opt.smart_tag:
Nico Sallembiena1bfd2c2010-04-06 10:40:01 -0700338 if not self.manifest.manifest_server:
339 print >>sys.stderr, \
340 'error: cannot smart sync: no manifest server defined in manifest'
341 sys.exit(1)
342 try:
343 server = xmlrpclib.Server(self.manifest.manifest_server)
Victor Boivie08c880d2011-04-19 10:32:52 +0200344 if opt.smart_sync:
345 p = self.manifest.manifestProject
346 b = p.GetBranch(p.CurrentBranch)
347 branch = b.merge
348 if branch.startswith(R_HEADS):
349 branch = branch[len(R_HEADS):]
Nico Sallembiena1bfd2c2010-04-06 10:40:01 -0700350
Victor Boivie08c880d2011-04-19 10:32:52 +0200351 env = os.environ.copy()
352 if (env.has_key('TARGET_PRODUCT') and
353 env.has_key('TARGET_BUILD_VARIANT')):
354 target = '%s-%s' % (env['TARGET_PRODUCT'],
355 env['TARGET_BUILD_VARIANT'])
356 [success, manifest_str] = server.GetApprovedManifest(branch, target)
357 else:
358 [success, manifest_str] = server.GetApprovedManifest(branch)
Nico Sallembiena1bfd2c2010-04-06 10:40:01 -0700359 else:
Victor Boivie08c880d2011-04-19 10:32:52 +0200360 assert(opt.smart_tag)
361 [success, manifest_str] = server.GetManifest(opt.smart_tag)
Nico Sallembiena1bfd2c2010-04-06 10:40:01 -0700362
363 if success:
364 manifest_name = "smart_sync_override.xml"
365 manifest_path = os.path.join(self.manifest.manifestProject.worktree,
366 manifest_name)
367 try:
368 f = open(manifest_path, 'w')
369 try:
370 f.write(manifest_str)
Nico Sallembiena1bfd2c2010-04-06 10:40:01 -0700371 finally:
372 f.close()
373 except IOError:
374 print >>sys.stderr, 'error: cannot write manifest to %s' % \
375 manifest_path
376 sys.exit(1)
Nico Sallembien719965a2010-04-20 15:28:19 -0700377 self.manifest.Override(manifest_name)
Nico Sallembiena1bfd2c2010-04-06 10:40:01 -0700378 else:
379 print >>sys.stderr, 'error: %s' % manifest_str
380 sys.exit(1)
381 except socket.error:
382 print >>sys.stderr, 'error: cannot connect to manifest server %s' % (
383 self.manifest.manifest_server)
384 sys.exit(1)
385
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700386 rp = self.manifest.repoProject
387 rp.PreSync()
388
389 mp = self.manifest.manifestProject
390 mp.PreSync()
391
Shawn O. Pearcec9ef7442008-11-03 10:32:09 -0800392 if opt.repo_upgraded:
Shawn O. Pearcee756c412009-04-13 11:51:15 -0700393 _PostRepoUpgrade(self.manifest)
Shawn O. Pearcec9ef7442008-11-03 10:32:09 -0800394
Nico Sallembien9bb18162009-12-07 15:38:01 -0800395 if not opt.local_only:
Shawn O. Pearce16614f82010-10-29 12:05:43 -0700396 mp.Sync_NetworkHalf(quiet=opt.quiet)
Nico Sallembien9bb18162009-12-07 15:38:01 -0800397
398 if mp.HasChanges:
399 syncbuf = SyncBuffer(mp.config)
400 mp.Sync_LocalHalf(syncbuf)
401 if not syncbuf.Finish():
402 sys.exit(1)
403 self.manifest._Unload()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700404 all = self.GetProjects(args, missing_ok=True)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700405
Shawn O. Pearceb1562fa2009-04-10 17:04:08 -0700406 if not opt.local_only:
Shawn O. Pearcef6906872009-04-18 10:49:00 -0700407 to_fetch = []
408 now = time.time()
409 if (24 * 60 * 60) <= (now - rp.LastFetch):
410 to_fetch.append(rp)
Shawn O. Pearcef6906872009-04-18 10:49:00 -0700411 to_fetch.extend(all)
412
Shawn O. Pearce16614f82010-10-29 12:05:43 -0700413 fetched = self._Fetch(to_fetch, opt)
Shawn O. Pearcee756c412009-04-13 11:51:15 -0700414 _PostRepoFetch(rp, opt.no_repo_verify)
Shawn O. Pearceb1562fa2009-04-10 17:04:08 -0700415 if opt.network_only:
416 # bail out now; the rest touches the working tree
417 return
418
Shawn O. Pearceb1562fa2009-04-10 17:04:08 -0700419 self.manifest._Unload()
420 all = self.GetProjects(args, missing_ok=True)
421 missing = []
422 for project in all:
423 if project.gitdir not in fetched:
424 missing.append(project)
Shawn O. Pearce16614f82010-10-29 12:05:43 -0700425 self._Fetch(missing, opt)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700426
Shawn O. Pearcecd1d7ff2009-06-04 16:15:53 -0700427 if self.manifest.IsMirror:
428 # bail out now, we have no working tree
429 return
430
Jaikumar Ganesh4f2517f2009-06-01 21:10:33 -0700431 if self.UpdateProjectList():
432 sys.exit(1)
433
Shawn O. Pearce350cde42009-04-16 11:21:18 -0700434 syncbuf = SyncBuffer(mp.config,
435 detach_head = opt.detach_head)
Shawn O. Pearce68194f42009-04-10 16:48:52 -0700436 pm = Progress('Syncing work tree', len(all))
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700437 for project in all:
Shawn O. Pearce68194f42009-04-10 16:48:52 -0700438 pm.update()
Shawn O. Pearcee284ad12008-11-04 07:37:10 -0800439 if project.worktree:
Shawn O. Pearce350cde42009-04-16 11:21:18 -0700440 project.Sync_LocalHalf(syncbuf)
Shawn O. Pearce68194f42009-04-10 16:48:52 -0700441 pm.end()
Shawn O. Pearce350cde42009-04-16 11:21:18 -0700442 print >>sys.stderr
443 if not syncbuf.Finish():
444 sys.exit(1)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700445
Doug Anderson2b8db3c2010-11-01 15:08:06 -0700446 # If there's a notice that's supposed to print at the end of the sync, print
447 # it now...
448 if self.manifest.notice:
449 print self.manifest.notice
450
Shawn O. Pearcee756c412009-04-13 11:51:15 -0700451def _PostRepoUpgrade(manifest):
452 for project in manifest.projects.values():
453 if project.Exists:
454 project.PostRepoUpgrade()
455
456def _PostRepoFetch(rp, no_repo_verify=False, verbose=False):
457 if rp.HasChanges:
458 print >>sys.stderr, 'info: A new version of repo is available'
459 print >>sys.stderr, ''
460 if no_repo_verify or _VerifyTag(rp):
Shawn O. Pearce350cde42009-04-16 11:21:18 -0700461 syncbuf = SyncBuffer(rp.config)
462 rp.Sync_LocalHalf(syncbuf)
463 if not syncbuf.Finish():
Shawn O. Pearcee756c412009-04-13 11:51:15 -0700464 sys.exit(1)
465 print >>sys.stderr, 'info: Restarting repo with latest version'
466 raise RepoChangedException(['--repo-upgraded'])
467 else:
468 print >>sys.stderr, 'warning: Skipped upgrade to unverified version'
469 else:
470 if verbose:
471 print >>sys.stderr, 'repo version %s is current' % rp.work_git.describe(HEAD)
472
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700473def _VerifyTag(project):
474 gpg_dir = os.path.expanduser('~/.repoconfig/gnupg')
475 if not os.path.exists(gpg_dir):
476 print >>sys.stderr,\
477"""warning: GnuPG was not available during last "repo init"
478warning: Cannot automatically authenticate repo."""
479 return True
480
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700481 try:
Shawn O. Pearce3c8dea12009-05-29 18:38:17 -0700482 cur = project.bare_git.describe(project.GetRevisionId())
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700483 except GitError:
484 cur = None
485
486 if not cur \
487 or re.compile(r'^.*-[0-9]{1,}-g[0-9a-f]{1,}$').match(cur):
Shawn O. Pearce3c8dea12009-05-29 18:38:17 -0700488 rev = project.revisionExpr
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700489 if rev.startswith(R_HEADS):
490 rev = rev[len(R_HEADS):]
491
492 print >>sys.stderr
493 print >>sys.stderr,\
494 "warning: project '%s' branch '%s' is not signed" \
495 % (project.name, rev)
496 return False
497
Shawn O. Pearcef18cb762010-12-07 11:41:05 -0800498 env = os.environ.copy()
499 env['GIT_DIR'] = project.gitdir.encode()
500 env['GNUPGHOME'] = gpg_dir.encode()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700501
502 cmd = [GIT, 'tag', '-v', cur]
503 proc = subprocess.Popen(cmd,
504 stdout = subprocess.PIPE,
505 stderr = subprocess.PIPE,
506 env = env)
507 out = proc.stdout.read()
508 proc.stdout.close()
509
510 err = proc.stderr.read()
511 proc.stderr.close()
512
513 if proc.wait() != 0:
514 print >>sys.stderr
515 print >>sys.stderr, out
516 print >>sys.stderr, err
517 print >>sys.stderr
518 return False
519 return True