()
| 168 | |
| 169 | |
| 170 | def main() -> int: |
| 171 | version = sys.argv[1] if len(sys.argv) > 1 else read_cargo_version() |
| 172 | |
| 173 | text = CHANGELOG_PATH.read_text(encoding="utf-8") |
| 174 | preface, blocks = parse_changelog(text) |
| 175 | |
| 176 | unrel_idx = next( |
| 177 | (i for i, b in enumerate(blocks) if b["name"] == "Unreleased"), -1 |
| 178 | ) |
| 179 | ver_idx = next( |
| 180 | (i for i, b in enumerate(blocks) if b["name"] == version), -1 |
| 181 | ) |
| 182 | |
| 183 | if unrel_idx == -1: |
| 184 | print("prepare-release: no [Unreleased] block - nothing to do") |
| 185 | return 0 |
| 186 | |
| 187 | unrel = blocks[unrel_idx] |
| 188 | if not block_has_content(unrel["body"]): |
| 189 | print("prepare-release: [Unreleased] is empty - nothing to do") |
| 190 | return 0 |
| 191 | |
| 192 | if ver_idx == -1: |
| 193 | # Case A — promote Unreleased -> [version]. |
| 194 | today = today_utc_iso() |
| 195 | promoted = { |
| 196 | "header": f"## [{version}] - {today}", |
| 197 | "name": version, |
| 198 | "date": today, |
| 199 | "body": trim_trailing_blank(unrel["body"]) + [""], |
| 200 | } |
| 201 | emptied = { |
| 202 | "header": "## [Unreleased]", |
| 203 | "name": "Unreleased", |
| 204 | "date": None, |
| 205 | "body": ["", ""], |
| 206 | } |
| 207 | blocks[unrel_idx : unrel_idx + 1] = [emptied, promoted] |
| 208 | out = append_link_ref(join_changelog(preface, blocks), version) |
| 209 | CHANGELOG_PATH.write_text(out, encoding="utf-8") |
| 210 | n = sum(1 for line in promoted["body"] if BULLET_RE.match(line)) |
| 211 | print( |
| 212 | f"prepare-release: {version} - renamed [Unreleased] to " |
| 213 | f"[{version}] - {today} ({n} entries promoted)" |
| 214 | ) |
| 215 | return 0 |
| 216 | |
| 217 | # Case B — merge Unreleased sub-sections into the existing [version]. |
| 218 | ver = blocks[ver_idx] |
| 219 | _, unrel_subs = split_subsections(unrel["body"]) |
| 220 | ver_leading, ver_subs = split_subsections(ver["body"]) |
| 221 | |
| 222 | merged = 0 |
| 223 | for us in unrel_subs: |
| 224 | us_body = trim_trailing_blank(us["body"]) |
| 225 | if not us_body: |
| 226 | continue |
| 227 | target = next( |
no test coverage detected