Skip to content
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

Feature-PWD-per-drive 2.0 #14546

Open
wants to merge 114 commits into
base: main
Choose a base branch
from

Conversation

PegasusPlusUS
Copy link
Contributor

@PegasusPlusUS PegasusPlusUS commented Dec 9, 2024

Upgrade for PR #14411
This PR implements PWD-per-drive as described in discussion #14355

Description

The first version of the implementation was relatively complex and incompatible with overlays. The second version simplifies the implementation by removing the independent DriveToPwd map and avoiding modifications to Stack. Instead, the pwd information is stored in the Stack as an environment variable according to the requirements of the native Windows shell. When expanding relative paths, the Stack is queried for the corresponding environment variable. This approach allows seamless integration with the powerful layered overlay system of Nushell, maintaining perfect harmony between set-env, overlays, and PWD functionality, preserving the original Nushell behavior.

The summary of related file changes is as follows:

  1. pwd_per_drive.rs
    Moved from the nu_path module to the nu_protocol::engine module.

1.1 File system commands can use expand_path_with(), to replace previously (directly) used nu_path::expand_path_with. If the path is relative to a drive, it will expand and return the result; otherwise, it processes paths as before by calling nu_path::expand_path_with. File system commands can also directly call expand_pwd() for converting drive relative path.

1.2 When user changes current directory, current stack shall add "PWD" environment variable to store current directory. PWD-per-drive hooks in Stack::add_env_var() and EngineState::add_env_var(). If found the variable name is "PWD", hooking code will call set_pwd() to notify PWD-per-drive recording PWD for current drive. It does the job by requesting the stack or engine_state (via EnvMaintainer trait) to store the information in environment variables according to the native Windows shell conventions. An extend_automatic_env_vars() is designed to help keep dedicated environment variables from being modified manually.

1.3 Other fn()s are auxiliary path-handling functions needed for the above two parts. Unit tests are in test mod.

  1. crates/nu_protocol/src/engine/stack.rs
    Removed the first version's modifications to the Stack structure.
    Added a single line in set_cwd() to call set_pwd() mentioned in 1.2.

  2. src/run.rs
    Reverted changes made in the first version.

  3. crates/nu_protocol/src/engine/mod.rs
    Added the module declaration and re-export for pwd_per_drive.

  4. crates/nu_protocol/Cargo.toml
    Added reference to omnipath.

  5. crates/nu_path/src/lib.rs
    Reverted changes made in the first version.

  6. crates/nu-engine/src/eval_ir.rs
    Continued updates from the first version, replacing three calls to nu_path::expand_path_with() with expand_path_with() mentioned in 1.1.

  7. crates/nu-engine/src/eval.rs
    Removed modifications to caller/callee Stack operations from the first version.
    Replaced two calls to nu_path::expand_path_with() with expand_path_with() mentioned in 1.1.

  8. crates/nu-engine/src/env.rs
    Reverted changes made in the first version.

  9. crates/nu-cmd-plugin/src/util.rs
    Replaced two calls to nu_path::expand_path_with() with expand_path_with() mentioned in 1.1.

  10. crates/nu-cli/src/repl.rs
    Reverted the first version's changes and no longer modified the do_auto_cd implementation.
    Replaced one call to nu_path::expand_path_with() with expand_path_with() mentioned in 1.1.
    Updated the logic for path.is_dir() in parse_operation() to account for Windows relative paths.

  11. crates/nu-command/src/filesystem/cd.rs
    Revert the change made in the first version.

  12. crates/nu-cli/src/completions/completion_common.rs
    Continued updates from the first version, replacing one call to nu_path::expand_path_with() with
    expand_path_with() mentioned in 1.1.

Apart from auto_cd/cd/ls/save/watch, other file systems support relative path for drive syntax, and need to be modified to support PWD-per-drive, they are under testing and will be upgraded near after this PR is accepted.

'glob' currently does not support windows path syntax, so this command also needs to be updated.

=================================================================
Make sure you've run and fixed any issues with these commands:

Pass - cargo fmt --all -- --check to check standard code formatting (cargo fmt --all applies these changes)
Pass - cargo clippy --workspace -- -D warnings -D clippy::unwrap_used to check that you're using the standard code style
Pass - cargo test --workspace to check that all tests pass (on Windows make sure to enable developer mode)
Pass - cargo run -- -c "use toolkit.nu; toolkit test stdlib" to run the tests for the standard library

After Submitting

