Skip to content

Commit c452d4d

Browse files
committed
Support /melpa/at-least-days-old/{number}
This points to the most recent snapshot that is at least {number} days old.
1 parent 8ca162c commit c452d4d

File tree

4 files changed

+83
-3
lines changed

4 files changed

+83
-3
lines changed

Dockerfile

+6-2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ RUN apk add --no-cache wget
3333

3434
RUN wget --check-certificate https://delpa.org/melpa_snapshot_versions.json && \
3535
wget --check-certificate https://delpa.org/melpa_snapshot_versions.json.sha256
36+
# ISO date in UTC
37+
RUN echo $(date -I -u) | tee TODAY
3638

3739
# Verify that melpa_snapshot_versions.json is in the sha256 checksum file and
3840
# verify checksum
@@ -43,6 +45,8 @@ RUN grep melpa_snapshot_versions.json melpa_snapshot_versions.json.sha256 && \
4345
FROM snapshot-versions-getter-base as snapshot-versions-getter-test
4446

4547
COPY ./melpa_snapshot_versions.json .
48+
# Mock date to the birthday of Delpa for testing purposes.
49+
RUN echo 2025-01-02 > TODAY
4650

4751
FROM snapshot-versions-getter-${snapshot_versions_type} as snapshot-versions-getter
4852

@@ -52,8 +56,8 @@ FROM docker.io/node:22.12.0-alpine@sha256:6e80991f69cc7722c561e5d14d5e72ab47c0d6
5256
COPY package.json package-lock.json ./
5357
RUN npm install -g npm && npm install
5458
COPY . .
55-
COPY --from=snapshot-versions-getter ./melpa_snapshot_versions.json .
56-
RUN npx tsx gen_caddy.ts > Caddyfile
59+
COPY --from=snapshot-versions-getter ./melpa_snapshot_versions.json ./TODAY .
60+
RUN env TODAY="$(cat TODAY)" npx tsx gen_caddy.ts > Caddyfile
5761

5862
FROM docker.io/caddy:2.8.4-alpine@sha256:e97e0e3f8f51be708a9d5fadbbd75e3398c22fc0eecd4b26d48561e3f7daa9eb
5963

gen_caddy.ts

+53
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,45 @@
2020

2121
import snapshotVersions from "./melpa_snapshot_versions.json" with { type: "json" };
2222

23+
const today = process.env.TODAY ? new Date(process.env.TODAY) : new Date();
2324
const melpaSnapshotLeadingComp = "/melpa/snapshot" as const;
25+
const melpaAgeLeadingComp = "/melpa/at-least-days-old" as const;
2426
const snapshotVersionsRegexp = snapshotVersions.join("|");
27+
// Snapshot versions from latest to oldest.
28+
const maxAge = 270 as const; // We support <= 270 days old.
29+
30+
interface SnapshotVersionWithAge {
31+
version: string;
32+
ageRegexp: string; // age of the snapshot in days
33+
}
34+
35+
/** Create a list of snapshots and their age regexps. Sorted from most recent to
36+
* least recent. */
37+
function createSnapshotVersionWithAges(): SnapshotVersionWithAge[] {
38+
const sortedSnapshotVersions = snapshotVersions.toSorted().reverse();
39+
const ageRegexps: SnapshotVersionWithAge[] = [];
40+
let lastSnapshotAge = 0;
41+
for (const snapshotVersion of sortedSnapshotVersions) {
42+
const snapshotDate = new Date(snapshotVersion);
43+
const ageOfSnapshot = Math.min(
44+
maxAge,
45+
Math.floor(
46+
(today.getTime() - snapshotDate.getTime()) / (1000 * 60 * 60 * 24),
47+
),
48+
);
49+
const days = [...Array(ageOfSnapshot - lastSnapshotAge).keys()].map((i) =>
50+
(lastSnapshotAge + i + 1).toString(),
51+
);
52+
ageRegexps.push({ ageRegexp: days.join("|"), version: snapshotVersion });
53+
lastSnapshotAge = ageOfSnapshot;
54+
if (lastSnapshotAge >= maxAge) {
55+
break;
56+
}
57+
}
58+
return ageRegexps;
59+
}
60+
61+
const snapshotVersionWithAges = createSnapshotVersionWithAges();
2562

2663
const caddyfile = `
2764
{
@@ -66,6 +103,22 @@ For more information, please visit the Delpa homepage: https://delpa.org"
66103
close
67104
}
68105
}
106+
107+
# /melpa/at-least-days-old/{number}
108+
route ${melpaAgeLeadingComp}/* {
109+
${snapshotVersionWithAges
110+
.map((snapshotVersionWithAge) => {
111+
const matcherName = `@valid-age-root-${snapshotVersionWithAge.version}`;
112+
return `
113+
${matcherName} path_regexp ^${melpaAgeLeadingComp}/(${snapshotVersionWithAge.ageRegexp})/*$
114+
respond ${matcherName} 200 {
115+
body "{re.1} days old points to snapshot version ${snapshotVersionWithAge.version}."
116+
close
117+
}
118+
`;
119+
})
120+
.join("\n")}
121+
}
69122
}
70123
`;
71124

index.test.ts

+23
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,26 @@ describe("/melpa/snapshot", () => {
119119
});
120120
}
121121
});
122+
123+
describe("/melpa/at-least-days-old", () => {
124+
const ageLeadingPathComp = "melpa/at-least-days-old" as const;
125+
for (const [name, path, snapshotVersion] of [
126+
["without a trailing slash", "1", "2024-10-10"],
127+
["with a trailing slash", "270/", "2024-03-03"],
128+
] as const) {
129+
test(`Report OK with valid snapshot version at a root dir of /melpa/at-least-days-old: ${name}`, async () => {
130+
const response = await fetch(
131+
`${hostAddress}/${ageLeadingPathComp}/${path}`,
132+
{
133+
redirect: "manual",
134+
},
135+
);
136+
137+
expect(response.status).toBe(200);
138+
const responseText = await response.text();
139+
expect(responseText).toBe(
140+
`${path.split("/")[0]} days old points to snapshot version ${snapshotVersion}.`,
141+
);
142+
});
143+
}
144+
});

melpa_snapshot_versions.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
["2024-01-01", "2024-02-02", "2024-03-03"]
1+
["2024-01-01", "2024-02-02", "2024-03-03", "2024-08-08", "2024-10-10"]

0 commit comments

Comments
 (0)