예제 #1
0
    def _ParseManifestXml(self, path, include_root):
        try:
            root = xml.dom.minidom.parse(path)
        except (OSError, xml.parsers.expat.ExpatError) as e:
            raise ManifestParseError("error parsing manifest %s: %s" %
                                     (path, e))

        if not root or not root.childNodes:
            raise ManifestParseError("no root node in %s" % (path, ))

        for manifest in root.childNodes:
            if manifest.nodeName == 'manifest':
                break
        else:
            raise ManifestParseError("no <manifest> in %s" % (path, ))

        nodes = []
        for node in manifest.childNodes:  # pylint:disable=W0631
            # We only get here if manifest is initialised
            if node.nodeName == 'include':
                name = self._reqatt(node, 'name')
                fp = os.path.join(include_root, name)
                if not os.path.isfile(fp):
                    raise ManifestParseError(
                        "include %s doesn't exist or isn't a file" % (name, ))
                try:
                    nodes.extend(self._ParseManifestXml(fp, include_root))
                # should isolate this to the exact exception, but that's
                # tricky.  actual parsing implementation may vary.
                except (KeyboardInterrupt, RuntimeError, SystemExit):
                    raise
                except Exception as e:
                    raise ManifestParseError(
                        "failed parsing included manifest %s: %s", (name, e))
            else:
                nodes.append(node)
        return nodes
예제 #2
0
    def _ParseProject(self, name):
        gm = self._modules
        gr = self._review

        path = gm.GetString('submodule.%s.path' % name)
        if not path:
            path = name

        revId = self._GetRevisionId(path)
        if not revId:
            raise ManifestParseError(
              'submodule "%s" has no revision at "%s"' \
              % (name, path))

        url = gm.GetString('submodule.%s.url' % name)
        if not url:
            url = name
        url = self._ResolveUrl(url)

        review = gr.GetString('review.%s.url' % name)
        if not review:
            review = gr.GetString('review.url')
        if not review:
            review = self._Remote().review

        remote = RemoteSpec(self._Remote().name, url, review)
        revExpr = gm.GetString('submodule.%s.revision' % name)
        if revExpr == '.':
            revExpr = self.branch

        if self.IsMirror:
            relpath = None
            worktree = None
            gitdir = os.path.join(self.topdir, '%s.git' % name)
        else:
            worktree = os.path.join(self.topdir, path)
            gitdir = os.path.join(self.repodir, 'projects/%s.git' % name)

        return Project(manifest=self,
                       name=name,
                       remote=remote,
                       gitdir=gitdir,
                       worktree=worktree,
                       relpath=path,
                       revisionExpr=revExpr,
                       revisionId=revId)
예제 #3
0
    def _AddMetaProjectMirror(self, m):
        name = None
        m_url = m.GetRemote(m.remote.name).url
        if m_url.endswith('/.git'):
            raise ManifestParseError('refusing to mirror %s' % m_url)

        if self._default and self._default.remote:
            url = self._default.remote.resolvedFetchUrl
            if not url.endswith('/'):
                url += '/'
            if m_url.startswith(url):
                remote = self._default.remote
                name = m_url[len(url):]

        if name is None:
            s = m_url.rindex('/') + 1
            manifestUrl = self.manifestProject.config.GetString(
                'remote.origin.url')
            remote = _XmlRemote('origin',
                                fetch=m_url[:s],
                                manifestUrl=manifestUrl)
            name = m_url[s:]

        if name.endswith('.git'):
            name = name[:-4]

        if name not in self._projects:
            m.PreSync()
            gitdir = os.path.join(self.topdir, '%s.git' % name)
            project = Project(manifest=self,
                              name=name,
                              remote=remote.ToRemoteSpec(name),
                              gitdir=gitdir,
                              objdir=gitdir,
                              worktree=None,
                              relpath=name or None,
                              revisionExpr=m.revisionExpr,
                              revisionId=None)
            self._projects[project.name] = [project]
            self._paths[project.relpath] = project
