|
1 | 1 | """Add git repositories to the catalog as entries in catalog/. |
2 | 2 |
|
| 3 | +Entries are Markdown files: the fields go in the YAML front matter and the |
| 4 | +body is free text shown on the dataset page. |
| 5 | +
|
3 | 6 | A repo that already carries metadata (dataherb.json, dataherb.yml or the |
4 | 7 | legacy .dataherb/metadata.yml) gets a short pointer entry; the builder reads |
5 | 8 | the metadata on every build. A repo without metadata is cloned and scanned |
|
22 | 25 | from .infer import scaffold |
23 | 26 | from .resolve import METADATA_CANDIDATES, load_entries |
24 | 27 | from .stores import GitStore, StoreError, git_key, make_stores |
25 | | -from .util import FetchError, env_token, http_get, slugify |
| 28 | +from .util import ( |
| 29 | + FetchError, |
| 30 | + env_token, |
| 31 | + front_matter_document, |
| 32 | + http_get, |
| 33 | + slugify, |
| 34 | + split_front_matter, |
| 35 | +) |
26 | 36 |
|
27 | 37 |
|
28 | 38 | @dataclass |
@@ -107,6 +117,7 @@ def add_repos( |
107 | 117 | clone_url_template: str | None = None, |
108 | 118 | force: bool = False, |
109 | 119 | dry_run: bool = False, |
| 120 | + fmt: str = "md", |
110 | 121 | ) -> list[Added]: |
111 | 122 | stores = make_stores(cfg.stores, cfg.root) |
112 | 123 | git_stores = {n: s for n, s in stores.items() if isinstance(s, GitStore)} |
@@ -154,7 +165,7 @@ def add_repos( |
154 | 165 | continue |
155 | 166 | did = str(existing["id"]) if existing else default_id(repo, strip_prefix) |
156 | 167 | target = ( |
157 | | - cfg.path(existing["_file"]) if existing else out_dir / f"{did}.yml" |
| 168 | + cfg.path(existing["_file"]) if existing else out_dir / f"{did}.{fmt}" |
158 | 169 | ) |
159 | 170 | if not existing and (did in known_ids or target.exists()) and not force: |
160 | 171 | results.append( |
@@ -205,16 +216,24 @@ def add_repos( |
205 | 216 |
|
206 | 217 | if not dry_run: |
207 | 218 | target.parent.mkdir(parents=True, exist_ok=True) |
208 | | - target.write_text( |
209 | | - yaml.safe_dump(entry, sort_keys=False, allow_unicode=True), |
210 | | - encoding="utf-8", |
211 | | - ) |
| 219 | + if target.suffix == ".md": |
| 220 | + text = front_matter_document(entry, _keep_body(target) if force else "") |
| 221 | + else: |
| 222 | + text = yaml.safe_dump(entry, sort_keys=False, allow_unicode=True) |
| 223 | + target.write_text(text, encoding="utf-8") |
212 | 224 | known_ids.add(did) |
213 | 225 | known_repos[repo.lower()] = {"id": did, "_file": str(target)} |
214 | 226 | results.append(Added(repo, did, target, kind, note)) |
215 | 227 | return results |
216 | 228 |
|
217 | 229 |
|
| 230 | +def _keep_body(path: Path) -> str: |
| 231 | + """The Markdown body of an entry that is being overwritten, so --force keeps hand-written notes.""" |
| 232 | + if not path.exists(): |
| 233 | + return "" |
| 234 | + return split_front_matter(path.read_text(encoding="utf-8"))[1] |
| 235 | + |
| 236 | + |
218 | 237 | def org_token(cfg: Config, store_name: str | None) -> str | None: |
219 | 238 | for name, conf in (cfg.stores or {}).items(): |
220 | 239 | if conf.get("type") == "git" and (store_name in (None, name)): |
|
0 commit comments