Skip to content

Action Fusion skips then_run for Git Bash/MSYS/Cygwin/WSL drive paths on Windows #45

Description

@kaluli123123

Summary

On Windows, a fused edit/write whose path comes from a Git Bash, MSYS, Cygwin, or WSL shell mutates one file while Action Fusion's queue and hash guard address another, so then_run is skipped with ENOENT.

resolveToolPath() handles @, file://, ~, and ~/, then calls path.resolve().

function stripToolPathPrefix(filePath: string): string {
return filePath.startsWith("@") ? filePath.slice(1) : filePath;
}
export function resolveToolPath(cwd: string, filePath: string): string {
const stripped = stripToolPathPrefix(filePath);
// Pi accepts file URLs; the queue and hash guard must use the same target.
const expanded = stripped.startsWith("file://") ? fileURLToPath(stripped) : stripped;
if (expanded === "~") return homedir();
if (expanded.startsWith("~/")) return resolve(homedir(), expanded.slice(2));
return resolve(cwd, expanded);
}

Pi's resolveToCwd() does two more things on Windows, in utils/paths.js:

if (process.platform === "win32") {
    normalized = normalizeWindowsShellPath(normalized);   // /c/src -> C:\src
}
if (options.expandTilde ?? true) {
    if (normalized.startsWith("~/") || (process.platform === "win32" && normalized.startsWith("~\\"))) {
        return join(home, normalized.slice(2));
    }
}
export function normalizeWindowsShellPath(filePath) {
    if (!filePath.startsWith("/") || filePath.startsWith("//") || filePath.includes("\\")) return filePath;
    const match = filePath.match(/^\/(?:mnt\/|cygdrive\/)?([a-z])(?:\/(.*))?$/i);
    if (!match) return filePath;
    const suffix = match[2]?.replaceAll("/", "\\");
    return `${match[1].toUpperCase()}:\\${suffix ?? ""}`;
}

Actual behavior

For path: "/c/src/app.ts" the built-in mutation writes C:\src\app.ts, while resolveToolPath() returns a literal \c\src\app.ts for the queue slot and the assertUnchangedBeforeCommand() hash. The mutation succeeds, the guard reads a path that does not exist, and the model gets:

Error: [then_run:skipped] ENOENT: no such file or directory, open '...\c\src\app.ts'; the command was not run.

The same applies to ~\notes.txt, which Pi expands and SoL-Pi treats as a relative filename.

Scope of the claim

I do not have a Windows machine, so this is derived from Pi 0.84.2's own resolver source quoted above rather than executed on Windows. The divergence itself is checkable without a Windows runner; a confirmation on one would be welcome before merging anything.

This is the same parity class as #2 and #7, on a different input class — the file-URL fix in #4 and the Unicode-space work in #7 do not touch shell drive paths. Given #16, Windows users are running this.

Expected behavior

Action Fusion should apply the same drive-path conversion and ~\ expansion Pi's own resolver applies, so the queue and hash guard observe the file the built-in mutation tool wrote. Both should stay no-ops off Windows, so a POSIX user whose repository genuinely contains /c/src/app.ts is unaffected.

I have a fix that mirrors Pi's function, with tests that drive the platform branch explicitly.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions