Skip to content
Open
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
14 changes: 14 additions & 0 deletions reccmp/project/common.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
import textwrap

RECCMP_PROJECT_CONFIG = "reccmp-project.yml"
RECCMP_USER_CONFIG = "reccmp-user.yml"
RECCMP_BUILD_CONFIG = "reccmp-build.yml"


def helper_create_project(target_name: str, filename: str, sha256: str) -> str:
"""Creates YML for a project file with one target using the given parameters."""
return textwrap.dedent(f"""\
targets:
{target_name}:
filename: {filename}
source-root: sources
hash:
sha256: {sha256}
""")
4 changes: 2 additions & 2 deletions reccmp/project/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def executable_or_library(path: Path) -> TargetType:
def get_default_cmakelists_txt(project_name: str, targets: dict[str, Path]) -> str:
"""Generate template CMakeLists.txt file contents to build each target."""
result = textwrap.dedent(f"""\
cmake_minimum_required(VERSION 3.20)
cmake_minimum_required(VERSION 3.20...4.3)
project({project_name})

include("${{CMAKE_CURRENT_SOURCE_DIR}}/cmake/reccmp.cmake")
Expand Down Expand Up @@ -246,7 +246,7 @@ def create_project(
f.write(f"{RECCMP_BUILD_CONFIG}\n")

if cmake:
# Generate tempalte files so you can start building each target with CMake.
# Generate template files so you can start building each target with CMake.
project_cmake_dir = project_directory / "cmake"
reccmp_cmake_path = project_cmake_dir / "reccmp.cmake"
project_cmake_dir.mkdir(exist_ok=True)
Expand Down
22 changes: 22 additions & 0 deletions reccmp/project/update.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import logging
from pathlib import Path
import shutil

from reccmp.assets import get_asset_file

logger = logging.getLogger(__name__)


def update_project(
project_directory: Path,
) -> None:
reccmp_cmake_path = project_directory / "cmake/reccmp.cmake"

if reccmp_cmake_path.is_file():
# Copy template CMake script that generates reccmp-build.yml
logger.info("Copying %s...", "cmake/reccmp.cmake")
shutil.copy(
get_asset_file("cmake/reccmp.cmake"),
reccmp_cmake_path,
)
logger.info("Done")
23 changes: 22 additions & 1 deletion reccmp/tools/project.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
import argparse
import logging
import enum
Expand All @@ -14,13 +14,15 @@
find_filename_recursively,
DetectWhat,
)
from reccmp.project.update import update_project

logger = logging.getLogger(__name__)


class ProjectSubcommand(enum.Enum):
CREATE = enum.auto()
DETECT = enum.auto()
UPDATE = enum.auto()


def main():
Expand Down Expand Up @@ -93,6 +95,9 @@ def main():
help="Detect original or recompiled binaries (default is original)",
)

update_parser = subparsers.add_parser("update")
update_parser.set_defaults(subcommand=ProjectSubcommand.UPDATE)

argparse_add_logging_args(parser=parser)

args = parser.parse_args()
Expand Down Expand Up @@ -131,6 +136,22 @@ def main():
except RecCmpProjectException as e:
logger.error("Project detection failed: %s", e.args[0])

elif args.subcommand == ProjectSubcommand.UPDATE:
project_path = find_filename_recursively(
directory=Path.cwd(), filename=RECCMP_PROJECT_CONFIG
)
if project_path is None:
parser.error(
f"Cannot find reccmp project. Run '{parser.prog} create' first."
)
try:
update_project(
project_directory=project_path,
)
return 0
except RecCmpProjectException as e:
logger.error("Project update failed: %s", e.args[0])

return 1


Expand Down
19 changes: 19 additions & 0 deletions tests/test_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@
RECCMP_BUILD_CONFIG,
RECCMP_PROJECT_CONFIG,
RECCMP_USER_CONFIG,
helper_create_project,
)
from reccmp.project.create import (
create_project,
RecCmpProjectAlreadyExistsError,
)
from reccmp.project.update import (
update_project,
)
from reccmp.project.config import (
ProjectFile,
UserFile,
Expand Down Expand Up @@ -398,3 +402,18 @@ def test_materialize_project_target():
del project.targets["TEST"].source_paths
with pytest.raises(IncompleteReccmpTargetError):
project.get("TEST")


def test_project_update_cmake_file(tmp_path_factory):
"""Test `reccmp-project detect --what original --search-path <file>`"""
project_text = helper_create_project("LEGO1", "LEGO1.DLL", LEGO1_SHA256)
project_root = tmp_path_factory.mktemp("project")
(project_root / RECCMP_PROJECT_CONFIG).write_text(project_text)
reccmp_cmake_path = project_root / "cmake/reccmp.cmake"
reccmp_cmake_path.parent.mkdir()
dummy_reccmp_cmake_contents = """message(STATUS "HELLO WORLD")\n"""
reccmp_cmake_path.write_text(dummy_reccmp_cmake_contents)
assert reccmp_cmake_path.read_text() == dummy_reccmp_cmake_contents

update_project(project_root)
assert reccmp_cmake_path.read_text() != dummy_reccmp_cmake_contents
15 changes: 1 addition & 14 deletions tests/test_project_detect.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
"""Tests for the detect_project() function, the main part of the reccmp-project utility."""

import textwrap

from reccmp.project.common import (
RECCMP_BUILD_CONFIG,
RECCMP_PROJECT_CONFIG,
RECCMP_USER_CONFIG,
helper_create_project,
)
from reccmp.project.config import (
BuildFile,
Expand All @@ -19,18 +18,6 @@
from .constants import LEGO1_SHA256


def helper_create_project(target_name: str, filename: str, sha256: str) -> str:
"""Creates YML for a project file with one target using the given parameters."""
return textwrap.dedent(f"""\
targets:
{target_name}:
filename: {filename}
source-root: sources
hash:
sha256: {sha256}
""")


def test_project_original_detection_miss(tmp_path_factory):
"""Test `reccmp-project detect --what original --search-path <dir>` without success"""
project_text = helper_create_project("LEGO1", "LEGO1.DLL", LEGO1_SHA256)
Expand Down
Loading