Skip to content

Commit dd99f11

Browse files
committed
Fetch release tags from releaseTags.json
1 parent b879c0e commit dd99f11

File tree

5 files changed

+203
-36
lines changed

5 files changed

+203
-36
lines changed

data/0.17.0/releaseTags.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"tools": {
3+
"1.5.1": "v1.5.1-0",
4+
"2.0.0": "v2.0.0-5",
5+
"2.1.0": "v2.1.0-0",
6+
"2.1.1": "v2.1.1-1"
7+
},
8+
"picotool": {
9+
"2.0.0": "v2.0.0-5",
10+
"2.1.0": "v2.1.0-0",
11+
"2.1.1": "v2.1.1-1"
12+
},
13+
"openocd": {
14+
"0.12.0+dev": "v2.0.0-5"
15+
}
16+
}

src/extension.mts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ import NewExampleProjectCommand from "./commands/newExampleProject.mjs";
7878
import SwitchBoardCommand from "./commands/switchBoard.mjs";
7979
import UninstallPicoSDKCommand from "./commands/uninstallPicoSDK.mjs";
8080
import FlashProjectSWDCommand from "./commands/flashProjectSwd.mjs";
81+
import ReleaseTagsLoader from "./utils/releaseTags.mjs";
8182
// eslint-disable-next-line max-len
8283
import { NewMicroPythonProjectPanel } from "./webview/newMicroPythonProjectPanel.mjs";
8384
import type { Progress as GotProgress } from "got";
@@ -92,6 +93,7 @@ export async function activate(context: ExtensionContext): Promise<void> {
9293
context.extension.packageJSON as PackageJSON
9394
);
9495
GithubApiCache.createInstance(context);
96+
ReleaseTagsLoader.createInstance(context.extensionUri);
9597

9698
const picoProjectActivityBarProvider = new PicoProjectActivityBar();
9799
const ui = new UI(picoProjectActivityBarProvider);

src/utils/download.mts

Lines changed: 54 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import {
4747
WINDOWS_X86_PYTHON_DOWNLOAD_URL,
4848
} from "./sharedConstants.mjs";
4949
import { compareGe } from "./semverUtil.mjs";
50+
import ReleaseTagsLoader from "./releaseTags.mjs";
5051

