From 79c194dc8519a2eaf7d6d696141f85f54465415d Mon Sep 17 00:00:00 2001 From: Scott K Logan Date: Thu, 18 Sep 2025 15:56:26 -0500 Subject: [PATCH] Make all tests work offline Relying only on local resources results in more reliable test results and enables development without reliable internet access. Signed-off-by: Scott K Logan --- test/__init__.py | 258 ++++++++++++++++++++++++++++++++ test/branch.txt | 2 +- test/export_exact.txt | 8 +- test/export_exact_with_tags.txt | 6 +- test/import.txt | 10 +- test/import_shallow.txt | 16 +- test/list.repos | 24 --- test/list2.repos | 17 --- test/log_limit.txt | 20 +-- test/log_merges_only.txt | 20 +-- test/reimport_force.txt | 8 +- test/reimport_skip.txt | 4 +- test/remotes_repos.txt | 16 +- test/status.txt | 2 +- test/test_commands.py | 85 ++++++----- test/validate.txt | 12 +- test/validate2.txt | 8 +- 17 files changed, 366 insertions(+), 150 deletions(-) create mode 100644 test/__init__.py delete mode 100644 test/list.repos delete mode 100644 test/list2.repos diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 0000000..a1c4d1d --- /dev/null +++ b/test/__init__.py @@ -0,0 +1,258 @@ +"""Fixtures and utilities for testing vcs2l.""" + +import os +import shutil +import subprocess +import tarfile +import unittest +import zipfile +from shutil import which +from tempfile import TemporaryDirectory +from urllib.parse import urljoin +from urllib.request import pathname2url + +import yaml + + +def to_file_url(path): + return urljoin('file:', pathname2url(path)) + + +class StagedReposFile(unittest.TestCase): + """Fixture for testing git, tar, and zip clients.""" + + _git = which('git') + _git_env = { + **os.environ, + 'GIT_AUTHOR_NAME': 'vcs2l', + 'GIT_AUTHOR_DATE': '2005-01-01T00:00:00-06:00', + 'GIT_AUTHOR_EMAIL': 'vcs2l@example.com', + 'GIT_COMMITTER_NAME': 'vcs2l', + 'GIT_COMMITTER_DATE': '2005-01-01T00:00:00-06:00', + 'GIT_COMMITTER_EMAIL': 'vcs2l@example.com', + 'GIT_CONFIG_GLOBAL': os.path.join(os.path.dirname(__file__), '.gitconfig'), + 'LANG': 'en_US.UTF-8', + } + _commit_date = '2005-01-01T00:00:00' + + temp_dir = None + repos_file_path = None + + @classmethod + def setUpClass(cls): + if not cls._git: + raise unittest.SkipTest('`git` was not found') + + cls.temp_dir = TemporaryDirectory(suffix='.vcstmp') + + # Create the staged git repository + gitrepo_path = os.path.join(cls.temp_dir.name, 'gitrepo') + os.mkdir(gitrepo_path) + shutil.copy( + os.path.join(os.path.dirname(os.path.dirname(__file__)), 'LICENSE'), + gitrepo_path, + ) + for command in ( + ('init', '--quiet', '.'), + ('commit', '--quiet', '--allow-empty', '-m', '0.1.26'), + ('tag', '0.1.26'), + ('checkout', '--quiet', '-b', 'license'), + ('add', 'LICENSE'), + ('commit', '--quiet', '-m', 'Add LICENSE'), + ('checkout', '--quiet', 'main'), + ('merge', '--no-ff', '--quiet', 'license', '-m', "Merge branch 'license'"), + ('branch', '--quiet', '-D', 'license'), + ('commit', '--quiet', '--allow-empty', '-m', 'update changelog'), + ('commit', '--quiet', '--allow-empty', '-m', '0.1.27'), + ('tag', '0.1.27'), + ('commit', '--quiet', '--allow-empty', '-m', "codin' codin' codin'"), + ): + subprocess.check_call( + [ + cls._git, + *command, + ], + cwd=gitrepo_path, + env=cls._git_env, + ) + + # Create the archive stage + archive_path = os.path.join(cls.temp_dir.name, 'archive_dir') + os.mkdir(archive_path) + with open(os.path.join(archive_path, 'file_name.txt'), 'wb') as f: + f.write(b'Lorem Ipsum\n') + + # Create a tar file + tarball_path = os.path.join(cls.temp_dir.name, 'archive.tar.gz') + with tarfile.TarFile.open(tarball_path, 'w:gz') as f: + f.add(archive_path, 'archive_dir') + + # Create a zip file + zip_path = os.path.join(cls.temp_dir.name, 'archive.zip') + with zipfile.ZipFile(zip_path, mode='w') as f: + f.write( + os.path.join(archive_path, 'file_name.txt'), + os.path.join('archive_dir', 'file_name.txt'), + ) + + # Populate the staged.repos file + repos = { + 'immutable/hash': { + 'type': 'git', + 'url': to_file_url(gitrepo_path), + 'version': '5b3504594f7354121cf024dc734bf79e270cffd3', + }, + 'immutable/hash_tar': { + 'type': 'tar', + 'url': to_file_url(tarball_path), + 'version': 'archive_dir', + }, + 'immutable/hash_zip': { + 'type': 'zip', + 'url': to_file_url(zip_path), + 'version': 'archive_dir', + }, + 'immutable/tag': { + 'type': 'git', + 'url': to_file_url(gitrepo_path), + 'version': 'tags/0.1.27', + }, + 'vcs2l': { + 'type': 'git', + 'url': to_file_url(gitrepo_path), + 'version': 'heads/main', + }, + 'without_version': { + 'type': 'git', + 'url': to_file_url(gitrepo_path), + }, + } + + cls.repos_file_path = os.path.join(cls.temp_dir.name, 'staged.repos') + with open(cls.repos_file_path, 'wb') as f: + yaml.safe_dump({'repositories': repos}, f, encoding='utf-8') + + @classmethod + def tearDownClass(cls): + cls.repos_file_path = None + if cls.temp_dir: + cls.temp_dir.cleanup() + cls.temp_dir = None + + +class StagedReposFile2(unittest.TestCase): + """Fixture for testing subversion and mercurial clients.""" + + _svn = which('svn') + _svnadmin = which('svnadmin') + _hg = which('hg') + _hg_env = { + **os.environ, + 'HGUSER': 'vcs2l', + 'EMAIL': 'vcs2l@example.com', + } + _commit_date = '2005-01-01T00:00:00-06:00' + + temp_dir = None + repos_file_path = None + + @classmethod + def setUpClass(cls): + if not cls._svn: + raise unittest.SkipTest('`svn` was not found') + if not cls._svnadmin: + raise unittest.SkipTest('`svnadmin` was not found') + if not cls._hg: + raise unittest.SkipTest('`hg` was not found') + try: + # check if the svn executable is usable (on macOS) + # and not only exists to state that the program is not installed + subprocess.check_call([cls._svn, '--version'], stdout=subprocess.DEVNULL) + except subprocess.CalledProcessError as e: + raise unittest.SkipTest('`svn` was not found') from e + + cls.temp_dir = TemporaryDirectory(suffix='.vcstmp') + + # Create the staged subversion repository + svnrepo_path = os.path.join(cls.temp_dir.name, 'svnrepo') + os.mkdir(svnrepo_path) + subprocess.check_call( + [ + 'svnadmin', + 'create', + '.', + ], + cwd=svnrepo_path, + ) + + svnclone_path = os.path.join(cls.temp_dir.name, 'svnclone') + os.mkdir(svnclone_path) + shutil.copy( + os.path.join(os.path.dirname(os.path.dirname(__file__)), 'LICENSE'), + svnclone_path, + ) + for command in ( + ('checkout', to_file_url(svnrepo_path), '.', '--quiet'), + ('add', 'LICENSE', '--quiet'), + ('commit', 'LICENSE', '-m', 'Initial commit', '--quiet'), + ): + subprocess.check_call( + [ + cls._svn, + *command, + ], + cwd=svnclone_path, + ) + + # Create the staged mercurial repository + hgrepo_path = os.path.join(cls.temp_dir.name, 'hgrepo') + os.mkdir(hgrepo_path) + for command in ( + ('init', '.'), + ('branch', '--quiet', 'stable'), + ('commit', '-m', 'Initial commit', '-d', cls._commit_date), + ('tag', '-d', cls._commit_date, '5.8'), + ): + subprocess.check_call( + [ + cls._hg, + *command, + ], + cwd=hgrepo_path, + env=cls._hg_env, + ) + + # Populate the staged.repos file + repos = { + 'hg/branch': { + 'type': 'hg', + 'url': to_file_url(hgrepo_path), + 'version': 'stable', + }, + 'hg/hash': { + 'type': 'hg', + 'url': to_file_url(hgrepo_path), + 'version': '9bd654917508', + }, + 'hg/tag': { + 'type': 'hg', + 'url': to_file_url(hgrepo_path), + 'version': '5.8', + }, + 'svn/rev': { + 'type': 'svn', + 'url': to_file_url(svnrepo_path), + 'version': '1', + }, + } + + cls.repos_file_path = os.path.join(cls.temp_dir.name, 'staged.repos') + with open(cls.repos_file_path, 'wb') as f: + yaml.safe_dump({'repositories': repos}, f, encoding='utf-8') + + @classmethod + def tearDownClass(cls): + cls.repos_file_path = None + if cls.temp_dir: + cls.temp_dir.cleanup() + cls.temp_dir = None diff --git a/test/branch.txt b/test/branch.txt index c0a2e41..61818b8 100644 --- a/test/branch.txt +++ b/test/branch.txt @@ -1,6 +1,6 @@ .... === ./immutable/hash (git) === -(HEAD detached at 377d5b3) +(HEAD detached at 5b35045) === ./immutable/tag (git) === (HEAD detached at 0.1.27) === ./vcs2l (git) === diff --git a/test/export_exact.txt b/test/export_exact.txt index 2524fa0..c466690 100644 --- a/test/export_exact.txt +++ b/test/export_exact.txt @@ -1,9 +1,9 @@ repositories: hash: type: git - url: https://github.com/ros-infrastructure/vcs2l.git - version: 377d5b3d03c212f015cc832fdb368f4534d0d583 + url: file:///vcstmp/gitrepo + version: 5b3504594f7354121cf024dc734bf79e270cffd3 tag: type: git - url: https://github.com/ros-infrastructure/vcs2l.git - version: bf9ca56de693a02b93ed423bcef589259d75eb0f + url: file:///vcstmp/gitrepo + version: 8087b72504968800cdf54759b11e0b753ec90736 diff --git a/test/export_exact_with_tags.txt b/test/export_exact_with_tags.txt index d42a985..59cd53b 100644 --- a/test/export_exact_with_tags.txt +++ b/test/export_exact_with_tags.txt @@ -1,9 +1,9 @@ repositories: hash: type: git - url: https://github.com/ros-infrastructure/vcs2l.git - version: 377d5b3d03c212f015cc832fdb368f4534d0d583 + url: file:///vcstmp/gitrepo + version: 5b3504594f7354121cf024dc734bf79e270cffd3 tag: type: git - url: https://github.com/ros-infrastructure/vcs2l.git + url: file:///vcstmp/gitrepo version: 0.1.27 diff --git a/test/import.txt b/test/import.txt index e90a3af..95523e2 100644 --- a/test/import.txt +++ b/test/import.txt @@ -1,7 +1,7 @@ ...... === ./immutable/hash (git) === Cloning into '.'... -Note: switching to '377d5b3d03c212f015cc832fdb368f4534d0d583'. +Note: switching to '5b3504594f7354121cf024dc734bf79e270cffd3'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this @@ -18,11 +18,11 @@ Or undo this operation with: Turn off this advice by setting config variable advice.detachedHead to false -HEAD is now at 377d5b3... update changelog +HEAD is now at 5b35045... update changelog === ./immutable/hash_tar (tar) === -Downloaded tarball from 'https://github.com/ros-infrastructure/vcs2l/archive/377d5b3d03c212f015cc832fdb368f4534d0d583.tar.gz' and unpacked it +Downloaded tarball from 'file:///vcstmp/archive.tar.gz' and unpacked it === ./immutable/hash_zip (zip) === -Downloaded zipfile from 'https://github.com/ros-infrastructure/vcs2l/archive/377d5b3d03c212f015cc832fdb368f4534d0d583.zip' and unpacked it +Downloaded zipfile from 'file:///vcstmp/archive.zip' and unpacked it === ./immutable/tag (git) === Cloning into '.'... Note: switching to 'tags/0.1.27'. @@ -42,7 +42,7 @@ Or undo this operation with: Turn off this advice by setting config variable advice.detachedHead to false -HEAD is now at bf9ca56... 0.1.27 +HEAD is now at 8087b72... 0.1.27 === ./vcs2l (git) === Cloning into '.'... === ./without_version (git) === diff --git a/test/import_shallow.txt b/test/import_shallow.txt index 3bca974..e664894 100644 --- a/test/import_shallow.txt +++ b/test/import_shallow.txt @@ -2,9 +2,9 @@ === ./immutable/hash (git) === Initialized empty Git repository in ./immutable/hash/.git/ -From https://github.com/ros-infrastructure/vcs2l - * branch 377d5b3d03c212f015cc832fdb368f4534d0d583 -> FETCH_HEAD -Note: switching to '377d5b3d03c212f015cc832fdb368f4534d0d583'. +From file:///vcstmp/gitrepo + * branch 5b3504594f7354121cf024dc734bf79e270cffd3 -> FETCH_HEAD +Note: switching to '5b3504594f7354121cf024dc734bf79e270cffd3'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this @@ -21,15 +21,15 @@ Or undo this operation with: Turn off this advice by setting config variable advice.detachedHead to false -HEAD is now at 377d5b3... update changelog +HEAD is now at 5b35045... update changelog === ./immutable/hash_tar (tar) === -Downloaded tarball from 'https://github.com/ros-infrastructure/vcs2l/archive/377d5b3d03c212f015cc832fdb368f4534d0d583.tar.gz' and unpacked it +Downloaded tarball from 'file:///vcstmp/archive.tar.gz' and unpacked it === ./immutable/hash_zip (zip) === -Downloaded zipfile from 'https://github.com/ros-infrastructure/vcs2l/archive/377d5b3d03c212f015cc832fdb368f4534d0d583.zip' and unpacked it +Downloaded zipfile from 'file:///vcstmp/archive.zip' and unpacked it === ./immutable/tag (git) === Initialized empty Git repository in ./immutable/tag/.git/ -From https://github.com/ros-infrastructure/vcs2l +From file:///vcstmp/gitrepo * [new tag] 0.1.27 -> 0.1.27 Note: switching to 'tags/0.1.27'. @@ -48,7 +48,7 @@ Or undo this operation with: Turn off this advice by setting config variable advice.detachedHead to false -HEAD is now at bf9ca56... 0.1.27 +HEAD is now at 8087b72... 0.1.27 === ./vcs2l (git) === Cloning into '.'... === ./without_version (git) === diff --git a/test/list.repos b/test/list.repos deleted file mode 100644 index 5696e91..0000000 --- a/test/list.repos +++ /dev/null @@ -1,24 +0,0 @@ -repositories: - immutable/hash: - type: git - url: https://github.com/ros-infrastructure/vcs2l.git - version: 377d5b3d03c212f015cc832fdb368f4534d0d583 - immutable/hash_tar: - type: tar - url: https://github.com/ros-infrastructure/vcs2l/archive/377d5b3d03c212f015cc832fdb368f4534d0d583.tar.gz - version: vcs2l-377d5b3d03c212f015cc832fdb368f4534d0d583 - immutable/hash_zip: - type: zip - url: https://github.com/ros-infrastructure/vcs2l/archive/377d5b3d03c212f015cc832fdb368f4534d0d583.zip - version: vcs2l-377d5b3d03c212f015cc832fdb368f4534d0d583 - immutable/tag: - type: git - url: https://github.com/ros-infrastructure/vcs2l.git - version: tags/0.1.27 - vcs2l: - type: git - url: https://github.com/ros-infrastructure/vcs2l.git - version: heads/main - without_version: - type: git - url: https://github.com/ros-infrastructure/vcs2l.git diff --git a/test/list2.repos b/test/list2.repos deleted file mode 100644 index be1dbe6..0000000 --- a/test/list2.repos +++ /dev/null @@ -1,17 +0,0 @@ -repositories: - hg/branch: - type: hg - url: https://www.mercurial-scm.org/repo/hg-stable - version: stable - hg/hash: - type: hg - url: https://www.mercurial-scm.org/repo/hg-stable - version: 6d79894d3460 - hg/tag: - type: hg - url: https://www.mercurial-scm.org/repo/hg-stable - version: 5.8 - svn/rev: - type: svn - url: https://svn.apache.org/repos/asf/subversion - version: 1928014 diff --git a/test/log_limit.txt b/test/log_limit.txt index eee49cd..a60a59a 100644 --- a/test/log_limit.txt +++ b/test/log_limit.txt @@ -1,22 +1,22 @@ .. === ./hash (git) === -commit 377d5b3d03c212f015cc832fdb368f4534d0d583 (HEAD) -Author: Dirk Thomas +commit 5b3504594f7354121cf024dc734bf79e270cffd3 (HEAD) +Author: vcs2l update changelog -commit f01ce3845fa0783bef9f97545e518e0f02cd509a -Merge: 14f9968 e7770d3 -Author: Dirk Thomas +commit e1ac7fa53634c69bdb8e181a20d3717e52dea234 +Merge: 89e3430 ec135e9 +Author: vcs2l - Merge pull request #44 from dirk-thomas/fix_loop_exit + Merge branch 'license' === ./tag (git) === -commit bf9ca56de693a02b93ed423bcef589259d75eb0f (HEAD, tag: 0.1.27) -Author: Dirk Thomas +commit 8087b72504968800cdf54759b11e0b753ec90736 (HEAD, tag: 0.1.27) +Author: vcs2l 0.1.27 -commit 377d5b3d03c212f015cc832fdb368f4534d0d583 -Author: Dirk Thomas +commit 5b3504594f7354121cf024dc734bf79e270cffd3 +Author: vcs2l update changelog diff --git a/test/log_merges_only.txt b/test/log_merges_only.txt index 2001edc..ce49b9c 100644 --- a/test/log_merges_only.txt +++ b/test/log_merges_only.txt @@ -1,18 +1,6 @@ === . (git) === -commit f01ce3845fa0783bef9f97545e518e0f02cd509a -Merge: 14f9968 e7770d3 -Author: Dirk Thomas +commit e1ac7fa53634c69bdb8e181a20d3717e52dea234 +Merge: 89e3430 ec135e9 +Author: vcs2l - Merge pull request #44 from dirk-thomas/fix_loop_exit - -commit 418cd63cc242aeb19bff17696adf1617b9c994b7 -Merge: 6fdb8e8 89448bd -Author: Dirk Thomas - - Merge pull request #42 from dirk-thomas/fix_depends_regression - -commit a3c4c33d9e958a5d297e2d1d777fe2d850b2566f -Merge: a5dfaac 8a7101c -Author: Dirk Thomas - - Merge pull request #41 from dirk-thomas/parent_path_dependencies + Merge branch 'license' diff --git a/test/reimport_force.txt b/test/reimport_force.txt index e9ff222..791a028 100644 --- a/test/reimport_force.txt +++ b/test/reimport_force.txt @@ -1,14 +1,14 @@ ...... === ./immutable/hash (git) === -HEAD is now at 377d5b3... update changelog +HEAD is now at 5b35045... update changelog === ./immutable/hash_tar (tar) === -Downloaded tarball from 'https://github.com/ros-infrastructure/vcs2l/archive/377d5b3d03c212f015cc832fdb368f4534d0d583.tar.gz' and unpacked it +Downloaded tarball from 'file:///vcstmp/archive.tar.gz' and unpacked it === ./immutable/hash_zip (zip) === -Downloaded zipfile from 'https://github.com/ros-infrastructure/vcs2l/archive/377d5b3d03c212f015cc832fdb368f4534d0d583.zip' and unpacked it +Downloaded zipfile from 'file:///vcstmp/archive.zip' and unpacked it === ./immutable/tag (git) === -HEAD is now at bf9ca56... 0.1.27 +HEAD is now at 8087b72... 0.1.27 === ./vcs2l (git) === Already on 'main' diff --git a/test/reimport_skip.txt b/test/reimport_skip.txt index e37be9b..c3f5a5a 100644 --- a/test/reimport_skip.txt +++ b/test/reimport_skip.txt @@ -1,9 +1,9 @@ ...... === ./immutable/hash (git) === === ./immutable/hash_tar (tar) === -Downloaded tarball from 'https://github.com/ros-infrastructure/vcs2l/archive/377d5b3d03c212f015cc832fdb368f4534d0d583.tar.gz' and unpacked it +Downloaded tarball from 'file:///vcstmp/archive.tar.gz' and unpacked it === ./immutable/hash_zip (zip) === -Downloaded zipfile from 'https://github.com/ros-infrastructure/vcs2l/archive/377d5b3d03c212f015cc832fdb368f4534d0d583.zip' and unpacked it +Downloaded zipfile from 'file:///vcstmp/archive.zip' and unpacked it === ./immutable/tag (git) === === ./vcs2l (git) === === ./without_version (git) === diff --git a/test/remotes_repos.txt b/test/remotes_repos.txt index 10a0187..3b08f59 100644 --- a/test/remotes_repos.txt +++ b/test/remotes_repos.txt @@ -4,14 +4,14 @@ ./without_version (git) .... === ./immutable/hash (git) === -origin https://github.com/ros-infrastructure/vcs2l.git (fetch) -origin https://github.com/ros-infrastructure/vcs2l.git (push) +origin file:///vcstmp/gitrepo (fetch) +origin file:///vcstmp/gitrepo (push) === ./immutable/tag (git) === -origin https://github.com/ros-infrastructure/vcs2l.git (fetch) -origin https://github.com/ros-infrastructure/vcs2l.git (push) +origin file:///vcstmp/gitrepo (fetch) +origin file:///vcstmp/gitrepo (push) === ./vcs2l (git) === -origin https://github.com/ros-infrastructure/vcs2l.git (fetch) -origin https://github.com/ros-infrastructure/vcs2l.git (push) +origin file:///vcstmp/gitrepo (fetch) +origin file:///vcstmp/gitrepo (push) === ./without_version (git) === -origin https://github.com/ros-infrastructure/vcs2l.git (fetch) -origin https://github.com/ros-infrastructure/vcs2l.git (push) +origin file:///vcstmp/gitrepo (fetch) +origin file:///vcstmp/gitrepo (push) diff --git a/test/status.txt b/test/status.txt index 3eb0863..0c48ff2 100644 --- a/test/status.txt +++ b/test/status.txt @@ -1,6 +1,6 @@ .... === ./immutable/hash (git) === -HEAD detached at 377d5b3 +HEAD detached at 5b35045 nothing to commit, working tree clean === ./immutable/tag (git) === HEAD detached at 0.1.27 diff --git a/test/test_commands.py b/test/test_commands.py index a9c6ad7..151deef 100644 --- a/test/test_commands.py +++ b/test/test_commands.py @@ -1,46 +1,35 @@ import os +import re import subprocess import sys import unittest from io import StringIO -from shutil import which import vcs2l.executor as executor from vcs2l.clients.git import GitClient from vcs2l.commands.pull import main from vcs2l.util import rmtree -sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) +from . import StagedReposFile, StagedReposFile2, to_file_url -file_uri_scheme = 'file://' if sys.platform != 'win32' else 'file:///' +sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) -REPOS_FILE = os.path.join(os.path.dirname(__file__), 'list.repos') -REPOS_FILE_URL = file_uri_scheme + REPOS_FILE -REPOS2_FILE = os.path.join(os.path.dirname(__file__), 'list2.repos') BAD_REPOS_FILE = os.path.join(os.path.dirname(__file__), 'bad.repos') TEST_WORKSPACE = os.path.join( os.path.dirname(os.path.dirname(__file__)), 'test_workspace' ) -svn = which('svn') -hg = which('hg') -if svn: - # check if the svn executable is usable (on macOS) - # and not only exists to state that the program is not installed - try: - subprocess.check_call([svn, '--version']) - except subprocess.CalledProcessError: - svn = False - -class TestCommands(unittest.TestCase): +class TestCommands(StagedReposFile): @classmethod def setUpClass(cls): + super().setUpClass() + cls.repos_file_url = to_file_url(cls.repos_file_path) assert not os.path.exists(TEST_WORKSPACE) os.makedirs(TEST_WORKSPACE) try: - output = run_command('import', ['--input', REPOS_FILE, '.']) + output = run_command('import', ['--input', cls.repos_file_path, '.']) expected = get_expected_output('import') # newer git versions don't append three dots after the commit hash assert output == expected or output == expected.replace(b'... ', b' ') @@ -51,6 +40,7 @@ def setUpClass(cls): @classmethod def tearDownClass(cls): rmtree(TEST_WORKSPACE) + super().tearDownClass() def test_branch(self): output = run_command('branch') @@ -177,7 +167,9 @@ def test_reimport(self): stderr=subprocess.STDOUT, cwd=cwd_without_version, ) - output = run_command('import', ['--skip-existing', '--input', REPOS_FILE, '.']) + output = run_command( + 'import', ['--skip-existing', '--input', self.repos_file_path, '.'] + ) expected = get_expected_output('reimport_skip') # newer git versions don't append three dots after the commit hash assert output == expected or output == expected.replace(b'... ', b' ') @@ -187,9 +179,11 @@ def test_reimport(self): stderr=subprocess.STDOUT, cwd=cwd_without_version, ) - run_command('import', ['--skip-existing', '--input', REPOS_FILE, '.']) + run_command('import', ['--skip-existing', '--input', self.repos_file_path, '.']) - output = run_command('import', ['--force', '--input', REPOS_FILE, '.']) + output = run_command( + 'import', ['--force', '--input', self.repos_file_path, '.'] + ) expected = get_expected_output('reimport_force') # on Windows, the "Already on 'main'" message is after the # "Your branch is up to date with ..." message, so remove it @@ -215,7 +209,9 @@ def test_reimport_failed(self): ['git', 'remote', 'rm', 'origin'], stderr=subprocess.STDOUT, cwd=cwd_tag ) try: - run_command('import', ['--skip-existing', '--input', REPOS_FILE, '.']) + run_command( + 'import', ['--skip-existing', '--input', self.repos_file_path, '.'] + ) finally: subprocess.check_output( ['git', 'remote', 'rm', 'foo'], stderr=subprocess.STDOUT, cwd=cwd_tag @@ -226,7 +222,7 @@ def test_reimport_failed(self): 'remote', 'add', 'origin', - 'https://github.com/ros-infrastructure/vcs2l.git', + to_file_url(os.path.join(self.temp_dir.name, 'gitrepo')), ], stderr=subprocess.STDOUT, cwd=cwd_tag, @@ -238,7 +234,7 @@ def test_import_force_non_empty(self): try: output = run_command( 'import', - ['--force', '--input', REPOS_FILE, '.'], + ['--force', '--input', self.repos_file_path, '.'], subfolder='force-non-empty', ) expected = get_expected_output('import') @@ -253,7 +249,7 @@ def test_import_shallow(self): try: output = run_command( 'import', - ['--shallow', '--input', REPOS_FILE, '.'], + ['--shallow', '--input', self.repos_file_path, '.'], subfolder='import-shallow', ) # the actual output contains absolute paths @@ -279,7 +275,7 @@ def test_import_url(self): os.makedirs(workdir) try: output = run_command( - 'import', ['--input', REPOS_FILE_URL, '.'], subfolder='import-url' + 'import', ['--input', self.repos_file_url, '.'], subfolder='import-url' ) # the actual output contains absolute paths output = output.replace( @@ -297,11 +293,11 @@ def test_deletion(self): os.makedirs(workdir) try: run_command( - 'import', ['--input', REPOS_FILE_URL, '.'], subfolder='deletion' + 'import', ['--input', self.repos_file_url, '.'], subfolder='deletion' ) output = run_command( 'delete', - ['--force', '--input', REPOS_FILE_URL, '.'], + ['--force', '--input', self.repos_file_url, '.'], subfolder='deletion', ) expected = get_expected_output('delete') @@ -325,11 +321,13 @@ def test_deletion(self): rmtree(workdir) def test_validate(self): - output = run_command('validate', ['--input', REPOS_FILE]) + output = run_command('validate', ['--input', self.repos_file_path]) expected = get_expected_output('validate') self.assertEqual(output, expected) - output = run_command('validate', ['--hide-empty', '--input', REPOS_FILE]) + output = run_command( + 'validate', ['--hide-empty', '--input', self.repos_file_path] + ) expected = get_expected_output('validate_hide') # we don't care what order these messages appear in output = b'\n'.join(sorted(output.split(b'\n'))) @@ -340,13 +338,6 @@ def test_validate(self): expected = get_expected_output('validate_bad') self.assertEqual(output, expected) - @unittest.skipIf(not svn, '`svn` was not found') - @unittest.skipIf(not hg, '`hg` was not found') - def test_validate_svn_and_hg(self): - output = run_command('validate', ['--input', REPOS2_FILE]) - expected = get_expected_output('validate2') - self.assertEqual(output, expected) - def test_remote(self): output = run_command('remotes', args=['--repos']) expected = get_expected_output('remotes_repos') @@ -363,6 +354,24 @@ def test_status(self): self.assertEqual(output, expected) +class TestCommands2(StagedReposFile2): + @classmethod + def setUpClass(cls): + super().setUpClass() + assert not os.path.exists(TEST_WORKSPACE) + os.makedirs(TEST_WORKSPACE) + + @classmethod + def tearDownClass(cls): + rmtree(TEST_WORKSPACE) + super().tearDownClass() + + def test_validate_svn_and_hg(self): + output = run_command('validate', ['--input', self.repos_file_path]) + expected = get_expected_output('validate2') + self.assertEqual(output, expected) + + def run_command(command, args=None, subfolder=None): repo_root = os.path.dirname(os.path.dirname(__file__)) script = os.path.join(repo_root, 'scripts', 'vcs-' + command) @@ -418,6 +427,8 @@ def adapt_command_output(output, cwd=None): b'Turn off this advice by setting config variable ' b'advice.detachedHead to false', ) + # normalize temporary path locations + output = re.sub(rb'file://.*\.vcstmp', b'file:///vcstmp', output) if sys.platform == 'win32': if cwd: # on Windows, git prints full path to repos diff --git a/test/validate.txt b/test/validate.txt index 52723b7..f2fed2f 100644 --- a/test/validate.txt +++ b/test/validate.txt @@ -1,13 +1,13 @@ ...... === immutable/hash (git) === -Found git repository 'https://github.com/ros-infrastructure/vcs2l.git' but unable to verify non-branch / non-tag ref '377d5b3d03c212f015cc832fdb368f4534d0d583' without cloning the repo +Found git repository 'file:///vcstmp/gitrepo' but unable to verify non-branch / non-tag ref '5b3504594f7354121cf024dc734bf79e270cffd3' without cloning the repo === immutable/hash_tar (tar) === -Tarball url 'https://github.com/ros-infrastructure/vcs2l/archive/377d5b3d03c212f015cc832fdb368f4534d0d583.tar.gz' exists +Tarball url 'file:///vcstmp/archive.tar.gz' exists === immutable/hash_zip (zip) === -Zip url 'https://github.com/ros-infrastructure/vcs2l/archive/377d5b3d03c212f015cc832fdb368f4534d0d583.zip' exists +Zip url 'file:///vcstmp/archive.zip' exists === immutable/tag (git) === -Found git repository 'https://github.com/ros-infrastructure/vcs2l.git' with tag '0.1.27' +Found git repository 'file:///vcstmp/gitrepo' with tag '0.1.27' === vcs2l (git) === -Found git repository 'https://github.com/ros-infrastructure/vcs2l.git' with branch 'main' +Found git repository 'file:///vcstmp/gitrepo' with branch 'main' === without_version (git) === -Found git repository 'https://github.com/ros-infrastructure/vcs2l.git' with default branch +Found git repository 'file:///vcstmp/gitrepo' with default branch diff --git a/test/validate2.txt b/test/validate2.txt index 479c5e2..806aafd 100644 --- a/test/validate2.txt +++ b/test/validate2.txt @@ -1,9 +1,9 @@ .... === hg/branch (hg) === -Found hg repository 'https://www.mercurial-scm.org/repo/hg-stable' with changeset 'stable' +Found hg repository 'file:///vcstmp/hgrepo' with changeset 'stable' === hg/hash (hg) === -Found hg repository 'https://www.mercurial-scm.org/repo/hg-stable' with changeset '6d79894d3460' +Found hg repository 'file:///vcstmp/hgrepo' with changeset '9bd654917508' === hg/tag (hg) === -Found hg repository 'https://www.mercurial-scm.org/repo/hg-stable' with changeset '5.8' +Found hg repository 'file:///vcstmp/hgrepo' with changeset '5.8' === svn/rev (svn) === -Found svn repository 'https://svn.apache.org/repos/asf/subversion' with revision '1928014' +Found svn repository 'file:///vcstmp/svnrepo' with revision '1'