66from pathlib import Path
77
88import typer
9- from copier import run_copy
109
1110from devman import __version__
1211from devman .application .use_cases import (
12+ CreateProjectCommand ,
13+ CreateProjectUseCase ,
1314 FindDevmanCommand ,
1415 FindDevmanUseCase ,
1516 RunDevenvCommand ,
1617 RunDevenvUseCase ,
17- ValidateTemplateCommand ,
18- ValidateTemplateUseCase ,
1918)
20- from devman .config import load_config
19+ from devman .config import ConfigRepository , load_config
2120from devman .domain .models import ProjectRoot
22- from devman .templates import TemplateReference
23-
24-
25- # Re-export domain DevmanFinder for backward compatibility
26- from devman .domain .finder import DevmanFinder as _DomainFinder # noqa: F401
27-
28-
29- class DevmanFinder :
30- """Locate the nearest devman configuration directory.
31-
32- Legacy wrapper for backward compatibility.
33- Prefer using devman.domain.finder.DevmanFinder directly.
34- """
35-
36- def __init__ (self , projects_root : Path | None = None ) -> None :
37- self .projects_root = projects_root
38-
39- @classmethod
40- def from_config (cls ) -> DevmanFinder :
41- config = load_config ()
42- return cls (projects_root = config .projects_root )
43-
44- def find (self , start_path : Path | None = None ) -> Path | None :
45- """Find .devman directory, returning Path or None for backward compat."""
46- root = None
47- if self .projects_root is not None :
48- root_result = ProjectRoot .create (self .projects_root )
49- if root_result .is_ok ():
50- root = root_result .unwrap ()
51-
52- domain_finder = _DomainFinder (projects_root = root )
53- result = domain_finder .find (start_path = start_path )
54-
55- if result .is_ok ():
56- return result .unwrap ().path
57- return None
5821
5922
6023app = typer .Typer ()
@@ -86,7 +49,7 @@ def run(
8649
8750 # Execute find use case
8851 find_use_case = FindDevmanUseCase ()
89- find_command = FindDevmanCommand (projects_root = root )
52+ find_command = FindDevmanCommand (start_path = Path . cwd (), projects_root = root )
9053 find_result = find_use_case .execute (find_command )
9154
9255 if find_result .is_err ():
@@ -125,66 +88,52 @@ def new(
12588 ),
12689) -> None :
12790 """Create a new project from a copier template."""
128- # Parse template reference
129- try :
130- template_ref = TemplateReference .from_string (template_source )
131- except ValueError as e :
132- typer .echo (f"Invalid template source: { e } " , err = True )
133- raise typer .Exit (1 )
134-
135- # Validate if requested
136- if validate :
137- typer .echo ("Validating template..." )
138-
139- validate_use_case = ValidateTemplateUseCase ()
140- validate_command = ValidateTemplateCommand (template_reference = template_ref )
141- validate_result = validate_use_case .execute (validate_command )
142-
143- vr = validate_result .validation_result
144-
145- if not vr .is_valid :
146- typer .echo ("Template validation errors:" , err = True )
147- for error in vr .errors :
148- loc = f" ({ error .location } )" if error .location else ""
149- typer .echo (f" - { error .message } { loc } " , err = True )
150- raise typer .Exit (1 )
151-
152- if vr .warnings :
153- typer .echo ("Template warnings:" )
154- for warning in vr .warnings :
155- loc = f" ({ warning .location } )" if warning .location else ""
156- typer .echo (f" - { warning .message } { loc } " )
157-
15891 # Parse data overrides
159- data_dict = {}
92+ data_dict : dict [ str , str ] = {}
16093 for item in data :
16194 if "=" not in item :
16295 typer .echo (f"Invalid data format: { item } (expected key=value)" , err = True )
16396 raise typer .Exit (1 )
16497 key , value = item .split ("=" , 1 )
16598 data_dict [key ] = value
16699
167- # Run copier
168- try :
169- typer .echo (f"Creating project at { destination } ..." )
100+ # Execute use case
101+ use_case = CreateProjectUseCase ()
102+ command = CreateProjectCommand (
103+ template_source = template_source ,
104+ destination = destination ,
105+ data = data_dict ,
106+ validate = validate ,
107+ )
170108
171- source = template_ref .location
172- if template_ref .source_type == "file" :
173- source = str (template_ref .resolve_path ())
109+ typer .echo (f"Creating project at { destination } ..." )
110+ result = use_case .execute (command )
174111
175- run_copy (
176- src_path = source ,
177- dst_path = str (destination ),
178- data = data_dict if data_dict else None ,
179- unsafe = True ,
180- )
112+ if result .is_err ():
113+ error = result .unwrap_err ()
181114
182- typer .echo (f"Project created successfully at { destination } " )
115+ # Show validation errors if present
116+ if error .validation_result and not error .validation_result .is_valid :
117+ typer .echo ("Template validation errors:" , err = True )
118+ for issue in error .validation_result .errors :
119+ loc = f" ({ issue .location } )" if issue .location else ""
120+ typer .echo (f" - { issue .message } { loc } " , err = True )
121+ else :
122+ typer .echo (error .message , err = True )
183123
184- except Exception as e :
185- typer .echo (f"Failed to create project: { e } " , err = True )
186124 raise typer .Exit (1 )
187125
126+ success = result .unwrap ()
127+
128+ # Show warnings if any
129+ if success .validation_result and success .validation_result .warnings :
130+ typer .echo ("Template warnings:" )
131+ for warning in success .validation_result .warnings :
132+ loc = f" ({ warning .location } )" if warning .location else ""
133+ typer .echo (f" - { warning .message } { loc } " )
134+
135+ typer .echo (f"Project created successfully at { destination } " )
136+
188137
189138@app .command ()
190139def config (
@@ -199,23 +148,20 @@ def config(
199148 typer .echo ("No configuration changes provided." , err = True )
200149 raise typer .Exit (1 )
201150
151+ repo = ConfigRepository ()
152+
202153 if show :
203- current_config = load_config ()
154+ current_config = repo . load ()
204155 typer .echo ("Current configuration:" )
205156 if current_config .projects_root is None :
206157 typer .echo (" projects_root: (not set)" )
207158 else :
208159 typer .echo (f" projects_root: { current_config .projects_root } " )
209160
210161 if projects_root is not None :
211- config_path = Path ("~/.config/devman/config.env" ).expanduser ()
212- config_path .parent .mkdir (parents = True , exist_ok = True )
213- resolved_root = projects_root .expanduser ().resolve ()
214- config_path .write_text (
215- f"DEVMAN_PROJECTS_ROOT={ resolved_root } \n " ,
216- encoding = "utf-8" ,
217- )
218- typer .echo (f"Updated projects root to { resolved_root } ." )
162+ repo .save_projects_root (projects_root )
163+ resolved = projects_root .expanduser ().resolve ()
164+ typer .echo (f"Updated projects root to { resolved } ." )
219165
220166
221167@app .command ()
0 commit comments