Skip to content

Commit

Permalink
fix: provide multiple build path guesses
Browse files Browse the repository at this point in the history
IDE2 does not know what casing the CLI uses

Signed-off-by: Akos Kitta <[email protected]>
  • Loading branch information
Akos Kitta committed Jan 16, 2023
1 parent 0efa410 commit 2d85902
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 9 deletions.
6 changes: 4 additions & 2 deletions arduino-ide-extension/src/browser/contributions/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,10 @@ export class Debug extends SketchContribution {
): Promise<boolean> {
if (err instanceof Error) {
try {
const tempBuildPath = await this.sketchService.tempBuildPath(sketch);
return err.message.includes(tempBuildPath);
const tempBuildPaths = await this.sketchService.tempBuildPath(sketch);
return tempBuildPaths.some((tempBuildPath) =>
err.message.includes(tempBuildPath)
);
} catch {
return false;
}
Expand Down
9 changes: 7 additions & 2 deletions arduino-ide-extension/src/common/protocol/sketches-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,14 @@ export interface SketchesService {

/**
* This is the JS/TS re-implementation of [`GenBuildPath`](https://github.com/arduino/arduino-cli/blob/c0d4e4407d80aabad81142693513b3306759cfa6/arduino/sketch/sketch.go#L296-L306) of the CLI.
* Pass in a sketch and get the build temporary folder filesystem path calculated from the main sketch file location. This method does not check the existence of the sketch.
* Pass in a sketch and get the build temporary folder filesystem path calculated from the main sketch file location. Can be multiple ones. This method does not check the existence of the sketch.
*
* The case sensitivity of the drive letter on Windows matters when the CLI calculates the MD5 hash of the temporary build folder.
* IDE2 does not know and does not want to rely on how the CLI treats the paths: with lowercase or uppercase drive letters.
* Hence, IDE2 has to provide multiple build paths on Windows. This hack will be obsolete when the CLI can provide error codes:
* https://github.com/arduino/arduino-cli/issues/1762.
*/
tempBuildPath(sketch: Sketch): Promise<string>;
tempBuildPath(sketch: Sketch): Promise<string[]>;
}

export interface SketchRef {
Expand Down
6 changes: 5 additions & 1 deletion arduino-ide-extension/src/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ export function firstToUpperCase(what: string): string {
return what.charAt(0).toUpperCase() + what.slice(1);
}

export function isNullOrUndefined(what: any): what is undefined | null {
export function startsWithUpperCase(what: string): boolean {
return !!what && what.charAt(0) === firstToUpperCase(what.charAt(0));
}

export function isNullOrUndefined(what: unknown): what is undefined | null {
return what === undefined || what === null;
}
2 changes: 1 addition & 1 deletion arduino-ide-extension/src/node/is-temp-sketch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { isWindows, isOSX } from '@theia/core/lib/common/os';
import { injectable } from '@theia/core/shared/inversify';
import { firstToLowerCase } from '../common/utils';

const Win32DriveRegex = /^[a-zA-Z]:\\/;
export const Win32DriveRegex = /^[a-zA-Z]:\\/;
export const TempSketchPrefix = '.arduinoIDE-unsaved';

@injectable()
Expand Down
48 changes: 45 additions & 3 deletions arduino-ide-extension/src/node/sketches-service-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,16 @@ import {
IsTempSketch,
maybeNormalizeDrive,
TempSketchPrefix,
Win32DriveRegex,
} from './is-temp-sketch';
import { join } from 'path';
import { ErrnoException } from './utils/errors';
import { isWindows } from '@theia/core/lib/common/os';
import {
firstToLowerCase,
firstToUpperCase,
startsWithUpperCase,
} from '../common/utils';

const RecentSketches = 'recent-sketches.json';
const DefaultIno = `void setup() {
Expand Down Expand Up @@ -668,14 +675,49 @@ export class SketchesServiceImpl
);
}

async tempBuildPath(sketch: Sketch): Promise<string> {
async tempBuildPath(sketch: Sketch): Promise<string[]> {
const sketchPath = FileUri.fsPath(sketch.uri);
const { tempDirRealpath } = this.isTempSketch;
const tempBuildPaths = [
this.tempBuildPathMD5Hash(tempDirRealpath, sketchPath),
];

// If on Windows, provide both the upper and the lowercase drive letter MD5 hashes. All together four paths are expected:
// One of them should match if the sketch is not yet compiled.
// https://github.com/arduino/arduino-ide/pull/1809#discussion_r1071031040
if (isWindows && Win32DriveRegex.test(tempDirRealpath)) {
const toggleFirstCharCasing = (s: string) =>
startsWithUpperCase(s) ? firstToLowerCase(s) : firstToUpperCase(s);
const otherCaseTempDirRealPath = toggleFirstCharCasing(tempDirRealpath);
tempBuildPaths.push(
this.tempBuildPathMD5Hash(otherCaseTempDirRealPath, sketchPath)
);
if (Win32DriveRegex.test(sketchPath)) {
const otherCaseSketchPath = toggleFirstCharCasing(sketchPath);
tempBuildPaths.push(
this.tempBuildPathMD5Hash(tempDirRealpath, otherCaseSketchPath),
this.tempBuildPathMD5Hash(
otherCaseTempDirRealPath,
otherCaseSketchPath
)
);
}
}
return tempBuildPaths;
}

private tempBuildPathMD5Hash(tempFolderPath: string, path: string): string {
return join(tempFolderPath, this.tempBuildFolderMD5Hash(path));
}

private tempBuildFolderMD5Hash(path: string): string {
const hash = crypto
.createHash('md5')
.update(sketchPath)
.update(path)
.digest('hex')
.toUpperCase();
return join(this.isTempSketch.tempDirRealpath, `arduino-sketch-${hash}`);
const folderName = `arduino-sketch-${hash}`;
return folderName;
}

async deleteSketch(sketch: Sketch): Promise<void> {
Expand Down

0 comments on commit 2d85902

Please sign in to comment.