Added config
This commit is contained in:
11
config.yaml
Normal file
11
config.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
base: /home/kevinveenbirkenbach/Repositories/
|
||||
repos:
|
||||
- account: kevinveenbirkenbach
|
||||
command: ''
|
||||
description: Package Manager for the Kevin Veen-Birkenbach Scripting Universe
|
||||
provider: github.com
|
||||
replacement: ''
|
||||
repository: package-manager
|
||||
setup: ''
|
||||
teardown: ''
|
||||
verified: ''
|
||||
131
main.py
131
main.py
@@ -21,10 +21,14 @@ This script provides the following commands:
|
||||
- Combines pull and install; if --system is specified also runs system update commands.
|
||||
status {identifier(s)|--all|--system}
|
||||
- Shows git status for each repository or, if --system is set, shows basic system update information.
|
||||
config {identifier(s)|--all}
|
||||
- Displays the configuration for one or more repositories. If no identifier is given, shows the entire config.
|
||||
add
|
||||
- Starts an interactive dialog to add a new repository configuration entry.
|
||||
|
||||
Additional flags:
|
||||
--preview Only show the changes without executing commands.
|
||||
--list When used with preview or status, only list affected repositories.
|
||||
--list When used with preview or status, only list affected repositories (for status).
|
||||
|
||||
Identifiers:
|
||||
- If a repository’s name is unique then you can just use the repository name.
|
||||
@@ -71,6 +75,12 @@ def load_config(config_path):
|
||||
sys.exit(1)
|
||||
return config
|
||||
|
||||
def save_config(config, config_path):
|
||||
"""Save the config dictionary back to the YAML file."""
|
||||
with open(config_path, 'w') as f:
|
||||
yaml.dump(config, f)
|
||||
print(f"Configuration updated in {config_path}.")
|
||||
|
||||
def run_command(command, cwd=None, preview=False):
|
||||
"""Run a shell command in a given directory, or print it in preview mode."""
|
||||
if preview:
|
||||
@@ -94,19 +104,16 @@ def get_repo_identifier(repo, all_repos):
|
||||
|
||||
def resolve_repos(identifiers, all_repos):
|
||||
"""
|
||||
Given a list of identifier strings (or an empty list), return a list of repository configs.
|
||||
If identifiers is empty, return an empty list (caller can decide what to do).
|
||||
Given a list of identifier strings, return a list of repository configs.
|
||||
The identifier can be either just the repository name (if unique) or full provider/account/repository.
|
||||
"""
|
||||
selected = []
|
||||
for ident in identifiers:
|
||||
matches = []
|
||||
for repo in all_repos:
|
||||
# Check for full identifier match
|
||||
full_id = f'{repo.get("provider")}/{repo.get("account")}/{repo.get("repository")}'
|
||||
if ident == full_id:
|
||||
matches.append(repo)
|
||||
# Or if repository name matches and it is unique, accept it
|
||||
elif ident == repo.get("repository"):
|
||||
# Only add if it is unique among all_repos
|
||||
if sum(1 for r in all_repos if r.get("repository") == ident) == 1:
|
||||
@@ -117,7 +124,7 @@ def resolve_repos(identifiers, all_repos):
|
||||
selected.extend(matches)
|
||||
return selected
|
||||
|
||||
def create_executable(repo, base_dir, bin_dir, preview=False):
|
||||
def create_executable(repo, base_dir, bin_dir, all_repos, preview=False):
|
||||
"""Create an executable bash wrapper for the repository."""
|
||||
repo_identifier = get_repo_identifier(repo, all_repos)
|
||||
repo_dir = os.path.join(base_dir, repo.get("provider"), repo.get("account"), repo.get("repository"))
|
||||
@@ -149,7 +156,7 @@ cd "{repo_dir}"
|
||||
os.chmod(alias_path, 0o755)
|
||||
print(f"Installed executable for {repo_identifier} at {alias_path}")
|
||||
|
||||
def install_repos(selected_repos, base_dir, bin_dir, preview=False):
|
||||
def install_repos(selected_repos, base_dir, bin_dir, all_repos, preview=False):
|
||||
"""Install one or more repositories by creating their executable wrappers and running setup."""
|
||||
for repo in selected_repos:
|
||||
repo_identifier = get_repo_identifier(repo, all_repos)
|
||||
@@ -157,13 +164,13 @@ def install_repos(selected_repos, base_dir, bin_dir, preview=False):
|
||||
if not os.path.exists(repo_dir):
|
||||
print(f"Repository directory '{repo_dir}' does not exist. Clone it first.")
|
||||
continue
|
||||
create_executable(repo, base_dir, bin_dir, preview=preview)
|
||||
create_executable(repo, base_dir, bin_dir, all_repos, preview=preview)
|
||||
# Execute setup command if defined
|
||||
setup_cmd = repo.get("setup")
|
||||
if setup_cmd:
|
||||
run_command(setup_cmd, cwd=repo_dir, preview=preview)
|
||||
|
||||
def pull_repos(selected_repos, base_dir, preview=False):
|
||||
def pull_repos(selected_repos, base_dir, all_repos, preview=False):
|
||||
"""Run 'git pull' in the repository directory."""
|
||||
for repo in selected_repos:
|
||||
repo_identifier = get_repo_identifier(repo, all_repos)
|
||||
@@ -173,7 +180,7 @@ def pull_repos(selected_repos, base_dir, preview=False):
|
||||
else:
|
||||
print(f"Repository directory '{repo_dir}' not found for {repo_identifier}.")
|
||||
|
||||
def clone_repos(selected_repos, base_dir, preview=False):
|
||||
def clone_repos(selected_repos, base_dir, all_repos, preview=False):
|
||||
"""Clone repositories based on the config.
|
||||
Uses replacement if defined; otherwise, constructs URL from provider/account/repository.
|
||||
"""
|
||||
@@ -191,7 +198,7 @@ def clone_repos(selected_repos, base_dir, preview=False):
|
||||
os.makedirs(parent_dir, exist_ok=True)
|
||||
run_command(f"git clone {clone_url} {repo_dir}", cwd=parent_dir, preview=preview)
|
||||
|
||||
def push_repos(selected_repos, base_dir, preview=False):
|
||||
def push_repos(selected_repos, base_dir, all_repos, preview=False):
|
||||
"""Run 'git push' in the repository directory."""
|
||||
for repo in selected_repos:
|
||||
repo_identifier = get_repo_identifier(repo, all_repos)
|
||||
@@ -201,7 +208,7 @@ def push_repos(selected_repos, base_dir, preview=False):
|
||||
else:
|
||||
print(f"Repository directory '{repo_dir}' not found for {repo_identifier}.")
|
||||
|
||||
def deinstall_repos(selected_repos, base_dir, bin_dir, preview=False):
|
||||
def deinstall_repos(selected_repos, base_dir, bin_dir, all_repos, preview=False):
|
||||
"""Remove the executable wrapper and run teardown command if defined."""
|
||||
for repo in selected_repos:
|
||||
repo_identifier = get_repo_identifier(repo, all_repos)
|
||||
@@ -220,7 +227,7 @@ def deinstall_repos(selected_repos, base_dir, bin_dir, preview=False):
|
||||
if teardown_cmd and os.path.exists(repo_dir):
|
||||
run_command(teardown_cmd, cwd=repo_dir, preview=preview)
|
||||
|
||||
def delete_repos(selected_repos, base_dir, preview=False):
|
||||
def delete_repos(selected_repos, base_dir, all_repos, preview=False):
|
||||
"""Delete the repository directory (rm -rv equivalent)."""
|
||||
for repo in selected_repos:
|
||||
repo_identifier = get_repo_identifier(repo, all_repos)
|
||||
@@ -234,16 +241,16 @@ def delete_repos(selected_repos, base_dir, preview=False):
|
||||
else:
|
||||
print(f"Repository directory '{repo_dir}' not found for {repo_identifier}.")
|
||||
|
||||
def update_repos(selected_repos, base_dir, bin_dir, system_update=False, preview=False):
|
||||
def update_repos(selected_repos, base_dir, bin_dir, all_repos, system_update=False, preview=False):
|
||||
"""Combine pull and install. If system_update is True, run system update commands."""
|
||||
pull_repos(selected_repos, base_dir, preview=preview)
|
||||
install_repos(selected_repos, base_dir, bin_dir, preview=preview)
|
||||
pull_repos(selected_repos, base_dir, all_repos, preview=preview)
|
||||
install_repos(selected_repos, base_dir, bin_dir, all_repos, preview=preview)
|
||||
if system_update:
|
||||
# Example system update commands (for Arch-based systems)
|
||||
run_command("yay -S", preview=preview)
|
||||
run_command("sudo pacman -Syyu", preview=preview)
|
||||
|
||||
def status_repos(selected_repos, base_dir, list_only=False, system_status=False, preview=False):
|
||||
def status_repos(selected_repos, base_dir, all_repos, list_only=False, system_status=False, preview=False):
|
||||
"""Show status information for repositories.
|
||||
If list_only is True, only list affected repositories.
|
||||
If system_status is True, show system update status.
|
||||
@@ -251,7 +258,6 @@ def status_repos(selected_repos, base_dir, list_only=False, system_status=False,
|
||||
if system_status:
|
||||
print("System status:")
|
||||
run_command("yay -Qu", preview=preview)
|
||||
# You might want to add additional system status commands here.
|
||||
for repo in selected_repos:
|
||||
repo_identifier = get_repo_identifier(repo, all_repos)
|
||||
if list_only:
|
||||
@@ -264,11 +270,50 @@ def status_repos(selected_repos, base_dir, list_only=False, system_status=False,
|
||||
else:
|
||||
print(f"Repository directory '{repo_dir}' not found for {repo_identifier}.")
|
||||
|
||||
def show_config(selected_repos, full_config=False):
|
||||
"""Display configuration for one or more repositories. If full_config is True, display entire config."""
|
||||
if full_config:
|
||||
with open(CONFIG_PATH, 'r') as f:
|
||||
print(f.read())
|
||||
else:
|
||||
for repo in selected_repos:
|
||||
identifier = f'{repo.get("provider")}/{repo.get("account")}/{repo.get("repository")}'
|
||||
print(f"Repository: {identifier}")
|
||||
for key, value in repo.items():
|
||||
print(f" {key}: {value}")
|
||||
print("-" * 40)
|
||||
|
||||
def interactive_add(config):
|
||||
"""Interactively prompt the user to add a new repository entry to the config."""
|
||||
print("Adding a new repository configuration entry.")
|
||||
new_entry = {}
|
||||
new_entry["provider"] = input("Provider (e.g., github.com): ").strip()
|
||||
new_entry["account"] = input("Account (e.g., yourusername): ").strip()
|
||||
new_entry["repository"] = input("Repository name (e.g., mytool): ").strip()
|
||||
new_entry["verified"] = input("Verified commit id: ").strip()
|
||||
new_entry["command"] = input("Command (optional, leave blank to auto-detect): ").strip()
|
||||
new_entry["description"] = input("Description (optional): ").strip()
|
||||
new_entry["replacement"] = input("Replacement (optional): ").strip()
|
||||
new_entry["setup"] = input("Setup command (optional): ").strip()
|
||||
new_entry["teardown"] = input("Teardown command (optional): ").strip()
|
||||
|
||||
# Confirm addition
|
||||
print("\nNew entry:")
|
||||
for key, value in new_entry.items():
|
||||
if value:
|
||||
print(f"{key}: {value}")
|
||||
confirm = input("Add this entry to config? (y/N): ").strip().lower()
|
||||
if confirm == "y":
|
||||
config["repos"].append(new_entry)
|
||||
save_config(config, CONFIG_PATH)
|
||||
else:
|
||||
print("Entry not added.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Load configuration
|
||||
config = load_config(CONFIG_PATH)
|
||||
base_dir = config["base"]
|
||||
all_repos = config["repos"]
|
||||
all_repos_list = config["repos"]
|
||||
|
||||
parser = argparse.ArgumentParser(description="Package Manager")
|
||||
subparsers = parser.add_subparsers(dest="command", help="Subcommands")
|
||||
@@ -314,30 +359,56 @@ if __name__ == "__main__":
|
||||
add_identifier_arguments(status_parser)
|
||||
status_parser.add_argument("--system", action="store_true", help="Show system status")
|
||||
|
||||
# config: show configuration details
|
||||
config_parser = subparsers.add_parser("config", help="Show configuration for repository/repositories or entire config")
|
||||
add_identifier_arguments(config_parser)
|
||||
|
||||
# add: interactive add of a new repository entry
|
||||
add_parser = subparsers.add_parser("add", help="Interactively add a new repository configuration entry")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Determine which repositories to operate on
|
||||
# Handle "config" command separately
|
||||
if args.command == "config":
|
||||
if args.all or (hasattr(args, "identifiers") and not args.identifiers):
|
||||
selected = all_repos
|
||||
# Show the entire configuration file
|
||||
show_config([], full_config=True)
|
||||
else:
|
||||
selected = resolve_repos(args.identifiers, all_repos)
|
||||
selected = resolve_repos(args.identifiers, all_repos_list)
|
||||
if selected:
|
||||
show_config(selected, full_config=False)
|
||||
sys.exit(0)
|
||||
|
||||
# Handle "add" command
|
||||
if args.command == "add":
|
||||
interactive_add(config)
|
||||
sys.exit(0)
|
||||
|
||||
# For commands using identifiers, decide which repositories to operate on
|
||||
if hasattr(args, "identifiers"):
|
||||
if args.all or (not args.identifiers):
|
||||
selected = all_repos_list
|
||||
else:
|
||||
selected = resolve_repos(args.identifiers, all_repos_list)
|
||||
else:
|
||||
selected = []
|
||||
|
||||
# Dispatch commands
|
||||
if args.command == "install":
|
||||
install_repos(selected, base_dir, BIN_DIR, preview=args.preview)
|
||||
install_repos(selected, base_dir, BIN_DIR, all_repos_list, preview=args.preview)
|
||||
elif args.command == "pull":
|
||||
pull_repos(selected, base_dir, preview=args.preview)
|
||||
pull_repos(selected, base_dir, all_repos_list, preview=args.preview)
|
||||
elif args.command == "clone":
|
||||
clone_repos(selected, base_dir, preview=args.preview)
|
||||
clone_repos(selected, base_dir, all_repos_list, preview=args.preview)
|
||||
elif args.command == "push":
|
||||
push_repos(selected, base_dir, preview=args.preview)
|
||||
push_repos(selected, base_dir, all_repos_list, preview=args.preview)
|
||||
elif args.command == "deinstall":
|
||||
deinstall_repos(selected, base_dir, BIN_DIR, preview=args.preview)
|
||||
deinstall_repos(selected, base_dir, BIN_DIR, all_repos_list, preview=args.preview)
|
||||
elif args.command == "delete":
|
||||
delete_repos(selected, base_dir, preview=args.preview)
|
||||
delete_repos(selected, base_dir, all_repos_list, preview=args.preview)
|
||||
elif args.command == "update":
|
||||
update_repos(selected, base_dir, BIN_DIR, system_update=args.system, preview=args.preview)
|
||||
update_repos(selected, base_dir, BIN_DIR, all_repos_list, system_update=args.system, preview=args.preview)
|
||||
elif args.command == "status":
|
||||
status_repos(selected, base_dir, list_only=args.list, system_status=args.system, preview=args.preview)
|
||||
status_repos(selected, base_dir, all_repos_list, list_only=args.list, system_status=args.system, preview=args.preview)
|
||||
else:
|
||||
parser.print_help()
|
||||
|
||||
Reference in New Issue
Block a user