11import os
2- import re
32import shutil
43import tempfile
54from contextlib import contextmanager
87import yaml
98from git import Repo
109
11- import repo_smith .steps .add_step
12- import repo_smith .steps .bash_step
13- import repo_smith .steps .branch_delete_step
14- import repo_smith .steps .branch_rename_step
15- import repo_smith .steps .branch_step
16- import repo_smith .steps .checkout_step
17- import repo_smith .steps .commit_step
18- import repo_smith .steps .fetch_step
19- import repo_smith .steps .file_step
20- import repo_smith .steps .merge_step
21- import repo_smith .steps .remote_step
2210import repo_smith .steps .tag_step
2311from repo_smith .clone_from import CloneFrom
2412from repo_smith .spec import Spec
25- from repo_smith .steps .step import Step
26- from repo_smith .steps .step_type import StepType
13+ from repo_smith .steps .dispatcher import Dispatcher
2714
2815Hook : TypeAlias = Callable [[Repo ], None ]
2916
@@ -46,7 +33,7 @@ def initialize(self, existing_path: Optional[str] = None) -> Iterator[Repo]:
4633 if self .__spec .clone_from is not None :
4734 repo = Repo .clone_from (self .__spec .clone_from .repo_url , tmp_dir )
4835 else :
49- repo = Repo .init (tmp_dir )
36+ repo = Repo .init (tmp_dir , initial_branch = "main" )
5037
5138 for step in self .__spec .steps :
5239 if step .id in self .__pre_hooks :
@@ -118,8 +105,8 @@ def __get_all_ids(self, spec: Spec) -> Set[str]:
118105 def __parse_spec (self , spec : Any ) -> Spec :
119106 steps = []
120107
121- for step in spec .get ("initialization" , {}).get ("steps" , []):
122- steps .append (self . __parse_step (step ))
108+ for step in spec .get ("initialization" , {}).get ("steps" , []) or [] :
109+ steps .append (Dispatcher . dispatch (step ))
123110
124111 clone_from = None
125112 if spec .get ("initialization" , {}).get ("clone-from" , None ) is not None :
@@ -134,233 +121,6 @@ def __parse_spec(self, spec: Any) -> Spec:
134121 clone_from = clone_from ,
135122 )
136123
137- def __parse_step (self , step : Any ) -> Step :
138- if "type" not in step :
139- raise ValueError ('Missing "type" field in step.' )
140-
141- name = step .get ("name" )
142- description = step .get ("description" )
143- step_type = StepType .from_value (step ["type" ])
144- id = step .get ("id" )
145-
146- if step_type == StepType .COMMIT :
147- if "message" not in step :
148- raise ValueError ('Missing "message" field in commit step.' )
149-
150- return repo_smith .steps .commit_step .CommitStep (
151- name = name ,
152- description = description ,
153- step_type = StepType .COMMIT ,
154- id = id ,
155- empty = step .get ("empty" , False ),
156- message = step ["message" ],
157- )
158- elif step_type == StepType .ADD :
159- if "files" not in step :
160- raise ValueError ('Missing "files" field in add step.' )
161-
162- if step ["files" ] is None or step ["files" ] == []:
163- raise ValueError ('Empty "files" list in add step.' )
164-
165- return repo_smith .steps .add_step .AddStep (
166- name = name ,
167- description = description ,
168- step_type = StepType .ADD ,
169- id = id ,
170- files = step ["files" ],
171- )
172- elif step_type == StepType .TAG :
173- if "tag-name" not in step :
174- raise ValueError ('Missing "tag-name" field in tag step.' )
175-
176- if step ["tag-name" ] is None or step ["tag-name" ].strip () == "" :
177- raise ValueError ('Empty "tag-name" field in tag step.' )
178-
179- tag_name_regex = "^[0-9a-zA-Z-_.]*$"
180- if re .search (tag_name_regex , step ["tag-name" ]) is None :
181- raise ValueError (
182- 'Field "tag-name" can only contain alphanumeric characters, _, -, .'
183- )
184-
185- return repo_smith .steps .tag_step .TagStep (
186- name = name ,
187- description = description ,
188- step_type = StepType .TAG ,
189- id = id ,
190- tag_name = step ["tag-name" ],
191- tag_message = step .get ("tag-message" ),
192- )
193- elif step_type == StepType .BASH :
194- if "runs" not in step :
195- raise ValueError ('Missing "runs" field in bash step.' )
196-
197- if step ["runs" ] is None or step ["runs" ].strip () == "" :
198- raise ValueError ('Empty "runs" field in file step.' )
199-
200- return repo_smith .steps .bash_step .BashStep (
201- name = name ,
202- description = description ,
203- step_type = step_type ,
204- id = id ,
205- body = step ["runs" ],
206- )
207- elif step_type == StepType .BRANCH :
208- if "branch-name" not in step :
209- raise ValueError ('Missing "branch-name" field in branch step.' )
210-
211- if step ["branch-name" ] is None or step ["branch-name" ].strip () == "" :
212- raise ValueError ('Empty "branch-name" field in branch step.' )
213-
214- return repo_smith .steps .branch_step .BranchStep (
215- name = name ,
216- description = description ,
217- step_type = step_type ,
218- id = id ,
219- branch_name = step ["branch-name" ],
220- )
221- elif step_type == StepType .BRANCH_RENAME :
222- if "branch-name" not in step :
223- raise ValueError ('Missing "branch-name" field in branch-rename step.' )
224-
225- if step ["branch-name" ] is None or step ["branch-name" ].strip () == "" :
226- raise ValueError ('Empty "branch-name" field in branch-rename step.' )
227-
228- if "new-name" not in step :
229- raise ValueError ('Missing "new-name" field in branch-rename step.' )
230-
231- if step ["new-name" ] is None or step ["new-name" ].strip () == "" :
232- raise ValueError ('Empty "new-name" field in branch-rename step.' )
233-
234- return repo_smith .steps .branch_rename_step .BranchRenameStep (
235- name = name ,
236- description = description ,
237- step_type = step_type ,
238- id = id ,
239- original_branch_name = step ["branch-name" ],
240- target_branch_name = step ["new-name" ],
241- )
242- elif step_type == StepType .BRANCH_DELETE :
243- if "branch-name" not in step :
244- raise ValueError ('Missing "branch-name" field in branch step.' )
245-
246- if step ["branch-name" ] is None or step ["branch-name" ].strip () == "" :
247- raise ValueError ('Empty "branch-name" field in branch step.' )
248-
249- return repo_smith .steps .branch_delete_step .BranchDeleteStep (
250- name = name ,
251- description = description ,
252- step_type = step_type ,
253- id = id ,
254- branch_name = step ["branch-name" ],
255- )
256- elif step_type == StepType .CHECKOUT :
257- if step .get ("branch-name" ) is None and step .get ("commit-hash" ) is None :
258- raise ValueError (
259- 'Provide either "branch-name" or "commit-hash" in checkout step.'
260- )
261-
262- return repo_smith .steps .checkout_step .CheckoutStep (
263- name = name ,
264- description = description ,
265- step_type = step_type ,
266- id = id ,
267- branch_name = step .get ("branch-name" ),
268- commit_hash = step .get ("commit-hash" ),
269- )
270- elif step_type == StepType .MERGE :
271- if step .get ("branch-name" ) is None :
272- raise ValueError ('Provide either "branch-name" in merge step.' )
273-
274- return repo_smith .steps .merge_step .MergeStep (
275- name = name ,
276- description = description ,
277- step_type = step_type ,
278- id = id ,
279- branch_name = step .get ("branch-name" ),
280- no_fast_forward = step .get ("no-ff" , False ),
281- squash = step .get ("squash" , False ),
282- )
283- elif step_type == StepType .REMOTE :
284- if "remote-url" not in step :
285- raise ValueError ('Missing "remote-url" field in remote step.' )
286-
287- if "remote-name" not in step :
288- raise ValueError ('Missing "remote-name" field in remote step.' )
289-
290- return repo_smith .steps .remote_step .RemoteStep (
291- name = name ,
292- description = description ,
293- id = id ,
294- step_type = step_type ,
295- remote_name = step ["remote-name" ],
296- remote_url = step ["remote-url" ],
297- )
298- elif step_type == StepType .FETCH :
299- if "remote-name" not in step :
300- raise ValueError ('Missing "remote-name" field in fetch step.' )
301-
302- return repo_smith .steps .fetch_step .FetchStep (
303- name = name ,
304- description = description ,
305- id = id ,
306- step_type = step_type ,
307- remote_name = step ["remote-name" ],
308- )
309- elif step_type in {
310- StepType .NEW_FILE ,
311- StepType .APPEND_FILE ,
312- StepType .EDIT_FILE ,
313- StepType .DELETE_FILE ,
314- }:
315- if "filename" not in step :
316- raise ValueError ('Missing "filename" field in file step.' )
317-
318- if step ["filename" ] is None or step ["filename" ].strip () == "" :
319- raise ValueError ('Empty "filename" field in file step.' )
320-
321- filename = step ["filename" ]
322- contents = step .get ("contents" , "" ) or ""
323-
324- match step_type :
325- case StepType .NEW_FILE :
326- return repo_smith .steps .file_step .NewFileStep (
327- name = name ,
328- description = description ,
329- step_type = step_type ,
330- id = id ,
331- filename = filename ,
332- contents = contents ,
333- )
334- case StepType .EDIT_FILE :
335- return repo_smith .steps .file_step .EditFileStep (
336- name = name ,
337- description = description ,
338- step_type = step_type ,
339- id = id ,
340- filename = filename ,
341- contents = contents ,
342- )
343- case StepType .DELETE_FILE :
344- return repo_smith .steps .file_step .DeleteFileStep (
345- name = name ,
346- description = description ,
347- step_type = step_type ,
348- id = id ,
349- filename = filename ,
350- contents = contents ,
351- )
352- case StepType .APPEND_FILE :
353- return repo_smith .steps .file_step .AppendFileStep (
354- name = name ,
355- description = description ,
356- step_type = step_type ,
357- id = id ,
358- filename = filename ,
359- contents = contents ,
360- )
361- else :
362- raise ValueError ('Improper "type" field in spec.' )
363-
364124
365125def initialize_repo (spec_path : str ) -> RepoInitializer :
366126 if not os .path .isfile (spec_path ):
0 commit comments