def merge_conflicting_changes(env: Environment): """Reconciles packages between local and remote""" remote_dir = env.local_io.get_remote_dir() remote_io = EnvIO(env_directory=remote_dir) remote_history = remote_io.get_history() local_history = env.history update_conda_environment(env_dir=remote_dir) if _r_env_needs_updating(local_history=local_history, remote_history=remote_history): update_r_environment(name=env.name, env_dir=remote_dir) EnvIO.overwrite_local(local_io=env.local_io, remote_io=remote_io) new_env = Environment(name=env.name, history=remote_history) new_env.validate() extra_logs = [] for log in local_history.logs: if log not in set(remote_history.logs): extra_logs.append(log) for log in extra_logs: new_env = _update_from_extra_log(env=new_env, history=local_history, log=log) new_env.validate() new_env.export() env.history = new_env.history logger.info("Successfully updated the environment.") return new_env
def test_export(mocker): name = "test-export" io_mock = mocker.patch("conda_env_tracker.env.EnvIO") mocker.patch( "conda_env_tracker.env.get_dependencies", mocker.Mock( return_value={ "conda": { "python": Package("python", "python=3.7.2=buildstr", "3.7.2", "buildstr") }, "pip": {}, }), ) mocker.patch("conda_env_tracker.history.get_pip_version", mocker.Mock(return_value="18.1")) history = History.parse({ "name": name, "channels": ["conda-forge", "main"], "packages": { "conda": { "python": "3.7.2=buildstr" } }, "logs": ["conda create --name test python=3.7"], "actions": ["conda create --name test python=3.7.2=buildstr"], "debug": [{ "platform": "osx", "conda_version": "4.6.1", "pip_version": "18.1" }], }) env = Environment(name=name, history=history) env.export() expected = """name: test-export channels: - conda-forge - main - nodefaults dependencies: - python=3.7.2=buildstr """ assert io_mock.mock_calls == [ mocker.call(env_directory=Path(USER_ENVS_DIR / name)), mocker.call().write_history_file(history=history), mocker.call().export_packages( contents=expected.replace("=buildstr", "")), mocker.call().delete_install_r(), ]
def pull(env: Environment, yes: bool = False) -> Environment: """Pull history from remote to local""" remote_dir = env.local_io.get_remote_dir() remote_io = EnvIO(env_directory=remote_dir) remote_history = remote_io.get_history() local_history = env.history _check_for_errors(local_history=local_history, remote_history=remote_history) if _nothing_to_pull(local_history=local_history, remote_history=remote_history): logger.info("Nothing to pull.") return env if _local_needs_update(local_history=local_history, remote_history=remote_history): update( env=env, remote_dir=remote_dir, remote_io=remote_io, remote_history=remote_history, ) return env if _actions_in_different_order( local_history=local_history, remote_history=remote_history ): if not yes and not prompt_yes_no( prompt_msg="Remote environment has same packages but in different order, " "Should we overwrite local with remote environment" ): logger.info("Exiting without updating local environment.") return env update( env=env, remote_dir=remote_dir, remote_io=remote_io, remote_history=remote_history, ) return env if not yes and not prompt_yes_no( prompt_msg=( "Remote and local have different packages, do you want to overwrite " "with remote and append local" ) ): logger.info("Exiting without updating local environment.") return env update_conda_environment(env_dir=remote_dir) if _r_env_needs_updating( local_history=local_history, remote_history=remote_history ): update_r_environment(name=env.name, env_dir=remote_dir) EnvIO.overwrite_local(local_io=env.local_io, remote_io=remote_io) new_env = Environment(name=env.name, history=remote_history) new_env.validate() extra_logs = [] for log in local_history.logs: if log not in set(remote_history.logs): extra_logs.append(log) for log in extra_logs: new_env = _update_from_extra_log(env=new_env, history=local_history, log=log) new_env = _update_r_packages( env=new_env, local_history=local_history, remote_history=remote_history ) new_env.validate() new_env.export() env.history = new_env.history logger.info("Successfully updated the environment.") return new_env