blob: 3eb44edf96832782cfc33bfa86a85505f72f3ee7 [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
16import os
17import re
18import subprocess
19import sys
20
21from git_command import GIT
22from command import Command
23from error import RepoChangedException, GitError
24from project import R_HEADS
25
26class Sync(Command):
27 common = True
28 helpSummary = "Update working tree to the latest revision"
29 helpUsage = """
30%prog [<project>...]
31"""
32 helpDescription = """
33The '%prog' command synchronizes local project directories
34with the remote repositories specified in the manifest. If a local
35project does not yet exist, it will clone a new local directory from
36the remote repository and set up tracking branches as specified in
37the manifest. If the local project already exists, '%prog'
38will update the remote branches and rebase any new local changes
39on top of the new remote changes.
40
41'%prog' will synchronize all projects listed at the command
42line. Projects can be specified either by name, or by a relative
43or absolute path to the project's local directory. If no projects
44are specified, '%prog' will synchronize all projects listed in
45the manifest.
46"""
47
48 def _Options(self, p):
49 p.add_option('--no-repo-verify',
50 dest='no_repo_verify', action='store_true',
51 help='do not verify repo source code')
52
53 def _Fetch(self, *projects):
54 fetched = set()
55 for project in projects:
56 if project.Sync_NetworkHalf():
57 fetched.add(project.gitdir)
58 else:
59 print >>sys.stderr, 'error: Cannot fetch %s' % project.name
60 sys.exit(1)
61 return fetched
62
63 def Execute(self, opt, args):
64 rp = self.manifest.repoProject
65 rp.PreSync()
66
67 mp = self.manifest.manifestProject
68 mp.PreSync()
69
70 all = self.GetProjects(args, missing_ok=True)
71 fetched = self._Fetch(rp, mp, *all)
72
73 if rp.HasChanges:
74 print >>sys.stderr, 'info: A new version of repo is available'
75 print >>sys.stderr, ''
76 if opt.no_repo_verify or _VerifyTag(rp):
77 if not rp.Sync_LocalHalf():
78 sys.exit(1)
79 print >>sys.stderr, 'info: Restarting repo with latest version'
80 raise RepoChangedException()
81 else:
82 print >>sys.stderr, 'warning: Skipped upgrade to unverified version'
83
84 if mp.HasChanges:
85 if not mp.Sync_LocalHalf():
86 sys.exit(1)
87
88 self.manifest._Unload()
89 all = self.GetProjects(args, missing_ok=True)
90 missing = []
91 for project in all:
92 if project.gitdir not in fetched:
93 missing.append(project)
94 self._Fetch(*missing)
95
96 for project in all:
97 if not project.Sync_LocalHalf():
98 sys.exit(1)
99
100
101def _VerifyTag(project):
102 gpg_dir = os.path.expanduser('~/.repoconfig/gnupg')
103 if not os.path.exists(gpg_dir):
104 print >>sys.stderr,\
105"""warning: GnuPG was not available during last "repo init"
106warning: Cannot automatically authenticate repo."""
107 return True
108
109 remote = project.GetRemote(project.remote.name)
110 ref = remote.ToLocal(project.revision)
111
112 try:
113 cur = project.bare_git.describe(ref)
114 except GitError:
115 cur = None
116
117 if not cur \
118 or re.compile(r'^.*-[0-9]{1,}-g[0-9a-f]{1,}$').match(cur):
119 rev = project.revision
120 if rev.startswith(R_HEADS):
121 rev = rev[len(R_HEADS):]
122
123 print >>sys.stderr
124 print >>sys.stderr,\
125 "warning: project '%s' branch '%s' is not signed" \
126 % (project.name, rev)
127 return False
128
129 env = dict(os.environ)
130 env['GIT_DIR'] = project.gitdir
131 env['GNUPGHOME'] = gpg_dir
132
133 cmd = [GIT, 'tag', '-v', cur]
134 proc = subprocess.Popen(cmd,
135 stdout = subprocess.PIPE,
136 stderr = subprocess.PIPE,
137 env = env)
138 out = proc.stdout.read()
139 proc.stdout.close()
140
141 err = proc.stderr.read()
142 proc.stderr.close()
143
144 if proc.wait() != 0:
145 print >>sys.stderr
146 print >>sys.stderr, out
147 print >>sys.stderr, err
148 print >>sys.stderr
149 return False
150 return True