Skip to content
This repository was archived by the owner on Nov 25, 2025. It is now read-only.

Commit b7dcb20

Browse files
authored
Merge pull request #475 from ziglang/cache-mirrors
Cache mirror and version list
2 parents 1275e80 + 2d3b371 commit b7dcb20

File tree

3 files changed

+63
-37
lines changed

3 files changed

+63
-37
lines changed

src/versionManager.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export interface Config {
3636
* `"version"` for Zig, `"--version"` for ZLS
3737
*/
3838
versionArg: string;
39-
mirrorUrls: vscode.Uri[];
39+
getMirrorUrls: () => Promise<vscode.Uri[]>;
4040
canonicalUrl: {
4141
release: vscode.Uri;
4242
nightly: vscode.Uri;
@@ -93,7 +93,7 @@ async function installGuarded(config: Config, version: semver.SemVer): Promise<s
9393
throw new Error(`Can't install ${config.title} because 'tar' could not be found`);
9494
}
9595

96-
const mirrors = [...config.mirrorUrls]
96+
const mirrors = [...(await config.getMirrorUrls())]
9797
.map((mirror) => ({ mirror, sort: Math.random() }))
9898
.sort((a, b) => a.sort - b.sort)
9999
.map(({ mirror }) => mirror);

src/zigSetup.ts

Lines changed: 58 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -71,33 +71,24 @@ async function findClosestSatisfyingZigVersion(
7171
version: semver.SemVer,
7272
): Promise<semver.SemVer> {
7373
if (version.prerelease.length !== 0) return version;
74-
const cacheKey = `zig-satisfying-version-${version.raw}`;
7574

7675
try {
7776
// We can't just return `version` because `0.12.0` should return `0.12.1`.
78-
const availableVersions = (await getVersions()).map((item) => item.version);
77+
const availableVersions = (await getVersions(context)).map((item) => item.version);
7978
const selectedVersion = semver.maxSatisfying(availableVersions, `^${version.toString()}`);
80-
await context.globalState.update(cacheKey, selectedVersion ? selectedVersion.raw : undefined);
8179
return selectedVersion ?? version;
8280
} catch {
83-
const selectedVersion = context.globalState.get<string | null>(cacheKey, null);
84-
return selectedVersion ? new semver.SemVer(selectedVersion) : version;
81+
return version;
8582
}
8683
}
8784

8885
async function getLatestTaggedZigVersion(context: vscode.ExtensionContext): Promise<semver.SemVer | null> {
89-
const cacheKey = "zig-latest-tagged";
9086
try {
91-
const zigVersion = await getVersions();
87+
const zigVersion = await getVersions(context);
9288
const latestTagged = zigVersion.find((item) => item.version.prerelease.length === 0);
9389
const result = latestTagged?.version ?? null;
94-
await context.globalState.update(cacheKey, latestTagged?.version.raw);
9590
return result;
9691
} catch {
97-
const latestTagged = context.globalState.get<string | null>(cacheKey, null);
98-
if (latestTagged) {
99-
return new semver.SemVer(latestTagged);
100-
}
10192
return null;
10293
}
10394
}
@@ -108,13 +99,29 @@ async function getLatestTaggedZigVersion(context: vscode.ExtensionContext): Prom
10899
*
109100
* Throws an exception when no network connection is available.
110101
*/
111-
async function getVersions(): Promise<zigUtil.ZigVersion[]> {
112-
const [zigIndexJson, machIndexJson] = await Promise.all(
113-
["https://ziglang.org/download/index.json", "https://pkg.machengine.org/zig/index.json"].map(async (url) => {
114-
const response = await fetch(url);
115-
return response.json() as Promise<zigUtil.VersionIndex>;
116-
}),
117-
);
102+
async function getVersions(context: vscode.ExtensionContext): Promise<zigUtil.ZigVersion[]> {
103+
const cacheKey = "zig-version-list";
104+
let zigIndexJson, machIndexJson;
105+
try {
106+
[zigIndexJson, machIndexJson] = await Promise.all(
107+
["https://ziglang.org/download/index.json", "https://pkg.machengine.org/zig/index.json"].map(
108+
async (url) => {
109+
const response = await fetch(url);
110+
return response.json() as Promise<zigUtil.VersionIndex>;
111+
},
112+
),
113+
);
114+
} catch (error) {
115+
const cached = context.globalState.get<zigUtil.ZigVersion[]>(cacheKey);
116+
if (cached !== undefined) {
117+
for (const version of cached) {
118+
// Must be instanceof SemVer
119+
version.version = new semver.SemVer(version.version.raw);
120+
}
121+
return cached;
122+
}
123+
throw error;
124+
}
118125
const indexJson = { ...machIndexJson, ...zigIndexJson };
119126

120127
const result: zigUtil.ZigVersion[] = [];
@@ -140,6 +147,7 @@ async function getVersions(): Promise<zigUtil.ZigVersion[]> {
140147
);
141148
}
142149
sortVersions(result);
150+
await context.globalState.update(cacheKey, result);
143151
return result;
144152
}
145153

@@ -182,7 +190,7 @@ async function selectVersionAndInstall(context: vscode.ExtensionContext) {
182190
}));
183191

