mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-06-09 21:56:32 +00:00
fix: try fetch the sketch by path if not in the cache
The sketch cache might be empty, when trying to generate the secrets include in the main sketch file from the `secrets` property. Closes #1999 Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
This commit is contained in:
parent
5540170341
commit
54f210d4de
@ -57,6 +57,30 @@ export class CreateApi {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* `sketchPath` is not the POSIX path but the path with the user UUID, username, etc.
|
||||
* See [Create.Resource#path](./typings.ts). If `cache` is `true` and a sketch exists with the path,
|
||||
* the cache will be updated with the new state of the sketch.
|
||||
*/
|
||||
// TODO: no nulls in API
|
||||
async sketchByPath(
|
||||
sketchPath: string,
|
||||
cache = false
|
||||
): Promise<Create.Sketch | null> {
|
||||
const url = new URL(`${this.domain()}/sketches/byPath/${sketchPath}`);
|
||||
const headers = await this.headers();
|
||||
const sketch = await this.run<Create.Sketch>(url, {
|
||||
method: 'GET',
|
||||
headers,
|
||||
});
|
||||
if (sketch && cache) {
|
||||
this.sketchCache.addSketch(sketch);
|
||||
const posixPath = createPaths.toPosixPath(sketch.path);
|
||||
this.sketchCache.purgeByPath(posixPath);
|
||||
}
|
||||
return sketch;
|
||||
}
|
||||
|
||||
async sketches(limit = 50): Promise<Create.Sketch[]> {
|
||||
const url = new URL(`${this.domain()}/sketches`);
|
||||
url.searchParams.set('user_id', 'me');
|
||||
@ -86,7 +110,11 @@ export class CreateApi {
|
||||
|
||||
async createSketch(
|
||||
posixPath: string,
|
||||
contentProvider: MaybePromise<string> = this.sketchesService.defaultInoContent()
|
||||
contentProvider: MaybePromise<string> = this.sketchesService.defaultInoContent(),
|
||||
payloadOverride: Record<
|
||||
string,
|
||||
string | boolean | number | Record<string, unknown>
|
||||
> = {}
|
||||
): Promise<Create.Sketch> {
|
||||
const url = new URL(`${this.domain()}/sketches`);
|
||||
const [headers, content] = await Promise.all([
|
||||
@ -97,6 +125,7 @@ export class CreateApi {
|
||||
ino: btoa(content),
|
||||
path: posixPath,
|
||||
user_id: 'me',
|
||||
...payloadOverride,
|
||||
};
|
||||
const init = {
|
||||
method: 'PUT',
|
||||
@ -212,7 +241,17 @@ export class CreateApi {
|
||||
return data;
|
||||
}
|
||||
|
||||
const sketch = this.sketchCache.getSketch(createPaths.parentPosix(path));
|
||||
const posixPath = createPaths.parentPosix(path);
|
||||
let sketch = this.sketchCache.getSketch(posixPath);
|
||||
// Workaround for https://github.com/arduino/arduino-ide/issues/1999.
|
||||
if (!sketch) {
|
||||
// Convert the ordinary sketch POSIX path to the Create path.
|
||||
// For example, `/sketch_apr6a` will be transformed to `8a694e4b83878cc53472bd75ee928053:kittaakos/sketches_v2/sketch_apr6a`.
|
||||
const createPathPrefix = this.sketchCache.createPathPrefix;
|
||||
if (createPathPrefix) {
|
||||
sketch = await this.sketchByPath(createPathPrefix + posixPath, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
sketch &&
|
||||
@ -448,13 +487,18 @@ export class CreateApi {
|
||||
await this.run(url, init, ResponseResultProvider.NOOP);
|
||||
}
|
||||
|
||||
private fetchCounter = 0;
|
||||
private async run<T>(
|
||||
requestInfo: URL,
|
||||
init: RequestInit | undefined,
|
||||
resultProvider: ResponseResultProvider = ResponseResultProvider.JSON
|
||||
): Promise<T> {
|
||||
console.debug(`HTTP ${init?.method}: ${requestInfo.toString()}`);
|
||||
const fetchCount = `[${++this.fetchCounter}]`;
|
||||
const fetchStart = performance.now();
|
||||
const method = init?.method ? `${init.method}: ` : '';
|
||||
const url = requestInfo.toString();
|
||||
const response = await fetch(requestInfo.toString(), init);
|
||||
const fetchEnd = performance.now();
|
||||
if (!response.ok) {
|
||||
let details: string | undefined = undefined;
|
||||
try {
|
||||
@ -465,7 +509,18 @@ export class CreateApi {
|
||||
const { statusText, status } = response;
|
||||
throw new CreateError(statusText, status, details);
|
||||
}
|
||||
const parseStart = performance.now();
|
||||
const result = await resultProvider(response);
|
||||
const parseEnd = performance.now();
|
||||
console.debug(
|
||||
`HTTP ${fetchCount} ${method} ${url} [fetch: ${(
|
||||
fetchEnd - fetchStart
|
||||
).toFixed(2)} ms, parse: ${(parseEnd - parseStart).toFixed(
|
||||
2
|
||||
)} ms] body: ${
|
||||
typeof result === 'string' ? result : JSON.stringify(result)
|
||||
}`
|
||||
);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,13 @@
|
||||
import { FileStat } from '@theia/filesystem/lib/common/files';
|
||||
import { injectable } from '@theia/core/shared/inversify';
|
||||
import { toPosixPath } from '../../create/create-paths';
|
||||
import { splitSketchPath } from '../../create/create-paths';
|
||||
import { Create } from '../../create/typings';
|
||||
|
||||
@injectable()
|
||||
export class SketchCache {
|
||||
sketches: Record<string, Create.Sketch> = {};
|
||||
fileStats: Record<string, FileStat> = {};
|
||||
private _createPathPrefix: string | undefined;
|
||||
|
||||
init(): void {
|
||||
// reset the data
|
||||
@ -32,7 +33,10 @@ export class SketchCache {
|
||||
|
||||
addSketch(sketch: Create.Sketch): void {
|
||||
const { path } = sketch;
|
||||
const posixPath = toPosixPath(path);
|
||||
const [pathPrefix, posixPath] = splitSketchPath(path);
|
||||
if (pathPrefix !== this._createPathPrefix) {
|
||||
this._createPathPrefix = pathPrefix;
|
||||
}
|
||||
this.sketches[posixPath] = sketch;
|
||||
}
|
||||
|
||||
@ -40,6 +44,10 @@ export class SketchCache {
|
||||
return this.sketches[path] || null;
|
||||
}
|
||||
|
||||
get createPathPrefix(): string | undefined {
|
||||
return this._createPathPrefix;
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
return JSON.stringify({
|
||||
sketches: this.sketches,
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { Container, ContainerModule } from '@theia/core/shared/inversify';
|
||||
import { assert, expect } from 'chai';
|
||||
import fetch from 'cross-fetch';
|
||||
import { posix } from 'path';
|
||||
import { v4 } from 'uuid';
|
||||
import { ArduinoPreferences } from '../../browser/arduino-preferences';
|
||||
import { AuthenticationClientService } from '../../browser/auth/authentication-client-service';
|
||||
@ -251,6 +252,39 @@ describe('create-api', () => {
|
||||
expect(sketch).to.be.undefined;
|
||||
});
|
||||
});
|
||||
|
||||
it("should fetch the sketch when transforming the 'secrets' into '#include' and the sketch is not in the cache", async () => {
|
||||
const name = v4();
|
||||
const posixPath = toPosix(name);
|
||||
const newSketch = await createApi.createSketch(
|
||||
posixPath,
|
||||
'void setup(){} void loop(){}',
|
||||
{
|
||||
secrets: {
|
||||
data: [
|
||||
{
|
||||
name: 'SECRET_THING',
|
||||
value: '❤︎',
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
);
|
||||
expect(newSketch).to.be.not.undefined;
|
||||
expect(newSketch.secrets).to.be.not.undefined;
|
||||
expect(Array.isArray(newSketch.secrets)).to.be.true;
|
||||
expect(newSketch.secrets?.length).to.be.equal(1);
|
||||
expect(newSketch.secrets?.[0]).to.be.deep.equal({
|
||||
name: 'SECRET_THING',
|
||||
value: '❤︎',
|
||||
});
|
||||
createApi.sketchCache.init(); // invalidate the cache
|
||||
const content = await createApi.readFile(
|
||||
posix.join(posixPath, `${name}.ino`)
|
||||
);
|
||||
expect(content.includes(`#include "${Create.arduino_secrets_file}"`)).to.be
|
||||
.true;
|
||||
});
|
||||
});
|
||||
|
||||
// Using environment variables is recommended for testing but you can modify the module too.
|
||||
|
Loading…
x
Reference in New Issue
Block a user