diff --git a/html/app/actions/api.ts b/html/app/actions/api.ts
index b3637d04..e9b4223a 100644
--- a/html/app/actions/api.ts
+++ b/html/app/actions/api.ts
@@ -14,8 +14,8 @@ function postHTTP(url, postData) {
return window.fetch(request);
}
-export function getBoardPackages() {
- return window.fetch("/api/boardpackages").then((response) => response.json());
+export function getBoardPackages(update) {
+ return window.fetch(`/api/boardpackages?update=${update}`).then((response) => response.json());
}
export function installBoard(packageName, arch, version) {
@@ -39,8 +39,8 @@ export function openLink(link) {
}).then((response) => response.json());
}
-export function getLibraries() {
- return window.fetch("/api/libraries").then((response) => response.json());
+export function getLibraries(update) {
+ return window.fetch(`/api/libraries?update=${update}`).then((response) => response.json());
}
export function installLibrary(libraryName, version) {
diff --git a/html/app/actions/index.ts b/html/app/actions/index.ts
index af633145..2e1a4f12 100644
--- a/html/app/actions/index.ts
+++ b/html/app/actions/index.ts
@@ -149,9 +149,9 @@ export function uninstallLibraryFailure(libraryName, errorMessage) {
};
}
-export function getBoardPackages(dispatch) {
+export function getBoardPackages(dispatch, update: boolean) {
dispatch(boardPackagesRequest());
- API.getBoardPackages().then((response) => {
+ API.getBoardPackages(update).then((response) => {
const { platforms } = response;
dispatch(boardPackagesSuccess(JSONHelper.retrocycle(platforms)));
}).catch((error) => {
@@ -183,9 +183,9 @@ export function uninstallBoard(dispatch, boardName, packagePath, callback?: Func
});
}
-export function getLibraries(dispatch, callback?: Function) {
+export function getLibraries(dispatch, update: boolean, callback?: Function) {
dispatch(librariesRequest());
- API.getLibraries().then((response) => {
+ API.getLibraries(update).then((response) => {
const { libraries } = response;
dispatch(librariesSuccess(libraries));
if (callback) {
diff --git a/html/app/components/BoardManager.tsx b/html/app/components/BoardManager.tsx
index 755d25ef..ca7d118c 100644
--- a/html/app/components/BoardManager.tsx
+++ b/html/app/components/BoardManager.tsx
@@ -45,12 +45,12 @@ const mapStateToProps = (state) => {
const mapDispatchToProps = (dispatch) => {
return {
- loadBoardPackages: () => actions.getBoardPackages(dispatch),
+ loadBoardPackages: () => actions.getBoardPackages(dispatch, true),
installBoard: (boardName, packageName, arch, version) => actions.installBoard(dispatch, boardName, packageName, arch, version, () => {
- actions.getBoardPackages(dispatch);
+ actions.getBoardPackages(dispatch, false);
}),
uninstallBoard: (boardName, packagePath) => actions.uninstallBoard(dispatch, boardName, packagePath, () => {
- actions.getBoardPackages(dispatch);
+ actions.getBoardPackages(dispatch, false);
}),
};
};
diff --git a/html/app/components/LibraryManager.tsx b/html/app/components/LibraryManager.tsx
index 72b2e71b..6fff40d9 100644
--- a/html/app/components/LibraryManager.tsx
+++ b/html/app/components/LibraryManager.tsx
@@ -45,11 +45,11 @@ const mapStateToProps = (store) => {
const mapDispatchToProps = (dispatch) => {
return {
- loadLibraries: () => actions.getLibraries(dispatch),
+ loadLibraries: () => actions.getLibraries(dispatch, true),
installLibrary: (libraryName, version, callback) => actions.installLibrary(dispatch, libraryName, version, (error) => {
if (!error) {
// Refresh library manager view
- actions.getLibraries(dispatch, callback);
+ actions.getLibraries(dispatch, false, callback);
} else {
callback();
}
@@ -57,7 +57,7 @@ const mapDispatchToProps = (dispatch) => {
uninstallLibrary: (libraryName, libraryPath, callback) => actions.uninstallLibrary(dispatch, libraryName, libraryPath, (error) => {
if (!error) {
// Refresh library manager view
- actions.getLibraries(dispatch, callback);
+ actions.getLibraries(dispatch, false, callback);
} else {
callback();
}
diff --git a/package.json b/package.json
index ffd2c239..ca5fc41d 100644
--- a/package.json
+++ b/package.json
@@ -126,6 +126,11 @@
"info",
"verbose"
]
+ },
+ "arduino.autoUpdateIndexFiles": {
+ "type": "boolean",
+ "default": false,
+ "description": "Controls auto update of package_index.json and library_index.json index files. If enabled, each time when you open Boards Manager/Libraries Manager, download latest index files first. Otherwise, using index files cached on local disk for Boards Manager/Libraries Manager."
}
}
},
diff --git a/src/arduino/arduino.ts b/src/arduino/arduino.ts
index 0db52af1..0f74c62b 100644
--- a/src/arduino/arduino.ts
+++ b/src/arduino/arduino.ts
@@ -41,7 +41,7 @@ export class ArduinoApp {
if (force || !util.fileExistsSync(path.join(this._settings.packagePath, "package_index.json"))) {
try {
// Use the dummy package to initialize the Arduino IDE
- await this.installBoard("dummy", "dummy", "", false);
+ await this.installBoard("dummy", "", "", true);
} catch (ex) {
}
}
@@ -49,12 +49,13 @@ export class ArduinoApp {
/**
* Initialize the arduino library.
+ * @param {boolean} force - Whether force refresh library index file
*/
- public async initializeLibrary() {
- if (!util.fileExistsSync(path.join(this._settings.packagePath, "library_index.json"))) {
+ public async initializeLibrary(force: boolean = false) {
+ if (force || !util.fileExistsSync(path.join(this._settings.packagePath, "library_index.json"))) {
try {
// Use the dummy library to initialize the Arduino IDE
- await this.installLibrary("dummy", "", false);
+ await this.installLibrary("dummy", "", true);
} catch (ex) {
}
}
@@ -177,17 +178,35 @@ export class ArduinoApp {
/**
* Install arduino board package based on package name and platform hardware architecture.
*/
- public async installBoard(packageName: string, arch: string, version: string = "", showOutput: boolean = true) {
+ public async installBoard(packageName: string, arch: string = "", version: string = "", showOutput: boolean = true) {
arduinoChannel.show();
- arduinoChannel.start(`Install package - ${packageName}...`);
+ const updatingIndex = packageName === "dummy" && !arch && !version;
+ if (updatingIndex) {
+ arduinoChannel.start(`Update package index files...`);
+ } else {
+ arduinoChannel.start(`Install package - ${packageName}...`);
+ }
try {
await util.spawn(this._settings.commandPath,
showOutput ? arduinoChannel.channel : null,
- ["--install-boards", `${packageName}:${arch}${version && ":" + version}`]);
+ ["--install-boards", `${packageName}${arch && ":" + arch}${version && ":" + version}`]);
- arduinoChannel.end(`Installed board package - ${packageName}${os.EOL}`);
+ if (updatingIndex) {
+ arduinoChannel.end("Updated package index files.");
+ } else {
+ arduinoChannel.end(`Installed board package - ${packageName}${os.EOL}`);
+ }
} catch (error) {
- arduinoChannel.error(`Exit with code=${error.code}${os.EOL}`);
+ // If a platform with the same version is already installed, nothing is installed and program exits with exit code 1
+ if (error.code === 1) {
+ if (updatingIndex) {
+ arduinoChannel.end("Updated package index files.");
+ } else {
+ arduinoChannel.end(`Installed board package - ${packageName}${os.EOL}`);
+ }
+ } else {
+ arduinoChannel.error(`Exit with code=${error.code}${os.EOL}`);
+ }
}
}
@@ -199,15 +218,33 @@ export class ArduinoApp {
public async installLibrary(libName: string, version: string = "", showOutput: boolean = true) {
arduinoChannel.show();
- arduinoChannel.start(`Install library - ${libName}`);
+ const updatingIndex = (libName === "dummy" && !version);
+ if (updatingIndex) {
+ arduinoChannel.start("Update library index files...");
+ } else {
+ arduinoChannel.start(`Install library - ${libName}`);
+ }
try {
await util.spawn(this._settings.commandPath,
showOutput ? arduinoChannel.channel : null,
["--install-library", `${libName}${version && ":" + version}`]);
- arduinoChannel.end(`Installed library - ${libName}${os.EOL}`);
+ if (updatingIndex) {
+ arduinoChannel.end("Updated library index files.");
+ } else {
+ arduinoChannel.end(`Installed library - ${libName}${os.EOL}`);
+ }
} catch (error) {
- arduinoChannel.error(`Exit with code=${error.code}${os.EOL}`);
+ // If a library with the same version is already installed, nothing is installed and program exits with exit code 1
+ if (error.code === 1) {
+ if (updatingIndex) {
+ arduinoChannel.end("Updated library index files.");
+ } else {
+ arduinoChannel.end(`Installed library - ${libName}${os.EOL}`);
+ }
+ } else {
+ arduinoChannel.error(`Exit with code=${error.code}${os.EOL}`);
+ }
}
}
diff --git a/src/arduino/arduinoContentProvider.ts b/src/arduino/arduinoContentProvider.ts
index b6dbf326..2ba27afd 100644
--- a/src/arduino/arduinoContentProvider.ts
+++ b/src/arduino/arduinoContentProvider.ts
@@ -11,12 +11,14 @@ import { ArduinoApp } from "./arduino";
import { BoardManager } from "./boardManager";
import { LibraryManager } from "./libraryManager";
import LocalWebServer from "./localWebServer";
+import { IArduinoSettings } from "./settings";
export class ArduinoContentProvider implements vscode.TextDocumentContentProvider {
private _webserver: LocalWebServer;
private _onDidChange = new vscode.EventEmitter();
constructor(
+ private _settings: IArduinoSettings,
private _arduinoApp: ArduinoApp,
private _boardManager: BoardManager,
private _libraryManager: LibraryManager,
@@ -86,7 +88,8 @@ export class ArduinoContentProvider implements vscode.TextDocumentContentProvide
}
public async getBoardPackages(req, res) {
- await this._boardManager.loadPackages();
+ const update = (this._settings.autoUpdateIndexFiles && req.query.update === "true");
+ await this._boardManager.loadPackages(update);
return res.json({
platforms: JSONHelper.decycle(this._boardManager.platforms, undefined),
});
@@ -142,7 +145,8 @@ export class ArduinoContentProvider implements vscode.TextDocumentContentProvide
}
public async getLibraries(req, res) {
- await this._libraryManager.loadLibraries();
+ const update = (this._settings.autoUpdateIndexFiles && req.query.update === "true");
+ await this._libraryManager.loadLibraries(update);
return res.json({
libraries: this._libraryManager.libraries,
});
diff --git a/src/arduino/boardManager.ts b/src/arduino/boardManager.ts
index 14e3c2d2..b0bc4879 100644
--- a/src/arduino/boardManager.ts
+++ b/src/arduino/boardManager.ts
@@ -194,16 +194,21 @@ export class BoardManager {
this._boardStatusBar.tooltip = "Change Board Type";
}
- public async loadPackages() {
+ public async loadPackages(update: boolean = false) {
this._packages = [];
this._platforms = [];
+ this._installedPlatforms = [];
- let rootPackgeFolder = this._settings.packagePath;
- let indexFiles = ["package_index.json"];
- let preferences = this._arduinoApp.preferences;
- indexFiles = indexFiles.concat(this.getAddtionalIndexFiles());
+ if (update) { // Update index files.
+ await this._arduinoApp.setPref("boardsmanager.additional.urls", this.getAdditionalUrls().join(","));
+ await this._arduinoApp.initialize(true);
+ }
+
+ // Parse package index files.
+ const indexFiles = ["package_index.json"].concat(this.getAddtionalIndexFiles());
+ const rootPackgeFolder = this._settings.packagePath;
for (let indexFile of indexFiles) {
- if (!util.fileExistsSync(path.join(rootPackgeFolder, indexFile))) {
+ if (!update && !util.fileExistsSync(path.join(rootPackgeFolder, indexFile))) {
await this._arduinoApp.setPref("boardsmanager.additional.urls", this.getAdditionalUrls().join(","));
await this._arduinoApp.initialize(true);
}
@@ -211,9 +216,10 @@ export class BoardManager {
this.parsePackageIndex(JSON.parse(packageContent));
}
- this.loadDefaultPlatforms();
+ // Load default platforms from arduino installation directory and user manually installed platforms.
this.loadInstalledPlatforms();
+ // Load all supported boards type.
this.loadInstalledBoards();
this.updateStatusBar();
this._boardStatusBar.show();
@@ -256,10 +262,6 @@ export class BoardManager {
return this._platforms;
}
- public get installedPlatforms(): IPlatform[] {
- return this._installedPlatforms;
- }
-
public get installedBoards(): Map {
return this._boards;
}
@@ -268,6 +270,25 @@ export class BoardManager {
return this._currentBoard;
}
+ public getInstalledPlatforms(): any[] {
+ // Always using manually installed platforms to overwrite the same platform from arduino installation directory.
+ const installedPlatforms = this.getDefaultPlatforms();
+ const manuallyInstalled = this.getManuallyInstalledPlatforms();
+ manuallyInstalled.forEach((plat) => {
+ const find = installedPlatforms.find((_plat) => {
+ return _plat.packageName === plat.packageName && _plat.architecture === plat.architecture;
+ });
+ if (!find) {
+ installedPlatforms.push(plat);
+ } else {
+ find.defaultPlatform = plat.defaultPlatform;
+ find.version = plat.version;
+ find.rootBoardPath = plat.rootBoardPath;
+ }
+ });
+ return installedPlatforms;
+ }
+
private updateStatusBar(): void {
const dc = DeviceContext.getIntance();
let selectedBoard = this._boards.get(dc.board);
@@ -279,45 +300,6 @@ export class BoardManager {
}
}
- private loadDefaultPlatforms() {
- // Default arduino package information:
- const packageName = "arduino";
- const archName = "avr";
- try {
- let packageBundled = fs.readFileSync(path.join(this._settings.defaultPackagePath, "package_index_bundled.json"), "utf8");
- if (!packageBundled) {
- return;
- }
- let bundledObject = JSON.parse(packageBundled);
- if (bundledObject && bundledObject.packages && bundledObject.packages.length && bundledObject.packages[0].platforms) {
- let platforms = bundledObject.packages[0].platforms;
- if (platforms && platforms.length && platforms.length > 0) {
- const v = platforms[0].version;
- if (v) {
- let filteredPlat = this._platforms.find((_plat) => _plat.package.name === packageName && _plat.architecture === archName);
- if (!filteredPlat) {
- return;
- }
- filteredPlat.defaultPlatform = true;
- if (filteredPlat.installedVersion) {
- let installedPlat = this.installedPlatforms
- .find((_plat) => _plat.package.name === packageName && _plat.architecture === archName);
- if (installedPlat) {
- installedPlat.defaultPlatform = true;
- }
- return;
- } else {
- filteredPlat.installedVersion = v;
- filteredPlat.rootBoardPath = path.join(this._settings.defaultPackagePath, "arduino", "avr");
- this.installedPlatforms.push(filteredPlat);
- }
- }
- }
- }
- } catch (ex) {
- }
- }
-
private parsePackageIndex(rawModel: any): void {
this._packages.concat(rawModel.packages);
@@ -342,38 +324,85 @@ export class BoardManager {
});
}
- private loadInstalledPlatforms(): void {
- this._installedPlatforms = [];
+ private loadInstalledPlatforms() {
+ const installed = this.getInstalledPlatforms();
+ installed.forEach((platform) => {
+ let existingPlatform = this._platforms.find((_plat) => {
+ return _plat.package.name === platform.packageName && _plat.architecture === platform.architecture;
+ });
+ if (existingPlatform) {
+ existingPlatform.defaultPlatform = platform.defaultPlatform;
+ if (!existingPlatform.installedVersion) {
+ existingPlatform.installedVersion = platform.version;
+ existingPlatform.rootBoardPath = platform.rootBoardPath;
+ this._installedPlatforms.push(existingPlatform);
+ }
+ }
+ });
+ }
+
+ // Default arduino package information from arduino installation directory.
+ private getDefaultPlatforms(): any[] {
+ const defaultPlatforms = [];
+ try {
+ let packageBundled = fs.readFileSync(path.join(this._settings.defaultPackagePath, "package_index_bundled.json"), "utf8");
+ if (!packageBundled) {
+ return defaultPlatforms;
+ }
+ let bundledObject = JSON.parse(packageBundled);
+ if (bundledObject && bundledObject.packages) {
+ for (let pkg of bundledObject.packages) {
+ for (let platform of pkg.platforms) {
+ if (platform.version) {
+ defaultPlatforms.push({
+ packageName: pkg.name,
+ architecture: platform.architecture,
+ version: platform.version,
+ rootBoardPath: path.join(this._settings.defaultPackagePath, pkg.name, platform.architecture),
+ defaultPlatform: true,
+ });
+ }
+ }
+ }
+ }
+ } catch (ex) {
+ }
+ return defaultPlatforms;
+ }
+
+ // User manually installed packages.
+ private getManuallyInstalledPlatforms(): any[] {
+ const manuallyInstalled = [];
let rootPackagePath = path.join(path.join(this._settings.packagePath, "packages"));
if (!util.directoryExistsSync(rootPackagePath)) {
- return;
+ return manuallyInstalled;
}
const dirs = util.filterJunk(util.readdirSync(rootPackagePath, true)); // in Mac, filter .DS_Store file.
- dirs.forEach((packageName) => {
+ for (let packageName of dirs) {
let archPath = path.join(this._settings.packagePath, "packages", packageName, "hardware");
if (!util.directoryExistsSync(archPath)) {
- return;
+ continue;
}
let architectures = util.filterJunk(fs.readdirSync(archPath));
- if (!architectures || !architectures.length) {
- return;
- }
architectures.forEach((architecture) => {
let allVersion = util.filterJunk(fs.readdirSync(path.join(archPath, architecture)));
- let existingPlatform = this._platforms.find((_plat) => _plat.package.name === packageName && _plat.architecture === architecture);
- if (existingPlatform && allVersion && allVersion.length) {
- existingPlatform.defaultPlatform = false;
- existingPlatform.installedVersion = allVersion[0];
- existingPlatform.rootBoardPath = path.join(archPath, architecture, allVersion[0]);
- this._installedPlatforms.push(existingPlatform);
+ if (allVersion && allVersion.length) {
+ manuallyInstalled.push({
+ packageName,
+ architecture,
+ version: allVersion[0],
+ rootBoardPath: path.join(archPath, architecture, allVersion[0]),
+ defaultPlatform: false,
+ });
}
});
- });
+ }
+ return manuallyInstalled;
}
private loadInstalledBoards(): void {
this._boards = new Map();
- this.installedPlatforms.forEach((plat) => {
+ this._installedPlatforms.forEach((plat) => {
let dir = plat.rootBoardPath;
if (util.fileExistsSync(path.join(plat.rootBoardPath, "boards.txt"))) {
let boardContent = fs.readFileSync(path.join(plat.rootBoardPath, "boards.txt"), "utf8");
diff --git a/src/arduino/libraryManager.ts b/src/arduino/libraryManager.ts
index d6f07f71..3e5c700f 100644
--- a/src/arduino/libraryManager.ts
+++ b/src/arduino/libraryManager.ts
@@ -43,17 +43,16 @@ export class LibraryManager {
return this._libraries;
}
- public async loadLibraries() {
+ public async loadLibraries(update: boolean = false) {
this._libraryMap = new Map();
this._libraries = [];
- await this._arduinoApp.boardManager.loadPackages();
-
- // Parse libraries index file "library_index.json"
let libraryIndexFilePath = path.join(this._settings.packagePath, "library_index.json");
- if (!util.fileExistsSync(libraryIndexFilePath)) {
- await this._arduinoApp.initializeLibrary();
+ if (update || !util.fileExistsSync(libraryIndexFilePath)) {
+ await this._arduinoApp.initializeLibrary(true);
}
+
+ // Parse libraries index file "library_index.json"
let packageContent = fs.readFileSync(libraryIndexFilePath, "utf8");
this.parseLibraryIndex(JSON.parse(packageContent));
@@ -114,11 +113,10 @@ export class LibraryManager {
private async loadBoardLibraries() {
let builtinLibs = [];
const librarySet = new Set(this._libraryMap.keys());
- for (let board of this._arduinoApp.boardManager.platforms) {
- if (board.installedVersion) {
- const libs = await this.parseBoardLibraries(board.rootBoardPath, board.architecture, librarySet);
- builtinLibs = builtinLibs.concat(libs);
- }
+ const installedPlatforms = this._arduinoApp.boardManager.getInstalledPlatforms();
+ for (let board of installedPlatforms) {
+ const libs = await this.parseBoardLibraries(board.rootBoardPath, board.architecture, librarySet);
+ builtinLibs = builtinLibs.concat(libs);
}
return builtinLibs;
}
diff --git a/src/arduino/settings.ts b/src/arduino/settings.ts
index a7a1bbd6..056a72fb 100644
--- a/src/arduino/settings.ts
+++ b/src/arduino/settings.ts
@@ -17,6 +17,7 @@ import { resolveArduinoPath, validateArduinoPath } from "../common/platform";
export interface IArduinoSettings {
arduinoPath: string;
additionalUrls: string | string[];
+ autoUpdateIndexFiles: boolean;
logLevel: string;
commandPath: string;
packagePath: string;
@@ -116,6 +117,11 @@ export class ArduinoSettings implements IArduinoSettings {
}
}
+ public get autoUpdateIndexFiles(): boolean {
+ const workspaceConfig = vscode.workspace.getConfiguration();
+ return workspaceConfig.get("arduino.autoUpdateIndexFiles");
+ }
+
public get logLevel(): string {
const workspaceConfig = vscode.workspace.getConfiguration();
return workspaceConfig.get("arduino.logLevel") || "info";
diff --git a/src/extension.ts b/src/extension.ts
index d35f0260..e072d9f0 100644
--- a/src/extension.ts
+++ b/src/extension.ts
@@ -38,7 +38,7 @@ export async function activate(context: vscode.ExtensionContext) {
await boardManager.loadPackages();
const libraryManager = new LibraryManager(arduinoSettings, arduinoApp);
- const arduinoManagerProvider = new ArduinoContentProvider(arduinoApp, boardManager, libraryManager, context.extensionPath);
+ const arduinoManagerProvider = new ArduinoContentProvider(arduinoSettings, arduinoApp, boardManager, libraryManager, context.extensionPath);
context.subscriptions.push(vscode.workspace.registerTextDocumentContentProvider(ARDUINO_MANAGER_PROTOCOL, arduinoManagerProvider));
let registerCommand = (command: string, commandBody: (...args: any[]) => any, getUserData?: () => any): vscode.Disposable => {