184192
try {
185-
const onlineVersions = await getVersions();
193+
const onlineVersions = await getVersions(context);
186194
outer: for (const onlineVersion of onlineVersions) {
187195
for (const version of versions) {
188196
if (semver.eq(version.version, onlineVersion.version)) {
@@ -577,6 +585,33 @@ async function updateStatus(context: vscode.ExtensionContext): Promise<void> {
577585
});
578586
}
579587

588+
async function getMirrors(context: vscode.ExtensionContext): Promise<vscode.Uri[]> {
589+
const cacheKey = "zig-mirror-list";
590+
let cached = context.globalState.get(cacheKey, { timestamp: 0, mirrors: "" });
591+
592+
const millisecondsInDay = 24 * 60 * 60 * 1000;
593+
if (new Date().getTime() - cached.timestamp > millisecondsInDay) {
594+
try {
595+
const response = await fetch("https://ziglang.org/download/community-mirrors.txt");
596+
if (response.status !== 200) throw Error("invalid mirrors");
597+
const mirrorList = await response.text();
598+
cached = {
599+
timestamp: new Date().getTime(),
600+
mirrors: mirrorList,
601+
};
602+
await context.globalState.update(cacheKey, cached);
603+
} catch {
604+
// Cannot fetch mirrors, rely on cache.
605+
}
606+
}
607+
608+
return cached.mirrors
609+
.trim()
610+
.split("\n")
611+
.filter((u) => !!u)
612+
.map((u) => vscode.Uri.parse(u));
613+
}
614+
580615
export async function setupZig(context: vscode.ExtensionContext) {
581616
{
582617
// This check can be removed once enough time has passed so that most users switched to the new value
@@ -674,19 +709,6 @@ export async function setupZig(context: vscode.ExtensionContext) {
674709
break;
675710
}
676711

677-
let mirrors: vscode.Uri[] = [];
678-
try {
679-
const response = await fetch("https://ziglang.org/download/community-mirrors.txt");
680-
if (response.status !== 200) throw Error("invalid mirrors");
681-
const mirrorList = await response.text();
682-
mirrors = mirrorList
683-
.trim()
684-
.split("\n")
685-
.map((u) => vscode.Uri.parse(u));
686-
} catch {
687-
// Cannot fetch mirrors, attempt downloading from canonical source.
688-
}
689-
690712
versionManagerConfig = {
691713
context: context,
692714
title: "Zig",
@@ -695,7 +717,9 @@ export async function setupZig(context: vscode.ExtensionContext) {
695717
/** https://ziglang.org/download */
696718
minisignKey: minisign.parseKey("RWSGOq2NVecA2UPNdBUZykf1CCb147pkmdtYxgb3Ti+JO/wCYvhbAb/U"),
697719
versionArg: "version",
698-
mirrorUrls: mirrors,
720+
getMirrorUrls() {
721+
return getMirrors(context);
722+
},
699723
canonicalUrl: {
700724
release: vscode.Uri.parse("https://ziglang.org/download"),
701725
nightly: vscode.Uri.parse("https://ziglang.org/builds"),

src/zls.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,9 @@ export async function activate(context: vscode.ExtensionContext) {
518518
/** https://github.com/zigtools/release-worker */
519519
minisignKey: minisign.parseKey("RWR+9B91GBZ0zOjh6Lr17+zKf5BoSuFvrx2xSeDE57uIYvnKBGmMjOex"),
520520
versionArg: "--version",
521-
mirrorUrls: [],
521+
getMirrorUrls() {
522+
return Promise.resolve([]);
523+
},
522524
canonicalUrl: {
523525
release: vscode.Uri.parse("https://builds.zigtools.org"),
524526
nightly: vscode.Uri.parse("https://builds.zigtools.org"),

0 commit comments

Comments
 (0)