vcspull add - vcspull.cli.add

Add single repository functionality for vcspull.

class vcspull.cli.add.AddAction

Bases: Enum

Action resolved for a single repo during vcspull add.

vcspull.cli.add._classify_add_action(existing_entry)
function[source]

Classify the add action for a single repository.

Parameters:

existing_entry (Any) – Current config entry for this repo name, or None if absent.

Return type:

AddAction

Examples

Not in config:

>>> _classify_add_action(None)
<AddAction.ADD: 'add'>

Already exists (unpinned):

>>> _classify_add_action({"repo": "git+ssh://x"})
<AddAction.SKIP_EXISTING: 'skip_existing'>

Pinned for add:

>>> _classify_add_action({"repo": "git+ssh://x", "options": {"pin": True}})
<AddAction.SKIP_PINNED: 'skip_pinned'>
>>> entry = {"repo": "git+ssh://x", "options": {"pin": {"add": True}}}
>>> _classify_add_action(entry)
<AddAction.SKIP_PINNED: 'skip_pinned'>

Pinned for import only — not pinned for add:

>>> entry = {"repo": "git+ssh://x", "options": {"pin": {"import": True}}}
>>> _classify_add_action(entry)
<AddAction.SKIP_EXISTING: 'skip_existing'>
vcspull.cli.add.create_add_subparser(parser)
function[source]

Create vcspull add argument subparser.

Parameters:

parser (argparse.ArgumentParser) – The parser to configure

Return type:

None

vcspull.cli.add._resolve_workspace_path(workspace_root, repo_path_str, *, cwd)
function[source]

Resolve workspace path from arguments.

Parameters:
  • workspace_root (str | None) – Workspace root path from user

  • repo_path_str (str | None) – Repo path from user

  • cwd (pathlib.Path) – Current working directory

Returns:

Resolved workspace path

Return type:

pathlib.Path

vcspull.cli.add._detect_git_remote(repo_path)
function[source]

Return the origin remote URL for a Git repository if available.

Parameters:

repo_path (Path)

Return type:

str | None

vcspull.cli.add._normalize_detected_url(remote)
function[source]

Return display and config URLs derived from a detected remote.

Parameters:

remote (str | None)

Return type:

tuple[str, str]

vcspull.cli.add._build_ordered_items(top_level_items, raw_config)
function[source]

Return deep-copied top-level items preserving original ordering.

Parameters:
Return type:

list[dict[str, Any]]

vcspull.cli.add._aggregate_from_ordered_items(items)
function[source]

Collapse ordered top-level items into a mapping grouped by label.

Parameters:

items (list[dict[str, Any]])

Return type:

dict[str, Any]

vcspull.cli.add._collapse_ordered_items_to_dict(ordered_items)
function[source]

Collapse ordered items into a flat dict for JSON serialization.

JSON does not support duplicate keys, so sections with the same workspace label are merged at the repo level via dict.update() (last occurrence of a repo name wins).

Examples

Distinct labels pass through unchanged:

>>> _collapse_ordered_items_to_dict([
...     {"label": "~/code/", "section": {"repo1": {"repo": "git+x"}}},
...     {"label": "~/work/", "section": {"repo2": {"repo": "git+y"}}},
... ])
{'~/code/': {'repo1': {'repo': 'git+x'}}, '~/work/': {'repo2': {'repo': 'git+y'}}}

Duplicate labels are merged (repos from both sections appear):

>>> result = _collapse_ordered_items_to_dict([
...     {"label": "~/code/", "section": {"repo1": {"repo": "git+a"}}},
...     {"label": "~/code/", "section": {"repo2": {"repo": "git+b"}}},
... ])
>>> sorted(result["~/code/"].keys())
['repo1', 'repo2']
Parameters:

ordered_items (list[dict[str, Any]])

Return type:

dict[str, Any]

vcspull.cli.add._collect_duplicate_sections(items)
function[source]

Return mapping of labels to their repeated sections (>= 2 occurrences).

Parameters:

items (list[dict[str, Any]])

Return type:

dict[str, list[Any]]

vcspull.cli.add._save_ordered_items(config_file_path, ordered_items)
function[source]

Persist ordered items in the format matching the config file extension.

Parameters:
  • config_file_path (pathlib.Path) – Path to config file (.yaml or .json).

  • ordered_items (list of dict) – Each dict has "label" and "section" keys.

Return type:

None

Examples

YAML output:

>>> import pathlib
>>> config_file = tmp_path / "test.yaml"
>>> items = [{"label": "~/code/", "section": {"myrepo": "git+https://example.com/r.git"}}]
>>> _save_ordered_items(config_file, items)
>>> config_file.read_text().strip()
'~/code/...'

JSON output:

>>> config_file = tmp_path / "test.json"
>>> _save_ordered_items(config_file, items)
>>> import json
>>> data = json.loads(config_file.read_text())
>>> "~/code/" in data
True
vcspull.cli.add.handle_add_command(args)
function[source]

Entry point for the vcspull add CLI command.

Parameters:

args (Namespace)

Return type:

None

vcspull.cli.add.add_repo(name, url, config_file_path_str, path, workspace_root_path, dry_run, *, merge_duplicates=True)
function[source]

Add a repository to the vcspull configuration.

Parameters:
  • name (str) – Repository name for the config

  • url (str) – Repository URL

  • config_file_path_str (str | None) – Path to config file, or None to use default

  • path (str | None) – Local path where repo will be cloned

  • workspace_root_path (str | None) – Workspace root to use in config

  • dry_run (bool) – If True, preview changes without writing

  • merge_duplicates (bool)

Return type:

None