예제 #4
0
  def _ParseDefault(self, node):
    """
    reads a <default> element from the manifest file
    """
    d = _Default()
    d.remote = self._get_remote(node)
    d.revisionExpr = node.getAttribute('revision')
    if d.revisionExpr == '':
      d.revisionExpr = None

    d.destBranchExpr = node.getAttribute('dest-branch') or None
    d.upstreamExpr = node.getAttribute('upstream') or None

    d.sync_j = XmlInt(node, 'sync-j', 1)
    if d.sync_j <= 0:
      raise ManifestParseError('%s: sync-j must be greater than 0, not "%s"' %
                               (self.manifestFile, d.sync_j))

    d.sync_c = XmlBool(node, 'sync-c', False)
    d.sync_s = XmlBool(node, 'sync-s', False)
    d.sync_tags = XmlBool(node, 'sync-tags', True)
    return d
예제 #5
0
def XmlInt(node, attr, default=None):
    """Determine integer value of |node|'s |attr|.

  Args:
    node: XML node whose attributes we access.
    attr: The attribute to access.
    default: If the attribute is not set (value is empty), then use this.

  Returns:
    The number if the attribute is a valid number.

  Raises:
    ManifestParseError: The number is invalid.
  """
    value = node.getAttribute(attr)
    if not value:
        return default

    try:
        return int(value)
    except ValueError:
        raise ManifestParseError('manifest: invalid %s="%s" integer' % (attr, value))
예제 #6
0
    def _ParseProject(self, node, parent=None, **extra_proj_attrs):
        """
    reads a <project> element from the manifest file
    """
        name = self._reqatt(node, 'name')
        if parent:
            name = self._JoinName(parent.name, name)

        remote = self._get_remote(node)
        if remote is None:
            remote = self._default.remote
        if remote is None:
            raise ManifestParseError("no remote for project %s within %s" %
                                     (name, self.manifestFile))

        revisionExpr = node.getAttribute('revision') or remote.revision
        if not revisionExpr:
            revisionExpr = self._default.revisionExpr
        if not revisionExpr:
            raise ManifestParseError("no revision for project %s within %s" %
                                     (name, self.manifestFile))

        path = node.getAttribute('path')
        if not path:
            path = name
        if path.startswith('/'):
            raise ManifestParseError(
                "project %s path cannot be absolute in %s" %
                (name, self.manifestFile))

        rebase = XmlBool(node, 'rebase', True)
        sync_c = XmlBool(node, 'sync-c', False)
        sync_s = XmlBool(node, 'sync-s', self._default.sync_s)
        sync_tags = XmlBool(node, 'sync-tags', self._default.sync_tags)

        clone_depth = XmlInt(node, 'clone-depth')
        if clone_depth is not None and clone_depth <= 0:
            raise ManifestParseError(
                '%s: clone-depth must be greater than 0, not "%s"' %
                (self.manifestFile, clone_depth))

        dest_branch = node.getAttribute(
            'dest-branch') or self._default.destBranchExpr

        upstream = node.getAttribute('upstream') or self._default.upstreamExpr

        groups = ''
        if node.hasAttribute('groups'):
            groups = node.getAttribute('groups')
        groups = self._ParseGroups(groups)

        if parent is None:
            relpath, worktree, gitdir, objdir, use_git_worktrees = \
                self.GetProjectPaths(name, path)
        else:
            use_git_worktrees = False
            relpath, worktree, gitdir, objdir = \
                self.GetSubprojectPaths(parent, name, path)

        default_groups = ['all', 'name:%s' % name, 'path:%s' % relpath]
        groups.extend(set(default_groups).difference(groups))

        if self.IsMirror and node.hasAttribute('force-path'):
            if XmlBool(node, 'force-path', False):
                gitdir = os.path.join(self.topdir, '%s.git' % path)

        project = Project(manifest=self,
                          name=name,
                          remote=remote.ToRemoteSpec(name),
                          gitdir=gitdir,
                          objdir=objdir,
                          worktree=worktree,
                          relpath=relpath,
                          revisionExpr=revisionExpr,
                          revisionId=None,
                          rebase=rebase,
                          groups=groups,
                          sync_c=sync_c,
                          sync_s=sync_s,
                          sync_tags=sync_tags,
                          clone_depth=clone_depth,
                          upstream=upstream,
                          parent=parent,
                          dest_branch=dest_branch,
                          use_git_worktrees=use_git_worktrees,
                          **extra_proj_attrs)

        for n in node.childNodes:
            if n.nodeName == 'copyfile':
                self._ParseCopyFile(project, n)
            if n.nodeName == 'linkfile':
                self._ParseLinkFile(project, n)
            if n.nodeName == 'annotation':
                self._ParseAnnotation(project, n)
            if n.nodeName == 'project':
                project.subprojects.append(
                    self._ParseProject(n, parent=project))

        return project
