summaryrefslogtreecommitdiffstats
path: root/manifest_xml.py
diff options
context:
space:
mode:
Diffstat (limited to 'manifest_xml.py')
-rw-r--r--manifest_xml.py154
1 files changed, 122 insertions, 32 deletions
diff --git a/manifest_xml.py b/manifest_xml.py
index 6606575c..53f33537 100644
--- a/manifest_xml.py
+++ b/manifest_xml.py
@@ -40,6 +40,7 @@ class _Default(object):
40 remote = None 40 remote = None
41 sync_j = 1 41 sync_j = 1
42 sync_c = False 42 sync_c = False
43 sync_s = False
43 44
44class _XmlRemote(object): 45class _XmlRemote(object):
45 def __init__(self, 46 def __init__(self,
@@ -64,12 +65,19 @@ class _XmlRemote(object):
64 def _resolveFetchUrl(self): 65 def _resolveFetchUrl(self):
65 url = self.fetchUrl.rstrip('/') 66 url = self.fetchUrl.rstrip('/')
66 manifestUrl = self.manifestUrl.rstrip('/') 67 manifestUrl = self.manifestUrl.rstrip('/')
68 p = manifestUrl.startswith('persistent-http')
69 if p:
70 manifestUrl = manifestUrl[len('persistent-'):]
71
67 # urljoin will get confused if there is no scheme in the base url 72 # urljoin will get confused if there is no scheme in the base url
68 # ie, if manifestUrl is of the form <hostname:port> 73 # ie, if manifestUrl is of the form <hostname:port>
69 if manifestUrl.find(':') != manifestUrl.find('/') - 1: 74 if manifestUrl.find(':') != manifestUrl.find('/') - 1:
70 manifestUrl = 'gopher://' + manifestUrl 75 manifestUrl = 'gopher://' + manifestUrl
71 url = urlparse.urljoin(manifestUrl, url) 76 url = urlparse.urljoin(manifestUrl, url)
72 return re.sub(r'^gopher://', '', url) 77 url = re.sub(r'^gopher://', '', url)
78 if p:
79 url = 'persistent-' + url
80 return url
73 81
74 def ToRemoteSpec(self, projectName): 82 def ToRemoteSpec(self, projectName):
75 url = self.resolvedFetchUrl.rstrip('/') + '/' + projectName 83 url = self.resolvedFetchUrl.rstrip('/') + '/' + projectName
@@ -138,9 +146,8 @@ class XmlManifest(object):
138 mp = self.manifestProject 146 mp = self.manifestProject
139 147
140 groups = mp.config.GetString('manifest.groups') 148 groups = mp.config.GetString('manifest.groups')
141 if not groups: 149 if groups:
142 groups = 'all' 150 groups = [x for x in re.split(r'[,\s]+', groups) if x]
143 groups = [x for x in re.split(r'[,\s]+', groups) if x]
144 151
145 doc = xml.dom.minidom.Document() 152 doc = xml.dom.minidom.Document()
146 root = doc.createElement('manifest') 153 root = doc.createElement('manifest')
@@ -178,6 +185,9 @@ class XmlManifest(object):
178 if d.sync_c: 185 if d.sync_c:
179 have_default = True 186 have_default = True
180 e.setAttribute('sync-c', 'true') 187 e.setAttribute('sync-c', 'true')
188 if d.sync_s:
189 have_default = True
190 e.setAttribute('sync-s', 'true')
181 if have_default: 191 if have_default:
182 root.appendChild(e) 192 root.appendChild(e)
183 root.appendChild(doc.createTextNode('')) 193 root.appendChild(doc.createTextNode(''))
@@ -188,20 +198,25 @@ class XmlManifest(object):
188 root.appendChild(e) 198 root.appendChild(e)
189 root.appendChild(doc.createTextNode('')) 199 root.appendChild(doc.createTextNode(''))
190 200
191 sort_projects = list(self.projects.keys()) 201 def output_projects(parent, parent_node, projects):
192 sort_projects.sort() 202 for p in projects:
193 203 output_project(parent, parent_node, self.projects[p])
194 for p in sort_projects:
195 p = self.projects[p]
196 204
205 def output_project(parent, parent_node, p):
197 if not p.MatchesGroups(groups): 206 if not p.MatchesGroups(groups):
198 continue 207 return
208
209 name = p.name
210 relpath = p.relpath
211 if parent:
212 name = self._UnjoinName(parent.name, name)
213 relpath = self._UnjoinRelpath(parent.relpath, relpath)
199 214
200 e = doc.createElement('project') 215 e = doc.createElement('project')
201 root.appendChild(e) 216 parent_node.appendChild(e)
202 e.setAttribute('name', p.name) 217 e.setAttribute('name', name)
203 if p.relpath != p.name: 218 if relpath != name:
204 e.setAttribute('path', p.relpath) 219 e.setAttribute('path', relpath)
205 if not d.remote or p.remote.name != d.remote.name: 220 if not d.remote or p.remote.name != d.remote.name:
206 e.setAttribute('remote', p.remote.name) 221 e.setAttribute('remote', p.remote.name)
207 if peg_rev: 222 if peg_rev:
@@ -239,6 +254,19 @@ class XmlManifest(object):
239 if p.sync_c: 254 if p.sync_c:
240 e.setAttribute('sync-c', 'true') 255 e.setAttribute('sync-c', 'true')
241 256
257 if p.sync_s:
258 e.setAttribute('sync-s', 'true')
259
260 if p.subprojects:
261 sort_projects = [subp.name for subp in p.subprojects]
262 sort_projects.sort()
263 output_projects(p, e, sort_projects)
264
265 sort_projects = [key for key in self.projects.keys()
266 if not self.projects[key].parent]
267 sort_projects.sort()
268 output_projects(None, root, sort_projects)
269
242 if self._repo_hooks_project: 270 if self._repo_hooks_project:
243 root.appendChild(doc.createTextNode('')) 271 root.appendChild(doc.createTextNode(''))
244 e = doc.createElement('repo-hooks') 272 e = doc.createElement('repo-hooks')
@@ -317,13 +345,20 @@ class XmlManifest(object):
317 for local_file in sorted(os.listdir(local_dir)): 345 for local_file in sorted(os.listdir(local_dir)):
318 if local_file.endswith('.xml'): 346 if local_file.endswith('.xml'):
319 try: 347 try:
320 nodes.append(self._ParseManifestXml(local_file, self.repodir)) 348 local = os.path.join(local_dir, local_file)
349 nodes.append(self._ParseManifestXml(local, self.repodir))
321 except ManifestParseError as e: 350 except ManifestParseError as e:
322 print('%s' % str(e), file=sys.stderr) 351 print('%s' % str(e), file=sys.stderr)
323 except OSError: 352 except OSError:
324 pass 353 pass
325 354
326 self._ParseManifest(nodes) 355 try:
356 self._ParseManifest(nodes)
357 except ManifestParseError as e:
358 # There was a problem parsing, unload ourselves in case they catch
359 # this error and try again later, we will show the correct error
360 self._Unload()
361 raise e
327 362
328 if self.IsMirror: 363 if self.IsMirror:
329 self._AddMetaProjectMirror(self.repoProject) 364 self._AddMetaProjectMirror(self.repoProject)
@@ -409,14 +444,19 @@ class XmlManifest(object):
409 (self.manifestFile)) 444 (self.manifestFile))
410 self._manifest_server = url 445 self._manifest_server = url
411 446
447 def recursively_add_projects(project):
448 if self._projects.get(project.name):
449 raise ManifestParseError(
450 'duplicate project %s in %s' %
451 (project.name, self.manifestFile))
452 self._projects[project.name] = project
453 for subproject in project.subprojects:
454 recursively_add_projects(subproject)
455
412 for node in itertools.chain(*node_list): 456 for node in itertools.chain(*node_list):
413 if node.nodeName == 'project': 457 if node.nodeName == 'project':
414 project = self._ParseProject(node) 458 project = self._ParseProject(node)
415 if self._projects.get(project.name): 459 recursively_add_projects(project)
416 raise ManifestParseError(
417 'duplicate project %s in %s' %
418 (project.name, self.manifestFile))
419 self._projects[project.name] = project
420 if node.nodeName == 'repo-hooks': 460 if node.nodeName == 'repo-hooks':
421 # Get the name of the project and the (space-separated) list of enabled. 461 # Get the name of the project and the (space-separated) list of enabled.
422 repo_hooks_project = self._reqatt(node, 'in-project') 462 repo_hooks_project = self._reqatt(node, 'in-project')
@@ -524,6 +564,12 @@ class XmlManifest(object):
524 d.sync_c = False 564 d.sync_c = False
525 else: 565 else:
526 d.sync_c = sync_c.lower() in ("yes", "true", "1") 566 d.sync_c = sync_c.lower() in ("yes", "true", "1")
567
568 sync_s = node.getAttribute('sync-s')
569 if not sync_s:
570 d.sync_s = False
571 else:
572 d.sync_s = sync_s.lower() in ("yes", "true", "1")
527 return d 573 return d
528 574
529 def _ParseNotice(self, node): 575 def _ParseNotice(self, node):
@@ -565,11 +611,19 @@ class XmlManifest(object):
565 611
566 return '\n'.join(cleanLines) 612 return '\n'.join(cleanLines)
567 613
568 def _ParseProject(self, node): 614 def _JoinName(self, parent_name, name):
615 return os.path.join(parent_name, name)
616
617 def _UnjoinName(self, parent_name, name):
618 return os.path.relpath(name, parent_name)
619
620 def _ParseProject(self, node, parent = None):
569 """ 621 """
570 reads a <project> element from the manifest file 622 reads a <project> element from the manifest file
571 """ 623 """
572 name = self._reqatt(node, 'name') 624 name = self._reqatt(node, 'name')
625 if parent:
626 name = self._JoinName(parent.name, name)
573 627
574 remote = self._get_remote(node) 628 remote = self._get_remote(node)
575 if remote is None: 629 if remote is None:
@@ -607,6 +661,12 @@ class XmlManifest(object):
607 else: 661 else:
608 sync_c = sync_c.lower() in ("yes", "true", "1") 662 sync_c = sync_c.lower() in ("yes", "true", "1")
609 663
664 sync_s = node.getAttribute('sync-s')
665 if not sync_s:
666 sync_s = self._default.sync_s
667 else:
668 sync_s = sync_s.lower() in ("yes", "true", "1")
669
610 upstream = node.getAttribute('upstream') 670 upstream = node.getAttribute('upstream')
611 671
612 groups = '' 672 groups = ''
@@ -614,37 +674,67 @@ class XmlManifest(object):
614 groups = node.getAttribute('groups') 674 groups = node.getAttribute('groups')
615 groups = [x for x in re.split(r'[,\s]+', groups) if x] 675 groups = [x for x in re.split(r'[,\s]+', groups) if x]
616 676
617 default_groups = ['all', 'name:%s' % name, 'path:%s' % path] 677 if parent is None:
618 groups.extend(set(default_groups).difference(groups)) 678 relpath, worktree, gitdir = self.GetProjectPaths(name, path)
619
620 if self.IsMirror:
621 worktree = None
622 gitdir = os.path.join(self.topdir, '%s.git' % name)
623 else: 679 else:
624 worktree = os.path.join(self.topdir, path).replace('\\', '/') 680 relpath, worktree, gitdir = self.GetSubprojectPaths(parent, path)
625 gitdir = os.path.join(self.repodir, 'projects/%s.git' % path) 681
682 default_groups = ['all', 'name:%s' % name, 'path:%s' % relpath]
683 groups.extend(set(default_groups).difference(groups))
626 684
627 project = Project(manifest = self, 685 project = Project(manifest = self,
628 name = name, 686 name = name,
629 remote = remote.ToRemoteSpec(name), 687 remote = remote.ToRemoteSpec(name),
630 gitdir = gitdir, 688 gitdir = gitdir,
631 worktree = worktree, 689 worktree = worktree,
632 relpath = path, 690 relpath = relpath,
633 revisionExpr = revisionExpr, 691 revisionExpr = revisionExpr,
634 revisionId = None, 692 revisionId = None,
635 rebase = rebase, 693 rebase = rebase,
636 groups = groups, 694 groups = groups,
637 sync_c = sync_c, 695 sync_c = sync_c,
638 upstream = upstream) 696 sync_s = sync_s,
697 upstream = upstream,
698 parent = parent)
639 699
640 for n in node.childNodes: 700 for n in node.childNodes:
641 if n.nodeName == 'copyfile': 701 if n.nodeName == 'copyfile':
642 self._ParseCopyFile(project, n) 702 self._ParseCopyFile(project, n)
643 if n.nodeName == 'annotation': 703 if n.nodeName == 'annotation':
644 self._ParseAnnotation(project, n) 704 self._ParseAnnotation(project, n)
705 if n.nodeName == 'project':
706 project.subprojects.append(self._ParseProject(n, parent = project))
645 707
646 return project 708 return project
647 709
710 def GetProjectPaths(self, name, path):
711 relpath = path
712 if self.IsMirror:
713 worktree = None
714 gitdir = os.path.join(self.topdir, '%s.git' % name)
715 else:
716 worktree = os.path.join(self.topdir, path).replace('\\', '/')
717 gitdir = os.path.join(self.repodir, 'projects', '%s.git' % path)
718 return relpath, worktree, gitdir
719
720 def GetSubprojectName(self, parent, submodule_path):
721 return os.path.join(parent.name, submodule_path)
722
723 def _JoinRelpath(self, parent_relpath, relpath):
724 return os.path.join(parent_relpath, relpath)
725
726 def _UnjoinRelpath(self, parent_relpath, relpath):
727 return os.path.relpath(relpath, parent_relpath)
728
729 def GetSubprojectPaths(self, parent, path):
730 relpath = self._JoinRelpath(parent.relpath, path)
731 gitdir = os.path.join(parent.gitdir, 'subprojects', '%s.git' % path)
732 if self.IsMirror:
733 worktree = None
734 else:
735 worktree = os.path.join(parent.worktree, path).replace('\\', '/')
736 return relpath, worktree, gitdir
737
648 def _ParseCopyFile(self, project, node): 738 def _ParseCopyFile(self, project, node):
649 src = self._reqatt(node, 'src') 739 src = self._reqatt(node, 'src')
650 dest = self._reqatt(node, 'dest') 740 dest = self._reqatt(node, 'dest')