blob: d941ea0753e833b024354a7c6639d3a2ab554c5a [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
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070031from git_command import GIT
Nico Sallembien5732e472010-04-26 11:17:29 -070032from git_refs import R_HEADS
Shawn O. Pearcee756c412009-04-13 11:51:15 -070033from project import HEAD
Jaikumar Ganesh4f2517f2009-06-01 21:10:33 -070034from project import Project
35from project import RemoteSpec
Shawn O. Pearcec95583b2009-03-03 17:47:06 -080036from command import Command, MirrorSafeCommand
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070037from error import RepoChangedException, GitError
38from project import R_HEADS
Shawn O. Pearce350cde42009-04-16 11:21:18 -070039from project import SyncBuffer
Shawn O. Pearce68194f42009-04-10 16:48:52 -070040from progress import Progress
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070041
Doug Andersonfc06ced2011-03-16 15:49:18 -070042class _FetchError(Exception):
43 """Internal error thrown in _FetchHelper() when we don't want stack trace."""
44 pass
45
Shawn O. Pearcec95583b2009-03-03 17:47:06 -080046class Sync(Command, MirrorSafeCommand):
Roy Lee18afd7f2010-05-09 04:32:08 +080047 jobs = 1
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070048 common = True
49 helpSummary = "Update working tree to the latest revision"
50 helpUsage = """
51%prog [<project>...]
52"""
53 helpDescription = """
54The '%prog' command synchronizes local project directories
55with the remote repositories specified in the manifest. If a local
56project does not yet exist, it will clone a new local directory from
57the remote repository and set up tracking branches as specified in
58the manifest. If the local project already exists, '%prog'
59will update the remote branches and rebase any new local changes
60on top of the new remote changes.
61
62'%prog' will synchronize all projects listed at the command
63line. Projects can be specified either by name, or by a relative
64or absolute path to the project's local directory. If no projects
65are specified, '%prog' will synchronize all projects listed in
66the manifest.
Shawn O. Pearce3e768c92009-04-10 16:59:36 -070067
68The -d/--detach option can be used to switch specified projects
69back to the manifest revision. This option is especially helpful
70if the project is currently on a topic branch, but the manifest
71revision is temporarily needed.
Shawn O. Pearceeb7af872009-04-21 08:02:04 -070072
Nico Sallembiena1bfd2c2010-04-06 10:40:01 -070073The -s/--smart-sync option can be used to sync to a known good
74build as specified by the manifest-server element in the current
75manifest.
76
Andrei Warkentin5df6de02010-07-02 17:58:31 -050077The -f/--force-broken option can be used to proceed with syncing
78other projects if a project sync fails.
79
Shawn O. Pearceeb7af872009-04-21 08:02:04 -070080SSH Connections
81---------------
82
83If at least one project remote URL uses an SSH connection (ssh://,
84git+ssh://, or user@host:path syntax) repo will automatically
85enable the SSH ControlMaster option when connecting to that host.
86This feature permits other projects in the same '%prog' session to
87reuse the same SSH tunnel, saving connection setup overheads.
88
89To disable this behavior on UNIX platforms, set the GIT_SSH
90environment variable to 'ssh'. For example:
91
92 export GIT_SSH=ssh
93 %prog
94
95Compatibility
96~~~~~~~~~~~~~
97
98This feature is automatically disabled on Windows, due to the lack
99of UNIX domain socket support.
100
101This feature is not compatible with url.insteadof rewrites in the
102user's ~/.gitconfig. '%prog' is currently not able to perform the
103rewrite early enough to establish the ControlMaster tunnel.
104
105If the remote SSH daemon is Gerrit Code Review, version 2.0.10 or
106later is required to fix a server side protocol bug.
107
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700108"""
109
Nico Sallembien6623b212010-05-11 12:57:01 -0700110 def _Options(self, p, show_smart=True):
Andrei Warkentin5df6de02010-07-02 17:58:31 -0500111 p.add_option('-f', '--force-broken',
112 dest='force_broken', action='store_true',
113 help="continue sync even if a project fails to sync")
Shawn O. Pearceb1562fa2009-04-10 17:04:08 -0700114 p.add_option('-l','--local-only',
115 dest='local_only', action='store_true',
116 help="only update working tree, don't fetch")
Shawn O. Pearce96fdcef2009-04-10 16:29:20 -0700117 p.add_option('-n','--network-only',
118 dest='network_only', action='store_true',
119 help="fetch only, don't update working tree")
Shawn O. Pearce3e768c92009-04-10 16:59:36 -0700120 p.add_option('-d','--detach',
121 dest='detach_head', action='store_true',
122 help='detach projects back to manifest revision')
Shawn O. Pearce16614f82010-10-29 12:05:43 -0700123 p.add_option('-q','--quiet',
124 dest='quiet', action='store_true',
125 help='be more quiet')
Roy Lee18afd7f2010-05-09 04:32:08 +0800126 p.add_option('-j','--jobs',
127 dest='jobs', action='store', type='int',
128 help="number of projects to fetch simultaneously")
Nico Sallembien6623b212010-05-11 12:57:01 -0700129 if show_smart:
130 p.add_option('-s', '--smart-sync',
131 dest='smart_sync', action='store_true',
132 help='smart sync using manifest from a known good build')
Shawn O. Pearce3e768c92009-04-10 16:59:36 -0700133
Shawn O. Pearcefd89b672009-04-18 11:28:57 -0700134 g = p.add_option_group('repo Version options')
135 g.add_option('--no-repo-verify',
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700136 dest='no_repo_verify', action='store_true',
137 help='do not verify repo source code')
Shawn O. Pearcefd89b672009-04-18 11:28:57 -0700138 g.add_option('--repo-upgraded',
Shawn O. Pearcec9ef7442008-11-03 10:32:09 -0800139 dest='repo_upgraded', action='store_true',
Shawn O. Pearce2a1ccb22009-04-10 16:51:53 -0700140 help=SUPPRESS_HELP)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700141
Doug Andersonfc06ced2011-03-16 15:49:18 -0700142 def _FetchHelper(self, opt, project, lock, fetched, pm, sem, err_event):
143 """Main function of the fetch threads when jobs are > 1.
Roy Lee18afd7f2010-05-09 04:32:08 +0800144
Doug Andersonfc06ced2011-03-16 15:49:18 -0700145 Args:
146 opt: Program options returned from optparse. See _Options().
147 project: Project object for the project to fetch.
148 lock: Lock for accessing objects that are shared amongst multiple
149 _FetchHelper() threads.
150 fetched: set object that we will add project.gitdir to when we're done
151 (with our lock held).
152 pm: Instance of a Project object. We will call pm.update() (with our
153 lock held).
154 sem: We'll release() this semaphore when we exit so that another thread
155 can be started up.
156 err_event: We'll set this event in the case of an error (after printing
157 out info about the error).
158 """
159 # We'll set to true once we've locked the lock.
160 did_lock = False
161
162 # Encapsulate everything in a try/except/finally so that:
163 # - We always set err_event in the case of an exception.
164 # - We always make sure we call sem.release().
165 # - We always make sure we unlock the lock if we locked it.
166 try:
Shawn O. Pearcee6a0eeb2011-03-22 19:04:47 -0700167 try:
168 success = project.Sync_NetworkHalf(quiet=opt.quiet)
Doug Andersonfc06ced2011-03-16 15:49:18 -0700169
Shawn O. Pearcee6a0eeb2011-03-22 19:04:47 -0700170 # Lock around all the rest of the code, since printing, updating a set
171 # and Progress.update() are not thread safe.
172 lock.acquire()
173 did_lock = True
Doug Andersonfc06ced2011-03-16 15:49:18 -0700174
Shawn O. Pearcee6a0eeb2011-03-22 19:04:47 -0700175 if not success:
176 print >>sys.stderr, 'error: Cannot fetch %s' % project.name
177 if opt.force_broken:
178 print >>sys.stderr, 'warn: --force-broken, continuing to sync'
179 else:
180 raise _FetchError()
Doug Andersonfc06ced2011-03-16 15:49:18 -0700181
Shawn O. Pearcee6a0eeb2011-03-22 19:04:47 -0700182 fetched.add(project.gitdir)
183 pm.update()
184 except BaseException, e:
185 # Notify the _Fetch() function about all errors.
186 err_event.set()
Doug Andersonfc06ced2011-03-16 15:49:18 -0700187
Shawn O. Pearcee6a0eeb2011-03-22 19:04:47 -0700188 # If we got our own _FetchError, we don't want a stack trace.
189 # However, if we got something else (something in Sync_NetworkHalf?),
190 # we'd like one (so re-raise after we've set err_event).
191 if not isinstance(e, _FetchError):
192 raise
Doug Andersonfc06ced2011-03-16 15:49:18 -0700193 finally:
194 if did_lock:
195 lock.release()
196 sem.release()
Roy Lee18afd7f2010-05-09 04:32:08 +0800197
Shawn O. Pearce16614f82010-10-29 12:05:43 -0700198 def _Fetch(self, projects, opt):
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700199 fetched = set()
Shawn O. Pearce68194f42009-04-10 16:48:52 -0700200 pm = Progress('Fetching projects', len(projects))
Roy Lee18afd7f2010-05-09 04:32:08 +0800201
202 if self.jobs == 1:
203 for project in projects:
204 pm.update()
Shawn O. Pearce16614f82010-10-29 12:05:43 -0700205 if project.Sync_NetworkHalf(quiet=opt.quiet):
Roy Lee18afd7f2010-05-09 04:32:08 +0800206 fetched.add(project.gitdir)
207 else:
208 print >>sys.stderr, 'error: Cannot fetch %s' % project.name
Andrei Warkentin5df6de02010-07-02 17:58:31 -0500209 if opt.force_broken:
210 print >>sys.stderr, 'warn: --force-broken, continuing to sync'
211 else:
212 sys.exit(1)
Roy Lee18afd7f2010-05-09 04:32:08 +0800213 else:
214 threads = set()
215 lock = _threading.Lock()
216 sem = _threading.Semaphore(self.jobs)
Doug Andersonfc06ced2011-03-16 15:49:18 -0700217 err_event = _threading.Event()
Roy Lee18afd7f2010-05-09 04:32:08 +0800218 for project in projects:
Doug Andersonfc06ced2011-03-16 15:49:18 -0700219 # Check for any errors before starting any new threads.
220 # ...we'll let existing threads finish, though.
Daniel Sandler723c5dc2011-04-04 11:15:17 -0400221 if err_event.isSet():
Doug Andersonfc06ced2011-03-16 15:49:18 -0700222 break
223
Roy Lee18afd7f2010-05-09 04:32:08 +0800224 sem.acquire()
225 t = _threading.Thread(target = self._FetchHelper,
Shawn O. Pearce16614f82010-10-29 12:05:43 -0700226 args = (opt,
227 project,
228 lock,
229 fetched,
230 pm,
Doug Andersonfc06ced2011-03-16 15:49:18 -0700231 sem,
232 err_event))
Roy Lee18afd7f2010-05-09 04:32:08 +0800233 threads.add(t)
234 t.start()
235
236 for t in threads:
237 t.join()
238
Doug Andersonfc06ced2011-03-16 15:49:18 -0700239 # If we saw an error, exit with code 1 so that other scripts can check.
Daniel Sandler723c5dc2011-04-04 11:15:17 -0400240 if err_event.isSet():
Doug Andersonfc06ced2011-03-16 15:49:18 -0700241 print >>sys.stderr, '\nerror: Exited sync due to fetch errors'
242 sys.exit(1)
243
Shawn O. Pearce68194f42009-04-10 16:48:52 -0700244 pm.end()
Shawn O. Pearce0d2b61f2009-07-03 15:22:49 -0700245 for project in projects:
246 project.bare_git.gc('--auto')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700247 return fetched
248
Jaikumar Ganesh4f2517f2009-06-01 21:10:33 -0700249 def UpdateProjectList(self):
250 new_project_paths = []
251 for project in self.manifest.projects.values():
Shawn O. Pearce3a68bb42009-06-04 16:18:09 -0700252 if project.relpath:
253 new_project_paths.append(project.relpath)
Jaikumar Ganesh4f2517f2009-06-01 21:10:33 -0700254 file_name = 'project.list'
255 file_path = os.path.join(self.manifest.repodir, file_name)
256 old_project_paths = []
257
258 if os.path.exists(file_path):
259 fd = open(file_path, 'r')
260 try:
261 old_project_paths = fd.read().split('\n')
262 finally:
263 fd.close()
264 for path in old_project_paths:
Shawn O. Pearce3a68bb42009-06-04 16:18:09 -0700265 if not path:
266 continue
Jaikumar Ganesh4f2517f2009-06-01 21:10:33 -0700267 if path not in new_project_paths:
Anthonyf3fdf822009-09-26 13:38:52 -0400268 """If the path has already been deleted, we don't need to do it
269 """
270 if os.path.exists(self.manifest.topdir + '/' + path):
271 project = Project(
272 manifest = self.manifest,
273 name = path,
274 remote = RemoteSpec('origin'),
275 gitdir = os.path.join(self.manifest.topdir,
276 path, '.git'),
277 worktree = os.path.join(self.manifest.topdir, path),
278 relpath = path,
279 revisionExpr = 'HEAD',
280 revisionId = None)
281
282 if project.IsDirty():
283 print >>sys.stderr, 'error: Cannot remove project "%s": \
Jaikumar Ganesh4f2517f2009-06-01 21:10:33 -0700284uncommitted changes are present' % project.relpath
Anthonyf3fdf822009-09-26 13:38:52 -0400285 print >>sys.stderr, ' commit changes, then run sync again'
286 return -1
287 else:
288 print >>sys.stderr, 'Deleting obsolete path %s' % project.worktree
289 shutil.rmtree(project.worktree)
290 # Try deleting parent subdirs if they are empty
291 dir = os.path.dirname(project.worktree)
292 while dir != self.manifest.topdir:
293 try:
294 os.rmdir(dir)
295 except OSError:
296 break
297 dir = os.path.dirname(dir)
Jaikumar Ganesh4f2517f2009-06-01 21:10:33 -0700298
Shawn O. Pearce9fb29ce2009-06-04 20:41:02 -0700299 new_project_paths.sort()
Jaikumar Ganesh4f2517f2009-06-01 21:10:33 -0700300 fd = open(file_path, 'w')
301 try:
302 fd.write('\n'.join(new_project_paths))
Shawn O. Pearce3a68bb42009-06-04 16:18:09 -0700303 fd.write('\n')
Jaikumar Ganesh4f2517f2009-06-01 21:10:33 -0700304 finally:
305 fd.close()
306 return 0
307
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700308 def Execute(self, opt, args):
Roy Lee18afd7f2010-05-09 04:32:08 +0800309 if opt.jobs:
310 self.jobs = opt.jobs
Shawn O. Pearce3e768c92009-04-10 16:59:36 -0700311 if opt.network_only and opt.detach_head:
312 print >>sys.stderr, 'error: cannot combine -n and -d'
313 sys.exit(1)
Shawn O. Pearceb1562fa2009-04-10 17:04:08 -0700314 if opt.network_only and opt.local_only:
315 print >>sys.stderr, 'error: cannot combine -n and -l'
316 sys.exit(1)
Shawn O. Pearce3e768c92009-04-10 16:59:36 -0700317
Nico Sallembiena1bfd2c2010-04-06 10:40:01 -0700318 if opt.smart_sync:
319 if not self.manifest.manifest_server:
320 print >>sys.stderr, \
321 'error: cannot smart sync: no manifest server defined in manifest'
322 sys.exit(1)
323 try:
324 server = xmlrpclib.Server(self.manifest.manifest_server)
325 p = self.manifest.manifestProject
326 b = p.GetBranch(p.CurrentBranch)
327 branch = b.merge
Nico Sallembien5732e472010-04-26 11:17:29 -0700328 if branch.startswith(R_HEADS):
329 branch = branch[len(R_HEADS):]
Nico Sallembiena1bfd2c2010-04-06 10:40:01 -0700330
Shawn O. Pearcef18cb762010-12-07 11:41:05 -0800331 env = os.environ.copy()
Nico Sallembiena1bfd2c2010-04-06 10:40:01 -0700332 if (env.has_key('TARGET_PRODUCT') and
333 env.has_key('TARGET_BUILD_VARIANT')):
334 target = '%s-%s' % (env['TARGET_PRODUCT'],
335 env['TARGET_BUILD_VARIANT'])
336 [success, manifest_str] = server.GetApprovedManifest(branch, target)
337 else:
338 [success, manifest_str] = server.GetApprovedManifest(branch)
339
340 if success:
341 manifest_name = "smart_sync_override.xml"
342 manifest_path = os.path.join(self.manifest.manifestProject.worktree,
343 manifest_name)
344 try:
345 f = open(manifest_path, 'w')
346 try:
347 f.write(manifest_str)
Nico Sallembiena1bfd2c2010-04-06 10:40:01 -0700348 finally:
349 f.close()
350 except IOError:
351 print >>sys.stderr, 'error: cannot write manifest to %s' % \
352 manifest_path
353 sys.exit(1)
Nico Sallembien719965a2010-04-20 15:28:19 -0700354 self.manifest.Override(manifest_name)
Nico Sallembiena1bfd2c2010-04-06 10:40:01 -0700355 else:
356 print >>sys.stderr, 'error: %s' % manifest_str
357 sys.exit(1)
358 except socket.error:
359 print >>sys.stderr, 'error: cannot connect to manifest server %s' % (
360 self.manifest.manifest_server)
361 sys.exit(1)
362
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700363 rp = self.manifest.repoProject
364 rp.PreSync()
365
366 mp = self.manifest.manifestProject
367 mp.PreSync()
368
Shawn O. Pearcec9ef7442008-11-03 10:32:09 -0800369 if opt.repo_upgraded:
Shawn O. Pearcee756c412009-04-13 11:51:15 -0700370 _PostRepoUpgrade(self.manifest)
Shawn O. Pearcec9ef7442008-11-03 10:32:09 -0800371
Nico Sallembien9bb18162009-12-07 15:38:01 -0800372 if not opt.local_only:
Shawn O. Pearce16614f82010-10-29 12:05:43 -0700373 mp.Sync_NetworkHalf(quiet=opt.quiet)
Nico Sallembien9bb18162009-12-07 15:38:01 -0800374
375 if mp.HasChanges:
376 syncbuf = SyncBuffer(mp.config)
377 mp.Sync_LocalHalf(syncbuf)
378 if not syncbuf.Finish():
379 sys.exit(1)
380 self.manifest._Unload()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700381 all = self.GetProjects(args, missing_ok=True)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700382
Shawn O. Pearceb1562fa2009-04-10 17:04:08 -0700383 if not opt.local_only:
Shawn O. Pearcef6906872009-04-18 10:49:00 -0700384 to_fetch = []
385 now = time.time()
386 if (24 * 60 * 60) <= (now - rp.LastFetch):
387 to_fetch.append(rp)
Shawn O. Pearcef6906872009-04-18 10:49:00 -0700388 to_fetch.extend(all)
389
Shawn O. Pearce16614f82010-10-29 12:05:43 -0700390 fetched = self._Fetch(to_fetch, opt)
Shawn O. Pearcee756c412009-04-13 11:51:15 -0700391 _PostRepoFetch(rp, opt.no_repo_verify)
Shawn O. Pearceb1562fa2009-04-10 17:04:08 -0700392 if opt.network_only:
393 # bail out now; the rest touches the working tree
394 return
395
Shawn O. Pearceb1562fa2009-04-10 17:04:08 -0700396 self.manifest._Unload()
397 all = self.GetProjects(args, missing_ok=True)
398 missing = []
399 for project in all:
400 if project.gitdir not in fetched:
401 missing.append(project)
Shawn O. Pearce16614f82010-10-29 12:05:43 -0700402 self._Fetch(missing, opt)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700403
Shawn O. Pearcecd1d7ff2009-06-04 16:15:53 -0700404 if self.manifest.IsMirror:
405 # bail out now, we have no working tree
406 return
407
Jaikumar Ganesh4f2517f2009-06-01 21:10:33 -0700408 if self.UpdateProjectList():
409 sys.exit(1)
410
Shawn O. Pearce350cde42009-04-16 11:21:18 -0700411 syncbuf = SyncBuffer(mp.config,
412 detach_head = opt.detach_head)
Shawn O. Pearce68194f42009-04-10 16:48:52 -0700413 pm = Progress('Syncing work tree', len(all))
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700414 for project in all:
Shawn O. Pearce68194f42009-04-10 16:48:52 -0700415 pm.update()
Shawn O. Pearcee284ad12008-11-04 07:37:10 -0800416 if project.worktree:
Shawn O. Pearce350cde42009-04-16 11:21:18 -0700417 project.Sync_LocalHalf(syncbuf)
Shawn O. Pearce68194f42009-04-10 16:48:52 -0700418 pm.end()
Shawn O. Pearce350cde42009-04-16 11:21:18 -0700419 print >>sys.stderr
420 if not syncbuf.Finish():
421 sys.exit(1)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700422
Doug Anderson2b8db3c2010-11-01 15:08:06 -0700423 # If there's a notice that's supposed to print at the end of the sync, print
424 # it now...
425 if self.manifest.notice:
426 print self.manifest.notice
427
Shawn O. Pearcee756c412009-04-13 11:51:15 -0700428def _PostRepoUpgrade(manifest):
429 for project in manifest.projects.values():
430 if project.Exists:
431 project.PostRepoUpgrade()
432
433def _PostRepoFetch(rp, no_repo_verify=False, verbose=False):
434 if rp.HasChanges:
435 print >>sys.stderr, 'info: A new version of repo is available'
436 print >>sys.stderr, ''
437 if no_repo_verify or _VerifyTag(rp):
Shawn O. Pearce350cde42009-04-16 11:21:18 -0700438 syncbuf = SyncBuffer(rp.config)
439 rp.Sync_LocalHalf(syncbuf)
440 if not syncbuf.Finish():
Shawn O. Pearcee756c412009-04-13 11:51:15 -0700441 sys.exit(1)
442 print >>sys.stderr, 'info: Restarting repo with latest version'
443 raise RepoChangedException(['--repo-upgraded'])
444 else:
445 print >>sys.stderr, 'warning: Skipped upgrade to unverified version'
446 else:
447 if verbose:
448 print >>sys.stderr, 'repo version %s is current' % rp.work_git.describe(HEAD)
449
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700450def _VerifyTag(project):
451 gpg_dir = os.path.expanduser('~/.repoconfig/gnupg')
452 if not os.path.exists(gpg_dir):
453 print >>sys.stderr,\
454"""warning: GnuPG was not available during last "repo init"
455warning: Cannot automatically authenticate repo."""
456 return True
457
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700458 try:
Shawn O. Pearce3c8dea12009-05-29 18:38:17 -0700459 cur = project.bare_git.describe(project.GetRevisionId())
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700460 except GitError:
461 cur = None
462
463 if not cur \
464 or re.compile(r'^.*-[0-9]{1,}-g[0-9a-f]{1,}$').match(cur):
Shawn O. Pearce3c8dea12009-05-29 18:38:17 -0700465 rev = project.revisionExpr
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700466 if rev.startswith(R_HEADS):
467 rev = rev[len(R_HEADS):]
468
469 print >>sys.stderr
470 print >>sys.stderr,\
471 "warning: project '%s' branch '%s' is not signed" \
472 % (project.name, rev)
473 return False
474
Shawn O. Pearcef18cb762010-12-07 11:41:05 -0800475 env = os.environ.copy()
476 env['GIT_DIR'] = project.gitdir.encode()
477 env['GNUPGHOME'] = gpg_dir.encode()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700478
479 cmd = [GIT, 'tag', '-v', cur]
480 proc = subprocess.Popen(cmd,
481 stdout = subprocess.PIPE,
482 stderr = subprocess.PIPE,
483 env = env)
484 out = proc.stdout.read()
485 proc.stdout.close()
486
487 err = proc.stderr.read()
488 proc.stderr.close()
489
490 if proc.wait() != 0:
491 print >>sys.stderr
492 print >>sys.stderr, out
493 print >>sys.stderr, err
494 print >>sys.stderr
495 return False
496 return True