예제 #7
0
    def _ParseManifest(self, node_list):
        for node in itertools.chain(*node_list):
            if node.nodeName == 'remote':
                remote = self._ParseRemote(node)
                if remote:
                    if remote.name in self._remotes:
                        if remote != self._remotes[remote.name]:
                            raise ManifestParseError(
                                'remote %s already exists with different attributes'
                                % (remote.name))
                    else:
                        self._remotes[remote.name] = remote

        for node in itertools.chain(*node_list):
            if node.nodeName == 'default':
                new_default = self._ParseDefault(node)
                if self._default is None:
                    self._default = new_default
                elif new_default != self._default:
                    raise ManifestParseError('duplicate default in %s' %
                                             (self.manifestFile))

        if self._default is None:
            self._default = _Default()

        for node in itertools.chain(*node_list):
            if node.nodeName == 'notice':
                if self._notice is not None:
                    raise ManifestParseError('duplicate notice in %s' %
                                             (self.manifestFile))
                self._notice = self._ParseNotice(node)

        for node in itertools.chain(*node_list):
            if node.nodeName == 'manifest-server':
                url = self._reqatt(node, 'url')
                if self._manifest_server is not None:
                    raise ManifestParseError(
                        'duplicate manifest-server in %s' %
                        (self.manifestFile))
                self._manifest_server = url

        def recursively_add_projects(project):
            projects = self._projects.setdefault(project.name, [])
            if project.relpath is None:
                raise ManifestParseError('missing path for %s in %s' %
                                         (project.name, self.manifestFile))
            if project.relpath in self._paths:
                raise ManifestParseError('duplicate path %s in %s' %
                                         (project.relpath, self.manifestFile))
            self._paths[project.relpath] = project
            projects.append(project)
            for subproject in project.subprojects:
                recursively_add_projects(subproject)

        for node in itertools.chain(*node_list):
            if node.nodeName == 'project':
                project = self._ParseProject(node)
                recursively_add_projects(project)
            if node.nodeName == 'extend-project':
                name = self._reqatt(node, 'name')

                if name not in self._projects:
                    raise ManifestParseError(
                        'extend-project element specifies non-existent '
                        'project: %s' % name)

                path = node.getAttribute('path')
                groups = node.getAttribute('groups')
                if groups:
                    groups = self._ParseGroups(groups)
                revision = node.getAttribute('revision')
                remote = node.getAttribute('remote')
                if remote:
                    remote = self._get_remote(node)

                for p in self._projects[name]:
                    if path and p.relpath != path:
                        continue
                    if groups:
                        p.groups.extend(groups)
                    if revision:
                        p.revisionExpr = revision
                    if remote:
                        p.remote = remote.ToRemoteSpec(name)
            if node.nodeName == 'repo-hooks':
                # Get the name of the project and the (space-separated) list of enabled.
                repo_hooks_project = self._reqatt(node, 'in-project')
                enabled_repo_hooks = self._reqatt(node, 'enabled-list').split()

                # Only one project can be the hooks project
                if self._repo_hooks_project is not None:
                    raise ManifestParseError('duplicate repo-hooks in %s' %
                                             (self.manifestFile))

                # Store a reference to the Project.
                try:
                    repo_hooks_projects = self._projects[repo_hooks_project]
                except KeyError:
                    raise ManifestParseError(
                        'project %s not found for repo-hooks' %
                        (repo_hooks_project))

                if len(repo_hooks_projects) != 1:
                    raise ManifestParseError(
                        'internal error parsing repo-hooks in %s' %
                        (self.manifestFile))
                self._repo_hooks_project = repo_hooks_projects[0]

                # Store the enabled hooks in the Project object.
                self._repo_hooks_project.enabled_repo_hooks = enabled_repo_hooks
            if node.nodeName == 'remove-project':
                name = self._reqatt(node, 'name')

                if name not in self._projects:
                    raise ManifestParseError(
                        'remove-project element specifies non-existent '
                        'project: %s' % name)

                for p in self._projects[name]:
                    del self._paths[p.relpath]
                del self._projects[name]

                # If the manifest removes the hooks project, treat it as if it deleted
                # the repo-hooks element too.
                if self._repo_hooks_project and (self._repo_hooks_project.name
                                                 == name):
                    self._repo_hooks_project = None
