blob: eac0556da374cfc1f6649fc4662a486009387658 [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:
167 success = project.Sync_NetworkHalf(quiet=opt.quiet)
168
169 # Lock around all the rest of the code, since printing, updating a set
170 # and Progress.update() are not thread safe.
171 lock.acquire()
172 did_lock = True
173
174 if not success:
175 print >>sys.stderr, 'error: Cannot fetch %s' % project.name
176 if opt.force_broken:
177 print >>sys.stderr, 'warn: --force-broken, continuing to sync'
178 else:
179 raise _FetchError()
180
181 fetched.add(project.gitdir)
182 pm.update()
183 except BaseException, e:
184 # Notify the _Fetch() function about all errors.
185 err_event.set()
186
187 # If we got our own _FetchError, we don't want a stack trace.
188 # However, if we got something else (something in Sync_NetworkHalf?),
189 # we'd like one (so re-raise after we've set err_event).
190 if not isinstance(e, _FetchError):
191 raise
192 finally:
193 if did_lock:
194 lock.release()
195 sem.release()
Roy Lee18afd7f2010-05-09 04:32:08 +0800196
Shawn O. Pearce16614f82010-10-29 12:05:43 -0700197 def _Fetch(self, projects, opt):
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700198 fetched = set()
Shawn O. Pearce68194f42009-04-10 16:48:52 -0700199 pm = Progress('Fetching projects', len(projects))
Roy Lee18afd7f2010-05-09 04:32:08 +0800200
201 if self.jobs == 1:
202 for project in projects:
203 pm.update()
Shawn O. Pearce16614f82010-10-29 12:05:43 -0700204 if project.Sync_NetworkHalf(quiet=opt.quiet):
Roy Lee18afd7f2010-05-09 04:32:08 +0800205 fetched.add(project.gitdir)
206 else:
207 print >>sys.stderr, 'error: Cannot fetch %s' % project.name
Andrei Warkentin5df6de02010-07-02 17:58:31 -0500208 if opt.force_broken:
209 print >>sys.stderr, 'warn: --force-broken, continuing to sync'
210 else:
211 sys.exit(1)
Roy Lee18afd7f2010-05-09 04:32:08 +0800212 else:
213 threads = set()
214 lock = _threading.Lock()
215 sem = _threading.Semaphore(self.jobs)
Doug Andersonfc06ced2011-03-16 15:49:18 -0700216 err_event = _threading.Event()
Roy Lee18afd7f2010-05-09 04:32:08 +0800217 for project in projects:
Doug Andersonfc06ced2011-03-16 15:49:18 -0700218 # Check for any errors before starting any new threads.
219 # ...we'll let existing threads finish, though.
220 if err_event.is_set():
221 break
222
Roy Lee18afd7f2010-05-09 04:32:08 +0800223 sem.acquire()
224 t = _threading.Thread(target = self._FetchHelper,
Shawn O. Pearce16614f82010-10-29 12:05:43 -0700225 args = (opt,
226 project,
227 lock,
228 fetched,
229 pm,
Doug Andersonfc06ced2011-03-16 15:49:18 -0700230 sem,
231 err_event))
Roy Lee18afd7f2010-05-09 04:32:08 +0800232 threads.add(t)
233 t.start()
234
235 for t in threads:
236 t.join()
237
Doug Andersonfc06ced2011-03-16 15:49:18 -0700238 # If we saw an error, exit with code 1 so that other scripts can check.
239 if err_event.is_set():
240 print >>sys.stderr, '\nerror: Exited sync due to fetch errors'
241 sys.exit(1)
242
Shawn O. Pearce68194f42009-04-10 16:48:52 -0700243 pm.end()
Shawn O. Pearce0d2b61f2009-07-03 15:22:49 -0700244 for project in projects:
245 project.bare_git.gc('--auto')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700246 return fetched
247
Jaikumar Ganesh4f2517f2009-06-01 21:10:33 -0700248 def UpdateProjectList(self):
249 new_project_paths = []
250 for project in self.manifest.projects.values():
Shawn O. Pearce3a68bb42009-06-04 16:18:09 -0700251 if project.relpath:
252 new_project_paths.append(project.relpath)
Jaikumar Ganesh4f2517f2009-06-01 21:10:33 -0700253 file_name = 'project.list'
254 file_path = os.path.join(self.manifest.repodir, file_name)
255 old_project_paths = []
256
257 if os.path.exists(file_path):
258 fd = open(file_path, 'r')
259 try:
260 old_project_paths = fd.read().split('\n')
261 finally:
262 fd.close()
263 for path in old_project_paths:
Shawn O. Pearce3a68bb42009-06-04 16:18:09 -0700264 if not path:
265 continue
Jaikumar Ganesh4f2517f2009-06-01 21:10:33 -0700266 if path not in new_project_paths:
Anthonyf3fdf822009-09-26 13:38:52 -0400267 """If the path has already been deleted, we don't need to do it
268 """
269 if os.path.exists(self.manifest.topdir + '/' + path):
270 project = Project(
271 manifest = self.manifest,
272 name = path,
273 remote = RemoteSpec('origin'),
274 gitdir = os.path.join(self.manifest.topdir,
275 path, '.git'),
276 worktree = os.path.join(self.manifest.topdir, path),
277 relpath = path,
278 revisionExpr = 'HEAD',
279 revisionId = None)
280
281 if project.IsDirty():
282 print >>sys.stderr, 'error: Cannot remove project "%s": \
Jaikumar Ganesh4f2517f2009-06-01 21:10:33 -0700283uncommitted changes are present' % project.relpath
Anthonyf3fdf822009-09-26 13:38:52 -0400284 print >>sys.stderr, ' commit changes, then run sync again'
285 return -1
286 else:
287 print >>sys.stderr, 'Deleting obsolete path %s' % project.worktree
288 shutil.rmtree(project.worktree)
289 # Try deleting parent subdirs if they are empty
290 dir = os.path.dirname(project.worktree)
291 while dir != self.manifest.topdir:
292 try:
293 os.rmdir(dir)
294 except OSError:
295 break
296 dir = os.path.dirname(dir)
Jaikumar Ganesh4f2517f2009-06-01 21:10:33 -0700297
Shawn O. Pearce9fb29ce2009-06-04 20:41:02 -0700298 new_project_paths.sort()
Jaikumar Ganesh4f2517f2009-06-01 21:10:33 -0700299 fd = open(file_path, 'w')
300 try:
301 fd.write('\n'.join(new_project_paths))
Shawn O. Pearce3a68bb42009-06-04 16:18:09 -0700302 fd.write('\n')
Jaikumar Ganesh4f2517f2009-06-01 21:10:33 -0700303 finally:
304 fd.close()
305 return 0
306
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700307 def Execute(self, opt, args):
Roy Lee18afd7f2010-05-09 04:32:08 +0800308 if opt.jobs:
309 self.jobs = opt.jobs
Shawn O. Pearce3e768c92009-04-10 16:59:36 -0700310 if opt.network_only and opt.detach_head:
311 print >>sys.stderr, 'error: cannot combine -n and -d'
312 sys.exit(1)
Shawn O. Pearceb1562fa2009-04-10 17:04:08 -0700313 if opt.network_only and opt.local_only:
314 print >>sys.stderr, 'error: cannot combine -n and -l'
315 sys.exit(1)
Shawn O. Pearce3e768c92009-04-10 16:59:36 -0700316
Nico Sallembiena1bfd2c2010-04-06 10:40:01 -0700317 if opt.smart_sync:
318 if not self.manifest.manifest_server:
319 print >>sys.stderr, \
320 'error: cannot smart sync: no manifest server defined in manifest'
321 sys.exit(1)
322 try:
323 server = xmlrpclib.Server(self.manifest.manifest_server)
324 p = self.manifest.manifestProject
325 b = p.GetBranch(p.CurrentBranch)
326 branch = b.merge
Nico Sallembien5732e472010-04-26 11:17:29 -0700327 if branch.startswith(R_HEADS):
328 branch = branch[len(R_HEADS):]
Nico Sallembiena1bfd2c2010-04-06 10:40:01 -0700329
Shawn O. Pearcef18cb762010-12-07 11:41:05 -0800330 env = os.environ.copy()
Nico Sallembiena1bfd2c2010-04-06 10:40:01 -0700331 if (env.has_key('TARGET_PRODUCT') and
332 env.has_key('TARGET_BUILD_VARIANT')):
333 target = '%s-%s' % (env['TARGET_PRODUCT'],
334 env['TARGET_BUILD_VARIANT'])
335 [success, manifest_str] = server.GetApprovedManifest(branch, target)
336 else:
337 [success, manifest_str] = server.GetApprovedManifest(branch)
338
339 if success:
340 manifest_name = "smart_sync_override.xml"
341 manifest_path = os.path.join(self.manifest.manifestProject.worktree,
342 manifest_name)
343 try:
344 f = open(manifest_path, 'w')
345 try:
346 f.write(manifest_str)
Nico Sallembiena1bfd2c2010-04-06 10:40:01 -0700347 finally:
348 f.close()
349 except IOError:
350 print >>sys.stderr, 'error: cannot write manifest to %s' % \
351 manifest_path
352 sys.exit(1)
Nico Sallembien719965a2010-04-20 15:28:19 -0700353 self.manifest.Override(manifest_name)
Nico Sallembiena1bfd2c2010-04-06 10:40:01 -0700354 else:
355 print >>sys.stderr, 'error: %s' % manifest_str
356 sys.exit(1)
357 except socket.error:
358 print >>sys.stderr, 'error: cannot connect to manifest server %s' % (
359 self.manifest.manifest_server)
360 sys.exit(1)
361
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700362 rp = self.manifest.repoProject
363 rp.PreSync()
364
365 mp = self.manifest.manifestProject
366 mp.PreSync()
367
Shawn O. Pearcec9ef7442008-11-03 10:32:09 -0800368 if opt.repo_upgraded:
Shawn O. Pearcee756c412009-04-13 11:51:15 -0700369 _PostRepoUpgrade(self.manifest)
Shawn O. Pearcec9ef7442008-11-03 10:32:09 -0800370
Nico Sallembien9bb18162009-12-07 15:38:01 -0800371 if not opt.local_only:
Shawn O. Pearce16614f82010-10-29 12:05:43 -0700372 mp.Sync_NetworkHalf(quiet=opt.quiet)
Nico Sallembien9bb18162009-12-07 15:38:01 -0800373
374 if mp.HasChanges:
375 syncbuf = SyncBuffer(mp.config)
376 mp.Sync_LocalHalf(syncbuf)
377 if not syncbuf.Finish():
378 sys.exit(1)
379 self.manifest._Unload()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700380 all = self.GetProjects(args, missing_ok=True)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700381
Shawn O. Pearceb1562fa2009-04-10 17:04:08 -0700382 if not opt.local_only:
Shawn O. Pearcef6906872009-04-18 10:49:00 -0700383 to_fetch = []
384 now = time.time()
385 if (24 * 60 * 60) <= (now - rp.LastFetch):
386 to_fetch.append(rp)
Shawn O. Pearcef6906872009-04-18 10:49:00 -0700387 to_fetch.extend(all)
388
Shawn O. Pearce16614f82010-10-29 12:05:43 -0700389 fetched = self._Fetch(to_fetch, opt)
Shawn O. Pearcee756c412009-04-13 11:51:15 -0700390 _PostRepoFetch(rp, opt.no_repo_verify)
Shawn O. Pearceb1562fa2009-04-10 17:04:08 -0700391 if opt.network_only:
392 # bail out now; the rest touches the working tree
393 return
394
Shawn O. Pearceb1562fa2009-04-10 17:04:08 -0700395 self.manifest._Unload()
396 all = self.GetProjects(args, missing_ok=True)
397 missing = []
398 for project in all:
399 if project.gitdir not in fetched:
400 missing.append(project)
Shawn O. Pearce16614f82010-10-29 12:05:43 -0700401 self._Fetch(missing, opt)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700402
Shawn O. Pearcecd1d7ff2009-06-04 16:15:53 -0700403 if self.manifest.IsMirror:
404 # bail out now, we have no working tree
405 return
406
Jaikumar Ganesh4f2517f2009-06-01 21:10:33 -0700407 if self.UpdateProjectList():
408 sys.exit(1)
409
Shawn O. Pearce350cde42009-04-16 11:21:18 -0700410 syncbuf = SyncBuffer(mp.config,
411 detach_head = opt.detach_head)
Shawn O. Pearce68194f42009-04-10 16:48:52 -0700412 pm = Progress('Syncing work tree', len(all))
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700413 for project in all:
Shawn O. Pearce68194f42009-04-10 16:48:52 -0700414 pm.update()
Shawn O. Pearcee284ad12008-11-04 07:37:10 -0800415 if project.worktree:
Shawn O. Pearce350cde42009-04-16 11:21:18 -0700416 project.Sync_LocalHalf(syncbuf)
Shawn O. Pearce68194f42009-04-10 16:48:52 -0700417 pm.end()
Shawn O. Pearce350cde42009-04-16 11:21:18 -0700418 print >>sys.stderr
419 if not syncbuf.Finish():
420 sys.exit(1)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700421
Doug Anderson2b8db3c2010-11-01 15:08:06 -0700422 # If there's a notice that's supposed to print at the end of the sync, print
423 # it now...
424 if self.manifest.notice:
425 print self.manifest.notice
426
Shawn O. Pearcee756c412009-04-13 11:51:15 -0700427def _PostRepoUpgrade(manifest):
428 for project in manifest.projects.values():
429 if project.Exists:
430 project.PostRepoUpgrade()
431
432def _PostRepoFetch(rp, no_repo_verify=False, verbose=False):
433 if rp.HasChanges:
434 print >>sys.stderr, 'info: A new version of repo is available'
435 print >>sys.stderr, ''
436 if no_repo_verify or _VerifyTag(rp):
Shawn O. Pearce350cde42009-04-16 11:21:18 -0700437 syncbuf = SyncBuffer(rp.config)
438 rp.Sync_LocalHalf(syncbuf)
439 if not syncbuf.Finish():
Shawn O. Pearcee756c412009-04-13 11:51:15 -0700440 sys.exit(1)
441 print >>sys.stderr, 'info: Restarting repo with latest version'
442 raise RepoChangedException(['--repo-upgraded'])
443 else:
444 print >>sys.stderr, 'warning: Skipped upgrade to unverified version'
445 else:
446 if verbose:
447 print >>sys.stderr, 'repo version %s is current' % rp.work_git.describe(HEAD)
448
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700449def _VerifyTag(project):
450 gpg_dir = os.path.expanduser('~/.repoconfig/gnupg')
451 if not os.path.exists(gpg_dir):
452 print >>sys.stderr,\
453"""warning: GnuPG was not available during last "repo init"
454warning: Cannot automatically authenticate repo."""
455 return True
456
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700457 try:
Shawn O. Pearce3c8dea12009-05-29 18:38:17 -0700458 cur = project.bare_git.describe(project.GetRevisionId())
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700459 except GitError:
460 cur = None
461
462 if not cur \
463 or re.compile(r'^.*-[0-9]{1,}-g[0-9a-f]{1,}$').match(cur):
Shawn O. Pearce3c8dea12009-05-29 18:38:17 -0700464 rev = project.revisionExpr
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700465 if rev.startswith(R_HEADS):
466 rev = rev[len(R_HEADS):]
467
468 print >>sys.stderr
469 print >>sys.stderr,\
470 "warning: project '%s' branch '%s' is not signed" \
471 % (project.name, rev)
472 return False
473
Shawn O. Pearcef18cb762010-12-07 11:41:05 -0800474 env = os.environ.copy()
475 env['GIT_DIR'] = project.gitdir.encode()
476 env['GNUPGHOME'] = gpg_dir.encode()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700477
478 cmd = [GIT, 'tag', '-v', cur]
479 proc = subprocess.Popen(cmd,
480 stdout = subprocess.PIPE,
481 stderr = subprocess.PIPE,
482 env = env)
483 out = proc.stdout.read()
484 proc.stdout.close()
485
486 err = proc.stderr.read()
487 proc.stderr.close()
488
489 if proc.wait() != 0:
490 print >>sys.stderr
491 print >>sys.stderr, out
492 print >>sys.stderr, err
493 print >>sys.stderr
494 return False
495 return True