1- import argparse
21import configparser
32import sys
43from pathlib import Path
54from typing import NoReturn , Union
65
6+ import click
7+
78
89FAIL = "\033 [91m"
910ENDC = "\033 [0m"
@@ -18,81 +19,7 @@ def check_if_allowed(path: Path) -> Union[bool, NoReturn]:
1819 return True
1920
2021
21- def configure_arguments (parser : argparse .ArgumentParser , repo_types : dict [str , set [str ]]) -> None :
22- subparsers = parser .add_subparsers (description = "Subcommands for managing repositories" , dest = "subcommand" )
23-
24- # List repos
25- list_parser = subparsers .add_parser ("list" , help = "List matching repositories" )
26-
27- list_parser .add_argument (
28- "-t" ,
29- "--type" ,
30- required = True ,
31- choices = sorted (set (repo_types .keys ()) - {"ignore" , "all" }),
32- metavar = "TYPE" ,
33- help = "The type of repository to manage" ,
34- )
35-
36- # Add a new repo
37- add_parser = subparsers .add_parser ("add" , help = "Add a new repository" )
38-
39- add_parser .add_argument (
40- "repository" ,
41- choices = [str (directory ) for directory in Path ("." ).iterdir () if directory .is_dir ()],
42- metavar = "REPOSITORY" ,
43- help = "The name of the repository" ,
44- )
45-
46- add_parser .add_argument (
47- "-t" ,
48- "--type" ,
49- required = True ,
50- help = "The type of the repository" ,
51- )
52-
53- # Check a repo
54- flavor_parser = subparsers .add_parser ("flavors" , help = "List the configured types for a repository" )
55-
56- flavor_parser .add_argument (
57- "repository" ,
58- choices = [str (directory ) for directory in Path ("." ).iterdir () if directory .is_dir ()],
59- metavar = "REPOSITORY" ,
60- help = "The name of the repository" ,
61- )
62-
63- # Inspect repos
64- parser .add_argument (
65- "-k" ,
66- "--known" ,
67- action = "store_true" ,
68- help = "List known repository types" ,
69- )
70-
71- parser .add_argument (
72- "-d" ,
73- "--duplicates" ,
74- action = "store_true" ,
75- help = "List repositories without a configured type" ,
76- )
77-
78- parser .add_argument (
79- "-u" ,
80- "--unconfigured" ,
81- action = "store_true" ,
82- help = "List repositories without a configured type" ,
83- )
84-
85- parser .add_argument (
86- "-m" ,
87- "--missing" ,
88- action = "store_true" ,
89- help = "List configured repositories that aren't cloned" ,
90- )
91-
92-
9322def parse_repo_types (config : configparser .ConfigParser ) -> dict [str , set [str ]]:
94- config .read (REPO_TYPES_CFG )
95-
9623 repo_types : dict [str , set [str ]] = {"all" : set ()}
9724 for section in config .sections ():
9825 repos = {repo for repo in config [section ]["known" ].split ("\n " ) if repo }
@@ -120,99 +47,118 @@ def check_missing_repos(path: Path, repo_types: dict[str, set[str]]) -> None:
12047 return None
12148
12249
123- def handle_list (
124- path : Path , config : configparser .ConfigParser , args , repo_types : dict [str , set [str ]]
125- ) -> Union [None , NoReturn ]:
126- if args .type not in repo_types :
127- print (f"\n { FAIL } Unknown type { args .type } . Valid types are:{ ENDC } " )
128- for repo_type in repo_types :
129- if repo_type != "all" and repo_type != "ignore" :
130- print (f"\t { repo_type } " )
131- sys .exit (1 )
132-
133- for repo in repo_types [args .type ]:
134- print (repo )
135-
136- return None
137-
138-
139- def handle_add (path : Path , config : configparser .ConfigParser , args , repo_types : dict [str , set [str ]]) -> None :
140- if args .type in config :
141- original_config = config [args .type ]["known" ]
142- else :
143- original_config = ""
144- config .add_section (args .type )
50+ def get_valid_repo_types ():
51+ config = configparser .ConfigParser ()
52+ config .read (REPO_TYPES_CFG )
53+ valid_repo_types = parse_repo_types (config )
54+ return sorted (set (valid_repo_types .keys ()))
14555
146- if "known" not in config [args .type ] or args .repository not in config [args .type ]["known" ].split ("\n " ):
147- config .set (args .type , "known" , f"{ original_config } \n { args .repository } " )
14856
149- with open (REPO_TYPES_CFG , "w" ) as config_file :
150- config .write (config_file )
57+ def main ():
58+ path = Path ("." )
59+ check_if_allowed (path )
15160
152- return None
61+ config = configparser .ConfigParser ()
62+ config .read (REPO_TYPES_CFG )
63+ valid_repo_types = parse_repo_types (config )
64+ check_missing_repos (path , valid_repo_types )
15365
66+ cli ()
15467
155- def handle_flavors (path : Path , config : configparser .ConfigParser , args , repo_types : dict [str , set [str ]]) -> None :
156- found = set ()
157- for section in config .sections ():
158- if section == "ignore" :
159- continue
160- if args .repository in config [section ]["known" ].split ("\n " ):
161- found .add (section )
162- for repository in sorted (found ):
163- print (repository )
16468
165- return None
69+ @click .group (invoke_without_command = True , context_settings = {"help_option_names" : ["-h" , "--help" ]})
70+ @click .version_option (package_name = "repo-man" )
71+ @click .option ("-k" , "--known" , is_flag = True , help = "List known repository types" )
72+ @click .option ("-u" , "--unconfigured" , is_flag = True , help = "List repositories without a configured type" )
73+ @click .option ("-d" , "--duplicates" , is_flag = True , help = "List repositories with more than one configured type" )
74+ # @click.option("-v", "--verbose", "verbosity", count=True)
75+ def cli (known : bool , unconfigured : bool , duplicates : bool ):
76+ """Manage repositories of different types"""
16677
78+ path = Path ("." )
79+ config = configparser .ConfigParser ()
80+ config .read (REPO_TYPES_CFG )
81+ valid_repo_types = parse_repo_types (config )
16782
168- def handle_meta (path : Path , config : configparser .ConfigParser , args , repo_types : dict [str , set [str ]]) -> None :
169- if args .known :
83+ if known :
17084 known_repo_types = sorted (
171- [repo_type for repo_type in repo_types if repo_type != "all" and repo_type != "ignore" ]
85+ [repo_type for repo_type in valid_repo_types if repo_type != "all" and repo_type != "ignore" ]
17286 )
17387 for repo_type in known_repo_types :
17488 print (repo_type )
17589
176- if args . unconfigured :
90+ if unconfigured :
17791 for directory in sorted (path .iterdir ()):
17892 if (
17993 directory .is_dir ()
180- and str (directory ) not in repo_types ["all" ]
181- and str (directory ) not in repo_types .get ("ignore" , [])
94+ and str (directory ) not in valid_repo_types ["all" ]
95+ and str (directory ) not in valid_repo_types .get ("ignore" , [])
18296 ):
18397 print (directory )
18498
185- if args . duplicates :
99+ if duplicates :
186100 seen = set ()
187- for repo_type in repo_types :
101+ for repo_type in valid_repo_types :
188102 if repo_type != "all" and repo_type != "ignore" :
189- for repo in repo_types [repo_type ]:
103+ for repo in valid_repo_types [repo_type ]:
190104 if repo in seen :
191105 print (repo )
192106 seen .add (repo )
193107
194108
195- def main ():
196- path = Path ("." )
109+ @cli .command (name = "list" , help = "The type of repository to manage" )
110+ @click .option ("-t" , "--type" , "repo_type" , type = click .Choice (get_valid_repo_types ()), show_choices = False , required = True )
111+ def list_repos (repo_type : str ):
112+ """List matching repositories"""
113+
114+ config = configparser .ConfigParser ()
115+ config .read (REPO_TYPES_CFG )
116+ valid_repo_types = parse_repo_types (config )
117+
118+ for repo in valid_repo_types [repo_type ]:
119+ print (repo )
120+
121+ return None
122+
123+
124+ @cli .command
125+ @click .argument ("repo" , type = click .Path (exists = True , file_okay = False ))
126+ def flavors (repo : str ):
127+ """List the configured types for a repository"""
128+
129+ config = configparser .ConfigParser ()
130+ config .read (REPO_TYPES_CFG )
131+
132+ found = set ()
133+
134+ for section in config .sections ():
135+ if section == "ignore" :
136+ continue
137+ if repo in config [section ]["known" ].split ("\n " ):
138+ found .add (section )
139+
140+ for repository in sorted (found ):
141+ print (repository )
197142
198- check_if_allowed (path )
199143
200- parser = argparse .ArgumentParser (
201- prog = "repo-man" ,
202- description = "Manage repositories of different types" ,
203- )
144+ @cli .command
145+ @click .option ("-t" , "--type" , "repo_types" , multiple = True , help = "The type of the repository" , required = True )
146+ @click .argument ("repo" , type = click .Path (exists = True , file_okay = False ))
147+ def add (repo : str , repo_types : list ):
148+ """Add a new repository"""
204149
205150 config = configparser .ConfigParser ()
206- repo_types = parse_repo_types (config )
207- configure_arguments (parser , repo_types )
208- args = parser .parse_args ()
209- check_missing_repos (path , repo_types )
210-
211- if args .subcommand == "list" :
212- handle_list (path , config , args , repo_types )
213- elif args .subcommand == "add" :
214- handle_add (path , config , args , repo_types )
215- elif args .subcommand == "flavors" :
216- handle_flavors (path , config , args , repo_types )
217- else :
218- handle_meta (path , config , args , repo_types )
151+ config .read (REPO_TYPES_CFG )
152+
153+ for repo_type in repo_types :
154+ if repo_type in config :
155+ original_config = config [repo_type ]["known" ]
156+ else :
157+ original_config = ""
158+ config .add_section (repo_type )
159+
160+ if "known" not in config [repo_type ] or repo not in config [repo_type ]["known" ].split ("\n " ):
161+ config .set (repo_type , "known" , f"{ original_config } \n { repo } " )
162+
163+ with open (REPO_TYPES_CFG , "w" ) as config_file :
164+ config .write (config_file )
0 commit comments