diff --git a/src/tufup/repo/__init__.py b/src/tufup/repo/__init__.py index 4302934..6eef251 100644 --- a/src/tufup/repo/__init__.py +++ b/src/tufup/repo/__init__.py @@ -594,8 +594,9 @@ def save_config(self): """Save current configuration.""" config_file_path = self.get_config_file_path() # make paths relative to current working directory (cwd), - # if possible, otherwise keep absolute paths (note, to avoid - # confusion, using paths other than cwd is discouraged) + # if possible, otherwise keep absolute paths (see #50) + # (note, to avoid confusion, using paths other than cwd is discouraged) + # also enforce posix paths on windows (see #147) temp_config_dict = self.config_dict # note self.config_dict is a property for key in ['repo_dir', 'keys_dir']: try: @@ -630,11 +631,12 @@ def load_config(cls) -> dict: logger.warning(f'config file not found: {file_path}') except json.JSONDecodeError: logger.warning(f'config file invalid: {file_path}') - # force posix paths (in case legacy windows config is loaded on linux, see #147) + # enforce posix paths (for legacy windows configs loaded on linux, see #147) for key in ['repo_dir', 'keys_dir']: value = config_dict.get(key) if value: - config_dict[key] = pathlib.Path(value).as_posix() + # interpret the value as a windows path (\\ or /) then enforce posix (/) + config_dict[key] = pathlib.PureWindowsPath(value).as_posix() return config_dict @classmethod diff --git a/tests/test_repo.py b/tests/test_repo.py index 42fae9b..88fde46 100644 --- a/tests/test_repo.py +++ b/tests/test_repo.py @@ -561,7 +561,6 @@ def test_save_config_windows_paths(self): with self.subTest(msg=key): self.assertEqual(kwargs[key].replace('\\', '/'), config[key]) - def test_load_config(self): # file does not exist self.assertEqual(dict(), Repository.load_config()) @@ -570,6 +569,19 @@ def test_load_config(self): # test self.assertEqual(dict(), Repository.load_config()) + @unittest.skipIf(condition=ON_WINDOWS, reason='posix only') + def test_load_config_windows_paths(self): + # prepare (mix windows paths and posix paths for convenience) + mock_config = dict(repo_dir='foo\\repo', keys_dir='/tmp/bar/keys') + config_path = Repository.get_config_file_path() + config_path.write_text(json.dumps(mock_config)) + print(config_path.read_text()) + # test + config = Repository.load_config() + for key in mock_config.keys(): + with self.subTest(msg=key): + self.assertEqual(mock_config[key].replace('\\', '/'), config[key]) + def test_from_config(self): temp_dir = self.temp_dir_path.resolve() repo_dir_abs = temp_dir / 'repo'