diff --git a/docs/manifest-format.md b/docs/manifest-format.md index ed297ae7..8e0049b3 100644 --- a/docs/manifest-format.md +++ b/docs/manifest-format.md @@ -90,6 +90,7 @@ following DTD: + @@ -337,6 +338,11 @@ against changes to the original manifest. Attribute `path`: If specified, limit the change to projects checked out at the specified path, rather than all projects with the given name. +Attribute `dest-path`: If specified, a path relative to the top directory +of the repo client where the Git working directory for this project +should be placed. This is used to move a project in the checkout by +overriding the existing `path` setting. + Attribute `groups`: List of additional groups to which this project belongs. Same syntax as the corresponding element of `project`. diff --git a/manifest_xml.py b/manifest_xml.py index 86f20202..39656975 100644 --- a/manifest_xml.py +++ b/manifest_xml.py @@ -868,6 +868,7 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md 'project: %s' % name) path = node.getAttribute('path') + dest_path = node.getAttribute('dest-path') groups = node.getAttribute('groups') if groups: groups = self._ParseList(groups) @@ -876,6 +877,10 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md if remote: remote = self._get_remote(node) + named_projects = self._projects[name] + if dest_path and not path and len(named_projects) > 1: + raise ManifestParseError('extend-project cannot use dest-path when ' + 'matching multiple projects: %s' % name) for p in self._projects[name]: if path and p.relpath != path: continue @@ -889,6 +894,12 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md p.revisionId = None if remote: p.remote = remote.ToRemoteSpec(name) + if dest_path: + del self._paths[p.relpath] + relpath, worktree, gitdir, objdir, _ = self.GetProjectPaths(name, dest_path) + p.UpdatePaths(relpath, worktree, gitdir, objdir) + self._paths[p.relpath] = p + if node.nodeName == 'repo-hooks': # Only one project can be the hooks project if repo_hooks_project is not None: diff --git a/project.py b/project.py index 634d88c5..9ff9df0b 100644 --- a/project.py +++ b/project.py @@ -519,13 +519,7 @@ class Project(object): self.client = self.manifest = manifest self.name = name self.remote = remote - self.gitdir = gitdir.replace('\\', '/') - self.objdir = objdir.replace('\\', '/') - if worktree: - self.worktree = os.path.normpath(worktree).replace('\\', '/') - else: - self.worktree = None - self.relpath = relpath + self.UpdatePaths(relpath, worktree, gitdir, objdir) self.revisionExpr = revisionExpr if revisionId is None \ @@ -556,16 +550,6 @@ class Project(object): self.copyfiles = [] self.linkfiles = [] self.annotations = [] - self.config = GitConfig.ForRepository(gitdir=self.gitdir, - defaults=self.client.globalConfig) - - if self.worktree: - self.work_git = self._GitGetByExec(self, bare=False, gitdir=gitdir) - else: - self.work_git = None - self.bare_git = self._GitGetByExec(self, bare=True, gitdir=gitdir) - self.bare_ref = GitRefs(gitdir) - self.bare_objdir = self._GitGetByExec(self, bare=True, gitdir=objdir) self.dest_branch = dest_branch self.old_revision = old_revision @@ -573,6 +557,27 @@ class Project(object): # project containing repo hooks. self.enabled_repo_hooks = [] + def UpdatePaths(self, relpath, worktree, gitdir, objdir): + """Update paths used by this project""" + self.gitdir = gitdir.replace('\\', '/') + self.objdir = objdir.replace('\\', '/') + if worktree: + self.worktree = os.path.normpath(worktree).replace('\\', '/') + else: + self.worktree = None + self.relpath = relpath + + self.config = GitConfig.ForRepository(gitdir=self.gitdir, + defaults=self.manifest.globalConfig) + + if self.worktree: + self.work_git = self._GitGetByExec(self, bare=False, gitdir=self.gitdir) + else: + self.work_git = None + self.bare_git = self._GitGetByExec(self, bare=True, gitdir=self.gitdir) + self.bare_ref = GitRefs(self.gitdir) + self.bare_objdir = self._GitGetByExec(self, bare=True, gitdir=self.objdir) + @property def Derived(self): return self.is_derived diff --git a/tests/test_manifest_xml.py b/tests/test_manifest_xml.py index ce422536..cb3eb855 100644 --- a/tests/test_manifest_xml.py +++ b/tests/test_manifest_xml.py @@ -797,3 +797,49 @@ class RemoveProjectElementTests(ManifestParseTestCase): """) self.assertEqual(manifest.projects, []) + + +class ExtendProjectElementTests(ManifestParseTestCase): + """Tests for .""" + + def test_extend_project_dest_path_single_match(self): + manifest = self.getXmlManifest(""" + + + + + + +""") + self.assertEqual(len(manifest.projects), 1) + self.assertEqual(manifest.projects[0].relpath, 'bar') + + def test_extend_project_dest_path_multi_match(self): + with self.assertRaises(manifest_xml.ManifestParseError): + manifest = self.getXmlManifest(""" + + + + + + + +""") + manifest.projects + + def test_extend_project_dest_path_multi_match_path_specified(self): + manifest = self.getXmlManifest(""" + + + + + + + +""") + self.assertEqual(len(manifest.projects), 2) + if manifest.projects[0].relpath == 'y': + self.assertEqual(manifest.projects[1].relpath, 'bar') + else: + self.assertEqual(manifest.projects[0].relpath, 'bar') + self.assertEqual(manifest.projects[1].relpath, 'y')