Coverage for src/somesy/cli/sync.py: 31%

39 statements  

« prev     ^ index     » next       coverage.py v7.16.0, created at 2026-09-04 11:35 +0000

1"""Sync command for somesy.""" 

2 

3import logging 

4from pathlib import Path 

5 

6import typer 

7 

8from somesy.commands import sync as sync_command 

9from somesy.core.models import SomesyInput 

10 

11from .util import ( 

12 existing_file_arg_config, 

13 file_arg_config, 

14 resolved_somesy_input, 

15 wrap_exceptions, 

16) 

17 

18logger = logging.getLogger("somesy") 

19 

20app = typer.Typer() 

21 

22 

23@app.callback(invoke_without_command=True) 

24@wrap_exceptions 

25def sync( 

26 input_file: Path | None = typer.Option( 

27 None, 

28 "--input-file", 

29 "-i", 

30 help="Somesy input file path (default: .somesy.toml)", 

31 **file_arg_config, 

32 ), 

33 no_sync_pyproject: bool | None = typer.Option( 

34 None, 

35 "--no-sync-pyproject", 

36 "-P", 

37 help="Do not sync pyproject.toml file (default: False)", 

38 ), 

39 pyproject_file: list[Path] | None = typer.Option( 

40 None, 

41 "--pyproject-file", 

42 "-p", 

43 help="Existing pyproject.toml file path(s) (default: pyproject.toml)", 

44 **existing_file_arg_config, 

45 ), 

46 no_sync_package_json: bool | None = typer.Option( 

47 None, 

48 "--no-sync-package-json", 

49 "-J", 

50 help="Do not sync package.json file (default: False)", 

51 ), 

52 package_json_file: list[Path] | None = typer.Option( 

53 None, 

54 "--package-json-file", 

55 "-j", 

56 help="Existing package.json file path(s) (default: package.json)", 

57 **existing_file_arg_config, 

58 ), 

59 no_sync_julia: bool | None = typer.Option( 

60 None, 

61 "--no-sync-julia", 

62 "-L", 

63 help="Do not sync Project.toml (Julia) file (default: False)", 

64 ), 

65 julia_file: list[Path] | None = typer.Option( 

66 None, 

67 "--julia-file", 

68 "-l", 

69 help="Custom Project.toml (Julia) file path(s) (default: Project.toml)", 

70 **existing_file_arg_config, 

71 ), 

72 no_sync_fortran: bool | None = typer.Option( 

73 None, 

74 "--no-sync-fortran", 

75 "-F", 

76 help="Do not sync fpm.toml (Fortran) file (default: False)", 

77 ), 

78 fortran_file: list[Path] | None = typer.Option( 

79 None, 

80 "--fortran-file", 

81 "-f", 

82 help="Custom fpm.toml (Fortran) file path(s) (default: fpm.toml)", 

83 **existing_file_arg_config, 

84 ), 

85 no_sync_pom_xml: bool | None = typer.Option( 

86 None, 

87 "--no-sync-pomxml", 

88 "-X", 

89 help="Do not sync pom.xml (Java Maven) file (default: False)", 

90 ), 

91 pom_xml_file: list[Path] | None = typer.Option( 

92 None, 

93 "--pomxml-file", 

94 "-x", 

95 help="Custom pom.xml (Java Maven) file path(s) (default: pom.xml)", 

96 **existing_file_arg_config, 

97 ), 

98 no_sync_mkdocs: bool | None = typer.Option( 

99 None, 

100 "--no-sync-mkdocs", 

101 "-D", 

102 help="Do not sync mkdocs.yml file (default: False)", 

103 ), 

104 mkdocs_file: list[Path] | None = typer.Option( 

105 None, 

106 "--mkdocs-file", 

107 "-d", 

108 help="Custom mkdocs.yml file path(s) (default: mkdocs.yml)", 

109 **existing_file_arg_config, 

110 ), 

111 no_sync_rust: bool | None = typer.Option( 

112 None, 

113 "--no-sync-rust", 

114 "-R", 

115 help="Do not sync Cargo.toml file (default: False)", 

116 ), 

117 rust_file: list[Path] | None = typer.Option( 

118 None, 

119 "--rust-file", 

120 "-r", 

121 help="Custom Cargo.toml file path(s) (default: Cargo.toml)", 

122 **existing_file_arg_config, 

123 ), 

124 no_sync_cff: bool | None = typer.Option( 

125 None, 

126 "--no-sync-cff", 

127 "-C", 

128 help="Do not sync CITATION.cff file (default: False)", 

129 ), 

130 cff_file: list[Path] | None = typer.Option( 

131 None, 

132 "--cff-file", 

133 "-c", 

134 help="CITATION.cff file path(s) (default: CITATION.cff)", 

135 **file_arg_config, 

136 ), 

137 no_sync_codemeta: bool | None = typer.Option( 

138 None, 

139 "--no-sync-codemeta", 

140 "-M", 

141 help="Do not sync codemeta.json file (default: False)", 

142 ), 

143 codemeta_file: list[Path] | None = typer.Option( 

144 None, 

145 "--codemeta-file", 

146 "-m", 

147 help="Custom codemeta.json file path(s) (default: codemeta.json)", 

148 **file_arg_config, 

149 ), 

150 merge_codemeta: bool | None = typer.Option( 

151 False, 

152 "--merge/--overwrite", 

153 help="Merge codemeta.json with with an existing codemeta.json file (default: False)", 

154 ), 

155 pass_validation: bool | None = typer.Option( 

156 False, 

157 "--pass-validation", 

158 "-V", 

159 help="Pass validation of metadata files (default: False)", 

160 ), 

161 packages: list[Path] | None = typer.Option( 

162 None, 

163 "--packages", 

164 "-k", 

165 help="Packages (subfolders) for monorepos with their own somesy config.", 

166 **existing_file_arg_config, 

167 ), 

168): 

