blob: 8050e515df561552ef25c2c729a54370dfeebd7a [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')
Shawn O. Pearcec9ef7442008-11-03 10:32:09 -080052 p.add_option('--repo-upgraded',
53 dest='repo_upgraded', action='store_true',
54 help='perform additional actions after a repo upgrade')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070055
56 def _Fetch(self, *projects):
57 fetched = set()
58 for project in projects:
59 if project.Sync_NetworkHalf():
60 fetched.add(project.gitdir)
61 else:
62 print >>sys.stderr, 'error: Cannot fetch %s' % project.name
63 sys.exit(1)
64 return fetched
65
66 def Execute(self, opt, args):
67 rp = self.manifest.repoProject
68 rp.PreSync()
69
70 mp = self.manifest.manifestProject
71 mp.PreSync()
72
Shawn O. Pearcec9ef7442008-11-03 10:32:09 -080073 if opt.repo_upgraded:
74 for project in self.manifest.projects.values():
75 if project.Exists:
76 project.PostRepoUpgrade()
77
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070078 all = self.GetProjects(args, missing_ok=True)
79 fetched = self._Fetch(rp, mp, *all)
80
81 if rp.HasChanges:
82 print >>sys.stderr, 'info: A new version of repo is available'
83 print >>sys.stderr, ''
84 if opt.no_repo_verify or _VerifyTag(rp):
85 if not rp.Sync_LocalHalf():
86 sys.exit(1)
87 print >>sys.stderr, 'info: Restarting repo with latest version'
Shawn O. Pearcec9ef7442008-11-03 10:32:09 -080088 raise RepoChangedException(['--repo-upgraded'])
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070089 else:
90 print >>sys.stderr, 'warning: Skipped upgrade to unverified version'
91
92 if mp.HasChanges:
93 if not mp.Sync_LocalHalf():
94 sys.exit(1)
95
96 self.manifest._Unload()
97 all = self.GetProjects(args, missing_ok=True)
98 missing = []
99 for project in all:
100 if project.gitdir not in fetched:
101 missing.append(project)
102 self._Fetch(*missing)
103
104 for project in all:
Shawn O. Pearcee284ad12008-11-04 07:37:10 -0800105 if project.worktree:
106 if not project.Sync_LocalHalf():
107 sys.exit(1)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700108
109
110def _VerifyTag(project):
111 gpg_dir = os.path.expanduser('~/.repoconfig/gnupg')
112 if not os.path.exists(gpg_dir):
113 print >>sys.stderr,\
114"""warning: GnuPG was not available during last "repo init"
115warning: Cannot automatically authenticate repo."""
116 return True
117
118 remote = project.GetRemote(project.remote.name)
119 ref = remote.ToLocal(project.revision)
120
121 try:
122 cur = project.bare_git.describe(ref)
123 except GitError:
124 cur = None
125
126 if not cur \
127 or re.compile(r'^.*-[0-9]{1,}-g[0-9a-f]{1,}$').match(cur):
128 rev = project.revision
129 if rev.startswith(R_HEADS):
130 rev = rev[len(R_HEADS):]
131
132 print >>sys.stderr
133 print >>sys.stderr,\
134 "warning: project '%s' branch '%s' is not signed" \
135 % (project.name, rev)
136 return False
137
138 env = dict(os.environ)
139 env['GIT_DIR'] = project.gitdir
140 env['GNUPGHOME'] = gpg_dir
141
142 cmd = [GIT, 'tag', '-v', cur]
143 proc = subprocess.Popen(cmd,
144 stdout = subprocess.PIPE,
145 stderr = subprocess.PIPE,
146 env = env)
147 out = proc.stdout.read()
148 proc.stdout.close()
149
150 err = proc.stderr.read()
151 proc.stderr.close()
152
153 if proc.wait() != 0:
154 print >>sys.stderr
155 print >>sys.stderr, out
156 print >>sys.stderr, err
157 print >>sys.stderr
158 return False
159 return True