1+ import argparse
12import logging
23import sys
4+ import typing as t
35from copy import deepcopy
46
5- import click
6- import click .shell_completion
7- from click .shell_completion import CompletionItem
8-
97from libvcs ._internal .shortcuts import create_project
108from libvcs .url import registry as url_tools
11- from vcspull .types import ConfigDict
129
1310from ..config import filter_repos , find_config_files , load_configs
1411
1512log = logging .getLogger (__name__ )
1613
1714
18- def get_repo_completions (
19- ctx : click .Context , param : click .Parameter , incomplete : str
20- ) -> list [CompletionItem ]:
21- configs = (
22- load_configs (find_config_files (include_home = True ))
23- if ctx .params ["config" ] is None
24- else load_configs (files = [ctx .params ["config" ]])
25- )
26- found_repos : list [ConfigDict ] = []
27- repo_terms = [incomplete ]
28-
29- for repo_term in repo_terms :
30- dir , vcs_url , name = None , None , None
31- if any (repo_term .startswith (n ) for n in ["./" , "/" , "~" , "$HOME" ]):
32- dir = dir
33- elif any (repo_term .startswith (n ) for n in ["http" , "git" , "svn" , "hg" ]):
34- vcs_url = repo_term
35- else :
36- name = repo_term
37-
38- # collect the repos from the config files
39- found_repos .extend (filter_repos (configs , dir = dir , vcs_url = vcs_url , name = name ))
40- if len (found_repos ) == 0 :
41- found_repos = configs
42-
43- return [
44- CompletionItem (o ["name" ])
45- for o in found_repos
46- if o ["name" ].startswith (incomplete )
47- ]
48-
49-
50- def get_config_file_completions (ctx , args , incomplete ):
51- return [
52- click .shell_completion .CompletionItem (c )
53- for c in find_config_files (include_home = True )
54- if str (c ).startswith (incomplete )
55- ]
56-
57-
5815def clamp (n , _min , _max ):
5916 return max (_min , min (n , _max ))
6017
@@ -63,68 +20,64 @@ def clamp(n, _min, _max):
6320NO_REPOS_FOR_TERM_MSG = 'No repo found in config(s) for "{name}"'
6421
6522
66- @click .command (name = "sync" )
67- @click .pass_context
68- @click .argument (
69- "repo_terms" , type = click .STRING , nargs = - 1 , shell_complete = get_repo_completions
70- )
71- @click .option (
72- "config" ,
73- "--config" ,
74- "-c" ,
75- type = click .Path (exists = True ),
76- help = "Specify config" ,
77- shell_complete = get_config_file_completions ,
78- )
79- @click .option (
80- "exit_on_error" ,
81- "--exit-on-error" ,
82- "-x" ,
83- is_flag = True ,
84- default = False ,
85- help = "Exit immediately when encountering an error syncing multiple repos" ,
86- )
87- def sync (ctx , repo_terms , config , exit_on_error : bool ) -> None :
23+ def create_sync_subparser (parser : argparse .ArgumentParser ) -> argparse .ArgumentParser :
24+ parser .add_argument ("--config" , "-c" , help = "Specify config" )
25+ parser .add_argument ("repo_terms" , nargs = "+" , help = "Specify config" )
26+ parser .add_argument (
27+ "--exit-on-error" ,
28+ "-x" ,
29+ action = "store_true" ,
30+ dest = "exit_on_error" ,
31+ help = "Specify config" ,
32+ )
33+ return parser
34+
35+
36+ def sync (
37+ repo_terms ,
38+ config ,
39+ exit_on_error : bool ,
40+ parser : t .Optional [
41+ argparse .ArgumentParser
42+ ] = None , # optional so sync can be unit tested
43+ ) -> None :
8844 if config :
8945 configs = load_configs ([config ])
9046 else :
9147 configs = load_configs (find_config_files (include_home = True ))
9248 found_repos = []
9349
94- if repo_terms :
95- for repo_term in repo_terms :
96- dir , vcs_url , name = None , None , None
97- if any (repo_term .startswith (n ) for n in ["./" , "/" , "~" , "$HOME" ]):
98- dir = repo_term
99- elif any (repo_term .startswith (n ) for n in ["http" , "git" , "svn" , "hg" ]):
100- vcs_url = repo_term
101- else :
102- name = repo_term
103-
104- # collect the repos from the config files
105- found = filter_repos (configs , dir = dir , vcs_url = vcs_url , name = name )
106- if len (found ) == 0 :
107- click .echo (NO_REPOS_FOR_TERM_MSG .format (name = name ))
108- found_repos .extend (
109- filter_repos (configs , dir = dir , vcs_url = vcs_url , name = name )
110- )
111- else :
112- click .echo (ctx .get_help (), color = ctx .color )
113- ctx .exit ()
50+ for repo_term in repo_terms :
51+ dir , vcs_url , name = None , None , None
52+ if any (repo_term .startswith (n ) for n in ["./" , "/" , "~" , "$HOME" ]):
53+ dir = repo_term
54+ elif any (repo_term .startswith (n ) for n in ["http" , "git" , "svn" , "hg" ]):
55+ vcs_url = repo_term
56+ else :
57+ name = repo_term
58+
59+ # collect the repos from the config files
60+ found = filter_repos (configs , dir = dir , vcs_url = vcs_url , name = name )
61+ if len (found ) == 0 :
62+ print (NO_REPOS_FOR_TERM_MSG .format (name = name ))
63+ found_repos .extend (filter_repos (configs , dir = dir , vcs_url = vcs_url , name = name ))
11464
11565 for repo in found_repos :
11666 try :
11767 update_repo (repo )
11868 except Exception :
119- click . echo (
69+ print (
12070 f'Failed syncing { repo .get ("name" )} ' ,
12171 )
12272 if log .isEnabledFor (logging .DEBUG ):
12373 import traceback
12474
12575 traceback .print_exc ()
12676 if exit_on_error :
127- raise click .ClickException (EXIT_ON_ERROR_MSG )
77+ if parser is not None :
78+ parser .exit (status = 1 , message = EXIT_ON_ERROR_MSG )
79+ else :
80+ raise SystemExit (EXIT_ON_ERROR_MSG )
12881
12982
13083def progress_cb (output , timestamp ):
0 commit comments