From d251941ee285093aafd6b96e63bb0e33c7233131 Mon Sep 17 00:00:00 2001 From: Renata Date: Thu, 17 Oct 2024 16:32:34 -0400 Subject: [PATCH 1/9] fix: fix list targets and validate commands when a target repo has no remote url --- taf/api/targets.py | 38 ++++++++++++++++++--------------- taf/exceptions.py | 6 ++++++ taf/git.py | 3 +++ taf/repositoriesdb.py | 38 +++++++++++++++++++++++++-------- taf/tools/targets/__init__.py | 11 +++++----- taf/updater/updater_pipeline.py | 3 +++ 6 files changed, 67 insertions(+), 32 deletions(-) diff --git a/taf/api/targets.py b/taf/api/targets.py index 51e77f71..18a864a4 100644 --- a/taf/api/targets.py +++ b/taf/api/targets.py @@ -18,7 +18,7 @@ ) from taf.api.utils._git import check_if_clean, commit_and_push from taf.constants import DEFAULT_RSA_SIGNATURE_SCHEME -from taf.exceptions import TAFError +from taf.exceptions import NoRemoteError, TAFError from taf.git import GitRepository from taf.messages import git_commit_message @@ -246,10 +246,9 @@ def export_targets_history( def list_targets( path: str, - library_dir: Optional[str] = None, ) -> None: """ - Prints a list of target repositories of an authentication repository and their states (are the work directories clean, are there + Returns a dictionary containing target repositories of an authentication repository and their states (are the work directories clean, are there remove changes that have not yed been pulled, are there commits that have not yet been signed). Arguments: @@ -285,28 +284,33 @@ def list_targets( repo_output["cloned"] = local_repo_exists if local_repo_exists: repo_output["bare"] = repo.is_bare_repository + repo_output["unsigned"] = [] # there will only be one branch since only data corresponding to the top auth commit was loaded for branch, branch_data in repo_data.items(): - repo_output["unsigned"] = False + has_remote = repo.has_remote() + repo_output["has-remote"] = has_remote + if not repo.branch_exists(branch, include_remotes=False): repo_output["up-to-date"] = False else: - is_synced_with_remote = repo.synced_with_remote(branch=branch) - repo_output["up-to-date"] = is_synced_with_remote - if not is_synced_with_remote: - last_signed_commit = branch_data[0]["commit"] - if branch in repo.branches_containing_commit( - last_signed_commit + if has_remote: + is_synced_with_remote = repo.synced_with_remote(branch=branch) + repo_output["up-to-date"] = is_synced_with_remote + + last_signed_commit = branch_data[0]["commit"] + if branch in repo.branches_containing_commit(last_signed_commit): + branch_top_commit = repo.top_commit_of_branch(branch) + unsigned_commits = repo.all_commits_since_commit( + last_signed_commit, branch + ) + if ( + len(unsigned_commits) + and branch_top_commit in unsigned_commits ): - branch_top_commit = repo.top_commit_of_branch(branch) - repo_output[ - "unsigned" - ] = branch_top_commit in repo.all_commits_since_commit( - last_signed_commit, branch - ) + repo_output["unsigned"].append(branch) repo_output["something-to-commit"] = repo.something_to_commit() - taf_logger.log("NOTICE", json.dumps(output, indent=4)) + return output @log_on_start(INFO, "Signing target files", logger=taf_logger) diff --git a/taf/exceptions.py b/taf/exceptions.py index 1ca1051f..885c3192 100644 --- a/taf/exceptions.py +++ b/taf/exceptions.py @@ -117,6 +117,12 @@ def __init__( self.message = message +class NoRemoteError(GitError): + def __init__(self, repo): + message = f"No remotes configured for repository {repo.name}" + super().__init__(message) + + class ScriptExecutionError(TAFError): def __init__(self, script: str, error_msg: str): message = ( diff --git a/taf/git.py b/taf/git.py index 40927e98..4296cea4 100644 --- a/taf/git.py +++ b/taf/git.py @@ -14,6 +14,7 @@ import taf.settings as settings from taf.exceptions import ( + NoRemoteError, NothingToCommitError, TAFError, CloneRepoException, @@ -1516,6 +1517,8 @@ def synced_with_remote( # check if the latest local commit matches # the latest remote commit on the specified branch + if not self.has_remote(): + raise NoRemoteError(self) if url: urls = [url] elif self.urls: diff --git a/taf/repositoriesdb.py b/taf/repositoriesdb.py index 15b5a899..8fd8dd99 100644 --- a/taf/repositoriesdb.py +++ b/taf/repositoriesdb.py @@ -184,6 +184,7 @@ def load_repositories( commits: Optional[List[str]] = None, roles: Optional[List[str]] = None, excluded_target_globs: Optional[List[str]] = None, + raise_error_if_no_urls: bool = False, ) -> None: """ Creates target repositories by reading repositories.json and targets.json files @@ -225,6 +226,7 @@ def load_repositories( commits=commits, roles=roles, excluded_target_globs=excluded_target_globs, + raise_error_if_no_urls=raise_error_if_no_urls, ) if commits is None or len(commits) == 0: commit = auth_repo.head_commit_sha() @@ -248,6 +250,7 @@ def _load_repositories( commits: Optional[List[str]] = None, roles: Optional[List[str]] = None, excluded_target_globs: Optional[List[str]] = None, + raise_error_if_no_urls: bool = False, ) -> Dict: repositories = {} @@ -304,7 +307,7 @@ def _load_repositories( skipped_targets.append(name) continue custom = _get_custom_data(repo_data, targets.get(name)) - urls = _get_urls(mirrors, name, repo_data) + urls = _get_urls(mirrors, name, repo_data, raise_error_if_no_urls) default_branch = _get_target_default_branch(auth_repo, name, commit) git_repo = _initialize_repository( factory, @@ -367,14 +370,18 @@ def _get_json_file(auth_repo, name, commit): ) -def _get_urls(mirrors, repo_name, repo_data=None) -> List[str]: +def _get_urls( + mirrors, repo_name, repo_data=None, raise_error_if_no_mirrors=False +) -> List[str]: if repo_data is not None and "urls" in repo_data: return repo_data["urls"] elif mirrors is None: - raise RepositoryInstantiationError( - repo_name, - f"{MIRRORS_JSON_PATH} does not exists or is not valid and no urls of {repo_name} specified in {REPOSITORIES_JSON_PATH}", - ) + if raise_error_if_no_mirrors: + raise RepositoryInstantiationError( + repo_name, + f"{MIRRORS_JSON_PATH} does not exists or is not valid and no urls of {repo_name} specified in {REPOSITORIES_JSON_PATH}", + ) + return [] try: org_name, repo_name = repo_name.split("/") @@ -458,7 +465,8 @@ def _compare(name): def get_deduplicated_auth_repositories( - auth_repo: AuthenticationRepository, commits: List[str] + auth_repo: AuthenticationRepository, + commits: List[str], ) -> Dict[str, AuthenticationRepository]: return _get_deduplicated_target_or_auth_repositories(auth_repo, commits, True) @@ -468,14 +476,25 @@ def get_deduplicated_repositories( commits: Optional[List[str]] = None, excluded_target_globs: Optional[List[str]] = None, library_dir: Optional[str] = None, + raise_error_if_no_urls=False, ) -> Dict[str, GitRepository]: return _get_deduplicated_target_or_auth_repositories( - auth_repo, commits, False, excluded_target_globs, library_dir + auth_repo, + commits, + False, + excluded_target_globs, + library_dir, + raise_error_if_no_urls, ) def _get_deduplicated_target_or_auth_repositories( - auth_repo, commits, load_auth=False, excluded_target_globs=None, library_dir=None + auth_repo, + commits, + load_auth=False, + excluded_target_globs=None, + library_dir=None, + raise_error_if_no_urls=False, ): if commits is None: commits = [auth_repo.head_commit_sha()] @@ -501,6 +520,7 @@ def _get_deduplicated_target_or_auth_repositories( commits=commits, excluded_target_globs=excluded_target_globs, library_dir=library_dir, + raise_error_if_no_urls=raise_error_if_no_urls, ) } diff --git a/taf/tools/targets/__init__.py b/taf/tools/targets/__init__.py index f9eebb3a..ae2a2a67 100644 --- a/taf/tools/targets/__init__.py +++ b/taf/tools/targets/__init__.py @@ -61,8 +61,7 @@ def add_repo(path, target_path, target_name, role, keystore, prompt_for_keys, no custom = json.loads(Path(custom_file).read_text()) except json.JSONDecodeError: taf_logger.error("Invalid custom JSON provided") - sys.exit(1) - + sys.exit add_target_repo( path=path, target_path=target_path, @@ -111,11 +110,11 @@ def list_targets_command(): - if they are up-to-date with remote - if there are uncommitted changes""") @find_repository - @catch_cli_exception(handle=TAFError) + @catch_cli_exception(handle=TAFError, print_error=True) @click.option("--path", default=".", help="Authentication repository's location. If not specified, set to the current directory") - @click.option("--library-dir", default=None, help="Directory where target repositories and, optionally, authentication repository are located. If omitted it is calculated based on authentication repository's path. Authentication repo is presumed to be at library-dir/namespace/auth-repo-name") - def list(path, library_dir): - list_targets(path, library_dir) + def list(path): + targets_status = list_targets(path) + taf_logger.log("NOTICE", json.dumps(targets_status, indent=4)) return list diff --git a/taf/updater/updater_pipeline.py b/taf/updater/updater_pipeline.py index a3954bb6..79863b01 100644 --- a/taf/updater/updater_pipeline.py +++ b/taf/updater/updater_pipeline.py @@ -434,10 +434,12 @@ def set_existing_target_repositories(self): library_dir=self.library_dir, only_load_targets=True, excluded_target_globs=self.excluded_target_globs, + raise_error_if_no_urls=True, ) target_repositories = repositoriesdb.get_deduplicated_repositories( self.state.users_auth_repo, excluded_target_globs=self.excluded_target_globs, + raise_error_if_no_urls=True, ) self.state.repos_on_disk = { target_repo.name: target_repo @@ -956,6 +958,7 @@ def load_target_repositories(self): self.state.auth_commits_since_last_validated[-1::], excluded_target_globs=self.excluded_target_globs, library_dir=self.library_dir, + raise_error_if_no_urls=not self.only_validate, ) ) if self.only_validate: From 7f2dc9b810741cafe1180ceae6047929945ba3bc Mon Sep 17 00:00:00 2001 From: Renata Date: Thu, 17 Oct 2024 16:39:38 -0400 Subject: [PATCH 2/9] chore: fix mypy issues --- taf/api/repository.py | 2 +- taf/api/targets.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/taf/api/repository.py b/taf/api/repository.py index 2957d86d..d4d32337 100644 --- a/taf/api/repository.py +++ b/taf/api/repository.py @@ -194,7 +194,7 @@ def taf_status(path: str, library_dir: Optional[str] = None, indent: int = 0) -> print(f"{indent_str}Something to commit: {auth_repo.something_to_commit()}") print(f"{indent_str}Target Repositories Status:") # Call the list_targets function - list_targets(path=path, library_dir=library_dir) + list_targets(path=path) # Load dependencies using repositoriesdb.get_auth_repositories repositoriesdb.load_dependencies(auth_repo, library_dir=library_dir) diff --git a/taf/api/targets.py b/taf/api/targets.py index 18a864a4..78b03737 100644 --- a/taf/api/targets.py +++ b/taf/api/targets.py @@ -18,7 +18,7 @@ ) from taf.api.utils._git import check_if_clean, commit_and_push from taf.constants import DEFAULT_RSA_SIGNATURE_SCHEME -from taf.exceptions import NoRemoteError, TAFError +from taf.exceptions import TAFError from taf.git import GitRepository from taf.messages import git_commit_message @@ -246,7 +246,7 @@ def export_targets_history( def list_targets( path: str, -) -> None: +) -> Dict: """ Returns a dictionary containing target repositories of an authentication repository and their states (are the work directories clean, are there remove changes that have not yed been pulled, are there commits that have not yet been signed). From df266d3c04a503c0e59d6994e8a2785bf7e9f2bb Mon Sep 17 00:00:00 2001 From: Renata Date: Thu, 17 Oct 2024 18:06:19 -0400 Subject: [PATCH 3/9] refact: move commit and push to auth repo, minor logging improvements --- taf/api/dependencies.py | 6 ++-- taf/api/metadata.py | 4 +-- taf/api/repository.py | 3 +- taf/api/roles.py | 14 ++++---- taf/api/targets.py | 8 ++--- taf/api/utils/_git.py | 31 ----------------- taf/auth_repo.py | 28 +++++++++++++++ taf/git.py | 55 +++++++++++++++++++----------- taf/tests/test_updater/conftest.py | 3 +- 9 files changed, 81 insertions(+), 71 deletions(-) diff --git a/taf/api/dependencies.py b/taf/api/dependencies.py index 7308655b..b239dba5 100644 --- a/taf/api/dependencies.py +++ b/taf/api/dependencies.py @@ -8,7 +8,7 @@ update_snapshot_and_timestamp, update_target_metadata, ) -from taf.api.utils._git import check_if_clean, commit_and_push +from taf.api.utils._git import check_if_clean from taf.messages import git_commit_message from pathlib import Path @@ -176,7 +176,7 @@ def add_dependency( commit_msg = git_commit_message( "add-dependency", dependency_name=dependency_name ) - commit_and_push(auth_repo, commit_msg=commit_msg, push=push) + auth_repo.commit_and_push(commit_msg=commit_msg, push=push) else: print("\nPlease commit manually.\n") @@ -266,7 +266,7 @@ def remove_dependency( commit_msg = git_commit_message( "remove-dependency", dependency_name=dependency_name ) - commit_and_push(auth_repo, commit_msg=commit_msg, push=push) + auth_repo.commit_and_push(commit_msg=commit_msg, push=push) else: print("\nPlease commit manually.\n") diff --git a/taf/api/metadata.py b/taf/api/metadata.py index 45b6d495..eda526da 100644 --- a/taf/api/metadata.py +++ b/taf/api/metadata.py @@ -2,7 +2,7 @@ from logging import INFO, ERROR from typing import Dict, List, Optional, Tuple from logdecorator import log_on_end, log_on_error -from taf.api.utils._git import check_if_clean, commit_and_push +from taf.api.utils._git import check_if_clean from taf.exceptions import TAFError from taf.keys import load_signing_keys from taf.constants import DEFAULT_RSA_SIGNATURE_SCHEME @@ -156,7 +156,7 @@ def update_metadata_expiration_date( commit_msg = git_commit_message( "update-expiration-dates", roles=",".join(roles) ) - commit_and_push(auth_repo, commit_msg=commit_msg, push=push) + auth_repo.commit_and_push(commit_msg=commit_msg, push=push) @log_on_end(INFO, "Updated expiration date of {role:s}", logger=taf_logger) diff --git a/taf/api/repository.py b/taf/api/repository.py index d4d32337..7b0d4cde 100644 --- a/taf/api/repository.py +++ b/taf/api/repository.py @@ -6,7 +6,6 @@ from taf.messages import git_commit_message from taf.models.types import RolesIterator from taf.models.types import RolesKeysData -from taf.api.utils._git import commit_and_push from taf.models.converter import from_dict from pathlib import Path @@ -125,7 +124,7 @@ def create_repository( if commit: auth_repo.init_repo() commit_msg = git_commit_message("create-repo") - commit_and_push(auth_repo, push=False, commit_msg=commit_msg) + auth_repo.commit_and_push(push=False, commit_msg=commit_msg) else: print("\nPlease commit manually.\n") diff --git a/taf/api/roles.py b/taf/api/roles.py index c66781fb..778f4b23 100644 --- a/taf/api/roles.py +++ b/taf/api/roles.py @@ -10,7 +10,7 @@ from taf.api.utils._roles import _role_obj, create_delegations from taf.messages import git_commit_message from tuf.repository_tool import Targets -from taf.api.utils._git import check_if_clean, commit_and_push +from taf.api.utils._git import check_if_clean from taf.exceptions import KeystoreError, TAFError from taf.models.converter import from_dict from taf.models.types import RolesIterator, TargetsRole, compare_roles_data @@ -140,7 +140,7 @@ def add_role( auth_repo, keystore, scheme=scheme, prompt_for_keys=prompt_for_keys ) commit_msg = git_commit_message("add-role", role=role) - commit_and_push(auth_repo, commit_msg=commit_msg, push=push) + auth_repo.commit_and_push(commit_msg=commit_msg, push=push) else: taf_logger.log("NOTICE", "\nPlease commit manually\n") @@ -206,7 +206,7 @@ def add_role_paths( commit_msg = git_commit_message( "add-role-paths", paths=", ".join(paths), role=delegated_role ) - commit_and_push(auth_repo, commit_msg=commit_msg, push=push) + auth_repo.commit_and_push(commit_msg=commit_msg, push=push) else: taf_logger.log("NOTICE", "\nPlease commit manually\n") else: @@ -303,7 +303,7 @@ def add_multiple_roles( if commit: roles_names = [role.name for role in new_roles] commit_msg = git_commit_message("add-roles", roles=", ".join(roles_names)) - commit_and_push(auth_repo, commit_msg=commit_msg, push=push) + auth_repo.commit_and_push(commit_msg=commit_msg, push=push) else: taf_logger.log("NOTICE", "\nPlease commit manually\n") @@ -414,7 +414,7 @@ def add_signing_key( # commit_msg = git_commit_message( # "add-signing-key", role={role} # ) - commit_and_push(auth_repo, commit_msg=commit_msg, push=push) + auth_repo.commit_and_push(commit_msg=commit_msg, push=push) else: taf_logger.log("NOTICE", "\nPlease commit manually\n") @@ -842,7 +842,7 @@ def remove_role( ) if commit: commit_msg = git_commit_message("remove-role", role=role) - commit_and_push(auth_repo, commit_msg=commit_msg, push=push) + auth_repo.commit_and_push(commit_msg=commit_msg, push=push) else: taf_logger.log("NOTICE", "Please commit manually") @@ -903,7 +903,7 @@ def remove_paths( commit_msg = git_commit_message( "remove-role-paths", paths=", ".join(paths), role=delegated_role ) - commit_and_push(auth_repo, commit_msg=commit_msg, push=push) + auth_repo.commit_and_push(commit_msg=commit_msg, push=push) elif delegation_existed: taf_logger.log("NOTICE", "\nPlease commit manually\n") return delegation_existed diff --git a/taf/api/targets.py b/taf/api/targets.py index 78b03737..255a8cf5 100644 --- a/taf/api/targets.py +++ b/taf/api/targets.py @@ -16,7 +16,7 @@ add_role_paths, remove_paths, ) -from taf.api.utils._git import check_if_clean, commit_and_push +from taf.api.utils._git import check_if_clean from taf.constants import DEFAULT_RSA_SIGNATURE_SCHEME from taf.exceptions import TAFError from taf.git import GitRepository @@ -185,7 +185,7 @@ def add_target_repo( ) if commit: commit_msg = git_commit_message("add-target", target_name=target_name) - commit_and_push(auth_repo, commit_msg=commit_msg, push=push) + auth_repo.commit_and_push(commit_msg=commit_msg, push=push) else: taf_logger.log("NOTICE", "\nPlease commit manually\n") @@ -265,7 +265,7 @@ def list_targets( head_commit = auth_repo.head_commit_sha() if head_commit is None: taf_logger.log("NOTICE", "Repository is empty") - return + return {} top_commit = [head_commit] repositoriesdb.load_repositories(auth_repo) target_repositories = repositoriesdb.get_deduplicated_repositories(auth_repo) @@ -377,7 +377,7 @@ def register_target_files( if commit: auth_repo = AuthenticationRepository(path=taf_repo.path) commit_msg = git_commit_message("update-targets") - commit_and_push(auth_repo, commit_msg=commit_msg, push=push) + auth_repo.commit_and_push(commit_msg=commit_msg, push=push) elif not no_commit_warning: taf_logger.log("NOTICE", "\nPlease commit manually\n") diff --git a/taf/api/utils/_git.py b/taf/api/utils/_git.py index f13c3ab5..56f33a2f 100644 --- a/taf/api/utils/_git.py +++ b/taf/api/utils/_git.py @@ -20,34 +20,3 @@ def wrapper(*args, **kwargs): return func(*args, **kwargs) return wrapper - - -def commit_and_push( - auth_repo: AuthenticationRepository, - commit_msg: Optional[str] = None, - push: Optional[bool] = True, -) -> None: - if commit_msg is None: - commit_msg = input("\nEnter commit message and press ENTER\n\n") - auth_repo.commit(commit_msg) - - if push and auth_repo.has_remote(): - try: - auth_repo.push() - taf_logger.log("NOTICE", "Successfully pushed to remote") - - new_commit_branch = auth_repo.default_branch - if new_commit_branch: - new_commit = auth_repo.top_commit_of_branch(new_commit_branch) - if new_commit: - auth_repo.set_last_validated_commit(new_commit) - taf_logger.info(f"Updated last_validated_commit to {new_commit}") - else: - taf_logger.warning( - "Default branch is None, skipping last_validated_commit update." - ) - except GitError as e: - taf_logger.error( - f"Push failed: {str(e)}. Please check if there are upstream changes." - ) - raise TAFError("Push operation failed") from e diff --git a/taf/auth_repo.py b/taf/auth_repo.py index 242991ba..36f2c42d 100644 --- a/taf/auth_repo.py +++ b/taf/auth_repo.py @@ -150,6 +150,34 @@ def log_prefix(self) -> str: return f"{self.alias}: " return f"Auth repo {self.name}: " + def commit_and_push( + self, + commit_msg: Optional[str] = None, + push: Optional[bool] = True, + commit: Optional[bool] = True, + ) -> None: + + if commit: + if commit_msg is None: + commit_msg = input("\nEnter commit message and press ENTER\n\n") + self.commit(commit_msg) + + if push: + push_successful = self.push() + if push_successful: + new_commit_branch = self.default_branch + if new_commit_branch: + new_commit = self.top_commit_of_branch(new_commit_branch) + if new_commit: + self.set_last_validated_commit(new_commit) + self._log_notice( + "NOTICE", f"Updated last_validated_commit to {new_commit}" + ) + else: + self._log_warning( + "Default branch is None, skipping last_validated_commit update." + ) + def get_target(self, target_name, commit=None, safely=True) -> Optional[Dict]: if commit is None: commit = self.head_commit_sha() diff --git a/taf/git.py b/taf/git.py index 4296cea4..573f2afe 100644 --- a/taf/git.py +++ b/taf/git.py @@ -9,7 +9,7 @@ import subprocess import logging from collections import OrderedDict -from functools import reduce +from functools import partial, reduce from pathlib import Path import taf.settings as settings @@ -24,7 +24,7 @@ UpdateFailedError, PygitError, ) -from taf.log import taf_logger +from taf.log import NOTICE, taf_logger from taf.utils import run from typing import Callable, Dict, List, Optional, Tuple, Union from .pygit import PyGitRepository @@ -144,6 +144,7 @@ def to_json_dict(self): logging_functions = { logging.DEBUG: taf_logger.debug, logging.INFO: taf_logger.info, + NOTICE: partial(taf_logger.log, "NOTICE"), logging.WARNING: taf_logger.warning, logging.ERROR: taf_logger.error, logging.CRITICAL: taf_logger.critical, @@ -349,6 +350,9 @@ def _log_debug(self, message: str) -> None: def _log_info(self, message: str) -> None: self._log(self.logging_functions[logging.INFO], message) + def _log_notice(self, message: str) -> None: + self._log(self.logging_functions[NOTICE], message) + def _log_warning(self, message: str) -> None: self._log(self.logging_functions[logging.WARNING], message) @@ -1393,26 +1397,37 @@ def push( branch: Optional[str] = None, set_upstream: Optional[bool] = False, force: Optional[bool] = False, - ) -> None: - """Push all changes""" - if branch is None: - branch = self.get_current_branch() + ) -> bool: - hook_path = Path(self.path) / ".git" / "hooks" / "pre-push" - if hook_path.exists(): - self._log_info("Validating and pushing...") + if not self.has_remote(): + self._log_warning("Could not push changes. No remotes configured") + return False - upstream_flag = "-u" if set_upstream else "" - force_flag = "-f" if force else "" - self._git( - "push {} {} origin {}", - upstream_flag, - force_flag, - branch, - log_error=True, - reraise_error=True, - log_success_msg="Successfully pushed commit(s)", - ) + try: + """Push all changes""" + if branch is None: + branch = self.get_current_branch() + + hook_path = Path(self.path) / ".git" / "hooks" / "pre-push" + if hook_path.exists(): + self._log_notice("Validating and pushing...") + + upstream_flag = "-u" if set_upstream else "" + force_flag = "-f" if force else "" + self._git( + "push {} {} origin {}", + upstream_flag, + force_flag, + branch, + reraise_error=True, + ) + self._log_notice("Successfully pushed to remote") + return True + except GitError as e: + self._log_error( + f"Push failed: {str(e)}. Please check if there are upstream changes." + ) + raise TAFError("Push operation failed") from e def remove_remote(self, remote_name: str) -> None: try: diff --git a/taf/tests/test_updater/conftest.py b/taf/tests/test_updater/conftest.py index 287249c7..8fe480c0 100644 --- a/taf/tests/test_updater/conftest.py +++ b/taf/tests/test_updater/conftest.py @@ -41,7 +41,6 @@ KEYSTORE_PATH, TEST_INIT_DATA_PATH, ) -from taf.api.utils._git import commit_and_push KEYS_DESCRIPTION = str(TEST_INIT_DATA_PATH / "keys.json") @@ -678,7 +677,7 @@ def update_and_sign_metadata_without_clean_check( ) commit_msg = git_commit_message("update-expiration-dates", roles=",".join(roles)) - commit_and_push(auth_repo, commit_msg=commit_msg, push=False) + auth_repo.commit_and_push(commit_msg=commit_msg, push=False) def update_target_repository( From 3f7c36e3f091934319438a8e2b01d8d0c1b5b554 Mon Sep 17 00:00:00 2001 From: Renata Date: Wed, 23 Oct 2024 17:02:22 -0400 Subject: [PATCH 4/9] fix: properly specify pygit2 version --- setup.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/setup.py b/setup.py index 539c359c..722790cf 100644 --- a/setup.py +++ b/setup.py @@ -36,11 +36,6 @@ yubikey_require = ["yubikey-manager==5.1.*"] -# Determine the appropriate version of pygit2 based on the Python version -if sys.version_info >= (3, 11): - pygit2_version = "pygit2==1.14.1" -elif sys.version_info >= (3, 7) and sys.version_info < (3, 11): - pygit2_version = "pygit2==1.9.*" kwargs = { "name": PACKAGE_NAME, @@ -64,7 +59,8 @@ "cryptography==38.0.*", "securesystemslib==0.25.*", "loguru==0.7.*", - pygit2_version, + "pygit2==1.9.*; python_version < \"3.11\"", + "pygit2==1.14.*; python_version >= \"3.11\"", "pyOpenSSL==22.1.*", "logdecorator==2.*", ], From 407ecb1c8112ff9d8dca372ad07e8e59a8b81320 Mon Sep 17 00:00:00 2001 From: Renata Date: Wed, 23 Oct 2024 17:31:05 -0400 Subject: [PATCH 5/9] fix: fix log_notice call --- taf/auth_repo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/taf/auth_repo.py b/taf/auth_repo.py index 36f2c42d..6b78f04a 100644 --- a/taf/auth_repo.py +++ b/taf/auth_repo.py @@ -171,7 +171,7 @@ def commit_and_push( if new_commit: self.set_last_validated_commit(new_commit) self._log_notice( - "NOTICE", f"Updated last_validated_commit to {new_commit}" + f"Updated last_validated_commit to {new_commit}" ) else: self._log_warning( From a0aa1fb79a0cea2af060327071d86abdfd126d7e Mon Sep 17 00:00:00 2001 From: Renata Date: Wed, 23 Oct 2024 17:54:51 -0400 Subject: [PATCH 6/9] chore: remove unused imports --- setup.py | 5 ++--- taf/api/utils/_git.py | 5 +---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/setup.py b/setup.py index 722790cf..2e83f39b 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,4 @@ from setuptools import find_packages, setup -import sys PACKAGE_NAME = "taf" VERSION = "0.31.2" @@ -59,8 +58,8 @@ "cryptography==38.0.*", "securesystemslib==0.25.*", "loguru==0.7.*", - "pygit2==1.9.*; python_version < \"3.11\"", - "pygit2==1.14.*; python_version >= \"3.11\"", + 'pygit2==1.9.*; python_version < "3.11"', + 'pygit2==1.14.*; python_version >= "3.11"', "pyOpenSSL==22.1.*", "logdecorator==2.*", ], diff --git a/taf/api/utils/_git.py b/taf/api/utils/_git.py index 56f33a2f..a5aa573a 100644 --- a/taf/api/utils/_git.py +++ b/taf/api/utils/_git.py @@ -1,9 +1,6 @@ import functools -from typing import Optional -from taf.auth_repo import AuthenticationRepository -from taf.exceptions import GitError, RepositoryNotCleanError, TAFError +from taf.exceptions import RepositoryNotCleanError from taf.git import GitRepository -from taf.log import taf_logger def check_if_clean(func): From f0da64fa7833b158dd4f5bedd3874fef6cd05115 Mon Sep 17 00:00:00 2001 From: Renata Date: Wed, 23 Oct 2024 19:17:08 -0400 Subject: [PATCH 7/9] chore: minor logging fix --- taf/api/targets.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/taf/api/targets.py b/taf/api/targets.py index 255a8cf5..9dc5a833 100644 --- a/taf/api/targets.py +++ b/taf/api/targets.py @@ -443,7 +443,7 @@ def remove_target_repo( os.unlink(str(target_file_path)) removed_targets_data[target_name] = {} else: - taf_logger.log("NOTICE", f"{target_file_path} target file does not exist") + taf_logger.info(f"{target_file_path} target file does not exist") changes_committed = False if len(added_targets_data) or len(removed_targets_data): @@ -480,7 +480,7 @@ def remove_target_repo( ) changes_committed = True else: - taf_logger.log("NOTICE", f"{target_name} not among delegated paths") + taf_logger.info(f"{target_name} not among delegated paths") # update snapshot and timestamp calls write_all, so targets updates will be saved too if changes_committed and push: auth_repo.push() From 5fc605be3acf20804a70b0f71c50adaeb167c7aa Mon Sep 17 00:00:00 2001 From: Renata Date: Wed, 23 Oct 2024 20:03:34 -0400 Subject: [PATCH 8/9] chore: update changelog and seutp.py --- CHANGELOG.md | 16 ++++++++++++++++ setup.py | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bc242b2..9d67ecfe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,21 @@ and this project adheres to [Semantic Versioning][semver]. ### Fixed +## [0.32.0] - 10/23/2024 + +### Added + + +### Changed + + +### Fixed + +- Fix specification of pygit2 version depending on the Python version [(558)] +- Fix validation and listing targets of an auth repo that does not contain `mirrors.json` [(558)] + +[558]: https://github.com/openlawlibrary/taf/pull/558 + ## [0.31.2] - 10/16/2024 @@ -1305,6 +1320,7 @@ and this project adheres to [Semantic Versioning][semver]. [keepachangelog]: https://keepachangelog.com/en/1.0.0/ [semver]: https://semver.org/spec/v2.0.0.html [unreleased]: https://github.com/openlawlibrary/taf/compare/v0.31.2...HEAD +[0.32.0]: https://github.com/openlawlibrary/taf/compare/v0.31.2...v0.32.0 [0.31.2]: https://github.com/openlawlibrary/taf/compare/v0.31.1...v0.31.2 [0.31.1]: https://github.com/openlawlibrary/taf/compare/v0.31.0...v0.31.1 [0.31.0]: https://github.com/openlawlibrary/taf/compare/v0.30.2...0.31.0 diff --git a/setup.py b/setup.py index 2e83f39b..4ad08c07 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ from setuptools import find_packages, setup PACKAGE_NAME = "taf" -VERSION = "0.31.2" +VERSION = "0.32.0" AUTHOR = "Open Law Library" AUTHOR_EMAIL = "info@openlawlib.org" DESCRIPTION = "Implementation of archival authentication" From e060f2b5b48cd3b2c24f005a7365d75ff8ac9804 Mon Sep 17 00:00:00 2001 From: Renata Date: Fri, 25 Oct 2024 15:24:37 -0400 Subject: [PATCH 9/9] fix: fix accidentally modified sys.exit call --- taf/tools/targets/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/taf/tools/targets/__init__.py b/taf/tools/targets/__init__.py index ae2a2a67..61e66ea1 100644 --- a/taf/tools/targets/__init__.py +++ b/taf/tools/targets/__init__.py @@ -61,7 +61,8 @@ def add_repo(path, target_path, target_name, role, keystore, prompt_for_keys, no custom = json.loads(Path(custom_file).read_text()) except json.JSONDecodeError: taf_logger.error("Invalid custom JSON provided") - sys.exit + sys.exit(1) + add_target_repo( path=path, target_path=target_path,