1
+ import argparse
1
2
import logging
2
3
import sys
4
+ import typing as t
3
5
from copy import deepcopy
4
6
5
- import click
6
- import click .shell_completion
7
- from click .shell_completion import CompletionItem
8
-
9
7
from libvcs ._internal .shortcuts import create_project
10
8
from libvcs .url import registry as url_tools
11
- from vcspull .types import ConfigDict
12
9
13
10
from ..config import filter_repos , find_config_files , load_configs
14
11
15
12
log = logging .getLogger (__name__ )
16
13
17
14
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
-
58
15
def clamp (n , _min , _max ):
59
16
return max (_min , min (n , _max ))
60
17
@@ -63,68 +20,64 @@ def clamp(n, _min, _max):
63
20
NO_REPOS_FOR_TERM_MSG = 'No repo found in config(s) for "{name}"'
64
21
65
22
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 :
88
44
if config :
89
45
configs = load_configs ([config ])
90
46
else :
91
47
configs = load_configs (find_config_files (include_home = True ))
92
48
found_repos = []
93
49
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 ))
114
64
115
65
for repo in found_repos :
116
66
try :
117
67
update_repo (repo )
118
68
except Exception :
119
- click . echo (
69
+ print (
120
70
f'Failed syncing { repo .get ("name" )} ' ,
121
71
)
122
72
if log .isEnabledFor (logging .DEBUG ):
123
73
import traceback
124
74
125
75
traceback .print_exc ()
126
76
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 )
128
81
129
82
130
83
def progress_cb (output , timestamp ):
0 commit comments