To DO
PWD-per-drive ready: auto_cd/cd/ls/save/watch
Other file system [du|mktemp|rm|open|touch|ucp|umkdir|umv|utouch] commands are pending for upgrade.

Zhenping Zhao and others added 14 commits December 5, 2024 03:42
- Updated `need_expand` function to accept a string instead of a Path reference, simplifying the logic for checking relative paths with drive letters.
- Enhanced `expand_pwd` method to handle leading quotes in paths, ensuring proper path expansion and returning dequoted paths when necessary.
- Introduced a new helper function `remove_leading_quotes` to clean up input paths by removing matching leading and trailing quotes.
- Added unit tests for the new functionality, ensuring robust handling of quoted paths and correct expansion behavior.

This refactor improves the clarity and functionality of path handling in the DriveToPwdMap implementation.
…nv freely. Wait review and other file system commands pending.
@fdncred
Copy link
Collaborator

fdncred commented Dec 9, 2024

do we have to have 5 mods in pwd_per_drive.rs (excluding tests)? it's kind of hard to read.

@PegasusPlusUS
Copy link
Contributor Author

Just split into several mods to improve understanding of the implementation before initiated PR, :(. OK, rollback to flatten the code without extra mods.

@PegasusPlusUS
Copy link
Contributor Author

PegasusPlusUS commented Jan 11, 2025

CI test for windows not very stable, currently these 3 failed:

failures:
commands::network::http::get::http_get_with_accept_errors_and_full_raw_response
commands::network::http::head::http_head_failed_due_to_server_error
commands::network::http::patch::http_patch_failed_due_to_server_error

Checked these tests, they're using stack variable, no global or shared, separately test all OK, do not understand what happened in CI test.

Sometimes other network commands fail, sometimes one or more tests for PWD-per-drive failed at SUBST not succeed etc. Usually at least one test will fail, maybe the CI environment needs upgrade to larger memory? :).

@fdncred
Copy link
Collaborator

fdncred commented Jan 11, 2025

I've retried the windows test twice now and it still fails. I'm still not sure we'll move forward with this though.

@PegasusPlusUS
Copy link
Contributor Author

I've retried the windows test twice now and it still fails. I'm still not sure we'll move forward with this though.

These network commands are not PWD-per-drive related, just recently some commands can't pass CI, seems somewhat randomly.

@PegasusPlusUS
Copy link
Contributor Author

I've retried the windows test twice now and it still fails. I'm still not sure we'll move forward with this though.

The 1700+ lines of changes may seem very complex, but actually:

  1. There is a bias in GitHub's statistics, as a single touch.rs file move from one directory to another contributes 654 lines, that's nothing about real change.
  2. Among the changes are about ten filesystem commands, each with just test cases spanning dozens of lines, and half of the remaining 1000 lines are test cases for these commands.
  3. Excluding parts unrelated to PWD but incidentally improved, such as auto_cd support for the Playground and refactoring of management of managed env variables, the actual implementation of the PWD functionality is less than 100 lines.

Since around 2024-12-15, I’ve primarily been writing tests, especially for the watch feature. Because Nushell doesn’t support background tasks, I tried numerous approaches, repeatedly encountering failures (and the output for nu!() macro is not friendly for debugging, have to manually proceeded line by line to isolate problems). Eventually, I solved the issue, wrapping up the PWD-related work.

So, in my view, this version of the PWD implementation is not complicated at all. It uses the existing layered env variable mechanism of the stack/engine_state to store and retrieve PWD information, naturally coexisting in harmony with overlays and export-env modules. Now, the refactoring and testing of filesystem commands have been fully completed. The reason CI cannot pass smoothly does not appear to be related to the test code itself; it might be due to insufficient resources in the CI environment as sometime PWD commands all succeed but some network commands randomly fail in CI at the same time. Hope after resolving CI unstable problem, PWD related work can be online soon, :).

@132ikl
Copy link
Contributor

132ikl commented Jan 12, 2025

It's concerning to me that the HTTP tests are specifically failing on Windows, since this PR specifically touches Windows. Those tests don't seem to be failing for any other recent commit CI runs, and they pass on this PR for Linux and macOS. We've disabled all of the tests which make actual outbound network connections, all of the HTTP remaining tests are mocked, so it's not an network issue. I know you didn't touch the HTTP code, but maybe some change in this PR changes the way the mock is set up, or some detail of how Nushell interacts with the mock, breaking those tests?

