Skip to content

Commit 2d85902

Browse files
author
Akos Kitta
committed
fix: provide multiple build path guesses
IDE2 does not know what casing the CLI uses Signed-off-by: Akos Kitta <[email protected]>
1 parent 0efa410 commit 2d85902

File tree

5 files changed

+62
-9
lines changed

5 files changed

+62
-9
lines changed

Diff for: arduino-ide-extension/src/browser/contributions/debug.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,10 @@ export class Debug extends SketchContribution {
246246
): Promise<boolean> {
247247
if (err instanceof Error) {
248248
try {
249-
const tempBuildPath = await this.sketchService.tempBuildPath(sketch);
250-
return err.message.includes(tempBuildPath);
249+
const tempBuildPaths = await this.sketchService.tempBuildPath(sketch);
250+
return tempBuildPaths.some((tempBuildPath) =>
251+
err.message.includes(tempBuildPath)
252+
);
251253
} catch {
252254
return false;
253255
}

Diff for: arduino-ide-extension/src/common/protocol/sketches-service.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,14 @@ export interface SketchesService {
108108

109109
/**
110110
* 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.
111-
* 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.
111+
* 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.
112+
*
113+
* The case sensitivity of the drive letter on Windows matters when the CLI calculates the MD5 hash of the temporary build folder.
114+
* IDE2 does not know and does not want to rely on how the CLI treats the paths: with lowercase or uppercase drive letters.
115+
* Hence, IDE2 has to provide multiple build paths on Windows. This hack will be obsolete when the CLI can provide error codes:
116+
* https://github.com/arduino/arduino-cli/issues/1762.
112117
*/
113-
tempBuildPath(sketch: Sketch): Promise<string>;
118+
tempBuildPath(sketch: Sketch): Promise<string[]>;
114119
}
115120

116121
export interface SketchRef {

Diff for: arduino-ide-extension/src/common/utils.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ export function firstToUpperCase(what: string): string {
1313
return what.charAt(0).toUpperCase() + what.slice(1);
1414
}
1515

16-
export function isNullOrUndefined(what: any): what is undefined | null {
16+
export function startsWithUpperCase(what: string): boolean {
17+
return !!what && what.charAt(0) === firstToUpperCase(what.charAt(0));
18+
}
19+
20+
export function isNullOrUndefined(what: unknown): what is undefined | null {
1721
return what === undefined || what === null;
1822
}

Diff for: arduino-ide-extension/src/node/is-temp-sketch.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { isWindows, isOSX } from '@theia/core/lib/common/os';
44
import { injectable } from '@theia/core/shared/inversify';
55
import { firstToLowerCase } from '../common/utils';
66

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

1010
@injectable()

Diff for: arduino-ide-extension/src/node/sketches-service-impl.ts

+45-3
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,16 @@ import {
3232
IsTempSketch,
3333
maybeNormalizeDrive,
3434
TempSketchPrefix,
35+
Win32DriveRegex,
3536
} from './is-temp-sketch';
3637
import { join } from 'path';
3738
import { ErrnoException } from './utils/errors';
39+
import { isWindows } from '@theia/core/lib/common/os';
40+
import {
41+
firstToLowerCase,
42+
firstToUpperCase,
43+
startsWithUpperCase,
44+
} from '../common/utils';
3845

3946
const RecentSketches = 'recent-sketches.json';
4047
const DefaultIno = `void setup() {
@@ -668,14 +675,49 @@ export class SketchesServiceImpl
668675
);
669676
}
670677

671-
async tempBuildPath(sketch: Sketch): Promise<string> {
678+
async tempBuildPath(sketch: Sketch): Promise<string[]> {
672679
const sketchPath = FileUri.fsPath(sketch.uri);
680+
const { tempDirRealpath } = this.isTempSketch;
681+
const tempBuildPaths = [
682+
this.tempBuildPathMD5Hash(tempDirRealpath, sketchPath),
683+
];
684+
685+
// If on Windows, provide both the upper and the lowercase drive letter MD5 hashes. All together four paths are expected:
686+
// One of them should match if the sketch is not yet compiled.
687+
// https://github.com/arduino/arduino-ide/pull/1809#discussion_r1071031040
688+
if (isWindows && Win32DriveRegex.test(tempDirRealpath)) {
689+
const toggleFirstCharCasing = (s: string) =>
690+
startsWithUpperCase(s) ? firstToLowerCase(s) : firstToUpperCase(s);
691+
const otherCaseTempDirRealPath = toggleFirstCharCasing(tempDirRealpath);
692+
tempBuildPaths.push(
693+
this.tempBuildPathMD5Hash(otherCaseTempDirRealPath, sketchPath)
694+
);
695+
if (Win32DriveRegex.test(sketchPath)) {
696+
const otherCaseSketchPath = toggleFirstCharCasing(sketchPath);
697+
tempBuildPaths.push(
698+
this.tempBuildPathMD5Hash(tempDirRealpath, otherCaseSketchPath),
699+
this.tempBuildPathMD5Hash(
700+
otherCaseTempDirRealPath,
701+
otherCaseSketchPath
702+
)
703+
);
704+
}
705+
}
706+
return tempBuildPaths;
707+
}
708+
709+
private tempBuildPathMD5Hash(tempFolderPath: string, path: string): string {
710+
return join(tempFolderPath, this.tempBuildFolderMD5Hash(path));
711+
}
712+
713+
private tempBuildFolderMD5Hash(path: string): string {
673714
const hash = crypto
674715
.createHash('md5')
675-
.update(sketchPath)
716+
.update(path)
676717
.digest('hex')
677718
.toUpperCase();
678-
return join(this.isTempSketch.tempDirRealpath, `arduino-sketch-${hash}`);
719+
const folderName = `arduino-sketch-${hash}`;
720+
return folderName;
679721
}
680722

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

0 commit comments

Comments
 (0)