Switch to FileMetadata to use statx instead of stat on Linux and Apple platforms#1772
Switch to FileMetadata to use statx instead of stat on Linux and Apple platforms#1772swankjesse merged 7 commits intomasterfrom
Conversation
|
This is good! Please refer to this code And if we couldn't use statx then we should really let the creation time be mtime.. as in some cases (ex, modifying the file permissions) will make ctime newer than mtime! |
| * createdAt: 2026-01-01T01:01:01Z | ||
| * lastModifiedAt: 2026-02-02T02:02:02Z | ||
| * | ||
| * It would be nicer to do this in the test itself with exec(), but we don't yet have a handy |
There was a problem hiding this comment.
What if okio provided an api to set file attributes?
Maybe something like this
https://github.com/MohammadKHC/mokio/blob/main/mokio/src/commonMain/kotlin/metadata/FileAttribute.kt
Although iam sure that you can even do better than it.
Iam really bad at writing documentation for things. I usually just leave the code as is..
There was a problem hiding this comment.
I don’t believe that it’s an API many people want?
There was a problem hiding this comment.
Some background here, where I argue that files are less frequently UI and therefore setting metadata is not as useful as it once was.
There is definitely a use for it, but it’s difficult to do well. For example, I don’t believe cloud file systems do a particularly good job of preserving metadata!
There was a problem hiding this comment.
I read your article, and I mostly agree with it.
It’s not just cloud file systems that don’t preserve file metadata—Git doesn’t either. Aside from whether a file is executable, Git ignores file metadata entirely.
https://softwareengineering.stackexchange.com/questions/350403/why-doesnt-git-set-the-file-time
https://superuser.com/a/1422661
That said, I think that we do need to support at least one piece of metadata: whether a file is executable.
This is very common on Unix systems.
Setting file creation or last-modified times only really makes sense for things like restoring family photo dates in the gallery 😄
And other attributes don’t seem necessary unless you’re building something very specialized.
However they are kinda nice to have in a filesystem API!
There was a problem hiding this comment.
Yeah, they are nice to have in a FileSystem API. I certainly prefer metadata over access control!
|
@MohammadKHC your mokio project is rad! I hope you don’t mind I’d like to copy your |
|
I absolutely don’t mind — and I’m glad you liked Mokio. I actually built it hoping some parts might eventually be useful for Okio, so feel free to copy the Process class and any supporting code. There may be some imperfect design decisions, but it works for my use case. Mokio doesn’t support iOS for the same reason you mentioned: forking processes isn’t supported there. I considered a custom source set or stubs, but I decided it wasn’t worth the extra complexity for my use case. Happy to see where this goes if it’s promoted later. Thanks! |
| @OptIn(UnsafeNumber::class) | ||
| internal val timespec.epochMillis: Long | ||
| get() = tv_sec * 1000L + tv_sec / 1_000_000L | ||
| get() = tv_sec * 1000L + tv_nsec / 1_000_000L |
There was a problem hiding this comment.
Longstanding severe bug!
There was a problem hiding this comment.
I assume we got away with it cause it's usually zero? Otherwise we wouldn't have passed our tests.
43630e5 to
ddd7c3f
Compare
| isDirectory = stat.st_mode.toInt() and S_IFMT == S_IFDIR, | ||
| symlinkTarget = symlinkTarget(stat.st_mode.toInt(), path), | ||
| size = stat.st_size, | ||
| createdAtMillis = stat.st_mtim.epochMillis, |
There was a problem hiding this comment.
behavior change from st_ctim
| } | ||
|
|
||
| fun fromIso8601String(iso8601String: String): Instant = | ||
| Instant.fromEpochMilliseconds(Instant.parse(iso8601String).toEpochMilliseconds()) |
There was a problem hiding this comment.
Why the round trip through millis after parsing?
There was a problem hiding this comment.
It's probably to ignore some nanosecond precision..
Although I am not sure if it's intentional or not..
Edit: after checking the assertInRange code I think that this is redundant.
Sorry for replying before checking the code 😶🌫️
There was a problem hiding this comment.
Yep. Just a bug. Fixed!
There was a problem hiding this comment.
(introduced by deleting our commonMain Instant for Wasm)
| /** | ||
| * Returns true if the host file system probably exposes metadata like file creation time. | ||
| * | ||
| * The file system that GitHub actions gives us doesn't do anything when we `touch` a file. | ||
| */ | ||
| val fileSystemHasGoodMetadata: Boolean | ||
| get() = getEnv("GITHUB_WORKSPACE") == null | ||
|
|
There was a problem hiding this comment.
After reviewing the code again, I don’t think this is a GitHub issue.
GNU touch itself does not modify the creation time (and on Linux there’s no way to do that anyway).
Relevant code:
https://github.com/coreutils/coreutils/blob/3d35e82b9b0460769c1966b1ef8acc0b5e5c8348/src/touch.c#L138-L160
https://github.com/coreutils/coreutils/blob/3d35e82b9b0460769c1966b1ef8acc0b5e5c8348/src/touch.c#L218
I’m not sure about macOS and Windows, though.
There was a problem hiding this comment.
Ahh, it’s a Linux issue, not a GitHub issue. That makes sense.
There was a problem hiding this comment.
I was able to do validate our code worked successfully running Linux in Docker on my Mac, but that would have relied on my Mac’s touch command.
Also fallback if STATX_BTIME isn't set
ddd7c3f to
069930f
Compare
#1755