Windows: `jolt C:/…/file.clj` is read as project-relative — `open-input-file` fails for `./C:/…`
- Dominant language
- Scheme
- Stars
- 290
- Forks
- 22
- Avg merge
- 4h 54m
- Merged PRs (30d)
- 259
Description
**Environment:** jolt v0.8.7 (`jolt-v0.8.7-x86_64-windows.zip`, `jolt.exe` invoked
directly — `JOLT_PWD` unset, so `project-dir` is `"."`, `main.clj:9`),
Windows 11, Git Bash. Reproduced from any cwd.
**Area:** `jolt-core/jolt/main.clj` (`file-arg`).
## Summary
An absolute Windows path passed as the FILE argument — `jolt C:/Users/x/hello.clj`,
`jolt run C:/Users/x/hello.clj`, any `C:/…` or `C:\…` — is classified as
project-relative because `file-arg` recognizes POSIX absolutes only. It becomes
`/C:/…`, so the prebuilt binary tries `./C:/…` and the file cannot
be opened, even though the path is correct.
## Repro
```clojure
;; jolt-core/jolt/main.clj:320-327
(defn- file-arg [x]
(cond
(= "-" x) "/dev/stdin"
(str/starts-with? x "/") x
;; a ./-prefixed argument is already project-relative: joining it as is
;; reported the file as ././x.clj
(str/starts-with? x "./") (str (project-dir) "/" (subs x 2))
:else (str (project-dir) "/" x)))
```
```
$ jolt C:/Users/x/hello.clj
Unhandled exception (IOException): open-input-file: failed for ./C:/Users/x/hello.clj: invalid argument
trace:
oif
read-file-string
load-jolt-file
$ jolt run C:/Users/x/hello.clj # same failure
```
Backslash form (`jolt C:\Users\x\hello.clj`) and any cwd behave the same — the
`:else` branch only ever sees a path it joins to `project-dir`.
The relative spellings work, from any cwd — which is why this is easy to miss:
```
$ jolt hello.clj # ok
$ jolt ./hello.clj # ok
```
## Suggested fix
Route the `:else` branch through a Windows-aware path classification instead of
`starts-with? "/"`: `jolt.deps/native-path-kind-for`
(`jolt-core/jolt/deps.clj:195-214`) already distinguishes drive-absolute
(`C:/x`), UNC (`//server/share`), root-relative (`/x`) and drive-relative (`C:x`),
and `io.ss`'s `jfile-abs` handles absolute Windows paths as well. The `"-"` →
`/dev/stdin` case stays first.
**Workaround:** pass a path relative to the cwd (`jolt Users/x/hello.clj` from
`C:\` works — verified), or use `-e` / stdin.
---
A related, independent defect — `File.getCanonicalPath` returning `/C:/…`, which
breaks reads and writes with the returned value — is filed as
[jolt#991](https://github.com/jolt-lang/jolt/issues/991).
Contributor guide
Research direction
Start in jolt-core/jolt/main.clj at file-arg (around lines 320-327), then read jolt.deps/native-path-kind-for in jolt-core/jolt/deps.clj:195-214 and the io.ss jfile-abs behavior. Check the existing relative and stdin cases, then verify that drive-absolute, UNC, root-relative, drive-relative, and POSIX paths are classified correctly without regressing ./ paths. Reproduce the CLI commands from the issue to confirm absolute files open successfully.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- clojure
- Domain
- cli, operating-systems
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100