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

Implement invocation_directory function (fix #312) #323

Merged
merged 6 commits into from
Jun 19, 2018

Conversation

joshuawarner32
Copy link
Contributor

invocation_directory retrieves the current directory that just was invoked from, before the cwd (current working directory) was changed to the location of the justfile.

The name's not perfect, but I'm not one for bikeshedding.

src/function.rs Outdated
if let Some(dir) = context.invocation_directory {
Ok(dir.to_string())
} else {
Err(String::from("error getting invocation directory"))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not super happy with this error message right now. The primary reason for this error would be an inability to decode the utf-8 of the original working directory, but it's not clear. Feedback/thoughts welcome.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that a really explicit error message is good, perhaps "invocation directory path not UTF-8, invocation-directory cannot be used"

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, you can use Option::ok_or_else to turn None into an error.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah - I don't disagree. The only thing that gives me pause is that where the error occurred is pretty far (in code) from where this string is - which makes me think that they could fall out of sync. For example, one day in the future there could be a different reason that invocation_directory can't be used, and it would be easy to forget to update this message.

What do you think about just having invocation_directory be passed along as a Result<String, String>? That way, the error string is constructed close to the error itself.

Alternatively, just could refuse to run when invoked from a non-utf8 path, but that seems rather draconian.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good thinking. Passing invocation_directory as a ` Result<String, String> sounds like a good idea.

Copy link
Owner

@casey casey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much for the PR! I added some comments inline.

We'll need a test for this. It should invoke the just binary with a recipe that prints out invocation_directory(), and then asserts that it prints the correct directory.

Since it needs to call the binary directly, it should be an integration test, so something like tests/invocation_directory.rs. If you look in tests/integration.rs, you'll see how to get the binary and path to the binary and invoke it.

Let me know if you have any questions!

src/function.rs Outdated
if let Some(dir) = context.invocation_directory {
Ok(dir.to_string())
} else {
Err(String::from("error getting invocation directory"))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that a really explicit error message is good, perhaps "invocation directory path not UTF-8, invocation-directory cannot be used"

src/run.rs Outdated
@@ -47,6 +47,11 @@ pub fn run() {
#[cfg(windows)]
enable_ansi_support().ok();

let invocation_directory = match env::current_dir() {
Ok(pathbuf) => pathbuf,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's do pathbuf.to_str().map(str::to_string) and then use Option<String> for the type of the invocation_directory value.

src/function.rs Outdated
if let Some(dir) = context.invocation_directory {
Ok(dir.to_string())
} else {
Err(String::from("error getting invocation directory"))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, you can use Option::ok_or_else to turn None into an error.

@joshuawarner32
Copy link
Contributor Author

Hmm... I'm at a loss with what to do with the windows test. It seems to be a fundamental mismatch between windows paths and cygwin (or msys?) paths. Here are a few options I can think of:

  • Bow to the cygwin gods, and use conditional compilation (or just normal ifs) to conform to the style of paths that sh will expect on that system.
  • Only enable the test for *nix systems, where pathing like this is a little more sane
  • Pick a different shell to run this test under, that's going to deal better with windows paths. Perhaps cmd.exe?

@casey
Copy link
Owner

casey commented Jun 18, 2018

Hmmm, there's a utility called cygpath which just already uses to generate shebang paths on windows. (See src/platform.rs:55.) Could we use it here to translate the windows-style path to the cygwin path that the test will output, when we're running on windows?

justfile_path.push("justfile");
brev::dump(justfile_path, "default:\n @echo {{invocation_directory()}}");

let mut dotenv_path = tmp.path().to_path_buf();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the dotenv stuff can be left out of this test.

@joshuawarner32
Copy link
Contributor Author

Apologies for the CI noise on this PR; I don't have a great place to test on windows so I've been using CI.

I pivoted to providing the cygwin "unix" path on windows (rather than the native C:\... style path), which makes the tests pass and generally will make sh happier I think.

I think there's an argument to be made to expand invocation_directory() into the native path, or perhaps an escaped native path (i.e. C:\\..., doubling all the backslashes - which would also have made the tests pass in this case). In the future, that could be specified as e.g. invocation_directory("native") or invocation_directory("escaped"). However, I think that's out of scope for this PR, and definitely worth getting feedback from people who use just on Windows before heading that direction.

Anyway, do you have further thoughts/comments @casey?

@casey casey merged commit 50fb1b3 into casey:master Jun 19, 2018
@casey
Copy link
Owner

casey commented Jun 19, 2018

That seems like the right thing to do, on windows recipes expect to be run in cygwin, so the unix path will be more immediately usable. I added the cd back into the test, as an extra test that the directory is in fact usable within recipes.

Nice work, and thanks for tackling what turned out to be much trickery issue than it first appeared!

@casey
Copy link
Owner

casey commented Jun 19, 2018

Just published the new release to crates.io; binaries will be available here once Travis and AppVeyor finish building them: https://github.com/casey/just/releases/tag/v0.3.12

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.

2 participants