Skip to content

Commit 9228dfb

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 be88074 commit 9228dfb

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
@@ -33,9 +33,16 @@ import {
3333
IsTempSketch,
3434
maybeNormalizeDrive,
3535
TempSketchPrefix,
36+
Win32DriveRegex,
3637
} from './is-temp-sketch';
3738
import { join } from 'path';
3839
import { ErrnoException } from './utils/errors';
40+
import { isWindows } from '@theia/core/lib/common/os';
41+
import {
42+
firstToLowerCase,
43+
firstToUpperCase,
44+
startsWithUpperCase,
45+
} from '../common/utils';
3946

4047
const RecentSketches = 'recent-sketches.json';
4148
const DefaultIno = `void setup() {
@@ -576,14 +583,49 @@ export class SketchesServiceImpl
576583
);
577584
}
578585

579-
async tempBuildPath(sketch: Sketch): Promise<string> {
586+
async tempBuildPath(sketch: Sketch): Promise<string[]> {
580587
const sketchPath = FileUri.fsPath(sketch.uri);
588+
const { tempDirRealpath } = this.isTempSketch;
589+
const tempBuildPaths = [
590+
this.tempBuildPathMD5Hash(tempDirRealpath, sketchPath),
591+
];
592+
593+
// If on Windows, provide both the upper and the lowercase drive letter MD5 hashes. All together four paths are expected:
594+
// One of them should match if the sketch is not yet compiled.
595+
// https://github.com/arduino/arduino-ide/pull/1809#discussion_r1071031040
596+
if (isWindows && Win32DriveRegex.test(tempDirRealpath)) {
597+
const toggleFirstCharCasing = (s: string) =>
598+
startsWithUpperCase(s) ? firstToLowerCase(s) : firstToUpperCase(s);
599+
const otherCaseTempDirRealPath = toggleFirstCharCasing(tempDirRealpath);
600+
tempBuildPaths.push(
601+
this.tempBuildPathMD5Hash(otherCaseTempDirRealPath, sketchPath)
602+
);
603+
if (Win32DriveRegex.test(sketchPath)) {
604+
const otherCaseSketchPath = toggleFirstCharCasing(sketchPath);
605+
tempBuildPaths.push(
606+
this.tempBuildPathMD5Hash(tempDirRealpath, otherCaseSketchPath),
607+
this.tempBuildPathMD5Hash(
608+
otherCaseTempDirRealPath,
609+
otherCaseSketchPath
610+
)
611+
);
612+
}
613+
}
614+
return tempBuildPaths;
615+
}
616+
617+
private tempBuildPathMD5Hash(tempFolderPath: string, path: string): string {
618+
return join(tempFolderPath, this.tempBuildFolderMD5Hash(path));
619+
}
620+
621+
private tempBuildFolderMD5Hash(path: string): string {
581622
const hash = crypto
582623
.createHash('md5')
583-
.update(sketchPath)
624+
.update(path)
584625
.digest('hex')
585626
.toUpperCase();
586-
return join(this.isTempSketch.tempDirRealpath, `arduino-sketch-${hash}`);
627+
const folderName = `arduino-sketch-${hash}`;
628+
return folderName;
587629
}
588630

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

0 commit comments

Comments
 (0)