예제 #8
0
    def _ParseProject(self, node, parent=None, **extra_proj_attrs):
        """
    reads a <project> element from the manifest file
    """
        name = self._reqatt(node, 'name')
        if parent:
            name = self._JoinName(parent.name, name)

        remote = self._get_remote(node)
        if remote is None:
            remote = self._default.remote
        if remote is None:
            raise ManifestParseError("no remote for project %s within %s" %
                                     (name, self.manifestFile))

        revisionExpr = node.getAttribute('revision') or remote.revision
        if not revisionExpr:
            revisionExpr = self._default.revisionExpr
        if not revisionExpr:
            raise ManifestParseError("no revision for project %s within %s" %
                                     (name, self.manifestFile))

        path = node.getAttribute('path')
        if not path:
            path = name
        if path.startswith('/'):
            raise ManifestParseError(
                "project %s path cannot be absolute in %s" %
                (name, self.manifestFile))

        rebase = node.getAttribute('rebase')
        if not rebase:
            rebase = True
        else:
            rebase = rebase.lower() in ("yes", "true", "1")

        sync_c = node.getAttribute('sync-c')
        if not sync_c:
            sync_c = False
        else:
            sync_c = sync_c.lower() in ("yes", "true", "1")

        sync_s = node.getAttribute('sync-s')
        if not sync_s:
            sync_s = self._default.sync_s
        else:
            sync_s = sync_s.lower() in ("yes", "true", "1")

        clone_depth = node.getAttribute('clone-depth')
        if clone_depth:
            try:
                clone_depth = int(clone_depth)
                if clone_depth <= 0:
                    raise ValueError()
            except ValueError:
                raise ManifestParseError('invalid clone-depth %s in %s' %
                                         (clone_depth, self.manifestFile))

        dest_branch = node.getAttribute(
            'dest-branch') or self._default.destBranchExpr

        upstream = node.getAttribute('upstream')

        groups = ''
        if node.hasAttribute('groups'):
            groups = node.getAttribute('groups')
        groups = self._ParseGroups(groups)

        if parent is None:
            relpath, worktree, gitdir, objdir = self.GetProjectPaths(
                name, path)
        else:
            relpath, worktree, gitdir, objdir = \
                self.GetSubprojectPaths(parent, name, path)

        default_groups = ['all', 'name:%s' % name, 'path:%s' % relpath]
        groups.extend(set(default_groups).difference(groups))

        if self.IsMirror and node.hasAttribute('force-path'):
            if node.getAttribute('force-path').lower() in ("yes", "true", "1"):
                gitdir = os.path.join(self.topdir, '%s.git' % path)

        project = Project(manifest=self,
                          name=name,
                          remote=remote.ToRemoteSpec(name),
                          gitdir=gitdir,
                          objdir=objdir,
                          worktree=worktree,
                          relpath=relpath,
                          revisionExpr=revisionExpr,
                          revisionId=None,
                          rebase=rebase,
                          groups=groups,
                          sync_c=sync_c,
                          sync_s=sync_s,
                          clone_depth=clone_depth,
                          upstream=upstream,
                          parent=parent,
                          dest_branch=dest_branch,
                          **extra_proj_attrs)

        for n in node.childNodes:
            if n.nodeName == 'copyfile':
                self._ParseCopyFile(project, n)
            if n.nodeName == 'linkfile':
                self._ParseLinkFile(project, n)
            if n.nodeName == 'annotation':
                self._ParseAnnotation(project, n)
            if n.nodeName == 'project':
                project.subprojects.append(
                    self._ParseProject(n, parent=project))

        return project
