scitex_git
scitex-git — git operations and utilities (extracted from SciTeX).
- scitex_git.init_git_repo(project_dir, git_strategy='child')[source]
Initialize or detect git repository based on git_strategy.
- Parameters:
project_dir (
Path) – Project directorygit_strategy (
Optional[str]) – Git initialization strategy - None: Git disabled, returns None - ‘child’: Creates isolated git repo in project directory - ‘parent’: Tries to use parent git, degrades to ‘child’ if not found - ‘origin’: Preserves template’s original git history (handled by clone)
- Return type:
- Returns:
Path to git repository root, or None if disabled
- scitex_git.find_parent_git(project_dir)[source]
Find parent git repository by walking up directory tree.
- scitex_git.create_child_git(project_dir)[source]
Create isolated git repository in project directory.
Uses GitPython to initialize and make initial commit.
- scitex_git.remove_child_git(project_dir)[source]
Remove project’s local .git folder.
When parent git is found, the project’s own .git/ is redundant and should be removed to avoid nested git repository issues.
- scitex_git.clone_repo(url, target_path, branch=None, tag=None, verbose=True)[source]
Safely clone a git repository.
- Parameters:
url (str) – Git repository URL
target_path (Path) – Destination path for cloning
branch (str, optional) – Specific branch to clone. If None, clones the default branch. Mutually exclusive with tag parameter.
tag (str, optional) – Specific tag/release to clone. If None, clones the default branch. Mutually exclusive with branch parameter.
verbose (bool) – Enable verbose output
- Returns:
True if successful, False otherwise
- Return type:
- Raises:
ValueError – If both branch and tag are specified
- scitex_git.git_add_all(repo_path, verbose=True)[source]
Add all files to git staging.
- Parameters:
repo_path (Path) – Git repository path
verbose (bool) – Enable verbose output
- Returns:
True if successful, False if: - repo_path is not a git repository - git add command fails - path is invalid
- Return type:
Examples
>>> git_add_all(Path("/my/repo")) True
- scitex_git.git_commit(repo_path, message, verbose=True)[source]
Create a git commit.
- Parameters:
- Returns:
True if successful, False if: - repo_path is not a git repository - message is empty - git commit command fails - no changes to commit
- Return type:
Examples
>>> git_commit(Path("/my/repo"), "Fix bug in parser") True
- scitex_git.git_branch_rename(repo_path, new_name, verbose=True)[source]
Rename current branch.
- Parameters:
- Returns:
True if successful, False if: - repo_path is not a git repository - new_name is invalid - git branch command fails
- Return type:
Examples
>>> git_branch_rename(Path("/my/repo"), "main") True
- scitex_git.git_checkout_new_branch(repo_path, branch_name, verbose=True)[source]
Create and checkout a new branch.
- Parameters:
- Returns:
True if successful, False if: - repo_path is not a git repository - branch_name is invalid - git checkout command fails
- Return type:
Examples
>>> git_checkout_new_branch(Path("/my/repo"), "feature/auth") True
- scitex_git.get_remote_url(repo_path, remote_name='origin', verbose=False)[source]
Get remote URL for a git repository.
- Parameters:
- Returns:
Remote URL if found, None otherwise
- Return type:
Optional[str]
Notes
Returns None if remote doesn’t exist or repo is not a git repository. Check stderr via sh() directly if detailed error info is needed.
- scitex_git.is_cloned_from(repo_path, expected_url, remote_name='origin')[source]
Check if directory is a git repository cloned from specific URL. Handles both HTTPS and SSH URL formats.
- scitex_git.ls_remote(url, ref=None, verbose=False)[source]
Get commit hash of a remote ref via
git ls-remote.- Parameters:
- Returns:
Commit SHA-1 hash (40 hex chars), or None on failure.
- Return type:
Optional[str]
Examples
>>> ls_remote("https://github.com/user/repo.git") 'abc123...' >>> ls_remote("https://github.com/user/repo.git", ref="main") 'abc123...' >>> ls_remote("https://github.com/user/repo.git", ref="v1.0.0") 'def456...'
- scitex_git.get_head_hash(repo_path, verbose=False)[source]
Get HEAD commit hash of a local git repository.
- scitex_git.setup_branches(repo_path, template_name, verbose=True)[source]
Setup standard git branches (main and develop).
- Parameters:
- Returns:
True if successful, False otherwise
- Return type:
Notes
This function attempts to rollback changes if branch operations fail. If add or commit fail, no rollback is needed as the repo state is unchanged.
- scitex_git.git_retry(operation, max_retries=5, initial_delay=0.1, max_delay=2.0, backoff_factor=2.0)[source]
Retry git operations with exponential backoff.
Handles git index.lock conflicts when multiple processes access git.
- Parameters:
- Returns:
Result of operation
- Return type:
T
- Raises:
TimeoutError – If all retries exhausted due to lock
Exception – Original exception if not a lock error
Examples
>>> def commit_file(): ... subprocess.run(["git", "commit", "-m", "msg"], check=True) >>> git_retry(commit_file)
- scitex_git.set_secret(repo, name, value)[source]
Push
valueinto the Actions secretnameforrepo.repofollows theowner/repoform. Idempotent — creates if missing, updates otherwise.- Return type:
- scitex_git.list_secrets(repo)[source]
Return
{secret_name: updated_at_iso}for the repo.Pagination is honoured (
--paginate) so this scales beyond GitHub’s 100-secret default page size.
- scitex_git.get_secret_metadata(repo, name)[source]
Return the secret’s metadata dict (name / created_at / updated_at), or None.
GitHub never exposes the value itself — that’s the whole point of Actions secrets. Use
get_variable()against a SHA sidecar (seeset_secret_with_sha_sidecar()) if you need to detect value drift.
- scitex_git.set_variable(repo, name, value)[source]
Create-or-update an Actions variable. Idempotent.
Variables are visible to anyone with repo read access. Use this for non-sensitive metadata (e.g. SHA256 fingerprints of secrets, feature flags). NEVER store token material here.
- Return type:
- scitex_git.set_secret_with_sha_sidecar(repo, name, value, *, sidecar_suffix='_SHA256')[source]
Push the secret AND its SHA256 fingerprint as a public variable.
Returns the SHA256 hex digest so the caller can show it in CLI output. The sidecar variable is named
{name}{sidecar_suffix}and holds the irreversible hash; laterget_variable(repo, f"{name}{sidecar_suffix}")lets you tell whether the GitHub-side secret matches a local value (compare withsha256_hex(local_value)).The hash itself is not sensitive — it cannot be reversed to the original token without a brute-force search of the OAuth/api-key namespace, which is computationally infeasible. It IS visible to repo readers, so don’t use the sidecar for tokens whose mere existence is sensitive (the hash leaks “this token was rotated at {time} to a value with hash {h}” but never the value).
- Return type:
- scitex_git.format_age(updated_iso)[source]
Render an ISO-8601 timestamp as a single-unit human age.
Picks the largest unit that gives a readable number: seconds for very fresh rotations, then minutes, hours, days. Mirrors the
git relative_datestyle — a single value + unit, no compound “1d 4h” form. Returns"?"forNoneinput.- Return type:
>>> format_age(None) '?'