summaryrefslogtreecommitdiffstats
path: root/git_superproject.py
diff options
context:
space:
mode:
Diffstat (limited to 'git_superproject.py')
-rw-r--r--git_superproject.py100
1 files changed, 85 insertions, 15 deletions
diff --git a/git_superproject.py b/git_superproject.py
index e2045cfd..465d1f87 100644
--- a/git_superproject.py
+++ b/git_superproject.py
@@ -25,8 +25,9 @@ Examples:
25import os 25import os
26import sys 26import sys
27 27
28from error import GitError 28from error import BUG_REPORT_URL, GitError
29from git_command import GitCommand 29from git_command import GitCommand
30import platform_utils
30 31
31 32
32class Superproject(object): 33class Superproject(object):
@@ -46,6 +47,9 @@ class Superproject(object):
46 self._repodir = os.path.abspath(repodir) 47 self._repodir = os.path.abspath(repodir)
47 self._superproject_dir = superproject_dir 48 self._superproject_dir = superproject_dir
48 self._superproject_path = os.path.join(self._repodir, superproject_dir) 49 self._superproject_path = os.path.join(self._repodir, superproject_dir)
50 self._manifest_path = os.path.join(self._superproject_path,
51 'superproject_override.xml')
52 self._work_git = os.path.join(self._superproject_path, 'superproject')
49 53
50 @property 54 @property
51 def project_shas(self): 55 def project_shas(self):
@@ -57,7 +61,7 @@ class Superproject(object):
57 61
58 Args: 62 Args:
59 url: superproject's url to be passed to git clone. 63 url: superproject's url to be passed to git clone.
60 branch: the branchname to be passed as argument to git clone. 64 branch: The branchname to be passed as argument to git clone.
61 65
62 Returns: 66 Returns:
63 True if 'git clone <url> <branch>' is successful, or False. 67 True if 'git clone <url> <branch>' is successful, or False.
@@ -86,13 +90,12 @@ class Superproject(object):
86 Returns: 90 Returns:
87 True if 'git pull <branch>' is successful, or False. 91 True if 'git pull <branch>' is successful, or False.
88 """ 92 """
89 git_dir = os.path.join(self._superproject_path, 'superproject') 93 if not os.path.exists(self._work_git):
90 if not os.path.exists(git_dir): 94 raise GitError('git pull missing drectory: %s' % self._work_git)
91 raise GitError('git pull. Missing drectory: %s' % git_dir)
92 cmd = ['pull'] 95 cmd = ['pull']
93 p = GitCommand(None, 96 p = GitCommand(None,
94 cmd, 97 cmd,
95 cwd=git_dir, 98 cwd=self._work_git,
96 capture_stdout=True, 99 capture_stdout=True,
97 capture_stderr=True) 100 capture_stderr=True)
98 retval = p.Wait() 101 retval = p.Wait()
@@ -110,14 +113,13 @@ class Superproject(object):
110 Returns: 113 Returns:
111 data: data returned from 'git ls-tree -r HEAD' instead of None. 114 data: data returned from 'git ls-tree -r HEAD' instead of None.
112 """ 115 """
113 git_dir = os.path.join(self._superproject_path, 'superproject') 116 if not os.path.exists(self._work_git):
114 if not os.path.exists(git_dir): 117 raise GitError('git ls-tree. Missing drectory: %s' % self._work_git)
115 raise GitError('git ls-tree. Missing drectory: %s' % git_dir)
116 data = None 118 data = None
117 cmd = ['ls-tree', '-z', '-r', 'HEAD'] 119 cmd = ['ls-tree', '-z', '-r', 'HEAD']
118 p = GitCommand(None, 120 p = GitCommand(None,
119 cmd, 121 cmd,
120 cwd=git_dir, 122 cwd=self._work_git,
121 capture_stdout=True, 123 capture_stdout=True,
122 capture_stderr=True) 124 capture_stderr=True)
123 retval = p.Wait() 125 retval = p.Wait()
@@ -130,22 +132,26 @@ class Superproject(object):
130 retval, p.stderr), file=sys.stderr) 132 retval, p.stderr), file=sys.stderr)
131 return data 133 return data
132 134
133 def GetAllProjectsSHAs(self, url, branch=None): 135 def _GetAllProjectsSHAs(self, url, branch=None):
134 """Get SHAs for all projects from superproject and save them in _project_shas. 136 """Get SHAs for all projects from superproject and save them in _project_shas.
135 137
136 Args: 138 Args:
137 url: superproject's url to be passed to git clone. 139 url: superproject's url to be passed to git clone or pull.
138 branch: the branchname to be passed as argument to git clone. 140 branch: The branchname to be passed as argument to git clone or pull.
139 141
140 Returns: 142 Returns:
141 A dictionary with the projects/SHAs instead of None. 143 A dictionary with the projects/SHAs instead of None.
142 """ 144 """
143 if not url: 145 if not url:
144 raise ValueError('url argument is not supplied.') 146 raise ValueError('url argument is not supplied.')
147 do_clone = True
145 if os.path.exists(self._superproject_path): 148 if os.path.exists(self._superproject_path):
146 if not self._Pull(): 149 if not self._Pull():
147 raise GitError('git pull failed for url: %s' % url) 150 # If pull fails due to a corrupted git directory, then do a git clone.
148 else: 151 platform_utils.rmtree(self._superproject_path)
152 else:
153 do_clone = False
154 if do_clone:
149 if not self._Clone(url, branch): 155 if not self._Clone(url, branch):
150 raise GitError('git clone failed for url: %s' % url) 156 raise GitError('git clone failed for url: %s' % url)
151 157
@@ -168,3 +174,67 @@ class Superproject(object):
168 174
169 self._project_shas = shas 175 self._project_shas = shas
170 return shas 176 return shas
177
178 def _WriteManfiestFile(self, manifest):
179 """Writes manifest to a file.
180
181 Args:
182 manifest: A Manifest object that is to be written to a file.
183
184 Returns:
185 manifest_path: Path name of the file into which manifest is written instead of None.
186 """
187 if not os.path.exists(self._superproject_path):
188 print('error: missing superproject directory %s' %
189 self._superproject_path,
190 file=sys.stderr)
191 return None
192 manifest_str = manifest.ToXml().toxml()
193 manifest_path = self._manifest_path
194 try:
195 with open(manifest_path, 'w', encoding='utf-8') as fp:
196 fp.write(manifest_str)
197 except IOError as e:
198 print('error: cannot write manifest to %s:\n%s'
199 % (manifest_path, e),
200 file=sys.stderr)
201 return None
202 return manifest_path
203
204 def UpdateProjectsRevisionId(self, manifest, projects, url, branch=None):
205 """Update revisionId of every project in projects with the SHA.
206
207 Args:
208 manifest: A Manifest object that is to be written to a file.
209 projects: List of projects whose revisionId needs to be updated.
210 url: superproject's url to be passed to git clone or fetch.
211 branch: The branchname to be passed as argument to git clone or pull.
212
213 Returns:
214 manifest_path: Path name of the overriding manfiest file instead of None.
215 """
216 try:
217 shas = self._GetAllProjectsSHAs(url=url, branch=branch)
218 except Exception as e:
219 print('error: Cannot get project SHAs for %s: %s: %s' %
220 (url, type(e).__name__, str(e)),
221 file=sys.stderr)
222 return None
223
224 projects_missing_shas = []
225 for project in projects:
226 path = project.relpath
227 if not path:
228 continue
229 sha = shas.get(path)
230 if sha:
231 project.SetRevisionId(sha)
232 else:
233 projects_missing_shas.append(path)
234 if projects_missing_shas:
235 print('error: please file a bug using %s to report missing shas for: %s' %
236 (BUG_REPORT_URL, projects_missing_shas), file=sys.stderr)
237 return None
238
239 manifest_path = self._WriteManfiestFile(manifest)
240 return manifest_path