def test_create_workspace_selects_proper_remote_host(workspace_config): working_dir = workspace_config.root / "foo" / "bar" workspace_config.configurations.append( RemoteConfig( host="other-host.example.com", directory=Path("other/dir"), shell="bash", shell_options="some options", label="bar", )) workspace_config.configurations.append( RemoteConfig(host="foo.example.com", directory=Path("other/dir"), shell="bash", shell_options="some options", label="foo")) workspace_config.default_configuration = 1 # workspace should select host from workspace_config.default_configuration workspace = SyncedWorkspace.from_config(workspace_config, working_dir) assert workspace.local_root == workspace_config.root assert workspace.remote == workspace_config.configurations[1] assert workspace.remote_working_dir == workspace_config.configurations[ 1].directory / "foo" / "bar" assert workspace.ignores == workspace_config.ignores assert workspace.remote.label == "bar" # now it should select host from override workspace = SyncedWorkspace.from_config(workspace_config, working_dir, remote_host_id=0) assert workspace.local_root == workspace_config.root assert workspace.remote == workspace_config.configurations[0] assert workspace.remote_working_dir == workspace_config.configurations[ 0].directory / "foo" / "bar" assert workspace.ignores == workspace_config.ignores # now it should select from the label passed workspace = SyncedWorkspace.from_config(workspace_config, working_dir, remote_host_id="foo") assert workspace.local_root == workspace_config.root assert workspace.remote == workspace_config.configurations[2] assert workspace.remote_working_dir == workspace_config.configurations[ 2].directory / "foo" / "bar" assert workspace.ignores == workspace_config.ignores assert workspace_config.configurations[2].label == "foo" # now it should raise an exception as the label is not present with pytest.raises(InvalidRemoteHostLabel): workspace = SyncedWorkspace.from_config(workspace_config, working_dir, remote_host_id="iamnotpresent")
def test_medium_load_extensive_config(tmp_path): (tmp_path / CONFIG_FILE_NAME).write_text("""\ # First host test-host.example.com:remote/dir # Second host other-host.example.com:other/dir RSHELL=bash RSHELL_OPTS=options # Third host third-host.example.com:.remote/dir RSHELL=zsh """) (tmp_path / INDEX_FILE_NAME).write_text("3") (tmp_path / IGNORE_FILE_NAME).write_text(f"""\ push: .git *.pyc __pycache__ pull: src/generated both: build {CONFIG_FILE_NAME} {IGNORE_FILE_NAME} """) medium = ClassicConfigurationMedium() config = medium.load_config(tmp_path) assert config.root == tmp_path assert config.default_configuration == 2 assert len(config.configurations) == 3 assert config.configurations == [ RemoteConfig(host="test-host.example.com", directory=Path("remote/dir"), shell="sh", shell_options=""), RemoteConfig(host="other-host.example.com", directory=Path("other/dir"), shell="bash", shell_options="options"), RemoteConfig(host="third-host.example.com", directory=Path(".remote/dir"), shell="zsh", shell_options=""), ] assert config.ignores == SyncIgnores( pull=["src/generated"], push=[".git", "*.pyc", "__pycache__"], both=["build", CONFIG_FILE_NAME, IGNORE_FILE_NAME, INDEX_FILE_NAME], )
def test_medium_load_config_no_directory(mock_home): global_config_file = mock_home / GLOBAL_CONFIG global_config_file.parent.mkdir(parents=True) global_config_file.write_text( """ [general] allow_uninitiated_workspaces = true remote_root = "my-remotes" [[hosts]] host = "test-host.example.com" """ ) workspace = mock_home / "foo" / "bar" medium = TomlConfigurationMedium() config = medium.load_config(workspace) # The path is randomly generated so we need to replace it config.root = Path(str(config.root).replace(str(mock_home), "/root")) assert config == WorkspaceConfig( root=Path("/root/foo/bar"), configurations=[ RemoteConfig( host="test-host.example.com", directory=Path(f"my-remotes/bar_{hash_path(workspace)}"), shell="sh", shell_options="", ) ], default_configuration=0, ignores=SyncRules(pull=[], push=[], both=[".remote.toml"]), includes=SyncRules(pull=[], push=[], both=[]), )
def test_create_workspace_selects_proper_remote_host(workspace_config): working_dir = workspace_config.root / "foo" / "bar" workspace_config.configurations.append( RemoteConfig(host="other-host.example.com", directory=Path("other/dir"), shell="bash", shell_options="some options")) workspace_config.default_configuration = 1 # workspace should select host from workspace_config.default_configuration workspace = SyncedWorkspace.from_config(workspace_config, working_dir) assert workspace.local_root == workspace_config.root assert workspace.remote == workspace_config.configurations[1] assert workspace.remote_working_dir == workspace_config.configurations[ 1].directory / "foo" / "bar" assert workspace.ignores == workspace_config.ignores # now it should select host from overrid workspace = SyncedWorkspace.from_config(workspace_config, working_dir, config_num=0) assert workspace.local_root == workspace_config.root assert workspace.remote == workspace_config.configurations[0] assert workspace.remote_working_dir == workspace_config.configurations[ 0].directory / "foo" / "bar" assert workspace.ignores == workspace_config.ignores
def test_medium_save_config_with_host_and_index(workspace_config): workspace_config.configurations.append( RemoteConfig( host="other-host.example.com", directory=Path("other/dir"), shell="bash", shell_options="some options" ) ) workspace_config.default_configuration = 1 medium = ClassicConfigurationMedium() medium.save_config(workspace_config) root = workspace_config.root assert (root / CONFIG_FILE_NAME).exists() assert ( (root / CONFIG_FILE_NAME).read_text() == """\ test-host.example.com:remote/dir other-host.example.com:other/dir RSHELL=bash RSHELL_OPTS='some options' """ ) assert (root / INDEX_FILE_NAME).exists() assert (root / INDEX_FILE_NAME).read_text() == "2\n" assert (root / IGNORE_FILE_NAME).exists() assert ( root / IGNORE_FILE_NAME ).read_text() == f"pull:\npush:\nboth:\n{CONFIG_FILE_NAME}\n{IGNORE_FILE_NAME}\n{INDEX_FILE_NAME}\n"
def test_medium_load_config_picks_up_vsc_ignore_files(mock_home): text = """ [[hosts]] host = "test-host.example.com" port = 2022 directory = ".remotes/workspace" default = true [push] exclude = ["env", ".git"] [pull] include_vsc_ignore_patterns = true [both] exclude = ["build"] include_vcs_ignore_patterns = true """ workspace = mock_home / "foo" / "bar" local_config_file = workspace / WORKSPACE_CONFIG local_config_file.parent.mkdir(parents=True) local_config_file.write_text(text) ignore_file = workspace / ".gitignore" ignore_file.write_text(""" # comment # Comment *.pattern # comment pattern_two """) medium = TomlConfigurationMedium() config = medium.load_config(workspace) # The path is randomly generated so we need to replace it config.root = Path(str(config.root).replace(str(mock_home), "/root")) assert config == WorkspaceConfig( root=Path("/root/foo/bar"), configurations=[ RemoteConfig(host="test-host.example.com", directory=Path(".remotes/workspace"), port=2022) ], default_configuration=0, ignores=SyncRules( pull=["*.pattern", "pattern_two"], push=[".git", "env"], both=["build", ".remote.toml", "*.pattern", "pattern_two"], ), includes=SyncRules(pull=[], push=[], both=[]), )
def workspace_config(tmp_path): # a workspace with one remote host and all default values workspace_root = tmp_path / "workspace" workspace_root.mkdir() config = WorkspaceConfig.empty(workspace_root) config.configurations.append( RemoteConfig(host="test-host.example.com", directory=Path("remote/dir"), shell="sh", shell_options="") ) return config
def test_add_host_to_workspace(tmp_path): config = WorkspaceConfig.empty(tmp_path) added, index = config.add_remote_host("test-host", Path("remote/dir")) assert added assert index == 0 assert config.default_configuration == 0 assert len(config.configurations) == 1 assert config.configurations[0] == RemoteConfig( host="test-host", directory=Path("remote/dir"), shell="sh", shell_options="")
def test_medium_load_minimal_config(tmp_path): (tmp_path / CONFIG_FILE_NAME).write_text("test-host.example.com:remote/dir") medium = ClassicConfigurationMedium() config = medium.load_config(tmp_path) assert config.root == tmp_path assert config.default_configuration == 0 assert len(config.configurations) == 1 assert config.configurations[0] == RemoteConfig( host="test-host.example.com", directory=Path("remote/dir"), shell="sh", shell_options="" ) # Ignore is always pre-populated even if it's empy in FS assert config.ignores == SyncRules(pull=[], push=[], both=[CONFIG_FILE_NAME, IGNORE_FILE_NAME, INDEX_FILE_NAME])
[push] exclude = ["env", ".git"] include = ["env"] [pull] exclude = ["src/generated"] [both] exclude = ["build"] """, None, WorkspaceConfig( root=Path("/root/foo/bar"), configurations=[ RemoteConfig(host="test-host.example.com", directory=Path("my-remotes/foo/bar",), label="bar"), RemoteConfig(host="other-host.example.com", directory=Path("my-remotes/foo/bar"), label="foo"), ], default_configuration=1, ignores=SyncRules(pull=["src/generated"], push=[".git", "env"], both=["build", ".remote.toml"]), includes=SyncRules(pull=[], push=["env"], both=[]), ), ), # Settings from local config overwrite global ones ( """\ [general] use_relative_remote_paths = true [[hosts]] host = "other-host.example.com"
CONFIG_FILE_NAME, IGNORE_FILE_NAME, INDEX_FILE_NAME, ClassicConfigurationMedium, parse_config_line, ) from remote.exceptions import ConfigurationError @pytest.mark.parametrize( "input_line, expected", [ ( "test-host.example.com:remote/dir", RemoteConfig(host="test-host.example.com", directory=Path("remote/dir"), shell="sh", shell_options=""), ), ( "test-host.example.com:remote/dir RSHELL=bash", RemoteConfig(host="test-host.example.com", directory=Path("remote/dir"), shell="bash", shell_options=""), ), ( "test-host.example.com:remote/dir RSHELL='bash'", RemoteConfig(host="test-host.example.com", directory=Path("remote/dir"), shell="bash", shell_options=""),
default = true [push] exclude = ["env", ".git"] [pull] exclude = ["src/generated"] [both] exclude = ["build"] """, None, WorkspaceConfig( root=Path("/root/foo/bar"), configurations=[ RemoteConfig(host="test-host.example.com", directory=Path("my-remotes/foo/bar")), RemoteConfig(host="other-host.example.com", directory=Path("my-remotes/foo/bar")), ], default_configuration=1, ignores=SyncIgnores(pull=["src/generated"], push=[".git", "env"], both=["build", ".remote.toml"]), ), ), # Settings from local config overwrite global ones ( """\ [general] use_relative_remote_paths = true