vcspull import - vcspull.cli.import_cmd¶
vcspull import subcommand package.
Each supported service (GitHub, GitLab, Codeberg, Gitea, Forgejo,
CodeCommit) is registered as a proper argparse subcommand so that
vcspull import <service> --help shows only the flags relevant to
that service.
- vcspull.cli.import_cmd.create_import_subparser(parser)[source]¶
Wire per-service subparsers into the
vcspull importparser.- Return type:
- Parameters:
parser (argparse.ArgumentParser) – The
importparser to attach service subcommands to.
Shared infrastructure for the vcspull import subcommand tree.
Provides parent argparse parsers (for flag composition via parents=[])
and the _run_import() function that all per-service handlers delegate to.
- class vcspull.cli.import_cmd._common.Importer[source]¶
Bases:
ProtocolStructural type for any remote service importer.
- fetch_repos(options)[source]¶
Yield repositories matching options.
- Return type:
Iterator[RemoteRepo]- Parameters:
options (ImportOptions)
- _abc_impl = <_abc._abc_data object>¶
- _is_protocol = True¶
- class vcspull.cli.import_cmd._common.ImportAction[source]¶
Bases:
EnumAction resolved for each repo candidate during
vcspull import.- ADD = 'add'¶
- SKIP_UNCHANGED = 'skip_unchanged'¶
- SKIP_EXISTING = 'skip_existing'¶
- UPDATE_URL = 'update_url'¶
- SKIP_PINNED = 'skip_pinned'¶
- PRUNE = 'prune'¶
- vcspull.cli.import_cmd._common._classify_import_action(*, incoming_url, existing_entry, sync)[source]¶
Classify the import action for a single repository.
- Return type:
- Parameters:
Examples
New repo is always added:
>>> _classify_import_action( ... incoming_url="git+ssh://x", existing_entry=None, sync=False ... ) <ImportAction.ADD: 'add'> >>> _classify_import_action( ... incoming_url="git+ssh://x", existing_entry=None, sync=True ... ) <ImportAction.ADD: 'add'>
Same URL is always classified as unchanged — even when pinned or sync is set.
Note:
_run_importmay still stamp provenance metadata on unchanged entries whenimport_sourceis provided.>>> _classify_import_action( ... incoming_url="git+ssh://x", ... existing_entry={"repo": "git+ssh://x"}, ... sync=True, ... ) <ImportAction.SKIP_UNCHANGED: 'skip_unchanged'> >>> _classify_import_action( ... incoming_url="git+ssh://x", ... existing_entry={"repo": "git+ssh://x", "options": {"pin": True}}, ... sync=True, ... ) <ImportAction.SKIP_UNCHANGED: 'skip_unchanged'>
urlkey takes precedence overrepokey (matches extract_repos semantics):>>> _classify_import_action( ... incoming_url="git+ssh://new", ... existing_entry={"repo": "git+ssh://old", "url": "git+ssh://new"}, ... sync=False, ... ) <ImportAction.SKIP_UNCHANGED: 'skip_unchanged'>
Different URL without sync is skipped:
>>> _classify_import_action( ... incoming_url="git+ssh://x", ... existing_entry={"repo": "git+https://x"}, ... sync=False, ... ) <ImportAction.SKIP_EXISTING: 'skip_existing'>
Different URL with sync updates the URL (unless pinned):
>>> _classify_import_action( ... incoming_url="git+ssh://x", ... existing_entry={"repo": "git+https://x"}, ... sync=True, ... ) <ImportAction.UPDATE_URL: 'update_url'>
URL update is blocked by pin (only when URL differs):
>>> _classify_import_action( ... incoming_url="git+ssh://x", ... existing_entry={"repo": "git+https://x", "options": {"pin": True}}, ... sync=True, ... ) <ImportAction.SKIP_PINNED: 'skip_pinned'>
Non-dict, non-str entries fall back to empty URL (treated as different):
>>> _classify_import_action( ... incoming_url="git+ssh://x", existing_entry=42, sync=False ... ) <ImportAction.SKIP_EXISTING: 'skip_existing'>
- vcspull.cli.import_cmd._common._classify_prune_action(*, existing_entry, imported_from_tag)[source]¶
Classify whether an existing config entry should be pruned.
- Return type:
- Parameters:
Examples
String entries (no metadata) are never pruned:
>>> _classify_prune_action( ... existing_entry="git+ssh://x", imported_from_tag="github:org" ... ) <ImportAction.SKIP_EXISTING: 'skip_existing'>
Entry with matching tag is pruned:
>>> _classify_prune_action( ... existing_entry={ ... "repo": "git+ssh://x", ... "metadata": {"imported_from": "github:org"}, ... }, ... imported_from_tag="github:org", ... ) <ImportAction.PRUNE: 'prune'>
Entry with different tag is not pruned:
>>> _classify_prune_action( ... existing_entry={ ... "repo": "git+ssh://x", ... "metadata": {"imported_from": "github:other"}, ... }, ... imported_from_tag="github:org", ... ) <ImportAction.SKIP_EXISTING: 'skip_existing'>
Pinned entry with matching tag is not pruned:
>>> _classify_prune_action( ... existing_entry={ ... "repo": "git+ssh://x", ... "options": {"pin": True}, ... "metadata": {"imported_from": "github:org"}, ... }, ... imported_from_tag="github:org", ... ) <ImportAction.SKIP_PINNED: 'skip_pinned'>
Entry without metadata is not pruned:
>>> _classify_prune_action( ... existing_entry={"repo": "git+ssh://x"}, ... imported_from_tag="github:org", ... ) <ImportAction.SKIP_EXISTING: 'skip_existing'>
- vcspull.cli.import_cmd._common._classify_untracked_prune_action(*, existing_entry)[source]¶
Classify whether an untracked config entry should be pruned.
“Untracked” means the entry has no import provenance from any source. This is the complement of
_classify_prune_action(), which checks for a specific source tag.- Return type:
- Parameters:
existing_entry (dict | str | Any) – Current config entry for this repo name.
- Returns:
PRUNEfor entries without provenance (untracked),SKIP_PINNEDfor pinned entries,SKIP_EXISTINGfor entries that have provenance from any source.- Return type:
Examples
String entries have no metadata — they are untracked:
>>> _classify_untracked_prune_action(existing_entry="git+ssh://x") <ImportAction.PRUNE: 'prune'>
Dict entry without metadata is untracked:
>>> _classify_untracked_prune_action( ... existing_entry={"repo": "git+ssh://x"}, ... ) <ImportAction.PRUNE: 'prune'>
Dict entry with provenance from any source is tracked (kept):
>>> _classify_untracked_prune_action( ... existing_entry={ ... "repo": "git+ssh://x", ... "metadata": {"imported_from": "github:org"}, ... }, ... ) <ImportAction.SKIP_EXISTING: 'skip_existing'>
>>> _classify_untracked_prune_action( ... existing_entry={ ... "repo": "git+ssh://x", ... "metadata": {"imported_from": "gitlab:other"}, ... }, ... ) <ImportAction.SKIP_EXISTING: 'skip_existing'>
Pinned entry without provenance is protected:
>>> _classify_untracked_prune_action( ... existing_entry={ ... "repo": "git+ssh://x", ... "options": {"pin": True}, ... }, ... ) <ImportAction.SKIP_PINNED: 'skip_pinned'>
Pinned entry with provenance is also protected:
>>> _classify_untracked_prune_action( ... existing_entry={ ... "repo": "git+ssh://x", ... "options": {"pin": True}, ... "metadata": {"imported_from": "github:org"}, ... }, ... ) <ImportAction.SKIP_PINNED: 'skip_pinned'>
Create parent parser with workspace, filtering, and output flags.
- Return type:
- Returns:
Parent parser (
add_help=False) carrying flags shared by all import service subcommands.- Return type:
- vcspull.cli.import_cmd._common._create_token_parent()[source]¶
Create parent parser with the
--tokenflag.- Return type:
- Returns:
Parent parser carrying
--token.- Return type:
- vcspull.cli.import_cmd._common._create_mode_parent()[source]¶
Create parent parser with the
-m/--modeflag.- Return type:
- Returns:
Parent parser carrying
-m/--mode.- Return type:
- vcspull.cli.import_cmd._common._create_target_parent()[source]¶
Create parent parser with the required
targetpositional.- Return type:
- Returns:
Parent parser carrying the
targetpositional argument.- Return type:
- vcspull.cli.import_cmd._common._resolve_config_file(config_path_str)[source]¶
Resolve the config file path.
- Return type:
- Parameters:
config_path_str (str | None) – Config file path from user, or None for default
- Returns:
Resolved config file path
- Return type:
- vcspull.cli.import_cmd._common._run_import(importer, *, service_name, target, workspace, mode, language, topics, min_stars, include_archived, include_forks, limit, config_path_str, dry_run, yes, output_json, output_ndjson, color, use_https=False, flatten_groups=False, with_shared=False, skip_groups=None, sync=False, prune=False, prune_untracked=False, import_source=None)[source]¶
Run the import workflow for a single service.
This is the core fetch / preview / confirm / write logic shared by every per-service handler. The caller is responsible for constructing the importer instance; this function only orchestrates the import flow.
- Return type:
- Parameters:
importer (Importer) – Already-constructed importer instance (any object satisfying the
Importerprotocol)service_name (str) – Canonical service name (e.g.
"github","gitlab","codecommit")target (str) – User, org, or search query
workspace (str) – Workspace root directory
mode (str) – Import mode (user, org, search)
language (str | None) – Language filter
topics (str | None) – Topics filter (comma-separated)
min_stars (int) – Minimum stars filter
include_archived (bool) – Include archived repositories
include_forks (bool) – Include forked repositories
limit (int) – Maximum repositories to fetch
config_path_str (str | None) – Config file path
dry_run (bool) – Preview without writing
yes (bool) – Skip confirmation
output_json (bool) – Output as JSON
output_ndjson (bool) – Output as NDJSON
color (str) – Color mode
use_https (bool) – Use HTTPS clone URLs instead of SSH (default: False, i.e., SSH)
flatten_groups (bool) – For GitLab org imports, flatten subgroup paths into base workspace
with_shared (bool) – Include projects shared into a group from other namespaces (GitLab only)
skip_groups (list[str] | None) – Exclude repos whose owner path contains any of these group name segments
sync (bool) – Sync existing config entries whose URL has changed (default: False). Entries with
options.pin.importoroptions.allow_overwrite: falseare exempt.prune (bool) – Remove config entries tagged by a previous import that are no longer on the remote (default: False). Does not update URLs for existing entries; use
syncfor that.import_source (str | None) – Provenance tag for imported repos, e.g.
"github:myorg". When provided, repos are tagged withmetadata.imported_fromand stale tagged entries are pruned whensyncis True.prune_untracked (bool)
- Returns:
0 on success, 1 on error
- Return type: