diff options
Diffstat (limited to 'manifest_xml.py')
-rw-r--r-- | manifest_xml.py | 103 |
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 | |||
18 | import os | 18 | import os |
19 | import re | 19 | import re |
20 | import sys | 20 | import sys |
21 | import urlparse | ||
22 | import xml.dom.minidom | 21 | import xml.dom.minidom |
23 | 22 | ||
23 | from pyversion import is_python3 | ||
24 | if is_python3(): | ||
25 | import urllib.parse | ||
26 | else: | ||
27 | import imp | ||
28 | import urlparse | ||
29 | urllib = imp.new_module('urllib') | ||
30 | urllib.parse = urlparse | ||
31 | |||
24 | from git_config import GitConfig | 32 | from git_config import GitConfig |
25 | from git_refs import R_HEADS, HEAD | 33 | from git_refs import R_HEADS, HEAD |
26 | from project import RemoteSpec, Project, MetaProject | 34 | from project import RemoteSpec, Project, MetaProject |
@@ -30,13 +38,14 @@ MANIFEST_FILE_NAME = 'manifest.xml' | |||
30 | LOCAL_MANIFEST_NAME = 'local_manifest.xml' | 38 | LOCAL_MANIFEST_NAME = 'local_manifest.xml' |
31 | LOCAL_MANIFESTS_DIR_NAME = 'local_manifests' | 39 | LOCAL_MANIFESTS_DIR_NAME = 'local_manifests' |
32 | 40 | ||
33 | urlparse.uses_relative.extend(['ssh', 'git']) | 41 | urllib.parse.uses_relative.extend(['ssh', 'git']) |
34 | urlparse.uses_netloc.extend(['ssh', 'git']) | 42 | urllib.parse.uses_netloc.extend(['ssh', 'git']) |
35 | 43 | ||
36 | class _Default(object): | 44 | class _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 | ||
89 | class XmlManifest(object): | 98 | class 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 |