This commit introduces a large-scale structural refactor of the pkgmgr
codebase. All functionality has been moved from the previous flat
top-level layout into three clearly separated namespaces:
• pkgmgr.actions – high-level operations invoked by the CLI
• pkgmgr.core – pure logic, helpers, repository utilities,
versioning, git helpers, config IO, and
command resolution
• pkgmgr.cli – parser, dispatch, context, and command
handlers
Key improvements:
- Moved all “branch”, “release”, “changelog”, repo-management
actions, installer pipelines, and proxy execution logic into
pkgmgr.actions.<domain>.
- Reworked installer structure under
pkgmgr.actions.repository.install.installers
including OS-package installers, Nix, Python, and Makefile.
- Consolidated all low-level functionality under pkgmgr.core:
• git helpers → core/git
• config load/save → core/config
• repository helpers → core/repository
• versioning & semver → core/version
• command helpers (alias, resolve, run, ink) → core/command
- Replaced pkgmgr.cli_core with pkgmgr.cli and updated all imports.
- Added minimal __init__.py files for clean package exposure.
- Updated all E2E, integration, and unit tests with new module paths.
- Fixed patch targets so mocks point to the new structure.
- Ensured backward compatibility at the CLI boundary (pkgmgr entry point unchanged).
This refactor produces a cleaner, layered architecture:
- `core` = logic
- `actions` = orchestrated behaviour
- `cli` = user interface
Reference: ChatGPT-assisted refactor discussion
https://chatgpt.com/share/6938221c-e24c-800f-8317-7732cedf39b9
42 lines
1.6 KiB
Python
42 lines
1.6 KiB
Python
import os
|
|
import hashlib
|
|
import re
|
|
|
|
def generate_alias(repo, bin_dir, existing_aliases):
|
|
"""
|
|
Generate an alias for a repository based on its repository name.
|
|
|
|
Steps:
|
|
1. Keep only consonants from the repository name (letters from BCDFGHJKLMNPQRSTVWXYZ).
|
|
2. Collapse consecutive identical consonants.
|
|
3. Truncate to at most 12 characters.
|
|
4. If that alias conflicts (already in existing_aliases or a file exists in bin_dir),
|
|
then prefix with the first letter of provider and account.
|
|
5. If still conflicting, append a three-character hash until the alias is unique.
|
|
"""
|
|
repo_name = repo.get("repository")
|
|
# Keep only consonants.
|
|
consonants = re.sub(r"[^bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ]", "", repo_name)
|
|
# Collapse consecutive identical consonants.
|
|
collapsed = re.sub(r"(.)\1+", r"\1", consonants)
|
|
base_alias = collapsed[:12] if len(collapsed) > 12 else collapsed
|
|
candidate = base_alias.lower()
|
|
|
|
def conflict(alias):
|
|
alias_path = os.path.join(bin_dir, alias)
|
|
return alias in existing_aliases or os.path.exists(alias_path)
|
|
|
|
if not conflict(candidate):
|
|
return candidate
|
|
|
|
prefix = (repo.get("provider", "")[0] + repo.get("account", "")[0]).lower()
|
|
candidate2 = (prefix + candidate)[:12]
|
|
if not conflict(candidate2):
|
|
return candidate2
|
|
|
|
h = hashlib.md5(repo_name.encode("utf-8")).hexdigest()[:3]
|
|
candidate3 = (candidate2 + h)[:12]
|
|
while conflict(candidate3):
|
|
candidate3 += "x"
|
|
candidate3 = candidate3[:12]
|
|
return candidate3 |