diff options
Diffstat (limited to 'manifest_xml.py')
| -rw-r--r-- | manifest_xml.py | 81 |
1 files changed, 47 insertions, 34 deletions
diff --git a/manifest_xml.py b/manifest_xml.py index 50417c60..cc441dc8 100644 --- a/manifest_xml.py +++ b/manifest_xml.py | |||
| @@ -18,7 +18,15 @@ import itertools | |||
| 18 | import os | 18 | import os |
| 19 | import re | 19 | import re |
| 20 | import sys | 20 | import sys |
| 21 | import urlparse | 21 | try: |
| 22 | # For python3 | ||
| 23 | import urllib.parse | ||
| 24 | except ImportError: | ||
| 25 | # For python2 | ||
| 26 | import imp | ||
| 27 | import urlparse | ||
| 28 | urllib = imp.new_module('urllib') | ||
| 29 | urllib.parse = urlparse | ||
| 22 | import xml.dom.minidom | 30 | import xml.dom.minidom |
| 23 | 31 | ||
| 24 | from git_config import GitConfig | 32 | from git_config import GitConfig |
| @@ -30,8 +38,8 @@ 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.""" |
| @@ -73,7 +81,7 @@ class _XmlRemote(object): | |||
| 73 | # ie, if manifestUrl is of the form <hostname:port> | 81 | # ie, if manifestUrl is of the form <hostname:port> |
| 74 | if manifestUrl.find(':') != manifestUrl.find('/') - 1: | 82 | if manifestUrl.find(':') != manifestUrl.find('/') - 1: |
| 75 | manifestUrl = 'gopher://' + manifestUrl | 83 | manifestUrl = 'gopher://' + manifestUrl |
| 76 | url = urlparse.urljoin(manifestUrl, url) | 84 | url = urllib.parse.urljoin(manifestUrl, url) |
| 77 | url = re.sub(r'^gopher://', '', url) | 85 | url = re.sub(r'^gopher://', '', url) |
| 78 | if p: | 86 | if p: |
| 79 | url = 'persistent-' + url | 87 | url = 'persistent-' + url |
| @@ -82,8 +90,6 @@ class _XmlRemote(object): | |||
| 82 | def ToRemoteSpec(self, projectName): | 90 | def ToRemoteSpec(self, projectName): |
| 83 | url = self.resolvedFetchUrl.rstrip('/') + '/' + projectName | 91 | url = self.resolvedFetchUrl.rstrip('/') + '/' + projectName |
| 84 | remoteName = self.name | 92 | remoteName = self.name |
| 85 | if self.remoteAlias: | ||
| 86 | remoteName = self.remoteAlias | ||
| 87 | return RemoteSpec(remoteName, url, self.reviewUrl) | 93 | return RemoteSpec(remoteName, url, self.reviewUrl) |
| 88 | 94 | ||
| 89 | class XmlManifest(object): | 95 | class XmlManifest(object): |
| @@ -164,10 +170,8 @@ class XmlManifest(object): | |||
| 164 | notice_element.appendChild(doc.createTextNode(indented_notice)) | 170 | notice_element.appendChild(doc.createTextNode(indented_notice)) |
| 165 | 171 | ||
| 166 | d = self.default | 172 | d = self.default |
| 167 | sort_remotes = list(self.remotes.keys()) | ||
| 168 | sort_remotes.sort() | ||
| 169 | 173 | ||
| 170 | for r in sort_remotes: | 174 | for r in sorted(self.remotes): |
| 171 | self._RemoteToXml(self.remotes[r], doc, root) | 175 | self._RemoteToXml(self.remotes[r], doc, root) |
| 172 | if self.remotes: | 176 | if self.remotes: |
| 173 | root.appendChild(doc.createTextNode('')) | 177 | root.appendChild(doc.createTextNode('')) |
| @@ -259,12 +263,11 @@ class XmlManifest(object): | |||
| 259 | e.setAttribute('sync-s', 'true') | 263 | e.setAttribute('sync-s', 'true') |
| 260 | 264 | ||
| 261 | if p.subprojects: | 265 | if p.subprojects: |
| 262 | sort_projects = [subp.name for subp in p.subprojects] | 266 | sort_projects = list(sorted([subp.name for subp in p.subprojects])) |
| 263 | sort_projects.sort() | ||
| 264 | output_projects(p, e, sort_projects) | 267 | output_projects(p, e, sort_projects) |
| 265 | 268 | ||
| 266 | sort_projects = [key for key in self.projects.keys() | 269 | sort_projects = list(sorted([key for key, value in self.projects.items() |
| 267 | if not self.projects[key].parent] | 270 | if not value.parent])) |
| 268 | sort_projects.sort() | 271 | sort_projects.sort() |
| 269 | output_projects(None, root, sort_projects) | 272 | output_projects(None, root, sort_projects) |
| 270 | 273 | ||
| @@ -388,9 +391,8 @@ class XmlManifest(object): | |||
| 388 | name = self._reqatt(node, 'name') | 391 | name = self._reqatt(node, 'name') |
| 389 | fp = os.path.join(include_root, name) | 392 | fp = os.path.join(include_root, name) |
| 390 | if not os.path.isfile(fp): | 393 | if not os.path.isfile(fp): |
| 391 | raise ManifestParseError, \ | 394 | raise ManifestParseError("include %s doesn't exist or isn't a file" |
| 392 | "include %s doesn't exist or isn't a file" % \ | 395 | % (name,)) |
| 393 | (name,) | ||
| 394 | try: | 396 | try: |
| 395 | nodes.extend(self._ParseManifestXml(fp, include_root)) | 397 | nodes.extend(self._ParseManifestXml(fp, include_root)) |
| 396 | # should isolate this to the exact exception, but that's | 398 | # should isolate this to the exact exception, but that's |
| @@ -496,7 +498,7 @@ class XmlManifest(object): | |||
| 496 | name = None | 498 | name = None |
| 497 | m_url = m.GetRemote(m.remote.name).url | 499 | m_url = m.GetRemote(m.remote.name).url |
| 498 | if m_url.endswith('/.git'): | 500 | if m_url.endswith('/.git'): |
| 499 | raise ManifestParseError, 'refusing to mirror %s' % m_url | 501 | raise ManifestParseError('refusing to mirror %s' % m_url) |
| 500 | 502 | ||
| 501 | if self._default and self._default.remote: | 503 | if self._default and self._default.remote: |
| 502 | url = self._default.remote.resolvedFetchUrl | 504 | url = self._default.remote.resolvedFetchUrl |
| @@ -590,7 +592,7 @@ class XmlManifest(object): | |||
| 590 | 592 | ||
| 591 | # Figure out minimum indentation, skipping the first line (the same line | 593 | # Figure out minimum indentation, skipping the first line (the same line |
| 592 | # as the <notice> tag)... | 594 | # as the <notice> tag)... |
| 593 | minIndent = sys.maxint | 595 | minIndent = sys.maxsize |
| 594 | lines = notice.splitlines() | 596 | lines = notice.splitlines() |
| 595 | for line in lines[1:]: | 597 | for line in lines[1:]: |
| 596 | lstrippedLine = line.lstrip() | 598 | lstrippedLine = line.lstrip() |
| @@ -629,25 +631,22 @@ class XmlManifest(object): | |||
| 629 | if remote is None: | 631 | if remote is None: |
| 630 | remote = self._default.remote | 632 | remote = self._default.remote |
| 631 | if remote is None: | 633 | if remote is None: |
| 632 | raise ManifestParseError, \ | 634 | raise ManifestParseError("no remote for project %s within %s" % |
| 633 | "no remote for project %s within %s" % \ | 635 | (name, self.manifestFile)) |
| 634 | (name, self.manifestFile) | ||
| 635 | 636 | ||
| 636 | revisionExpr = node.getAttribute('revision') | 637 | revisionExpr = node.getAttribute('revision') |
| 637 | if not revisionExpr: | 638 | if not revisionExpr: |
| 638 | revisionExpr = self._default.revisionExpr | 639 | revisionExpr = self._default.revisionExpr |
| 639 | if not revisionExpr: | 640 | if not revisionExpr: |
| 640 | raise ManifestParseError, \ | 641 | raise ManifestParseError("no revision for project %s within %s" % |
| 641 | "no revision for project %s within %s" % \ | 642 | (name, self.manifestFile)) |
| 642 | (name, self.manifestFile) | ||
| 643 | 643 | ||
| 644 | path = node.getAttribute('path') | 644 | path = node.getAttribute('path') |
| 645 | if not path: | 645 | if not path: |
| 646 | path = name | 646 | path = name |
| 647 | if path.startswith('/'): | 647 | if path.startswith('/'): |
| 648 | raise ManifestParseError, \ | 648 | raise ManifestParseError("project %s path cannot be absolute in %s" % |
| 649 | "project %s path cannot be absolute in %s" % \ | 649 | (name, self.manifestFile)) |
| 650 | (name, self.manifestFile) | ||
| 651 | 650 | ||
| 652 | rebase = node.getAttribute('rebase') | 651 | rebase = node.getAttribute('rebase') |
| 653 | if not rebase: | 652 | if not rebase: |
| @@ -667,6 +666,16 @@ class XmlManifest(object): | |||
| 667 | else: | 666 | else: |
| 668 | sync_s = sync_s.lower() in ("yes", "true", "1") | 667 | sync_s = sync_s.lower() in ("yes", "true", "1") |
| 669 | 668 | ||
| 669 | clone_depth = node.getAttribute('clone-depth') | ||
| 670 | if clone_depth: | ||
| 671 | try: | ||
| 672 | clone_depth = int(clone_depth) | ||
| 673 | if clone_depth <= 0: | ||
| 674 | raise ValueError() | ||
| 675 | except ValueError: | ||
| 676 | raise ManifestParseError('invalid clone-depth %s in %s' % | ||
| 677 | (clone_depth, self.manifestFile)) | ||
| 678 | |||
| 670 | upstream = node.getAttribute('upstream') | 679 | upstream = node.getAttribute('upstream') |
| 671 | 680 | ||
| 672 | groups = '' | 681 | groups = '' |
| @@ -682,6 +691,10 @@ class XmlManifest(object): | |||
| 682 | default_groups = ['all', 'name:%s' % name, 'path:%s' % relpath] | 691 | default_groups = ['all', 'name:%s' % name, 'path:%s' % relpath] |
| 683 | groups.extend(set(default_groups).difference(groups)) | 692 | groups.extend(set(default_groups).difference(groups)) |
| 684 | 693 | ||
| 694 | if self.IsMirror and node.hasAttribute('force-path'): | ||
| 695 | if node.getAttribute('force-path').lower() in ("yes", "true", "1"): | ||
| 696 | gitdir = os.path.join(self.topdir, '%s.git' % path) | ||
| 697 | |||
| 685 | project = Project(manifest = self, | 698 | project = Project(manifest = self, |
| 686 | name = name, | 699 | name = name, |
| 687 | remote = remote.ToRemoteSpec(name), | 700 | remote = remote.ToRemoteSpec(name), |
| @@ -694,6 +707,7 @@ class XmlManifest(object): | |||
| 694 | groups = groups, | 707 | groups = groups, |
| 695 | sync_c = sync_c, | 708 | sync_c = sync_c, |
| 696 | sync_s = sync_s, | 709 | sync_s = sync_s, |
| 710 | clone_depth = clone_depth, | ||
| 697 | upstream = upstream, | 711 | upstream = upstream, |
| 698 | parent = parent) | 712 | parent = parent) |
| 699 | 713 | ||
| @@ -751,7 +765,8 @@ class XmlManifest(object): | |||
| 751 | except ManifestParseError: | 765 | except ManifestParseError: |
| 752 | keep = "true" | 766 | keep = "true" |
| 753 | if keep != "true" and keep != "false": | 767 | if keep != "true" and keep != "false": |
| 754 | raise ManifestParseError, "optional \"keep\" attribute must be \"true\" or \"false\"" | 768 | raise ManifestParseError('optional "keep" attribute must be ' |
| 769 | '"true" or "false"') | ||
| 755 | project.AddAnnotation(name, value, keep) | 770 | project.AddAnnotation(name, value, keep) |
| 756 | 771 | ||
| 757 | def _get_remote(self, node): | 772 | def _get_remote(self, node): |
| @@ -761,9 +776,8 @@ class XmlManifest(object): | |||
| 761 | 776 | ||
| 762 | v = self._remotes.get(name) | 777 | v = self._remotes.get(name) |
| 763 | if not v: | 778 | if not v: |
| 764 | raise ManifestParseError, \ | 779 | raise ManifestParseError("remote %s not defined in %s" % |
| 765 | "remote %s not defined in %s" % \ | 780 | (name, self.manifestFile)) |
| 766 | (name, self.manifestFile) | ||
| 767 | return v | 781 | return v |
| 768 | 782 | ||
| 769 | def _reqatt(self, node, attname): | 783 | def _reqatt(self, node, attname): |
| @@ -772,7 +786,6 @@ class XmlManifest(object): | |||
| 772 | """ | 786 | """ |
| 773 | v = node.getAttribute(attname) | 787 | v = node.getAttribute(attname) |
| 774 | if not v: | 788 | if not v: |
| 775 | raise ManifestParseError, \ | 789 | raise ManifestParseError("no %s in <%s> within %s" % |
| 776 | "no %s in <%s> within %s" % \ | 790 | (attname, node.nodeName, self.manifestFile)) |
| 777 | (attname, node.nodeName, self.manifestFile) | ||
| 778 | return v | 791 | return v |
