From 2a089cfee4a3eb0c28cfb441861fc1fcb05797d3 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sat, 13 Nov 2021 23:29:42 -0500 Subject: project: migrate worktree .git/ dirs to symlinks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Historically we created a .git/ subdir in each source checkout and symlinked individual files to the .repo/projects/ paths. This layer of indirection isn't actually needed: the .repo/projects/ paths are guaranteed to only ever have a 1-to-1 mapping with the actual git checkout. So we don't need to worry about having files in .git/ be isolated. To that end, change how we manage the actual project checkouts from a dir full of symlinks (and a few files) to a symlink to the internal .repo/projects/ dir. This makes the code simpler & faster. The directory structure we have today is: .repo/ project-objects/chromiumos/third_party/kernel.git/ projects/src/third_party/kernel/ v3.8.git/ config description -> …/project-objects/…/config FETCH_HEAD HEAD hooks/ -> …/project-objects/…/hooks/ info/ -> …/project-objects/…/info/ logs/ objects/ -> …/project-objects/…/objects/ packed-refs refs/ rr-cache/ -> …/project-objects/…/rr-cache/ src/third_party/kernel/ v3.8/ .git/ config -> …/projects/…/v3.8.git/config description -> …/project-objects/…/v3.8.git/description HEAD hooks/ -> …/project-objects/…/v3.8.git/hooks/ index info/ -> …/project-objects/…/v3.8.git/info/ logs/ -> …/projects/…/v3.8.git/logs/ objects/ -> …/project-objects/…/v3.8.git/objects/ packed-refs -> …/projects/…/v3.8.git/packed-refs refs/ -> …/projects/…/v3.8.git/refs/ rr-cache/ -> …/project-objects/…/v3.8.git/rr-cache/ The directory structure we have after this commit: .repo/ src/third_party/kernel/ v3.8/ .git -> …/projects/…/v3.8.git Bug: https://crbug.com/gerrit/15273 Change-Id: I9dd8def23fbfb2f4cb209a93f8b1b2b24002a444 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/323695 Reviewed-by: Mike Nichols Reviewed-by: Xin Li Tested-by: Mike Frysinger --- tests/test_project.py | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'tests/test_project.py') diff --git a/tests/test_project.py b/tests/test_project.py index 9b2cc4e9..d578fe84 100644 --- a/tests/test_project.py +++ b/tests/test_project.py @@ -16,6 +16,7 @@ import contextlib import os +from pathlib import Path import shutil import subprocess import tempfile @@ -335,3 +336,52 @@ class LinkFile(CopyLinkTestCase): platform_utils.symlink(self.tempdir, dest) lf._Link() self.assertEqual(os.path.join('git-project', 'foo.txt'), os.readlink(dest)) + + +class MigrateWorkTreeTests(unittest.TestCase): + """Check _MigrateOldWorkTreeGitDir handling.""" + + _SYMLINKS = { + 'config', 'description', 'hooks', 'info', 'logs', 'objects', + 'packed-refs', 'refs', 'rr-cache', 'shallow', 'svn', + } + _FILES = { + 'COMMIT_EDITMSG', 'FETCH_HEAD', 'HEAD', 'index', 'ORIG_HEAD', + } + + @classmethod + @contextlib.contextmanager + def _simple_layout(cls): + """Create a simple repo client checkout to test against.""" + with tempfile.TemporaryDirectory() as tempdir: + tempdir = Path(tempdir) + + gitdir = tempdir / '.repo/projects/src/test.git' + gitdir.mkdir(parents=True) + cmd = ['git', 'init', '--bare', str(gitdir)] + subprocess.check_call(cmd) + + dotgit = tempdir / 'src/test/.git' + dotgit.mkdir(parents=True) + for name in cls._SYMLINKS: + (dotgit / name).symlink_to(f'../../../.repo/projects/src/test.git/{name}') + for name in cls._FILES: + (dotgit / name).write_text(name) + + subprocess.run(['tree', '-a', str(dotgit)]) + yield tempdir + + def test_standard(self): + """Migrate a standard checkout that we expect.""" + with self._simple_layout() as tempdir: + dotgit = tempdir / 'src/test/.git' + project.Project._MigrateOldWorkTreeGitDir(str(dotgit)) + + # Make sure the dir was transformed into a symlink. + self.assertTrue(dotgit.is_symlink()) + self.assertEqual(str(dotgit.readlink()), '../../.repo/projects/src/test.git') + + # Make sure files were moved over. + gitdir = tempdir / '.repo/projects/src/test.git' + for name in self._FILES: + self.assertEqual(name, (gitdir / name).read_text()) -- cgit v1.2.3-54-g00ecf