-
Notifications
You must be signed in to change notification settings - Fork 751
Add executable bit configuration to allow in_repo
and on_disk
permissions to diverge
#7484
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
0e64109
to
8a078c3
Compare
Random: this has the exact same set of digits as the previous PR, 4478 vs. 7484. |
45925e9
to
a92ecbc
Compare
Rebased off main and added a new test in |
I've removed the in-repo field from the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LG
Rebased off main and fixed an out-of-date comment in the third commit. |
137abe9
to
65d5a7a
Compare
I haven't looked at this yet but it would be nice to have better descriptions for commits 3-5. They don't say much about the motivation or whether there are observable differences. |
69be4fa
to
777c885
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The following commits do not follow our format for subject lines:
- 76261c5: (draft) flaky test fixes
Commits should have a subject line following the format <topic>: <description>
. Please review the commit guidelines for more information.
All commits are now correctly formatted. Thank you for your contribution!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks generally good to me, thanks for working this feature.
lib/src/local_working_copy.rs
Outdated
/// On Windows, we instead always set this to `false` because when we write | ||
/// files, we always create them anew, so the executable bit will be false | ||
/// even if shared with a Unix machine. | ||
fn new_from_repo(in_repo: bool) -> Self { | ||
Self(if cfg!(unix) { in_repo } else { false }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought this could be worked around by set_executable()
or its caller, but I'm not against the current implementation either. The difference would only matter in reset()
where we don't touch on-disk files at all.
fn set_executable(exec_bit: ExecBit, disk_path: &Path) -> Result<ExecBit, io::Error> {
....
// Windows
ExecBit(false)
}
let real_exec_bit = set_executable(desired_exec_bit, disk_path)?;
Ok(FileState::for_file(real_exec_bit, ...)
…iables The main reason for this change is that we now give variables different names based on their types. This helps avoid confusion and makes intent clearer. However, the type name `FileExecutableFlag` doesn't have a good shortening (`file_exec_flag` is annoyingly long), so I also renamed the type to something shorter, which makes the code more legible: easier to mentally parse and quicker to type. I removed `File` from the name both for length and because it doesn't really help distinguish from the executable field in `TreeValue` (because that field is nested under `TreeValue::File`). Instead, in the upcoming commits I update comments to consistently use the terms 'on-disk' and 'in-repo' to respectively refer to the fields in the `FileState` and `TreeValue` structs, which I find is better for keeping the difference clear in my head. I went with `Bit` in the new name just because I'm already changing it and I prefer `exec_bit` slightly over `exec_flag` as the variable name.
I've found an issue with the PR design that needs a fix, and I'd like to get a confirmation on the direction before I commit to changing anything. If we have the commands: jj config set --repo working-copy.exec-bit-change ignore
touch file
jj file chmod x file
# on-disk file is not executable
jj config set --repo working-copy.exec-bit-change respect
jj file chmod x file
# on-disk file should be executable The snapshot from the last command might not update the backend state, making the I did have this pattern inside a larger test case (and have re-added it as a distinct test), but I didn't realize it was an issue sooner because it would only happen occasionally in CI and I couldn't reproduce it on my machine. So I changed the original test slightly (which fixed CI) and I thought it was either fine or an issue with CI to report later. But it turns out the changed test actually can reproduce the issue on my machine sometimes, I just got incredibly unlucky the first few times I tried. Now that I can reproduce the issue on my machine, I've done a deep-dive and found the problem. Why does this happen, and why only rarely?The following file state cleanliness check should always set // lib/src/local_working_copy.rs:1600
let clean = new_file_state.is_clean(current_file_state)
&& current_file_state.mtime < self.tree_state.own_mtime; I didn't think about this part of the code much because I don't change it in this PR, but I eventually realized it was the culprit. The first line here is always true (it should be false), so the reason Since we want Because we only store the on-disk executable bit in the file states we're comparing, and the on-disk file never changed. What's the fix?When the configuration goes from One way would be to start reading the executable bit from the backend The other way would be to store both the on-disk and in-repo bits in I would like to go back to the original design of the |
This is common problem in EOL handling and watchman, and I personally don't think we need a special support. User should check out all files if they change If we need a workaround, we can record the previous |
Let's try this again!
This is a remaking of #4478 that builds off of the many smaller PRs I've been making the past month.
One key difference from the approach in #4478 is how the third commit starts out by preserving the
in_repo
executable bit on all platforms, which makes the later commit addingon_disk
for Unix easier to reason about.Closes #3949
It took me a while to come to the final representation of the executable bit, but I think it's correct for what we want.
I find the symmetry between the
from_repo
andfrom_disk
methods particularly convincing: if we're respecting the executable bit, thenon_disk
andin_repo
always update to match each other. If we're ignoring the executable bit, then the two values are allowed to diverge, and instead we set them to their previous values (if known).Checklist
If applicable:
CHANGELOG.md
README.md
,docs/
,demos/
)cli/src/config-schema.json
)