예제 #9
0
    def _ParseManifest(self, node_list):
        for node in itertools.chain(*node_list):
            if node.nodeName == 'remote':
                remote = self._ParseRemote(node)
                if remote:
                    if remote.name in self._remotes:
                        if remote != self._remotes[remote.name]:
                            raise ManifestParseError(
                                'remote %s already exists with different attributes'
                                % (remote.name))
                    else:
                        self._remotes[remote.name] = remote

        for node in itertools.chain(*node_list):
            if node.nodeName == 'default':
                if self._default is not None:
                    raise ManifestParseError('duplicate default in %s' %
                                             (self.manifestFile))
                self._default = self._ParseDefault(node)
        if self._default is None:
            self._default = _Default()

        for node in itertools.chain(*node_list):
            if node.nodeName == 'notice':
                if self._notice is not None:
                    raise ManifestParseError('duplicate notice in %s' %
                                             (self.manifestFile))
                self._notice = self._ParseNotice(node)

        for node in itertools.chain(*node_list):
            if node.nodeName == 'manifest-server':
                url = self._reqatt(node, 'url')
                if self._manifest_server is not None:
                    raise ManifestParseError(
                        'duplicate manifest-server in %s' %
                        (self.manifestFile))
                self._manifest_server = url

        def recursively_add_projects(project):
            if self._projects.get(project.name):
                raise ManifestParseError('duplicate project %s in %s' %
                                         (project.name, self.manifestFile))
            self._projects[project.name] = project
            for subproject in project.subprojects:
                recursively_add_projects(subproject)

        for node in itertools.chain(*node_list):
            if node.nodeName == 'project':
                project = self._ParseProject(node)
                recursively_add_projects(project)
            if node.nodeName == 'repo-hooks':
                # Get the name of the project and the (space-separated) list of enabled.
                repo_hooks_project = self._reqatt(node, 'in-project')
                enabled_repo_hooks = self._reqatt(node, 'enabled-list').split()

                # Only one project can be the hooks project
                if self._repo_hooks_project is not None:
                    raise ManifestParseError('duplicate repo-hooks in %s' %
                                             (self.manifestFile))

                # Store a reference to the Project.
                try:
                    self._repo_hooks_project = self._projects[
                        repo_hooks_project]
                except KeyError:
                    raise ManifestParseError(
                        'project %s not found for repo-hooks' %
                        (repo_hooks_project))

                # Store the enabled hooks in the Project object.
                self._repo_hooks_project.enabled_repo_hooks = enabled_repo_hooks
            if node.nodeName == 'remove-project':
                name = self._reqatt(node, 'name')
                try:
                    del self._projects[name]
                except KeyError:
                    raise ManifestParseError(
                        'remove-project element specifies non-existent '
                        'project: %s' % name)

                # If the manifest removes the hooks project, treat it as if it deleted
                # the repo-hooks element too.
                if self._repo_hooks_project and (self._repo_hooks_project.name
                                                 == name):
                    self._repo_hooks_project = None
예제 #10
0
    def _ParseProject(self, node, parent=None):
        """
        reads a <project> element from the manifest file
        """
        name = self._reqatt(node, 'name')
        if parent:
            name = self._JoinName(parent.name, name)

        remote = self._get_remote(node)
        if remote is None:
            remote = self._default.remote
        if remote is None:
            raise ManifestParseError( \
                "no remote for project %s within %s" % \
                (name, self.manifestFile))

        revisionExpr = node.getAttribute('revision')
        if not revisionExpr:
            revisionExpr = self._default.revisionExpr
        if not revisionExpr:
            raise ManifestParseError( \
                "no revision for project %s within %s" % \
                (name, self.manifestFile))

        path = node.getAttribute('path')
        if not path:
            path = name
        if path.startswith('/'):
            raise ManifestParseError( \
                "project %s path cannot be absolute in %s" % \
                (name, self.manifestFile))

        rebase = node.getAttribute('rebase')
        if not rebase:
            rebase = True
        else:
            rebase = rebase.lower() in ("yes", "true", "1")

        sync_c = node.getAttribute('sync-c')
        if not sync_c:
            sync_c = False
        else:
            sync_c = sync_c.lower() in ("yes", "true", "1")

        sync_s = node.getAttribute('sync-s')
        if not sync_s:
            sync_s = self._default.sync_s
        else:
            sync_s = sync_s.lower() in ("yes", "true", "1")

        upstream = node.getAttribute('upstream')

        groups = ''
        if node.hasAttribute('groups'):
            groups = node.getAttribute('groups')
        groups = [x for x in re.split(r'[,\s]+', groups) if x]

        if parent is None:
            relpath, worktree, gitdir = self.GetProjectPaths(name, path)
        else:
            relpath, worktree, gitdir = self.GetSubprojectPaths(parent, path)

        default_groups = ['all', 'name:%s' % name, 'path:%s' % relpath]
        groups.extend(set(default_groups).difference(groups))

        project = Project(manifest=self,
                          name=name,
                          remote=remote.ToRemoteSpec(name),
                          gitdir=gitdir,
                          worktree=worktree,
                          relpath=relpath,
                          revisionExpr=revisionExpr,
                          revisionId=None,
                          rebase=rebase,
                          groups=groups,
                          sync_c=sync_c,
                          sync_s=sync_s,
                          upstream=upstream,
                          parent=parent)

        for n in node.childNodes:
            if n.nodeName == 'copyfile':
                self._ParseCopyFile(project, n)
            if n.nodeName == 'annotation':
                self._ParseAnnotation(project, n)
            if n.nodeName == 'project':
                project.subprojects.append(
                    self._ParseProject(n, parent=project))

        return project
