4040from dfetch .project import create_super_project
4141from dfetch .project .gitsuperproject import GitSuperProject
4242from dfetch .project .metadata import Metadata
43- from dfetch .project .superproject import NoVcsSuperProject , RevisionRange
43+ from dfetch .project .superproject import NoVcsSuperProject , RevisionRange , SuperProject
4444from dfetch .util .util import (
45- catch_runtime_exceptions ,
4645 check_no_path_traversal ,
4746 in_directory ,
4847)
@@ -76,7 +75,7 @@ def __call__(self, args: argparse.Namespace) -> None:
7675 """Perform the update patch."""
7776 superproject = create_super_project ()
7877
79- exceptions : list [ str ] = []
78+ had_errors : bool = False
8079
8180 if isinstance (superproject , NoVcsSuperProject ):
8281 raise RuntimeError (
@@ -88,70 +87,79 @@ def __call__(self, args: argparse.Namespace) -> None:
8887
8988 with in_directory (superproject .root_directory ):
9089 for project in superproject .manifest .selected_projects (args .projects ):
91- with catch_runtime_exceptions (exceptions ) as exceptions :
92- subproject = dfetch .project .create_sub_project (project )
93- destination = project .destination
94-
95- def _ignored (dst : str = destination ) -> list [str ]:
96- return list (superproject .ignored_files (dst ))
97-
98- # Check if the project has a patch, maybe suggest creating one?
99- if not subproject .patch :
100- logger .print_warning_line (
101- project .name ,
102- f'skipped - there is no patch file, use "dfetch diff { project .name } "'
103- " to generate one instead" ,
104- )
105- continue
106-
107- # Check if the project was ever fetched
108- on_disk_version = subproject .on_disk_version ()
109- if not on_disk_version :
110- logger .print_warning_line (
111- project .name ,
112- f'skipped - the project was never fetched before, use "dfetch update { project .name } "' ,
113- )
114- continue
115-
116- # Make sure no uncommitted changes (don't care about ignored files)
117- if superproject .has_local_changes_in_dir (subproject .local_path ):
118- logger .print_warning_line (
119- project .name ,
120- f"skipped - Uncommitted changes in { subproject .local_path } " ,
121- )
122- continue
123-
124- # force update to fetched version from metadata without applying patch
125- subproject .update (
126- force = True ,
127- ignored_files_callback = _ignored ,
128- patch_count = len (subproject .patch ) - 1 ,
129- )
130-
131- # generate reverse patch
132- patch_text = superproject .diff (
133- subproject .local_path ,
134- revisions = RevisionRange ("" , "" ),
135- ignore = (Metadata .FILENAME ,),
136- reverse = True ,
137- )
138-
139- # Select patch to overwrite & make backup
140- if not self ._update_patch (
141- subproject .patch [- 1 ],
142- superproject .root_directory ,
143- project .name ,
144- patch_text ,
145- ):
146- continue
147-
148- # force update again to fetched version from metadata but with applying patch
149- subproject .update (
150- force = True , ignored_files_callback = _ignored , patch_count = - 1
151- )
152-
153- if exceptions :
154- raise RuntimeError ("\n " .join (exceptions ))
90+ try :
91+ self ._process_project (superproject , project )
92+ except RuntimeError as exc :
93+ logger .print_warning_line (project .name , str (exc ))
94+ had_errors = True
95+
96+ if had_errors :
97+ raise RuntimeError ()
98+
99+ def _process_project (
100+ self ,
101+ superproject : SuperProject ,
102+ project : dfetch .manifest .project .ProjectEntry ,
103+ ) -> None :
104+ """Perform the patch update for a single project."""
105+ subproject = dfetch .project .create_sub_project (project )
106+ destination = project .destination
107+
108+ def _ignored (dst : str = destination ) -> list [str ]:
109+ return list (superproject .ignored_files (dst ))
110+
111+ # Check if the project has a patch, maybe suggest creating one?
112+ if not subproject .patch :
113+ logger .print_warning_line (
114+ project .name ,
115+ f'skipped - there is no patch file, use "dfetch diff { project .name } "'
116+ " to generate one instead" ,
117+ )
118+ return
119+
120+ # Check if the project was ever fetched
121+ on_disk_version = subproject .on_disk_version ()
122+ if not on_disk_version :
123+ logger .print_warning_line (
124+ project .name ,
125+ f'skipped - the project was never fetched before, use "dfetch update { project .name } "' ,
126+ )
127+ return
128+
129+ # Make sure no uncommitted changes (don't care about ignored files)
130+ if superproject .has_local_changes_in_dir (subproject .local_path ):
131+ logger .print_warning_line (
132+ project .name ,
133+ f"skipped - Uncommitted changes in { subproject .local_path } " ,
134+ )
135+ return
136+
137+ # force update to fetched version from metadata without applying patch
138+ subproject .update (
139+ force = True ,
140+ ignored_files_callback = _ignored ,
141+ patch_count = len (subproject .patch ) - 1 ,
142+ )
143+
144+ # generate reverse patch
145+ patch_text = superproject .diff (
146+ subproject .local_path ,
147+ revisions = RevisionRange ("" , "" ),
148+ ignore = (Metadata .FILENAME ,),
149+ reverse = True ,
150+ )
151+
152+ # Select patch to overwrite & make backup
153+ if not self ._update_patch (
154+ subproject .patch [- 1 ],
155+ superproject .root_directory ,
156+ project .name ,
157+ patch_text ,
158+ ):
159+ return
160+
161+ # force update again to fetched version from metadata but with applying patch
162+ subproject .update (force = True , ignored_files_callback = _ignored , patch_count = - 1 )
155163
156164 def _update_patch (
157165 self ,
0 commit comments