@@ -20,7 +20,16 @@ def parse_args() -> argparse.Namespace:
2020 "--citation" ,
2121 type = Path ,
2222 default = Path ("CITATION.cff" ),
23- help = "Path to the repository CITATION.cff file." ,
23+ help = "Path to the source CITATION.cff file." ,
24+ )
25+ parser .add_argument (
26+ "--output" ,
27+ type = Path ,
28+ default = None ,
29+ help = (
30+ "Optional output path for the synced citation file. "
31+ "Defaults to overwriting --citation."
32+ ),
2433 )
2534 parser .add_argument (
2635 "--date" ,
@@ -78,44 +87,81 @@ def replace_scalar(text: str, key: str, value: str) -> str:
7887 return updated
7988
8089
81- def sync_citation (
90+ def build_synced_citation (
8291 citation_path : Path ,
8392 * ,
8493 tag : str ,
8594 release_date : str | None = None ,
8695 repo_root : Path | None = None ,
87- check : bool = False ,
88- ) -> bool :
96+ ) -> tuple [str , str , bool ]:
8997 repo_root = repo_root or citation_path .resolve ().parent
9098 version = tag_version (tag )
9199 release_date = release_date or resolve_release_date (tag , repo_root )
100+
92101 original = citation_path .read_text (encoding = "utf-8" )
93102 updated = replace_scalar (original , "version" , version )
94103 updated = replace_scalar (updated , "date-released" , release_date )
95104 changed = updated != original
105+ return original , updated , changed
106+
107+
108+ def sync_citation (
109+ citation_path : Path ,
110+ * ,
111+ tag : str ,
112+ output_path : Path | None = None ,
113+ release_date : str | None = None ,
114+ repo_root : Path | None = None ,
115+ check : bool = False ,
116+ ) -> bool :
117+ original , updated , changed = build_synced_citation (
118+ citation_path ,
119+ tag = tag ,
120+ release_date = release_date ,
121+ repo_root = repo_root ,
122+ )
123+
96124 if check :
97125 if changed :
98126 raise SystemExit (
99127 f"{ citation_path } is out of date for { normalize_tag (tag )} . "
100128 "Run tools/release/sync_citation.py before releasing."
101129 )
102130 return False
103- citation_path .write_text (updated , encoding = "utf-8" )
131+
132+ destination = output_path or citation_path
133+ destination .parent .mkdir (parents = True , exist_ok = True )
134+ destination .write_text (updated , encoding = "utf-8" )
104135 return changed
105136
106137
107138def main () -> int :
108139 args = parse_args ()
140+ destination = args .output or args .citation
141+
109142 changed = sync_citation (
110143 args .citation ,
111144 tag = args .tag ,
145+ output_path = args .output ,
112146 release_date = args .date ,
113147 repo_root = Path .cwd (),
114148 check = args .check ,
115149 )
116- action = "Validated" if args .check else "Updated"
117- print (f"{ action } { args .citation } for { normalize_tag (args .tag )} ." )
118- return 0 if (args .check or changed or not changed ) else 0
150+
151+ if args .check :
152+ print (f"Validated { args .citation } for { normalize_tag (args .tag )} ." )
153+ else :
154+ source = args .citation .resolve ()
155+ dest = destination .resolve ()
156+ if source == dest :
157+ print (f"Updated { args .citation } for { normalize_tag (args .tag )} ." )
158+ else :
159+ print (
160+ f"Wrote synced citation metadata from { args .citation } "
161+ f"to { destination } for { normalize_tag (args .tag )} ."
162+ )
163+
164+ return 0
119165
120166
121167if __name__ == "__main__" :
0 commit comments