68
68
"cylc install" even if present in the source directory.
69
69
"""
70
70
71
+ from functools import partial
71
72
from pathlib import Path
73
+ import re
72
74
import sys
73
- from typing import Optional , TYPE_CHECKING , List , Callable
74
- from functools import partial
75
+ from typing import (
76
+ TYPE_CHECKING ,
77
+ Callable ,
78
+ List ,
79
+ Optional ,
80
+ )
75
81
76
82
from ansimarkup import parse as cparse
77
83
78
84
from cylc .flow .exceptions import (
79
85
ServiceFileError ,
80
86
WorkflowFilesError ,
81
87
)
82
- from cylc .flow .install import (
83
- reinstall_workflow ,
84
- )
88
+ import cylc .flow .flags
89
+ from cylc .flow .install import reinstall_workflow
85
90
from cylc .flow .network .multi import call_multi
86
91
from cylc .flow .option_parsers import (
92
+ ID_MULTI_ARG_DOC ,
87
93
CylcOptionParser as COP ,
88
94
OptionSettings ,
89
- ID_MULTI_ARG_DOC
90
95
)
91
96
from cylc .flow .pathutil import get_workflow_run_dir
92
97
from cylc .flow .plugins import run_plugins_async
98
+ from cylc .flow .terminal import (
99
+ DIM ,
100
+ cli_function ,
101
+ is_terminal ,
102
+ )
93
103
from cylc .flow .workflow_files import (
94
104
get_workflow_source_dir ,
95
105
load_contact_file ,
96
106
)
97
- from cylc . flow . terminal import cli_function , DIM , is_terminal
107
+
98
108
99
109
if TYPE_CHECKING :
100
110
from optparse import Values
@@ -269,9 +279,8 @@ async def reinstall(
269
279
update anything, else returns True.
270
280
271
281
"""
272
- # run pre_configure plugins
273
282
if not dry_run :
274
- # don't run plugins in dry-mode
283
+ # run pre_configure plugins
275
284
async for _entry_point , _plugin_result in run_plugins_async (
276
285
'cylc.pre_configure' ,
277
286
srcdir = src_dir ,
@@ -287,18 +296,17 @@ async def reinstall(
287
296
dry_run = dry_run ,
288
297
)
289
298
290
- # display changes
291
299
if dry_run :
292
- if not stdout or stdout == 'send ./' :
293
- # no rsync output == no changes => exit
300
+ # display changes
301
+ changes = format_reinstall_output (stdout )
302
+ if not changes :
294
303
return False
295
304
296
305
# display rsync output
297
- write ('\n ' .join (format_rsync_out ( stdout ) ), file = sys .stderr )
306
+ write ('\n ' .join (changes ), file = sys .stderr )
298
307
299
- # run post_install plugins
300
308
if not dry_run :
301
- # don't run plugins in dry-mode
309
+ # run post_install plugins
302
310
async for _entry_point , _plugin_result in run_plugins_async (
303
311
'cylc.post_install' ,
304
312
srcdir = src_dir ,
@@ -311,15 +319,15 @@ async def reinstall(
311
319
return True
312
320
313
321
314
- def format_rsync_out (out : str ) -> List [str ]:
322
+ def format_reinstall_output (out : str ) -> List [str ]:
315
323
r"""Format rsync stdout for presenting to users.
316
324
317
325
Note: Output formats of different rsync implementations may differ so keep
318
326
this code simple and robust.
319
327
320
328
Example:
321
- >>> format_rsync_out (
322
- ... 'send foo\ndel . bar\nbaz'
329
+ >>> format_reinstall_output (
330
+ ... '>f+++++++++ send foo\n*deleting del . bar\nbaz'
323
331
... '\ncannot delete non-empty directory: opt'
324
332
... ) == [
325
333
... cparse('<green>send foo</green>'),
@@ -331,20 +339,23 @@ def format_rsync_out(out: str) -> List[str]:
331
339
"""
332
340
lines = []
333
341
for line in out .splitlines ():
334
- if line [0 :4 ] == 'send' :
335
- # file added or updated
336
- lines .append (cparse (f'<green>{ line } </green>' ))
337
- elif line [0 :4 ] == 'del.' :
338
- # file deleted
339
- lines .append (cparse (f'<red>{ line } </red>' ))
340
- elif line == 'cannot delete non-empty directory: opt' :
341
- # These "cannot delete non-empty directory" messages can arise
342
- # as a result of excluding files within sub-directories.
343
- # This opt dir message is likely to occur when a rose-suit.conf
342
+ if not line or line .startswith ('cannot delete non-empty directory:' ):
343
+ # This can arise as a result of deleting a subdir when we are
344
+ # excluding files within the subdir.
345
+ # This is likely to occur for the opt dir when a rose-suite.conf
344
346
# file is present.
347
+ # Skip this line as nothing will happen to this dir.
345
348
continue
349
+ match = re .match (r'^(.{11}) (send|del\.) (.*)$' , line )
350
+ if match :
351
+ summary , operation , file = match .groups ()
352
+ color = 'green' if operation == 'send' else 'red'
353
+ formatted_line = f"<{ color } >{ operation } { file } </{ color } >"
354
+ if cylc .flow .flags .verbosity > 0 :
355
+ formatted_line = f"<{ DIM } >{ summary } </{ DIM } > { formatted_line } "
356
+ lines .append (cparse (formatted_line ))
346
357
else :
347
- # other uncategorised log line
358
+ # shouldn't happen; tolerate unknown rsync implementation?
348
359
lines .append (line )
349
360
return lines
350
361
0 commit comments