summaryrefslogtreecommitdiffstats
path: root/manifest_xml.py
diff options
context:
space:
mode:
Diffstat (limited to 'manifest_xml.py')
-rw-r--r--manifest_xml.py103
1 files changed, 65 insertions, 38 deletions
diff --git a/manifest_xml.py b/manifest_xml.py
index 07f0c66a..bdbb1d40 100644
--- a/manifest_xml.py
+++ b/manifest_xml.py
@@ -18,9 +18,17 @@ import itertools
18import os 18import os
19import re 19import re
20import sys 20import sys
21import urlparse
22import xml.dom.minidom 21import xml.dom.minidom
23 22
23from pyversion import is_python3
24if is_python3():
25 import urllib.parse
26else:
27 import imp
28 import urlparse
29 urllib = imp.new_module('urllib')
30 urllib.parse = urlparse
31
24from git_config import GitConfig 32from git_config import GitConfig
25from git_refs import R_HEADS, HEAD 33from git_refs import R_HEADS, HEAD
26from project import RemoteSpec, Project, MetaProject 34from project import RemoteSpec, Project, MetaProject
@@ -30,13 +38,14 @@ MANIFEST_FILE_NAME = 'manifest.xml'
30LOCAL_MANIFEST_NAME = 'local_manifest.xml' 38LOCAL_MANIFEST_NAME = 'local_manifest.xml'
31LOCAL_MANIFESTS_DIR_NAME = 'local_manifests' 39LOCAL_MANIFESTS_DIR_NAME = 'local_manifests'
32 40
33urlparse.uses_relative.extend(['ssh', 'git']) 41urllib.parse.uses_relative.extend(['ssh', 'git'])
34urlparse.uses_netloc.extend(['ssh', 'git']) 42urllib.parse.uses_netloc.extend(['ssh', 'git'])
35 43
36class _Default(object): 44class _Default(object):
37 """Project defaults within the manifest.""" 45 """Project defaults within the manifest."""
38 46
39 revisionExpr = None 47 revisionExpr = None
48 destBranchExpr = None
40 remote = None 49 remote = None
41 sync_j = 1 50 sync_j = 1
42 sync_c = False 51 sync_c = False
@@ -73,7 +82,7 @@ class _XmlRemote(object):
73 # ie, if manifestUrl is of the form <hostname:port> 82 # ie, if manifestUrl is of the form <hostname:port>
74 if manifestUrl.find(':') != manifestUrl.find('/') - 1: 83 if manifestUrl.find(':') != manifestUrl.find('/') - 1:
75 manifestUrl = 'gopher://' + manifestUrl 84 manifestUrl = 'gopher://' + manifestUrl
76 url = urlparse.urljoin(manifestUrl, url) 85 url = urllib.parse.urljoin(manifestUrl, url)
77 url = re.sub(r'^gopher://', '', url) 86 url = re.sub(r'^gopher://', '', url)
78 if p: 87 if p:
79 url = 'persistent-' + url 88 url = 'persistent-' + url
@@ -83,7 +92,7 @@ class _XmlRemote(object):
83 url = self.resolvedFetchUrl.rstrip('/') + '/' + projectName 92 url = self.resolvedFetchUrl.rstrip('/') + '/' + projectName
84 remoteName = self.name 93 remoteName = self.name
85 if self.remoteAlias: 94 if self.remoteAlias:
86 remoteName = self.remoteAlias 95 remoteName = self.remoteAlias
87 return RemoteSpec(remoteName, url, self.reviewUrl) 96 return RemoteSpec(remoteName, url, self.reviewUrl)
88 97
89class XmlManifest(object): 98class XmlManifest(object):
@@ -94,6 +103,7 @@ class XmlManifest(object):
94 self.topdir = os.path.dirname(self.repodir) 103 self.topdir = os.path.dirname(self.repodir)
95 self.manifestFile = os.path.join(self.repodir, MANIFEST_FILE_NAME) 104 self.manifestFile = os.path.join(self.repodir, MANIFEST_FILE_NAME)
96 self.globalConfig = GitConfig.ForUser() 105 self.globalConfig = GitConfig.ForUser()
106 self.localManifestWarning = False
97 107
98 self.repoProject = MetaProject(self, 'repo', 108 self.repoProject = MetaProject(self, 'repo',
99 gitdir = os.path.join(repodir, 'repo/.git'), 109 gitdir = os.path.join(repodir, 'repo/.git'),
@@ -137,6 +147,8 @@ class XmlManifest(object):
137 root.appendChild(e) 147 root.appendChild(e)
138 e.setAttribute('name', r.name) 148 e.setAttribute('name', r.name)
139 e.setAttribute('fetch', r.fetchUrl) 149 e.setAttribute('fetch', r.fetchUrl)
150 if r.remoteAlias is not None:
151 e.setAttribute('alias', r.remoteAlias)
140 if r.reviewUrl is not None: 152 if r.reviewUrl is not None:
141 e.setAttribute('review', r.reviewUrl) 153 e.setAttribute('review', r.reviewUrl)
142 154
@@ -163,10 +175,8 @@ class XmlManifest(object):
163 notice_element.appendChild(doc.createTextNode(indented_notice)) 175 notice_element.appendChild(doc.createTextNode(indented_notice))
164 176
165 d = self.default 177 d = self.default
166 sort_remotes = list(self.remotes.keys())
167 sort_remotes.sort()
168 178
169 for r in sort_remotes: 179 for r in sorted(self.remotes):
170 self._RemoteToXml(self.remotes[r], doc, root) 180 self._RemoteToXml(self.remotes[r], doc, root)
171 if self.remotes: 181 if self.remotes:
172 root.appendChild(doc.createTextNode('')) 182 root.appendChild(doc.createTextNode(''))
@@ -217,7 +227,8 @@ class XmlManifest(object):
217 e.setAttribute('name', name) 227 e.setAttribute('name', name)
218 if relpath != name: 228 if relpath != name:
219 e.setAttribute('path', relpath) 229 e.setAttribute('path', relpath)
220 if not d.remote or p.remote.name != d.remote.name: 230 remoteName = d.remote.remoteAlias or d.remote.name
231 if not d.remote or p.remote.name != remoteName:
221 e.setAttribute('remote', p.remote.name) 232 e.setAttribute('remote', p.remote.name)
222 if peg_rev: 233 if peg_rev:
223 if self.IsMirror: 234 if self.IsMirror:
@@ -258,12 +269,11 @@ class XmlManifest(object):
258 e.setAttribute('sync-s', 'true') 269 e.setAttribute('sync-s', 'true')
259 270
260 if p.subprojects: 271 if p.subprojects:
261 sort_projects = [subp.name for subp in p.subprojects] 272 sort_projects = list(sorted([subp.name for subp in p.subprojects]))
262 sort_projects.sort()
263 output_projects(p, e, sort_projects) 273 output_projects(p, e, sort_projects)
264 274
265 sort_projects = [key for key in self.projects.keys() 275 sort_projects = list(sorted([key for key, value in self.projects.items()
266 if not self.projects[key].parent] 276 if not value.parent]))
267 sort_projects.sort() 277 sort_projects.sort()
268 output_projects(None, root, sort_projects) 278 output_projects(None, root, sort_projects)
269 279
@@ -335,9 +345,11 @@ class XmlManifest(object):
335 345
336 local = os.path.join(self.repodir, LOCAL_MANIFEST_NAME) 346 local = os.path.join(self.repodir, LOCAL_MANIFEST_NAME)
337 if os.path.exists(local): 347 if os.path.exists(local):
338 print('warning: %s is deprecated; put local manifests in `%s` instead' 348 if not self.localManifestWarning:
339 % (LOCAL_MANIFEST_NAME, os.path.join(self.repodir, LOCAL_MANIFESTS_DIR_NAME)), 349 self.localManifestWarning = True
340 file=sys.stderr) 350 print('warning: %s is deprecated; put local manifests in `%s` instead'
351 % (LOCAL_MANIFEST_NAME, os.path.join(self.repodir, LOCAL_MANIFESTS_DIR_NAME)),
352 file=sys.stderr)
341 nodes.append(self._ParseManifestXml(local, self.repodir)) 353 nodes.append(self._ParseManifestXml(local, self.repodir))
342 354
343 local_dir = os.path.abspath(os.path.join(self.repodir, LOCAL_MANIFESTS_DIR_NAME)) 355 local_dir = os.path.abspath(os.path.join(self.repodir, LOCAL_MANIFESTS_DIR_NAME))
@@ -385,9 +397,8 @@ class XmlManifest(object):
385 name = self._reqatt(node, 'name') 397 name = self._reqatt(node, 'name')
386 fp = os.path.join(include_root, name) 398 fp = os.path.join(include_root, name)
387 if not os.path.isfile(fp): 399 if not os.path.isfile(fp):
388 raise ManifestParseError, \ 400 raise ManifestParseError("include %s doesn't exist or isn't a file"
389 "include %s doesn't exist or isn't a file" % \ 401 % (name,))
390 (name,)
391 try: 402 try:
392 nodes.extend(self._ParseManifestXml(fp, include_root)) 403 nodes.extend(self._ParseManifestXml(fp, include_root))
393 # should isolate this to the exact exception, but that's 404 # should isolate this to the exact exception, but that's
@@ -493,7 +504,7 @@ class XmlManifest(object):
493 name = None 504 name = None
494 m_url = m.GetRemote(m.remote.name).url 505 m_url = m.GetRemote(m.remote.name).url
495 if m_url.endswith('/.git'): 506 if m_url.endswith('/.git'):
496 raise ManifestParseError, 'refusing to mirror %s' % m_url 507 raise ManifestParseError('refusing to mirror %s' % m_url)
497 508
498 if self._default and self._default.remote: 509 if self._default and self._default.remote:
499 url = self._default.remote.resolvedFetchUrl 510 url = self._default.remote.resolvedFetchUrl
@@ -550,6 +561,8 @@ class XmlManifest(object):
550 if d.revisionExpr == '': 561 if d.revisionExpr == '':
551 d.revisionExpr = None 562 d.revisionExpr = None
552 563
564 d.destBranchExpr = node.getAttribute('dest-branch') or None
565
553 sync_j = node.getAttribute('sync-j') 566 sync_j = node.getAttribute('sync-j')
554 if sync_j == '' or sync_j is None: 567 if sync_j == '' or sync_j is None:
555 d.sync_j = 1 568 d.sync_j = 1
@@ -587,7 +600,7 @@ class XmlManifest(object):
587 600
588 # Figure out minimum indentation, skipping the first line (the same line 601 # Figure out minimum indentation, skipping the first line (the same line
589 # as the <notice> tag)... 602 # as the <notice> tag)...
590 minIndent = sys.maxint 603 minIndent = sys.maxsize
591 lines = notice.splitlines() 604 lines = notice.splitlines()
592 for line in lines[1:]: 605 for line in lines[1:]:
593 lstrippedLine = line.lstrip() 606 lstrippedLine = line.lstrip()
@@ -626,25 +639,22 @@ class XmlManifest(object):
626 if remote is None: 639 if remote is None:
627 remote = self._default.remote 640 remote = self._default.remote
628 if remote is None: 641 if remote is None:
629 raise ManifestParseError, \ 642 raise ManifestParseError("no remote for project %s within %s" %
630 "no remote for project %s within %s" % \ 643 (name, self.manifestFile))
631 (name, self.manifestFile)
632 644
633 revisionExpr = node.getAttribute('revision') 645 revisionExpr = node.getAttribute('revision')
634 if not revisionExpr: 646 if not revisionExpr:
635 revisionExpr = self._default.revisionExpr 647 revisionExpr = self._default.revisionExpr
636 if not revisionExpr: 648 if not revisionExpr:
637 raise ManifestParseError, \ 649 raise ManifestParseError("no revision for project %s within %s" %
638 "no revision for project %s within %s" % \ 650 (name, self.manifestFile))
639 (name, self.manifestFile)
640 651
641 path = node.getAttribute('path') 652 path = node.getAttribute('path')
642 if not path: 653 if not path:
643 path = name 654 path = name
644 if path.startswith('/'): 655 if path.startswith('/'):
645 raise ManifestParseError, \ 656 raise ManifestParseError("project %s path cannot be absolute in %s" %
646 "project %s path cannot be absolute in %s" % \ 657 (name, self.manifestFile))
647 (name, self.manifestFile)
648 658
649 rebase = node.getAttribute('rebase') 659 rebase = node.getAttribute('rebase')
650 if not rebase: 660 if not rebase:
@@ -664,6 +674,18 @@ class XmlManifest(object):
664 else: 674 else:
665 sync_s = sync_s.lower() in ("yes", "true", "1") 675 sync_s = sync_s.lower() in ("yes", "true", "1")
666 676
677 clone_depth = node.getAttribute('clone-depth')
678 if clone_depth:
679 try:
680 clone_depth = int(clone_depth)
681 if clone_depth <= 0:
682 raise ValueError()
683 except ValueError:
684 raise ManifestParseError('invalid clone-depth %s in %s' %
685 (clone_depth, self.manifestFile))
686
687 dest_branch = node.getAttribute('dest-branch') or self._default.destBranchExpr
688
667 upstream = node.getAttribute('upstream') 689 upstream = node.getAttribute('upstream')
668 690
669 groups = '' 691 groups = ''
@@ -679,6 +701,10 @@ class XmlManifest(object):
679 default_groups = ['all', 'name:%s' % name, 'path:%s' % relpath] 701 default_groups = ['all', 'name:%s' % name, 'path:%s' % relpath]
680 groups.extend(set(default_groups).difference(groups)) 702 groups.extend(set(default_groups).difference(groups))
681 703
704 if self.IsMirror and node.hasAttribute('force-path'):
705 if node.getAttribute('force-path').lower() in ("yes", "true", "1"):
706 gitdir = os.path.join(self.topdir, '%s.git' % path)
707
682 project = Project(manifest = self, 708 project = Project(manifest = self,
683 name = name, 709 name = name,
684 remote = remote.ToRemoteSpec(name), 710 remote = remote.ToRemoteSpec(name),
@@ -691,8 +717,10 @@ class XmlManifest(object):
691 groups = groups, 717 groups = groups,
692 sync_c = sync_c, 718 sync_c = sync_c,
693 sync_s = sync_s, 719 sync_s = sync_s,
720 clone_depth = clone_depth,
694 upstream = upstream, 721 upstream = upstream,
695 parent = parent) 722 parent = parent,
723 dest_branch = dest_branch)
696 724
697 for n in node.childNodes: 725 for n in node.childNodes:
698 if n.nodeName == 'copyfile': 726 if n.nodeName == 'copyfile':
@@ -748,7 +776,8 @@ class XmlManifest(object):
748 except ManifestParseError: 776 except ManifestParseError:
749 keep = "true" 777 keep = "true"
750 if keep != "true" and keep != "false": 778 if keep != "true" and keep != "false":
751 raise ManifestParseError, "optional \"keep\" attribute must be \"true\" or \"false\"" 779 raise ManifestParseError('optional "keep" attribute must be '
780 '"true" or "false"')
752 project.AddAnnotation(name, value, keep) 781 project.AddAnnotation(name, value, keep)
753 782
754 def _get_remote(self, node): 783 def _get_remote(self, node):
@@ -758,9 +787,8 @@ class XmlManifest(object):
758 787
759 v = self._remotes.get(name) 788 v = self._remotes.get(name)
760 if not v: 789 if not v:
761 raise ManifestParseError, \ 790 raise ManifestParseError("remote %s not defined in %s" %
762 "remote %s not defined in %s" % \ 791 (name, self.manifestFile))
763 (name, self.manifestFile)
764 return v 792 return v
765 793
766 def _reqatt(self, node, attname): 794 def _reqatt(self, node, attname):
@@ -769,7 +797,6 @@ class XmlManifest(object):
769 """ 797 """
770 v = node.getAttribute(attname) 798 v = node.getAttribute(attname)
771 if not v: 799 if not v:
772 raise ManifestParseError, \ 800 raise ManifestParseError("no %s in <%s> within %s" %
773 "no %s in <%s> within %s" % \ 801 (attname, node.nodeName, self.manifestFile))
774 (attname, node.nodeName, self.manifestFile)
775 return v 802 return v