Skip to content

Install dependencies from local path using symlinks #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 26 additions & 27 deletions compilesketches/compilesketches.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class RunCommandOutput(enum.Enum):
not_applicable_indicator = "N/A"
relative_size_report_decimal_places = 2

temporary_directory = tempfile.TemporaryDirectory(prefix="compilesketches-")
arduino_cli_installation_path = pathlib.Path.home().joinpath("bin")
arduino_cli_user_directory_path = pathlib.Path.home().joinpath("Arduino")
arduino_cli_data_directory_path = pathlib.Path.home().joinpath(".arduino15")
Expand Down Expand Up @@ -254,7 +255,7 @@ def install_from_download(self, url, source_path, destination_parent_path, desti
"""
destination_parent_path = pathlib.Path(destination_parent_path)

# Create temporary folder for the download
# Create temporary folder with function duration for the download
with tempfile.TemporaryDirectory("-compilesketches-download_folder") as download_folder:
download_file_path = pathlib.PurePath(download_folder, url.rsplit(sep="/", maxsplit=1)[1])

Expand All @@ -268,23 +269,24 @@ def install_from_download(self, url, source_path, destination_parent_path, desti
break
out_file.write(block)

# Create temporary folder for the extraction
with tempfile.TemporaryDirectory("-compilesketches-extract_folder") as extract_folder:
# Extract archive
shutil.unpack_archive(filename=str(download_file_path), extract_dir=extract_folder)
# Create temporary folder with script run duration for the extraction
extract_folder = tempfile.mkdtemp(dir=self.temporary_directory.name, prefix="install_from_download-")

archive_root_path = get_archive_root_path(extract_folder)
# Extract archive
shutil.unpack_archive(filename=str(download_file_path), extract_dir=extract_folder)

absolute_source_path = pathlib.Path(archive_root_path, source_path).resolve()
archive_root_path = get_archive_root_path(extract_folder)

if not absolute_source_path.exists():
print("::error::Archive source path:", source_path, "not found")
sys.exit(1)
absolute_source_path = pathlib.Path(archive_root_path, source_path).resolve()

self.install_from_path(source_path=absolute_source_path,
destination_parent_path=destination_parent_path,
destination_name=destination_name,
force=force)
if not absolute_source_path.exists():
print("::error::Archive source path:", source_path, "not found")
sys.exit(1)

self.install_from_path(source_path=absolute_source_path,
destination_parent_path=destination_parent_path,
destination_name=destination_name,
force=force)

def install_platforms(self):
"""Install Arduino boards platforms."""
Expand Down Expand Up @@ -537,7 +539,7 @@ def __init__(self):
return platform_installation_path

def install_from_path(self, source_path, destination_parent_path, destination_name=None, force=False):
"""Copy the source path to the destination path.
"""Create a symlink to the source path in the destination path.

Keyword arguments:
source_path -- path to install
Expand All @@ -563,10 +565,7 @@ def install_from_path(self, source_path, destination_parent_path, destination_na
# Create the parent path if it doesn't already exist
destination_parent_path.mkdir(parents=True, exist_ok=True)

if source_path.is_dir():
shutil.copytree(src=source_path, dst=destination_path)
else:
shutil.copy(src=source_path, dst=destination_path)
destination_path.symlink_to(target=source_path, target_is_directory=source_path.is_dir())

def install_platforms_from_repository(self, platform_list):
"""Install libraries by cloning Git repositories
Expand Down Expand Up @@ -628,14 +627,14 @@ def install_from_repository(self,
# Use the repository name
destination_name = url.rstrip("/").rsplit(sep="/", maxsplit=1)[1].rsplit(sep=".", maxsplit=1)[0]

# Clone to a temporary folder to allow installing from subfolders of repos
with tempfile.TemporaryDirectory() as clone_folder:
self.clone_repository(url=url, git_ref=git_ref, destination_path=clone_folder)
# Install to the final location
self.install_from_path(source_path=pathlib.Path(clone_folder, source_path),
destination_parent_path=destination_parent_path,
destination_name=destination_name,
force=force)
# Clone to a temporary folder with script run duration to allow installing from subfolders of repos
clone_folder = tempfile.mkdtemp(dir=self.temporary_directory.name, prefix="install_from_repository-")
self.clone_repository(url=url, git_ref=git_ref, destination_path=clone_folder)
# Install to the final location
self.install_from_path(source_path=pathlib.Path(clone_folder, source_path),
destination_parent_path=destination_parent_path,
destination_name=destination_name,
force=force)

def clone_repository(self, url, git_ref, destination_path):
"""Clone a Git repository to a specified location and check out the specified ref
Expand Down
29 changes: 9 additions & 20 deletions compilesketches/tests/test_compilesketches.py
Original file line number Diff line number Diff line change
Expand Up @@ -1252,14 +1252,15 @@ def test_install_from_path(capsys,
exists,
force,
is_dir):
is_dir = unittest.mock.sentinel.is_dir

compile_sketches = get_compilesketches_object()

mocker.patch.object(pathlib.Path, "exists", autospec=True, return_value=exists)
mocker.patch("shutil.rmtree", autospec=True)
mocker.patch.object(pathlib.Path, "mkdir", autospec=True)
mocker.patch.object(pathlib.Path, "is_dir", autospec=True, return_value=is_dir)
mocker.patch("shutil.copytree", autospec=True)
mocker.patch("shutil.copy", autospec=True)
mocker.patch.object(pathlib.Path, "symlink_to", autospec=True)

if exists and not force:
with pytest.raises(expected_exception=SystemExit, match="1"):
Expand All @@ -1281,10 +1282,8 @@ def test_install_from_path(capsys,
else:
shutil.rmtree.assert_not_called()

if is_dir:
shutil.copytree.assert_called_once_with(src=source_path, dst=expected_destination_path)
else:
shutil.copy.assert_called_once_with(src=source_path, dst=expected_destination_path)
pathlib.Path.symlink_to.assert_called_once_with(expected_destination_path, target=source_path,
target_is_directory=is_dir)


def test_install_from_path_functional(tmp_path):
Expand Down Expand Up @@ -2610,19 +2609,7 @@ def test_install_from_repository(mocker, url, source_path, destination_name, exp
force = unittest.mock.sentinel.force
clone_path = pathlib.PurePath("/foo/ClonePath")

# Stub
class TemporaryDirectory:
def __init__(self, temporary_directory):
self.temporary_directory = temporary_directory

def __enter__(self):
return self.temporary_directory

def __exit__(self, *exc):
pass

mocker.patch("tempfile.TemporaryDirectory", autospec=True,
return_value=TemporaryDirectory(temporary_directory=clone_path))
mocker.patch("tempfile.mkdtemp", autospec=True, return_value=clone_path)
mocker.patch("compilesketches.CompileSketches.clone_repository", autospec=True)
mocker.patch("compilesketches.CompileSketches.install_from_path", autospec=True)

Expand All @@ -2635,7 +2622,9 @@ def __exit__(self, *exc):
destination_name=destination_name,
force=force)

tempfile.TemporaryDirectory.assert_called_once()
# noinspection PyUnresolvedReferences
tempfile.mkdtemp.assert_called_once_with(dir=compile_sketches.temporary_directory.name,
prefix="install_from_repository-")
compile_sketches.clone_repository.assert_called_once_with(compile_sketches,
url=url,
git_ref=git_ref,
Expand Down