Skip to content

Commit

Permalink
installer: preserve existing environment on failure
Browse files Browse the repository at this point in the history
This change ensures that if creation of a new environment fails, any
previously existing environment is restored.
  • Loading branch information
neersighted authored and abn committed Nov 12, 2021
1 parent 2bc3c7a commit 3487d4b
Showing 1 changed file with 42 additions and 33 deletions.
75 changes: 42 additions & 33 deletions install-poetry.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
- In `${POETRY_HOME}` if it's set.
- Installs the latest or given version of Poetry inside this virtual environment.
- Installs a `poetry` script in the Python user directory (or `${POETRY_HOME/bin}` if `POETRY_HOME` is set).
- On failure, the error log is written to poetry-installer-error-*.log.
- On failure, the error log is written to poetry-installer-error-*.log and any previously existing environment
is restored.
"""

import argparse
Expand Down Expand Up @@ -530,21 +531,13 @@ def install(self, version, upgrade=False):
)
)

env = self.make_env(version)
self.install_poetry(version, env)
self.make_bin(version, env)
with self.make_env(version) as env:
self.install_poetry(version, env)
self.make_bin(version, env)
self._data_dir.joinpath("VERSION").write_text(version)
self._install_comment(version, "Done")

self._overwrite(
"Installing {} ({}): {}".format(
colorize("info", "Poetry"),
colorize("b", version),
colorize("success", "Done"),
)
)

self._data_dir.joinpath("VERSION").write_text(version)

return 0
return 0

def uninstall(self) -> int:
if not self._data_dir.exists():
Expand Down Expand Up @@ -574,27 +567,49 @@ def uninstall(self) -> int:

return 0

def make_env(self, version: str) -> VirtualEnvironment:
def _install_comment(self, version: str, message: str):
self._overwrite(
"Installing {} ({}): {}".format(
colorize("info", "Poetry"),
colorize("b", version),
colorize("comment", "Creating environment"),
colorize("comment", message),
)
)

@contextmanager
def make_env(self, version: str) -> VirtualEnvironment:
env_path = self._data_dir.joinpath("venv")
return VirtualEnvironment.make(env_path)
env_path_saved = env_path.with_suffix(".save")

def make_bin(self, version: str, env: VirtualEnvironment) -> None:
self._overwrite(
"Installing {} ({}): {}".format(
colorize("info", "Poetry"),
colorize("b", version),
colorize("comment", "Creating script"),
)
)
if env_path.exists():
self._install_comment(version, "Saving existing environment")
if env_path_saved.exists():
shutil.rmtree(env_path_saved)
shutil.move(env_path, env_path_saved)

try:
self._install_comment(version, "Creating environment")
yield VirtualEnvironment.make(env_path)
except Exception as e: # noqa
if env_path.exists():
self._install_comment(
version, "An error occurred. Removing partial environment."
)
shutil.rmtree(env_path)

if env_path_saved.exists():
self._install_comment(
version, "Restoring previously saved environment."
)
shutil.move(env_path_saved, env_path)

raise e
else:
if env_path_saved.exists():
shutil.rmtree(env_path_saved, ignore_errors=True)

def make_bin(self, version: str, env: VirtualEnvironment) -> None:
self._install_comment(version, "Creating script")
self._bin_dir.mkdir(parents=True, exist_ok=True)

script = "poetry"
Expand All @@ -615,13 +630,7 @@ def make_bin(self, version: str, env: VirtualEnvironment) -> None:
shutil.copy(target_script, self._bin_dir.joinpath(script))

def install_poetry(self, version: str, env: VirtualEnvironment) -> None:
self._overwrite(
"Installing {} ({}): {}".format(
colorize("info", "Poetry"),
colorize("b", version),
colorize("comment", "Installing Poetry"),
)
)
self._install_comment(version, "Installing Poetry")

if self._git:
specification = "git+" + version
Expand Down

0 comments on commit 3487d4b

Please sign in to comment.