It sounds like based on @fdncred's comment that these tests are failing locally, not just in CI (unless he meant that he re-ran the CI tests). Have you tried running the tests locally? You can run them locally by running this in your nushell folder:

use toolkit.nu
toolkit check pr

@PegasusPlusUS
Copy link
Contributor Author

It's concerning to me that the HTTP tests are specifically failing on Windows, since this PR specifically touches Windows. Those tests don't seem to be failing for any other recent commit CI runs, and they pass on this PR for Linux and macOS. We've disabled all of the tests which make actual outbound network connections, all of the HTTP remaining tests are mocked, so it's not an network issue. I know you didn't touch the HTTP code, but maybe some change in this PR changes the way the mock is set up, or some detail of how Nushell interacts with the mock, breaking those tests?

It sounds like based on @fdncred's comment that these tests are failing locally, not just in CI. Have you tried running the tests locally? You can run them locally by running this in your nushell folder:

use toolkit.nu
toolkit check pr

Already locally run 'cargo test --workspace', and run separately in IDE, all can pass.

@PegasusPlusUS
Copy link
Contributor Author

It's concerning to me that the HTTP tests are specifically failing on Windows, since this PR specifically touches Windows. Those tests don't seem to be failing for any other recent commit CI runs, and they pass on this PR for Linux and macOS. We've disabled all of the tests which make actual outbound network connections, all of the HTTP remaining tests are mocked, so it's not an network issue. I know you didn't touch the HTTP code, but maybe some change in this PR changes the way the mock is set up, or some detail of how Nushell interacts with the mock, breaking those tests?

It sounds like based on @fdncred's comment that these tests are failing locally, not just in CI (unless he meant that he re-ran the CI tests). Have you tried running the tests locally? You can run them locally by running this in your nushell folder:

use toolkit.nu
toolkit check pr

Recently I added test case for 'watch', the test case also runs on Ubuntu and macOS, at first, tests passed at my local macOS and Ubuntu, however, they all fail in CI. Finally I found watch in nushell is sensitive on different events at macOS and Ubuntu, and CI machine may be resource constraint, it often misses some events. Then I modify the test case to repeat create/delete after a while. After that, CI test for 'watch' on all platform passed.

@PegasusPlusUS
Copy link
Contributor Author

CI test for windows not very stable, currently these 3 failed:

failures: commands::network::http::get::http_get_with_accept_errors_and_full_raw_response commands::network::http::head::http_head_failed_due_to_server_error commands::network::http::patch::http_patch_failed_due_to_server_error

Checked these tests, they're using stack variable, no global or shared, separately test all OK, do not understand what happened in CI test.

Sometimes other network commands fail, sometimes one or more tests for PWD-per-drive failed at SUBST not succeed etc. Usually at least one test will fail, maybe the CI environment needs upgrade to larger memory? :).

This time these 3 test cases failed in CI:
commands::network::http::get::http_get_with_accept_errors_and_full_raw_response
commands::network::http::get::http_get_with_unknown_mime_type
commands::network::http::patch::http_patch_failed_due_to_server_error
the first is the same, and the other 2 are not the same with last sample. So, it seems there might be interfere between some test cases in resource constraint environment.

@PegasusPlusUS
Copy link
Contributor Author

I see, I might understand why there're randomly testcases that will fail in CI, that might be the test of 'watch' that interfere some other test cases happened to run on other threads at the same time. Let me find and update a solution to test again.

…t interfere other test cases happened to run at the same time.
@PegasusPlusUS
Copy link
Contributor Author

Fixed, previously the powershell script kills watch process (since that process will never exit itself), and it used name to kill process, which will also kill the nu.exe in test cases that runs at other threads that uses nu!() to execute commands.

@132ikl
Copy link
Contributor

132ikl commented Jan 12, 2025

@PegasusPlusUS Is this PR ready for review then? If so I will try to take a look in the next couple of days

@PegasusPlusUS
Copy link
Contributor Author

@PegasusPlusUS Is this PR ready for review then? If so I will try to take a look in the next couple of days

All done for review, half of the time spent on 'watch', :).

@PegasusPlusUS
Copy link
Contributor Author

PegasusPlusUS commented Jan 12, 2025

@PegasusPlusUS Is this PR ready for review then? If so I will try to take a look in the next couple of days

In GitHub review, there’s a touch.rs in nu-command/tests/command/filesystem, it marks the whole file 654 lines new, indeed it was moved from ../, only last test is new added, other part does not need spend time to review.

