summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/manifest-format.md6
-rw-r--r--manifest_xml.py11
-rw-r--r--project.py39
-rw-r--r--tests/test_manifest_xml.py46
4 files changed, 85 insertions, 17 deletions
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:
90 <!ELEMENT extend-project EMPTY> 90 <!ELEMENT extend-project EMPTY>
91 <!ATTLIST extend-project name CDATA #REQUIRED> 91 <!ATTLIST extend-project name CDATA #REQUIRED>
92 <!ATTLIST extend-project path CDATA #IMPLIED> 92 <!ATTLIST extend-project path CDATA #IMPLIED>
93 <!ATTLIST extend-project dest-path CDATA #IMPLIED>
93 <!ATTLIST extend-project groups CDATA #IMPLIED> 94 <!ATTLIST extend-project groups CDATA #IMPLIED>
94 <!ATTLIST extend-project revision CDATA #IMPLIED> 95 <!ATTLIST extend-project revision CDATA #IMPLIED>
95 <!ATTLIST extend-project remote CDATA #IMPLIED> 96 <!ATTLIST extend-project remote CDATA #IMPLIED>
@@ -337,6 +338,11 @@ against changes to the original manifest.
337Attribute `path`: If specified, limit the change to projects checked out 338Attribute `path`: If specified, limit the change to projects checked out
338at the specified path, rather than all projects with the given name. 339at the specified path, rather than all projects with the given name.
339 340
341Attribute `dest-path`: If specified, a path relative to the top directory
342of the repo client where the Git working directory for this project
343should be placed. This is used to move a project in the checkout by
344overriding the existing `path` setting.
345
340Attribute `groups`: List of additional groups to which this project 346Attribute `groups`: List of additional groups to which this project
341belongs. Same syntax as the corresponding element of `project`. 347belongs. Same syntax as the corresponding element of `project`.
342 348
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
868 'project: %s' % name) 868 'project: %s' % name)
869 869
870 path = node.getAttribute('path') 870 path = node.getAttribute('path')
871 dest_path = node.getAttribute('dest-path')
871 groups = node.getAttribute('groups') 872 groups = node.getAttribute('groups')
872 if groups: 873 if groups:
873 groups = self._ParseList(groups) 874 groups = self._ParseList(groups)
@@ -876,6 +877,10 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
876 if remote: 877 if remote:
877 remote = self._get_remote(node) 878 remote = self._get_remote(node)
878 879
880 named_projects = self._projects[name]
881 if dest_path and not path and len(named_projects) > 1:
882 raise ManifestParseError('extend-project cannot use dest-path when '
883 'matching multiple projects: %s' % name)
879 for p in self._projects[name]: 884 for p in self._projects[name]:
880 if path and p.relpath != path: 885 if path and p.relpath != path:
881 continue 886 continue
@@ -889,6 +894,12 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
889 p.revisionId = None 894 p.revisionId = None
890 if remote: 895 if remote:
891 p.remote = remote.ToRemoteSpec(name) 896 p.remote = remote.ToRemoteSpec(name)
897 if dest_path:
898 del self._paths[p.relpath]
899 relpath, worktree, gitdir, objdir, _ = self.GetProjectPaths(name, dest_path)
900 p.UpdatePaths(relpath, worktree, gitdir, objdir)
901 self._paths[p.relpath] = p
902
892 if node.nodeName == 'repo-hooks': 903 if node.nodeName == 'repo-hooks':
893 # Only one project can be the hooks project 904 # Only one project can be the hooks project
894 if repo_hooks_project is not None: 905 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):
519 self.client = self.manifest = manifest 519 self.client = self.manifest = manifest
520 self.name = name 520 self.name = name
521 self.remote = remote 521 self.remote = remote
522 self.gitdir = gitdir.replace('\\', '/') 522 self.UpdatePaths(relpath, worktree, gitdir, objdir)
523 self.objdir = objdir.replace('\\', '/')
524 if worktree:
525 self.worktree = os.path.normpath(worktree).replace('\\', '/')
526 else:
527 self.worktree = None
528 self.relpath = relpath
529 self.revisionExpr = revisionExpr 523 self.revisionExpr = revisionExpr
530 524
531 if revisionId is None \ 525 if revisionId is None \
@@ -556,16 +550,6 @@ class Project(object):
556 self.copyfiles = [] 550 self.copyfiles = []
557 self.linkfiles = [] 551 self.linkfiles = []
558 self.annotations = [] 552 self.annotations = []
559 self.config = GitConfig.ForRepository(gitdir=self.gitdir,
560 defaults=self.client.globalConfig)
561
562 if self.worktree:
563 self.work_git = self._GitGetByExec(self, bare=False, gitdir=gitdir)
564 else:
565 self.work_git = None
566 self.bare_git = self._GitGetByExec(self, bare=True, gitdir=gitdir)
567 self.bare_ref = GitRefs(gitdir)
568 self.bare_objdir = self._GitGetByExec(self, bare=True, gitdir=objdir)
569 self.dest_branch = dest_branch 553 self.dest_branch = dest_branch
570 self.old_revision = old_revision 554 self.old_revision = old_revision
571 555
@@ -573,6 +557,27 @@ class Project(object):
573 # project containing repo hooks. 557 # project containing repo hooks.
574 self.enabled_repo_hooks = [] 558 self.enabled_repo_hooks = []
575 559
560 def UpdatePaths(self, relpath, worktree, gitdir, objdir):
561 """Update paths used by this project"""
562 self.gitdir = gitdir.replace('\\', '/')
563 self.objdir = objdir.replace('\\', '/')
564 if worktree:
565 self.worktree = os.path.normpath(worktree).replace('\\', '/')
566 else:
567 self.worktree = None
568 self.relpath = relpath
569
570 self.config = GitConfig.ForRepository(gitdir=self.gitdir,
571 defaults=self.manifest.globalConfig)
572
573 if self.worktree:
574 self.work_git = self._GitGetByExec(self, bare=False, gitdir=self.gitdir)
575 else:
576 self.work_git = None
577 self.bare_git = self._GitGetByExec(self, bare=True, gitdir=self.gitdir)
578 self.bare_ref = GitRefs(self.gitdir)
579 self.bare_objdir = self._GitGetByExec(self, bare=True, gitdir=self.objdir)
580
576 @property 581 @property
577 def Derived(self): 582 def Derived(self):
578 return self.is_derived 583 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):
797</manifest> 797</manifest>
798""") 798""")
799 self.assertEqual(manifest.projects, []) 799 self.assertEqual(manifest.projects, [])
800
801
802class ExtendProjectElementTests(ManifestParseTestCase):
803 """Tests for <extend-project>."""
804
805 def test_extend_project_dest_path_single_match(self):
806 manifest = self.getXmlManifest("""
807<manifest>
808 <remote name="default-remote" fetch="http://localhost" />
809 <default remote="default-remote" revision="refs/heads/main" />
810 <project name="myproject" />
811 <extend-project name="myproject" dest-path="bar" />
812</manifest>
813""")
814 self.assertEqual(len(manifest.projects), 1)
815 self.assertEqual(manifest.projects[0].relpath, 'bar')
816
817 def test_extend_project_dest_path_multi_match(self):
818 with self.assertRaises(manifest_xml.ManifestParseError):
819 manifest = self.getXmlManifest("""
820<manifest>
821 <remote name="default-remote" fetch="http://localhost" />
822 <default remote="default-remote" revision="refs/heads/main" />
823 <project name="myproject" path="x" />
824 <project name="myproject" path="y" />
825 <extend-project name="myproject" dest-path="bar" />
826</manifest>
827""")
828 manifest.projects
829
830 def test_extend_project_dest_path_multi_match_path_specified(self):
831 manifest = self.getXmlManifest("""
832<manifest>
833 <remote name="default-remote" fetch="http://localhost" />
834 <default remote="default-remote" revision="refs/heads/main" />
835 <project name="myproject" path="x" />
836 <project name="myproject" path="y" />
837 <extend-project name="myproject" path="x" dest-path="bar" />
838</manifest>
839""")
840 self.assertEqual(len(manifest.projects), 2)
841 if manifest.projects[0].relpath == 'y':
842 self.assertEqual(manifest.projects[1].relpath, 'bar')
843 else:
844 self.assertEqual(manifest.projects[0].relpath, 'bar')
845 self.assertEqual(manifest.projects[1].relpath, 'y')