예제 #11
0
    def _ParseManifest(self, is_root_file):
        root = xml.dom.minidom.parse(self.manifestFile)
        if not root or not root.childNodes:
            raise ManifestParseError("no root node in %s" % self.manifestFile)

        config = root.childNodes[0]
        if config.nodeName != 'manifest':
            raise ManifestParseError("no <manifest> in %s" % self.manifestFile)

        for node in config.childNodes:
            if node.nodeName == 'remove-project':
                name = self._reqatt(node, 'name')
                try:
                    del self._projects[name]
                except KeyError:
                    raise ManifestParseError('project %s not found' % (name))

                # If the manifest removes the hooks project, treat it as if it deleted
                # the repo-hooks element too.
                if self._repo_hooks_project and (self._repo_hooks_project.name
                                                 == name):
                    self._repo_hooks_project = None

        for node in config.childNodes:
            if node.nodeName == 'remote':
                remote = self._ParseRemote(node)
                if self._remotes.get(remote.name):
                    raise ManifestParseError('duplicate remote %s in %s' %
                                             (remote.name, self.manifestFile))
                self._remotes[remote.name] = remote

        for node in config.childNodes:
            if node.nodeName == 'default':
                if self._default is not None:
                    raise ManifestParseError('duplicate default in %s' %
                                             (self.manifestFile))
                self._default = self._ParseDefault(node)
        if self._default is None:
            self._default = _Default()

        for node in config.childNodes:
            if node.nodeName == 'notice':
                if self._notice is not None:
                    raise ManifestParseError('duplicate notice in %s' %
                                             (self.manifestFile))
                self._notice = self._ParseNotice(node)

        for node in config.childNodes:
            if node.nodeName == 'manifest-server':
                url = self._reqatt(node, 'url')
                if self._manifest_server is not None:
                    raise ManifestParseError(
                        'duplicate manifest-server in %s' %
                        (self.manifestFile))
                self._manifest_server = url

        for node in config.childNodes:
            if node.nodeName == 'project':
                project = self._ParseProject(node)
                if self._projects.get(project.name):
                    raise ManifestParseError('duplicate project %s in %s' %
                                             (project.name, self.manifestFile))
                self._projects[project.name] = project

        for node in config.childNodes:
            if node.nodeName == 'repo-hooks':
                # Get the name of the project and the (space-separated) list of enabled.
                repo_hooks_project = self._reqatt(node, 'in-project')
                enabled_repo_hooks = self._reqatt(node, 'enabled-list').split()

                # Only one project can be the hooks project
                if self._repo_hooks_project is not None:
                    raise ManifestParseError('duplicate repo-hooks in %s' %
                                             (self.manifestFile))

                # Store a reference to the Project.
                try:
                    self._repo_hooks_project = self._projects[
                        repo_hooks_project]
                except KeyError:
                    raise ManifestParseError(
                        'project %s not found for repo-hooks' %
                        (repo_hooks_project))

                # Store the enabled hooks in the Project object.
                self._repo_hooks_project.enabled_repo_hooks = enabled_repo_hooks