5152
/// Translate nodejs platform names to ninja platform names
5253
const NINJA_PLATFORMS: { [key: string]: string } = {
@@ -62,34 +63,6 @@ const TOOLS_PLATFORMS: { [key: string]: string } = {
6263
win32: "x64-win",
6364
};
6465

65-
/// Release tags for the sdk tools
66-
const TOOLS_RELEASES: { [key: string]: string } = {
67-
// eslint-disable-next-line @typescript-eslint/naming-convention
68-
"1.5.1": "v1.5.1-0",
69-
// eslint-disable-next-line @typescript-eslint/naming-convention
70-
"2.0.0": "v2.0.0-5",
71-
// eslint-disable-next-line @typescript-eslint/naming-convention
72-
"2.1.0": "v2.1.0-0",
73-
// eslint-disable-next-line @typescript-eslint/naming-convention
74-
"2.1.1": "v2.1.1-1",
75-
};
76-
77-
/// Release tags for picotool
78-
const PICOTOOL_RELEASES: { [key: string]: string } = {
79-
// eslint-disable-next-line @typescript-eslint/naming-convention
80-
"2.0.0": "v2.0.0-5",
81-
// eslint-disable-next-line @typescript-eslint/naming-convention
82-
"2.1.0": "v2.1.0-0",
83-
// eslint-disable-next-line @typescript-eslint/naming-convention
84-
"2.1.1": "v2.1.1-1",
85-
};
86-
87-
/// Release tags for openocd
88-
const OPENOCD_RELEASES: { [key: string]: string } = {
89-
// eslint-disable-next-line @typescript-eslint/naming-convention
90-
"0.12.0+dev": "v2.0.0-5",
91-
};
92-
9366
/// Translate nodejs platform names to cmake platform names
9467
const CMAKE_PLATFORMS: { [key: string]: string } = {
9568
darwin: "macos",
@@ -100,6 +73,26 @@ const CMAKE_PLATFORMS: { [key: string]: string } = {
10073
// Compute and cache the home directory
10174
const homeDirectory: string = homedir();
10275

76+
// Cache for release tags loader
77+
let releaseTagsLoader: ReleaseTagsLoader | undefined;
78+
79+
/**
80+
* Get the release tag for a specific version of a component
81+
* @param component The component to get the release tag for (tools, picotool, or openocd)
82+
* @param version The version to get the release tag for
83+
* @returns The release tag or undefined if not found
84+
*/
85+
async function getReleaseTag(
86+
component: "tools" | "picotool" | "openocd",
87+
version: string
88+
): Promise<string | undefined> {
89+
if (!releaseTagsLoader) {
90+
releaseTagsLoader = ReleaseTagsLoader.getInstance();
91+
}
92+
93+
return releaseTagsLoader.getReleaseTag(component, version);
94+
}
95+
10396
export function buildToolchainPath(version: string): string {
10497
return joinPosix(homeDirectory, ".pico-sdk", "toolchain", version);
10598
}
@@ -882,11 +875,20 @@ export async function downloadAndInstallTools(
882875
: "-x86_64"
883876
: ""
884877
}-${TOOLS_PLATFORMS[process.platform]}.${assetExt}`;
885-
const releaseVersion = TOOLS_RELEASES[version] ?? "v" + version + "-0";
878+
879+
const releaseTag = await getReleaseTag("tools", version);
880+
if (!releaseTag) {
881+
Logger.error(
882+
LoggerSource.downloader,
883+
`Could not find release tag for SDK tools version ${version}`
884+
);
885+
886+
return false;
887+
}
886888

887889
return downloadAndInstallGithubAsset(
888890
version,
889-
releaseVersion,
891+
releaseTag,
890892
GithubRepository.tools,
891893
targetDirectory,
892894
archiveFileName,
@@ -912,11 +914,20 @@ export async function downloadAndInstallPicotool(
912914
: "-x86_64"
913915
: ""
914916
}-${TOOLS_PLATFORMS[process.platform]}.${assetExt}`;
915-
const releaseVersion = PICOTOOL_RELEASES[version] ?? "v" + version + "-0";
917+
918+
const releaseTag = await getReleaseTag("picotool", version);
919+
if (!releaseTag) {
920+
Logger.error(
921+
LoggerSource.downloader,
922+
`Could not find release tag for picotool version ${version}`
923+
);
924+
925+
return false;
926+
}
916927

917928
return downloadAndInstallGithubAsset(
918929
version,
919-
releaseVersion,
930+
releaseTag,
920931
GithubRepository.tools,
921932
targetDirectory,
922933
archiveFileName,
@@ -1061,9 +1072,19 @@ export async function downloadAndInstallOpenOCD(
10611072
}
10621073
};
10631074

1075+
const releaseTag = await getReleaseTag("openocd", version);
1076+
if (!releaseTag) {
1077+
Logger.error(
1078+
LoggerSource.downloader,
1079+
`Could not find release tag for OpenOCD version ${version}`
1080+
);
1081+
1082+
return false;
1083+
}
1084+
10641085
return downloadAndInstallGithubAsset(
10651086
version,
1066-
OPENOCD_RELEASES[version],
1087+
releaseTag,
10671088
GithubRepository.tools,
10681089
targetDirectory,
10691090
archiveFileName,

src/utils/releaseTags.mts

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import { readFileSync } from "fs";
2+
import { Uri } from "vscode";
3+
import { isInternetConnected } from "./downloadHelpers.mjs";
4+
import { get } from "https";
5+
import Logger from "../logger.mjs";
6+
import { CURRENT_DATA_VERSION } from "./sharedConstants.mjs";
7+
8+
const releaseTagsUrl =
9+
"https://raspberrypi.github.io/pico-vscode/" +
10+
`${CURRENT_DATA_VERSION}/releaseTags.json`;
11+
12+
export interface ReleaseTags {
13+
tools: { [key: string]: string };
14+
picotool: { [key: string]: string };
15+
openocd: { [key: string]: string };
16+
}
17+
18+
export default class ReleaseTagsLoader {
19+
private static instance: ReleaseTagsLoader | undefined;
20+
private tags?: ReleaseTags;
21+
22+
private constructor(private readonly _extensionUri: Uri) {}
23+
24+
public static createInstance(extensionUri: Uri): ReleaseTagsLoader {
25+
if (!ReleaseTagsLoader.instance) {
26+
ReleaseTagsLoader.instance = new ReleaseTagsLoader(extensionUri);
27+
}
28+
29+
return ReleaseTagsLoader.instance;
30+
}
31+
32+
public static getInstance(): ReleaseTagsLoader {
33+
if (!ReleaseTagsLoader.instance) {
34+
throw new Error("ReleaseTagsLoader not initialized");
35+
}
36+
37+
return ReleaseTagsLoader.instance;
38+
}
39+
40+
private async loadTags(): Promise<void> {
41+
try {
42+
if (!(await isInternetConnected())) {
43+
throw new Error("No internet connection");
44+
}
45+
46+
const result = await new Promise<ReleaseTags>((resolve, reject) => {
47+
get(releaseTagsUrl, response => {
48+
if (response.statusCode !== 200) {
49+
reject(
50+
new Error(
51+
"Error while downloading release tags. " +
52+
`Status code: ${response.statusCode}`
53+
)
54+
);
55+
}
56+
let data = "";
57+
58+
// Append data as it arrives
59+
response.on("data", chunk => {
60+
data += chunk;
61+
});
62+
63+
// Parse the JSON data when the download is complete
64+
response.on("end", () => {
65+
try {
66+
// Resolve with the array of ReleaseTags
67+
resolve(JSON.parse(data) as ReleaseTags);
68+
} catch (error) {
69+
reject(
70+
new Error(
71+
`Failed to parse release tags JSON: ${
72+
error instanceof Error ? error.message : (error as string)
73+
}`
74+
)
75+
);
76+
}
77+
});
78+
79+
// Handle errors
80+
response.on("error", error => {
81+
reject(error);
82+
});
83+
});
84+
});
85+
86+
this.tags = result;
87+
} catch (error) {
88+
Logger.log(
89+
"Failed to download release tags:",
90+
error instanceof Error ? error.message : (error as string)
91+
);
92+
93+
try {
94+
const tags = readFileSync(
95+
Uri.joinPath(
96+
this._extensionUri,
97+
"data",
98+
CURRENT_DATA_VERSION,
99+
"releaseTags.json"
100+
).fsPath,
101+
"utf8"
102+
);
103+
this.tags = JSON.parse(tags) as ReleaseTags;
104+
} catch (e) {
105+
Logger.log(
106+
"Failed to load release tags from local file:",
107+
e instanceof Error ? e.message : (e as string)
108+
);
109+
this.tags = {
110+
tools: {},
111+
picotool: {},
112+
openocd: {}
113+
};
114+
}
115+
}
116+
}
117+
118+
public async getReleaseTag(
119+
component: keyof ReleaseTags,
120+
version: string
121+
): Promise<string | undefined> {
122+
if (this.tags === undefined) {
123+
await this.loadTags();
124+
}
125+
126+
return this.tags?.[component]?.[version];
127+
}
128+
}

src/utils/versionBundles.mts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ export default class VersionBundlesLoader {
5555
data += chunk;
5656
});
5757

58-
// Parse the INI data when the download is complete
58+
// Parse the JSON data when the download is complete
5959
response.on("end", () => {
60-
// Resolve with the array of SupportedToolchainVersion
60+
// Resolve with the array of VersionBundles
6161
resolve(JSON.parse(data) as VersionBundles);
6262
});
6363

@@ -88,7 +88,7 @@ export default class VersionBundlesLoader {
8888
this.bundles = JSON.parse(bundles) as VersionBundles;
8989
} catch (e) {
9090
Logger.log(
91-
"Faild to load version bundles from local file:",
91+
"Failed to load version bundles from local file:",
9292
e instanceof Error ? e.message : (e as string)
9393
);
9494
this.bundles = {};

0 commit comments

Comments
 (0)