implemented link instead of bash wrapper
This commit is contained in:
22
main.py
22
main.py
@@ -9,7 +9,7 @@ BIN_DIR = os.path.expanduser("~/.local/bin")
|
||||
|
||||
from pkgmgr.clone_repos import clone_repos
|
||||
from pkgmgr.config_init import config_init
|
||||
from pkgmgr.create_executable import create_executable
|
||||
from pkgmgr.create_ink import create_ink
|
||||
from pkgmgr.deinstall_repos import deinstall_repos
|
||||
from pkgmgr.delete_repos import delete_repos
|
||||
from pkgmgr.exec_git_command import exec_git_command
|
||||
@@ -72,20 +72,25 @@ For detailed help on each command, use:
|
||||
subparsers = parser.add_subparsers(dest="command", help="Subcommands")
|
||||
def add_identifier_arguments(subparser):
|
||||
subparser.add_argument("identifiers", nargs="*", help="Identifier(s) for repositories")
|
||||
subparser.add_argument("--all", action="store_true", default=False, help="Apply to all repositories in the config")
|
||||
subparser.add_argument(
|
||||
"--all",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Apply the subcommand to all repositories in the config. Some commands ask for confirmation. If you want to give this confirmation for all repositories, pipe 'yes'. E.g: yes | pkgmgr {subcommand} --all"
|
||||
)
|
||||
subparser.add_argument("--preview", action="store_true", help="Preview changes without executing commands")
|
||||
subparser.add_argument("--list", action="store_true", help="List affected repositories (with preview or status)")
|
||||
subparser.add_argument("-a", "--args", nargs=argparse.REMAINDER, dest="extra_args", help="Additional parameters to be forwarded e.g. to the git command",default=[])
|
||||
|
||||
install_parser = subparsers.add_parser("install", help="Install repository/repositories")
|
||||
install_parser = subparsers.add_parser("install", help="Setup repository/repositories alias links to executables")
|
||||
add_identifier_arguments(install_parser)
|
||||
install_parser.add_argument("-q", "--quiet", action="store_true", help="Suppress warnings and info messages")
|
||||
install_parser.add_argument("--no-verification", default=False, action="store_true", help="Disable verification of repository commit")
|
||||
|
||||
deinstall_parser = subparsers.add_parser("deinstall", help="Deinstall repository/repositories")
|
||||
deinstall_parser = subparsers.add_parser("deinstall", help="Remove alias links to repository/repositories")
|
||||
add_identifier_arguments(deinstall_parser)
|
||||
|
||||
delete_parser = subparsers.add_parser("delete", help="Delete repository directory for repository/repositories")
|
||||
delete_parser = subparsers.add_parser("delete", help="Delete repository/repositories alias links to executables")
|
||||
add_identifier_arguments(delete_parser)
|
||||
|
||||
update_parser = subparsers.add_parser("update", help="Update (pull + install) repository/repositories")
|
||||
@@ -143,11 +148,14 @@ For detailed help on each command, use:
|
||||
selected = get_selected_repos(args.all,all_repos_list,args.identifiers)
|
||||
install_repos(selected,repositories_base_dir, BIN_DIR, all_repos_list, args.no_verification, preview=args.preview, quiet=args.quiet)
|
||||
elif args.command in GIT_DEFAULT_COMMANDS:
|
||||
selected = get_selected_repos(args.all,all_repos_list,args.identifiers)
|
||||
selected = get_selected_repos(args.all, all_repos_list, args.identifiers)
|
||||
if args.command == "clone":
|
||||
clone_repos(selected, repositories_base_dir, all_repos_list, args.preview)
|
||||
elif args.command == "pull":
|
||||
from pkgmgr.pull_with_verification import pull_with_verification
|
||||
pull_with_verification(selected, repositories_base_dir, all_repos_list, args.extra_args, no_verification=args.no_verification, preview=args.preview)
|
||||
else:
|
||||
exec_git_command(selected, repositories_base_dir, all_repos_list, args.command, args.extra_args, preview)
|
||||
exec_git_command(selected, repositories_base_dir, all_repos_list, args.command, args.extra_args, args.preview)
|
||||
elif args.command == "list":
|
||||
list_repositories(all_repos_list, repositories_base_dir, BIN_DIR, search_filter=args.search, status_filter=args.status)
|
||||
elif args.command == "deinstall":
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
import os
|
||||
|
||||
def create_executable(repo, repositories_base_dir, bin_dir, all_repos, quiet=False, preview=False, no_verification=False):
|
||||
"""
|
||||
Create an executable bash wrapper for the repository.
|
||||
|
||||
If 'verified' is set, the wrapper will checkout that commit and warn (unless quiet is True).
|
||||
If no verified commit is set, a warning is printed unless quiet is True.
|
||||
If an 'alias' field is provided, a symlink is created in bin_dir with that alias.
|
||||
"""
|
||||
repo_identifier = get_repo_identifier(repo, all_repos)
|
||||
repo_dir = get_repo_dir(repositories_base_dir,repo)
|
||||
command = repo.get("command")
|
||||
if not command:
|
||||
main_sh = os.path.join(repo_dir, "main.sh")
|
||||
main_py = os.path.join(repo_dir, "main.py")
|
||||
if os.path.exists(main_sh):
|
||||
command = "bash main.sh"
|
||||
elif os.path.exists(main_py):
|
||||
command = "python3 main.py"
|
||||
else:
|
||||
if not quiet:
|
||||
print(f"No command defined and no main.sh/main.py found in {repo_dir}. Skipping alias creation.")
|
||||
return
|
||||
|
||||
ORANGE = r"\033[38;5;208m"
|
||||
RESET = r"\033[0m"
|
||||
|
||||
if no_verification:
|
||||
preamble = ""
|
||||
else:
|
||||
if verified := repo.get("verified"):
|
||||
if not quiet:
|
||||
preamble = f"""\
|
||||
git checkout {verified} || echo -e "{ORANGE}Warning: Failed to checkout commit {verified}.{RESET}"
|
||||
CURRENT=$(git rev-parse HEAD)
|
||||
if [ "$CURRENT" != "{verified}" ]; then
|
||||
echo -e "{ORANGE}Warning: Current commit ($CURRENT) does not match verified commit ({verified}).{RESET}"
|
||||
fi
|
||||
"""
|
||||
else:
|
||||
preamble = ""
|
||||
else:
|
||||
preamble = "" if quiet else f'echo -e "{ORANGE}Warning: No verified commit set for this repository.{RESET}"'
|
||||
|
||||
script_content = f"""#!/bin/bash
|
||||
cd "{repo_dir}"
|
||||
{preamble}
|
||||
{command} "$@"
|
||||
"""
|
||||
alias_path = os.path.join(bin_dir, repo_identifier)
|
||||
if preview:
|
||||
print(f"[Preview] Would create executable '{alias_path}' with content:\n{script_content}")
|
||||
else:
|
||||
os.makedirs(bin_dir, exist_ok=True)
|
||||
with open(alias_path, "w") as f:
|
||||
f.write(script_content)
|
||||
os.chmod(alias_path, 0o755)
|
||||
if not quiet:
|
||||
print(f"Installed executable for {repo_identifier} at {alias_path}")
|
||||
|
||||
alias_name = repo.get("alias")
|
||||
if alias_name:
|
||||
alias_link_path = os.path.join(bin_dir, alias_name)
|
||||
try:
|
||||
if os.path.exists(alias_link_path) or os.path.islink(alias_link_path):
|
||||
os.remove(alias_link_path)
|
||||
os.symlink(alias_path, alias_link_path)
|
||||
if not quiet:
|
||||
print(f"Created alias '{alias_name}' pointing to {repo_identifier}")
|
||||
except Exception as e:
|
||||
if not quiet:
|
||||
print(f"Error creating alias '{alias_name}': {e}")
|
||||
50
pkgmgr/create_ink.py
Normal file
50
pkgmgr/create_ink.py
Normal file
@@ -0,0 +1,50 @@
|
||||
import os
|
||||
from pkgmgr.get_repo_identifier import get_repo_identifier
|
||||
from pkgmgr.get_repo_dir import get_repo_dir
|
||||
|
||||
def create_ink(repo, repositories_base_dir, bin_dir, all_repos, quiet=False, preview=False):
|
||||
"""
|
||||
Creates a symbolic link for the repository's command.
|
||||
|
||||
Instead of creating an executable wrapper, this function creates a symlink
|
||||
that points to the command file within the repository (e.g., main.sh or main.py).
|
||||
"""
|
||||
repo_identifier = get_repo_identifier(repo, all_repos)
|
||||
repo_dir = get_repo_dir(repositories_base_dir, repo)
|
||||
command = repo.get("command")
|
||||
if not command:
|
||||
# Automatically detect main.sh or main.py:
|
||||
main_sh = os.path.join(repo_dir, "main.sh")
|
||||
main_py = os.path.join(repo_dir, "main.py")
|
||||
if os.path.exists(main_sh):
|
||||
command = main_sh
|
||||
elif os.path.exists(main_py):
|
||||
command = main_py
|
||||
else:
|
||||
if not quiet:
|
||||
print(f"No command defined and neither main.sh nor main.py found in {repo_dir}. Skipping link creation.")
|
||||
return
|
||||
|
||||
link_path = os.path.join(bin_dir, repo_identifier)
|
||||
if preview:
|
||||
print(f"[Preview] Would create symlink '{link_path}' pointing to '{command}'.")
|
||||
else:
|
||||
os.makedirs(bin_dir, exist_ok=True)
|
||||
if os.path.exists(link_path) or os.path.islink(link_path):
|
||||
os.remove(link_path)
|
||||
os.symlink(command, link_path)
|
||||
if not quiet:
|
||||
print(f"Symlink for {repo_identifier} created at {link_path}.")
|
||||
|
||||
alias_name = repo.get("alias")
|
||||
if alias_name:
|
||||
alias_link_path = os.path.join(bin_dir, alias_name)
|
||||
try:
|
||||
if os.path.exists(alias_link_path) or os.path.islink(alias_link_path):
|
||||
os.remove(alias_link_path)
|
||||
os.symlink(link_path, alias_link_path)
|
||||
if not quiet:
|
||||
print(f"Alias '{alias_name}' has been set to point to {repo_identifier}.")
|
||||
except Exception as e:
|
||||
if not quiet:
|
||||
print(f"Error creating alias '{alias_name}': {e}")
|
||||
@@ -1,17 +1,21 @@
|
||||
import os
|
||||
from pkgmgr.get_repo_identifier import get_repo_identifier
|
||||
from pkgmgr.get_repo_dir import get_repo_dir
|
||||
|
||||
def deinstall_repos(selected_repos, repositories_base_dir, bin_dir, all_repos, preview=False):
|
||||
for repo in selected_repos:
|
||||
repo_identifier = get_repo_identifier(repo, all_repos)
|
||||
alias_path = os.path.join(bin_dir, repo_identifier)
|
||||
if os.path.exists(alias_path):
|
||||
if preview:
|
||||
print(f"[Preview] Would remove executable '{alias_path}'.")
|
||||
else:
|
||||
os.remove(alias_path)
|
||||
print(f"Removed executable for {repo_identifier}.")
|
||||
confirm = input(f"Are you sure you want to delete link '{alias_path}' for {repo_identifier}? [y/N]: ").strip().lower()
|
||||
if confirm == "y":
|
||||
if preview:
|
||||
print(f"[Preview] Would remove link '{alias_path}'.")
|
||||
else:
|
||||
os.remove(alias_path)
|
||||
print(f"Removed link for {repo_identifier}.")
|
||||
else:
|
||||
print(f"No executable found for {repo_identifier} in {bin_dir}.")
|
||||
print(f"No link found for {repo_identifier} in {bin_dir}.")
|
||||
teardown_cmd = repo.get("teardown")
|
||||
repo_dir = get_repo_dir(repositories_base_dir,repo)
|
||||
if teardown_cmd and os.path.exists(repo_dir):
|
||||
|
||||
@@ -1,14 +1,52 @@
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from pkgmgr.get_repo_identifier import get_repo_identifier
|
||||
from pkgmgr.get_repo_dir import get_repo_dir
|
||||
from pkgmgr.create_ink import create_ink
|
||||
from pkgmgr.run_command import run_command
|
||||
|
||||
def install_repos(selected_repos, repositories_base_dir, bin_dir, all_repos:[], no_verification:bool, preview=False, quiet=False):
|
||||
"""Install repositories by creating executable wrappers and running setup."""
|
||||
def install_repos(selected_repos, repositories_base_dir, bin_dir, all_repos, no_verification, preview=False, quiet=False):
|
||||
"""
|
||||
Install repositories by creating symbolic links (via create_ink) and running setup commands.
|
||||
|
||||
This version applies hash verification:
|
||||
- It retrieves the current commit hash using 'git rev-parse HEAD' and compares it to the
|
||||
configured 'verified' hash.
|
||||
- If the hashes do not match and no_verification is False, the user is prompted for confirmation.
|
||||
- If the user does not confirm, the installation for that repository is skipped.
|
||||
"""
|
||||
for repo in selected_repos:
|
||||
repo_identifier = get_repo_identifier(repo, all_repos)
|
||||
repo_dir = get_repo_dir(repositories_base_dir,repo)
|
||||
repo_dir = get_repo_dir(repositories_base_dir, repo)
|
||||
if not os.path.exists(repo_dir):
|
||||
print(f"Repository directory '{repo_dir}' does not exist. Clone it first.")
|
||||
continue
|
||||
create_executable(repo, repositories_base_dir, bin_dir, all_repos, quiet=quiet, preview=preview, no_verification=no_verification)
|
||||
|
||||
# Apply hash verification if a verified hash is defined.
|
||||
verified_hash = repo.get("verified")
|
||||
if verified_hash:
|
||||
current_hash = ""
|
||||
try:
|
||||
result = subprocess.run("git rev-parse HEAD", cwd=repo_dir, shell=True, check=True,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||
current_hash = result.stdout.strip()
|
||||
except Exception as e:
|
||||
print(f"Error retrieving current commit for {repo_identifier}: {e}")
|
||||
|
||||
proceed = True
|
||||
if not no_verification and current_hash and current_hash != verified_hash:
|
||||
print(f"Warning: For {repo_identifier}, the current commit hash ({current_hash}) does not match the verified hash ({verified_hash}).")
|
||||
choice = input("Proceed with installation? (y/N): ").strip().lower()
|
||||
if choice != "y":
|
||||
proceed = False
|
||||
if not proceed:
|
||||
print(f"Skipping installation for {repo_identifier}.")
|
||||
continue
|
||||
|
||||
# Create the symlink using the new create_ink function.
|
||||
create_ink(repo, repositories_base_dir, bin_dir, all_repos, quiet=quiet, preview=preview)
|
||||
|
||||
setup_cmd = repo.get("setup")
|
||||
if setup_cmd:
|
||||
run_command(setup_cmd, cwd=repo_dir, preview=preview)
|
||||
47
pkgmgr/pull_with_verification.py
Normal file
47
pkgmgr/pull_with_verification.py
Normal file
@@ -0,0 +1,47 @@
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from pkgmgr.get_repo_identifier import get_repo_identifier
|
||||
from pkgmgr.get_repo_dir import get_repo_dir
|
||||
|
||||
def pull_with_verification(selected_repos, repositories_base_dir, all_repos, extra_args, no_verification, preview=False):
|
||||
"""
|
||||
Executes "git pull" for each repository with hash verification.
|
||||
|
||||
For repositories with a 'verified' hash in the configuration, this function first
|
||||
checks the current commit hash. If it does not match the verified hash, the user is prompted
|
||||
to confirm the pull (unless --no-verification is set, in which case the pull proceeds automatically).
|
||||
"""
|
||||
for repo in selected_repos:
|
||||
repo_identifier = get_repo_identifier(repo, all_repos)
|
||||
repo_dir = get_repo_dir(repositories_base_dir, repo)
|
||||
if not os.path.exists(repo_dir):
|
||||
print(f"Repository directory '{repo_dir}' not found for {repo_identifier}.")
|
||||
continue
|
||||
|
||||
verified_hash = repo.get("verified")
|
||||
current_hash = ""
|
||||
try:
|
||||
result = subprocess.run("git rev-parse HEAD", cwd=repo_dir, shell=True, check=True,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||
current_hash = result.stdout.strip()
|
||||
except Exception as e:
|
||||
print(f"Error retrieving current commit for {repo_identifier}: {e}")
|
||||
|
||||
proceed = True
|
||||
if not no_verification and verified_hash and current_hash != verified_hash:
|
||||
print(f"Warning: For {repo_identifier}, the current hash ({current_hash}) does not match the verified hash ({verified_hash}).")
|
||||
choice = input("Proceed with 'git pull'? (y/N): ").strip().lower()
|
||||
if choice != "y":
|
||||
proceed = False
|
||||
|
||||
if proceed:
|
||||
full_cmd = f"git pull {' '.join(extra_args)}"
|
||||
if preview:
|
||||
print(f"[Preview] In '{repo_dir}': {full_cmd}")
|
||||
else:
|
||||
print(f"Running in '{repo_dir}': {full_cmd}")
|
||||
result = subprocess.run(full_cmd, cwd=repo_dir, shell=True)
|
||||
if result.returncode != 0:
|
||||
print(f"'git pull' for {repo_identifier} failed with exit code {result.returncode}.")
|
||||
sys.exit(result.returncode)
|
||||
@@ -1,8 +1,16 @@
|
||||
import sys
|
||||
from pkgmgr.pull_with_verification import pull_with_verification
|
||||
from pkgmgr.install_repos import install_repos
|
||||
|
||||
def update_repos(selected_repos, repositories_base_dir, bin_dir, all_repos:[], no_verification:bool, system_update=False, preview=False, quiet=False):
|
||||
git_default_exec(selected_repos, repositories_base_dir, all_repos, extra_args=[],command="pull", preview=preview)
|
||||
install_repos(selected_repos, repositories_base_dir, bin_dir, all_repos, no_verification, preview=preview, quiet=quiet)
|
||||
def update_repos(selected_repos, repositories_base_dir, bin_dir, all_repos, no_verification, system_update=False, preview=False, quiet=False):
|
||||
# Use pull_with_verification instead of the old git_default_exec.
|
||||
pull_with_verification(selected_repos, repositories_base_dir, all_repos, extra_args=[], no_verification=no_verification, preview=preview)
|
||||
|
||||
# Proceed with the installation process.
|
||||
# Note: In the install process, we remove the --no-verification flag to avoid hash checks.
|
||||
install_repos(selected_repos, repositories_base_dir, bin_dir, all_repos, no_verification=no_verification, preview=preview, quiet=quiet)
|
||||
|
||||
if system_update:
|
||||
from pkgmgr.run_command import run_command
|
||||
run_command("yay -Syu", preview=preview)
|
||||
run_command("sudo pacman -Syyu", preview=preview)
|
||||
run_command("sudo pacman -Syyu", preview=preview)
|
||||
|
||||
Reference in New Issue
Block a user