169 """Sync project metadata input with metadata files.""" 

170 somesy_input = resolved_somesy_input( 

171 input_file=input_file, 

172 no_sync_cff=no_sync_cff, 

173 cff_file=cff_file, 

174 no_sync_pyproject=no_sync_pyproject, 

175 pyproject_file=pyproject_file, 

176 no_sync_package_json=no_sync_package_json, 

177 package_json_file=package_json_file, 

178 no_sync_codemeta=no_sync_codemeta, 

179 codemeta_file=codemeta_file, 

180 no_sync_julia=no_sync_julia, 

181 julia_file=julia_file, 

182 no_sync_fortran=no_sync_fortran, 

183 fortran_file=fortran_file, 

184 no_sync_pom_xml=no_sync_pom_xml, 

185 pom_xml_file=pom_xml_file, 

186 no_sync_mkdocs=no_sync_mkdocs, 

187 mkdocs_file=mkdocs_file, 

188 no_sync_rust=no_sync_rust, 

189 rust_file=rust_file, 

190 merge_codemeta=merge_codemeta, 

191 pass_validation=pass_validation, 

192 packages=packages, 

193 ) 

194 

195 run_sync(somesy_input) 

196 

197 

198def run_sync(somesy_input: SomesyInput): 

199 """Write log messages and run synchronization based on passed config.""" 

200 conf = somesy_input.config 

201 logger.info("[bold green]Synchronizing project metadata...[/bold green]") 

202 logger.info("Files to sync:") 

203 if not conf.no_sync_pyproject: 

204 logger.info( 

205 f" - [italic]pyproject.toml[/italic]:\t[grey]{conf.pyproject_file}[/grey]" 

206 ) 

207 if not conf.no_sync_package_json: 

208 logger.info( 

209 f" - [italic]package.json[/italic]:\t[grey]{conf.package_json_file}[/grey]" 

210 ) 

211 if not conf.no_sync_julia: 

212 logger.info( 

213 f" - [italic]Project.toml[/italic]:\t[grey]{conf.julia_file}[/grey]\n" 

214 ) 

215 if not conf.no_sync_fortran: 

216 logger.info( 

217 f" - [italic]fpm.toml(fortran)[/italic]:\t[grey]{conf.fortran_file}[/grey]" 

218 ) 

219 if not conf.no_sync_pom_xml: 

220 logger.info( 

221 f" - [italic]pom.xml[/italic]:\t[grey]{conf.pom_xml_file}[/grey]\n" 

222 ) 

223 if not conf.no_sync_mkdocs: 

224 logger.info( 

225 f" - [italic]mkdocs.yml[/italic]:\t[grey]{conf.mkdocs_file}[/grey]" 

226 ) 

227 if not conf.no_sync_rust: 

228 logger.info(f" - [italic]Cargo.toml[/italic]:\t[grey]{conf.rust_file}[/grey]") 

229 

230 if not conf.no_sync_cff: 

231 logger.info(f" - [italic]CITATION.cff[/italic]:\t[grey]{conf.cff_file}[/grey]") 

232 if not conf.no_sync_codemeta: 

233 logger.info( 

234 f" - [italic]codemeta.json[/italic]:\t[grey]{conf.codemeta_file}[/grey]\n" 

235 ) 

236 # ---- 

237 if conf.pass_validation: 

238 logger.info("[bold yellow]Passing validation of metadata files.[/bold yellow]") 

239 sync_command(somesy_input) 

240 # ---- 

241 logger.info("[bold green]Metadata synchronization completed.[/bold green]")