Skip to content

Commit 0c02dfe

Browse files
committed
Store last modified date and tagged releases in .gitmodules
1 parent 54791d1 commit 0c02dfe

File tree

2 files changed

+51
-24
lines changed

2 files changed

+51
-24
lines changed

src/backups2datalad/datasetter.py

Lines changed: 45 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import annotations
22

3+
from collections import defaultdict
34
from collections.abc import AsyncGenerator, Sequence
45
from contextlib import aclosing
56
from dataclasses import dataclass, field
@@ -37,6 +38,13 @@
3738
from .zarr import ZarrLink, sync_zarr
3839

3940

41+
@dataclass
42+
class UpdateReport:
43+
last_modified: datetime
44+
# List is in sorted order
45+
tagged_releases: list[str] | None
46+
47+
4048
@dataclass
4149
class DandiDatasetter(AsyncResource):
4250
dandi_client: AsyncDandiClient
@@ -80,12 +88,19 @@ async def update_from_backup(
8088
workers=self.config.workers,
8189
)
8290
to_save: list[str] = []
83-
access_status: dict[str, str] = {}
84-
for d, changed in report.results:
85-
if changed:
91+
gitmodule_attrs: dict[str, dict[str, str]] = defaultdict(dict)
92+
for d, r in report.results:
93+
if r is not None:
8694
to_save.append(d.identifier)
95+
gitmodule_attrs[d.identifier]["dandiset-last-modified"] = str(
96+
r.last_modified
97+
)
98+
if r.tagged_releases is not None:
99+
gitmodule_attrs[d.identifier]["dandiset-tagged-releases"] = (
100+
",".join(r.tagged_releases)
101+
)
87102
if self.config.gh_org is not None:
88-
access_status[d.identifier] = (
103+
gitmodule_attrs[d.identifier]["github-access-status"] = (
89104
"public"
90105
if d.embargo_status is EmbargoStatus.OPEN
91106
else "private"
@@ -110,24 +125,23 @@ async def update_from_backup(
110125
GHRepo(self.config.gh_org, d),
111126
private=True,
112127
)
113-
access_status[d] = "private"
128+
gitmodule_attrs[d]["github-access-status"] = "private"
114129
if to_save:
115130
log.debug("Committing superdataset")
116131
superds.assert_no_duplicates_in_gitmodules()
117132
msg = await self.get_superds_commit_message(superds, to_save)
118-
await superds.save(message=msg, path=to_save)
133+
await superds.save(message=msg, path=to_save + [".gitmodules"])
119134
superds.assert_no_duplicates_in_gitmodules()
120135
log.debug("Superdataset committed")
121-
if access_status:
122-
log.debug("Ensuring github-access-status in .gitmodules is up-to-date")
123-
for did, access in access_status.items():
124-
await superds.set_repo_config(
125-
f"submodule.{did}.github-access-status",
126-
access,
127-
file=".gitmodules",
128-
)
136+
if gitmodule_attrs:
137+
log.debug("Updating submodule properties in .gitmodules")
138+
for did, attrs in gitmodule_attrs.items():
139+
for k, v in attrs.items():
140+
await superds.set_repo_config(
141+
f"submodule.{did}.{k}", v, file=".gitmodules"
142+
)
129143
await superds.commit_if_changed(
130-
"[backups2datalad] Update github-access-status keys in .gitmodules",
144+
"[backups2datalad] Update .gitmodules",
131145
paths=[".gitmodules"],
132146
check_dirty=False,
133147
)
@@ -168,11 +182,11 @@ async def ensure_github_remote(self, ds: AsyncDataset, dandiset_id: str) -> None
168182

169183
async def update_dandiset(
170184
self, dandiset: RemoteDandiset, ds: AsyncDataset | None = None
171-
) -> bool:
172-
# Returns true iff any changes were committed to the repository
185+
) -> UpdateReport | None:
186+
# Returns non-None iff any changes were committed to the repository
173187
if dandiset.embargo_status is EmbargoStatus.UNEMBARGOING:
174188
log.info("Dandiset %s is unembargoing; not syncing", dandiset.identifier)
175-
return False
189+
return None
176190
if ds is None:
177191
ds = await self.init_dataset(
178192
self.config.dandiset_root / dandiset.identifier,
@@ -206,7 +220,7 @@ async def update_dandiset(
206220
)
207221
changed = False
208222
await self.ensure_github_remote(ds, dandiset.identifier)
209-
await self.tag_releases(
223+
tagged_releases = await self.tag_releases(
210224
dandiset, ds, push=self.config.gh_org is not None, log=dmanager.log
211225
)
212226
# Call `get_stats()` even if gh_org is None so that out-of-date stats
@@ -217,7 +231,12 @@ async def update_dandiset(
217231
dmanager.log.info("Pushing to sibling")
218232
await ds.push(to="github", jobs=self.config.jobs, data="nothing")
219233
await self.manager.set_dandiset_description(dandiset, stats, ds)
220-
return changed
234+
newstate = ds.get_assets_state()
235+
assert newstate is not None
236+
return UpdateReport(
237+
last_modified=newstate.timestamp,
238+
tagged_releases=tagged_releases,
239+
)
221240

222241
async def sync_dataset(
223242
self,
@@ -323,19 +342,22 @@ async def tag_releases(
323342
ds: AsyncDataset,
324343
push: bool,
325344
log: PrefixedLogger,
326-
) -> None:
345+
) -> list[str] | None:
346+
# Returns a sorted list of all tagged releases
327347
if not self.config.enable_tags:
328-
return
348+
return None
329349
log.info("Tagging releases for Dandiset")
330350
versions = [v async for v in dandiset.aget_versions(include_draft=False)]
331351
changed = False
352+
tagged_releases = []
332353
for v in versions:
333354
if await ds.read_git("tag", "-l", v.identifier):
334355
log.debug("Version %s already tagged", v.identifier)
335356
else:
336357
log.info("Tagging version %s", v.identifier)
337358
await self.mkrelease(dandiset.for_version(v), ds, push=push, log=log)
338359
changed = True
360+
tagged_releases.append(v.identifier)
339361
if versions:
340362
latest = max(map(attrgetter("identifier"), versions), key=PkgVersion)
341363
description = await ds.read_git("describe", "--tags", "--long", "--always")
@@ -361,6 +383,7 @@ async def tag_releases(
361383
)
362384
if push and (changed or merge):
363385
await ds.push(to="github", jobs=self.config.jobs, data="nothing")
386+
return sorted(tagged_releases)
364387

365388
async def mkrelease(
366389
self,

test/test_core.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,14 +228,18 @@ async def test_2(
228228
}
229229

230230
commits = superrepo.readcmd("rev-list", "HEAD").splitlines()
231-
assert superrepo.get_commit_message(commits[0]) == (
231+
assert (
232+
superrepo.get_commit_message(commits[0])
233+
== "[backups2datalad] Update .gitmodules"
234+
)
235+
assert superrepo.get_commit_message(commits[3]) == (
232236
f"1 updated ({dandiset_id})\n"
233237
"\n"
234238
f"{dandiset_id}:\n"
235239
" - [backups2datalad] 1 file deleted\n"
236240
" - [backups2datalad] 2 files added, 1 file updated"
237241
)
238-
assert superrepo.get_commit_message(commits[-3]) == (
242+
assert superrepo.get_commit_message(commits[9]) == (
239243
f"1 added ({dandiset_id})\n"
240244
"\n"
241245
f"{dandiset_id}:\n"

0 commit comments

Comments
 (0)