@NotTheDr01ds
Copy link
Contributor

NotTheDr01ds commented Jan 20, 2025

I'd like to apologize for the lack of feedback over the last week. I definitely appreciate both your contribution, as well as your thorough explanation of the changes, and I'm still working through them myself.

The team has been discussing this PR, and the general agreement is that it creates (at least some) additional maintenance burden for what might not be a common use-case. When future filesystem commands are contributed, it seems likely that it might miss this Windows nuance. It's especially likely that the contributor won't remember to add tests for this feature with the new command.

It seems that even now, some commands may have been overlooked? For example, I could be wrong, but it appears that path expand isn't currently on the list of commands that were updated here. I just tested 'C:' | path expand, and it's always returning C:\, even when there's different PWD on C:.

Side-note: I would recommend holding off on implementing this, though, until we reach a final decision.

Even the Windows users among us haven't commonly utilized per-drive-PWD in PowerShell or CMD in the past. At the same time, we do want Windows users to have a "first class" experience on Nushell, and we're not opposed to adding new OS-specific features when it makes sense.

At the request of the team, I've created a poll in the Discussions area here on GitHub in order to try to understand how commonly used this feature would be.

@PegasusPlusUS
Copy link
Contributor Author

PegasusPlusUS commented Jan 22, 2025

I'd like to apologize for the lack of feedback over the last week. I definitely appreciate both your contribution, as well as your thorough explanation of the changes, and I'm still working through them myself.

The team has been discussing this PR, and the general agreement is that it creates (at least some) additional maintenance burden for what might not be a common use-case. When future filesystem commands are contributed, it seems likely that it might miss this Windows nuance. It's especially likely that the contributor won't remember to add tests for this feature with the new command.

It seems that even now, some commands may have been overlooked? For example, I could be wrong, but it appears that path expand isn't currently on the list of commands that were updated here. I just tested 'C:' | path expand, and it's always returning C:\, even when there's different PWD on C:.

Side-note: I would recommend holding off on implementing this, though, until we reach a final decision.

Even the Windows users among us haven't commonly utilized per-drive-PWD in PowerShell or CMD in the past. At the same time, we do want Windows users to have a "first class" experience on Nushell, and we're not opposed to adding new OS-specific features when it makes sense.

At the request of the team, I've created a poll in the Discussions area here on GitHub in order to try to understand how commonly used this feature would be.

Yes, I just patched commands in filesystem\ subdir, there might be other commands that should be patched to fully support PWD, maybe I'd better to search for the usage of nu_path::expand_path_with() to find all commands that should support PWD. I guess if adding a signature for nu_path::expand_path_with() as deprecated, that might help newly created commands directly support PWD, and chances of missing test case to verify supporting of PWD can also be reduced.

OK, just wait guidance for additional action, :). If PWD-per-drive not used, I'll extract updates for test of 'watch' and some other improvements not directly related to PWD-per-drive to issue other small PRs.

@PegasusPlusUS
Copy link
Contributor Author

I'd like to apologize for the lack of feedback over the last week. I definitely appreciate both your contribution, as well as your thorough explanation of the changes, and I'm still working through them myself.

The team has been discussing this PR, and the general agreement is that it creates (at least some) additional maintenance burden for what might not be a common use-case. When future filesystem commands are contributed, it seems likely that it might miss this Windows nuance. It's especially likely that the contributor won't remember to add tests for this feature with the new command.

It seems that even now, some commands may have been overlooked? For example, I could be wrong, but it appears that path expand isn't currently on the list of commands that were updated here. I just tested 'C:' | path expand, and it's always returning C:\, even when there's different PWD on C:.

Side-note: I would recommend holding off on implementing this, though, until we reach a final decision.

Even the Windows users among us haven't commonly utilized per-drive-PWD in PowerShell or CMD in the past. At the same time, we do want Windows users to have a "first class" experience on Nushell, and we're not opposed to adding new OS-specific features when it makes sense.

At the request of the team, I've created a poll in the Discussions area here on GitHub in order to try to understand how commonly used this feature would be.

Will respect decision, but really can't agree with the conclusion of 'creates additional maintenance burden', if some new commands forget to support PWD-per-drive, (while the possibility is relatively low after nu_path::expand_path_with() marked as deprecated), why not try to improve the new commands, but rather let all commands discard support of PWD-per-drive? If supporting PWD-per-drive is optional not important, then it's okay for the new command not to support it. It wouldn't really count as increasing the maintenance difficulty, would it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants