Compare commits

..

No commits in common. "b81d106c918a9bc7fda453928c6999b93b317040" and "8186992340152bb9b8936d3943b5f35677271d06" have entirely different histories.

31 changed files with 224 additions and 611 deletions

View File

@ -1,56 +1,6 @@
Changelog Changelog
========= =========
[1.30.1](https://github.com/casey/just/releases/tag/1.30.1) - 2024-07-06
------------------------------------------------------------------------
### Fixed
- Fix function argument count mismatch error message ([#2231](https://github.com/casey/just/pull/2231) by [casey](https://github.com/casey))
[1.30.0](https://github.com/casey/just/releases/tag/1.30.0) - 2024-07-06
------------------------------------------------------------------------
### Fixed
- Allow comments after `mod` statements ([#2201](https://github.com/casey/just/pull/2201) by [casey](https://github.com/casey))
### Changed
- Allow unstable features with `--summary` ([#2210](https://github.com/casey/just/pull/2210) by [casey](https://github.com/casey))
- Don't analyze comments when `ignore-comments` is set ([#2180](https://github.com/casey/just/pull/2180) by [casey](https://github.com/casey))
- List recipes by group in group justfile order with `just --list --unsorted` ([#2164](https://github.com/casey/just/pull/2164) by [casey](https://github.com/casey))
- List groups in source order with `just --groups --unsorted` ([#2160](https://github.com/casey/just/pull/2160) by [casey](https://github.com/casey))
### Added
- Avoid `install` and add 32-bit arm targets to `install.sh` ([#2214](https://github.com/casey/just/pull/2214) by [CramBL](https://github.com/CramBL))
- Give modules doc comments for `--list` ([#2199](https://github.com/casey/just/pull/2199) by [Spatenheinz](https://github.com/Spatenheinz))
- Add `datetime()` and `datetime_utc()` functions ([#2167](https://github.com/casey/just/pull/2167) by [casey](https://github.com/casey))
- Allow setting more command-line options with environment variables ([#2161](https://github.com/casey/just/pull/2161) by [casey](https://github.com/casey))
### Library
- Don't exit process in `run()` on argument parse error ([#2176](https://github.com/casey/just/pull/2176) by [casey](https://github.com/casey))
- Allow passing command-line arguments into `run()` ([#2173](https://github.com/casey/just/pull/2173) by [casey](https://github.com/casey))
- Ignore env_logger initialization errors ([#2170](https://github.com/casey/just/pull/2170) by [EnigmaCurry](https://github.com/EnigmaCurry))
### Misc
- Tweak readme ([#2227](https://github.com/casey/just/pull/2227) by [casey](https://github.com/casey))
- Add development guide to readme ([#2226](https://github.com/casey/just/pull/2226) by [casey](https://github.com/casey))
- Add shell-expanded string syntax to grammar ([#2223](https://github.com/casey/just/pull/2223) by [casey](https://github.com/casey))
- Add recipe for testing bash completion script ([#2221](https://github.com/casey/just/pull/2221) by [casey](https://github.com/casey))
- Fix use of `justfile_directory()` in readme ([#2219](https://github.com/casey/just/pull/2219) by [casey](https://github.com/casey))
- Use default values for `--list-heading` and `--list-prefix` ([#2213](https://github.com/casey/just/pull/2213) by [casey](https://github.com/casey))
- Use `clap::ValueParser` ([#2211](https://github.com/casey/just/pull/2211) by [neunenak](https://github.com/neunenak))
- Document module doc comments in readme ([#2208](https://github.com/casey/just/pull/2208) by [casey](https://github.com/casey))
- Use `-and` instead of `&&` in PowerShell completion script ([#2204](https://github.com/casey/just/pull/2204) by [casey](https://github.com/casey))
- Fix readme formatting ([#2203](https://github.com/casey/just/pull/2203) by [casey](https://github.com/casey))
- Link to justfiles on GitHub in readme ([#2198](https://github.com/casey/just/pull/2198) by [bukowa](https://github.com/bukowa))
- Link to modules when first introduced in readme ([#2193](https://github.com/casey/just/pull/2193) by [casey](https://github.com/casey))
- Update `softprops/action-gh-release` ([#2183](https://github.com/casey/just/pull/2183) by [app/dependabot](https://github.com/app/dependabot))
- Document remote justfile workaround ([#2175](https://github.com/casey/just/pull/2175) by [casey](https://github.com/casey))
- Document library interface ([#2174](https://github.com/casey/just/pull/2174) by [casey](https://github.com/casey))
- Remove dependency on cradle ([#2169](https://github.com/casey/just/pull/2169) by [nc7s](https://github.com/nc7s))
- Add note to readme about quoting paths on Windows ([#2166](https://github.com/casey/just/pull/2166) by [casey](https://github.com/casey))
- Add missing changelog credits ([#2163](https://github.com/casey/just/pull/2163) by [casey](https://github.com/casey))
- Credit myself in changelog ([#2162](https://github.com/casey/just/pull/2162) by [casey](https://github.com/casey))
[1.29.1](https://github.com/casey/just/releases/tag/1.29.1) - 2024-06-14 [1.29.1](https://github.com/casey/just/releases/tag/1.29.1) - 2024-06-14
------------------------------------------------------------------------ ------------------------------------------------------------------------

158
Cargo.lock generated
View File

@ -121,9 +121,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.6.0" version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]] [[package]]
name = "blake3" name = "blake3"
@ -174,9 +174,9 @@ checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.104" version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74b6a57f98764a267ff415d50a25e6e166f3831a5071af4995296ea97d210490" checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
@ -201,7 +201,7 @@ dependencies = [
"js-sys", "js-sys",
"num-traits", "num-traits",
"wasm-bindgen", "wasm-bindgen",
"windows-targets 0.52.6", "windows-targets 0.52.5",
] ]
[[package]] [[package]]
@ -221,9 +221,9 @@ dependencies = [
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.5.8" version = "4.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84b3edb18336f4df585bc9aa31dd99c036dfa5dc5e9a2939a722a188f3a8970d" checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
"clap_derive", "clap_derive",
@ -231,9 +231,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_builder" name = "clap_builder"
version = "4.5.8" version = "4.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1c09dd5ada6c6c78075d6fd0da3f90d8080651e2d6cc8eb2f1aaa4034ced708" checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f"
dependencies = [ dependencies = [
"anstream", "anstream",
"anstyle", "anstyle",
@ -244,23 +244,23 @@ dependencies = [
[[package]] [[package]]
name = "clap_complete" name = "clap_complete"
version = "4.5.7" version = "4.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d598e88f6874d4b888ed40c71efbcbf4076f1dfbae128a08a8c9e45f710605d" checksum = "d2020fa13af48afc65a9a87335bda648309ab3d154cd03c7ff95b378c7ed39c4"
dependencies = [ dependencies = [
"clap 4.5.8", "clap 4.5.7",
] ]
[[package]] [[package]]
name = "clap_derive" name = "clap_derive"
version = "4.5.8" version = "4.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085" checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6"
dependencies = [ dependencies = [
"heck 0.5.0", "heck 0.5.0",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.69", "syn 2.0.66",
] ]
[[package]] [[package]]
@ -271,11 +271,11 @@ checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70"
[[package]] [[package]]
name = "clap_mangen" name = "clap_mangen"
version = "0.2.22" version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f50dde5bc0c853d6248de457e5eb6e5a674a54b93810a34ded88d882ca1fe2de" checksum = "74b70fc13e60c0e1d490dc50eb73a749be6d81f4ef03783df1d9b7b0c62bc937"
dependencies = [ dependencies = [
"clap 4.5.8", "clap 4.5.7",
"roff", "roff",
] ]
@ -407,15 +407,15 @@ checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
[[package]] [[package]]
name = "edit-distance" name = "edit-distance"
version = "2.1.2" version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "853fc7035888bd1c9320f3a05bfe7f344f49b8766a4bb4209b1ac5f0503d9577" checksum = "bbbaaaf38131deb9ca518a274a45bfdb8771f139517b073b16c2d3d32ae5037b"
[[package]] [[package]]
name = "either" name = "either"
version = "1.13.0" version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b"
[[package]] [[package]]
name = "env_filter" name = "env_filter"
@ -591,13 +591,13 @@ dependencies = [
[[package]] [[package]]
name = "just" name = "just"
version = "1.30.1" version = "1.29.1"
dependencies = [ dependencies = [
"ansi_term", "ansi_term",
"blake3", "blake3",
"camino", "camino",
"chrono", "chrono",
"clap 4.5.8", "clap 4.5.7",
"clap_complete", "clap_complete",
"clap_mangen", "clap_mangen",
"ctrlc", "ctrlc",
@ -635,9 +635,9 @@ dependencies = [
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.5.0" version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "lexiclean" name = "lexiclean"
@ -657,7 +657,7 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
dependencies = [ dependencies = [
"bitflags 2.6.0", "bitflags 2.5.0",
"libc", "libc",
] ]
@ -669,9 +669,9 @@ checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.22" version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]] [[package]]
name = "memchr" name = "memchr"
@ -694,7 +694,7 @@ version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
dependencies = [ dependencies = [
"bitflags 2.6.0", "bitflags 2.5.0",
"cfg-if", "cfg-if",
"cfg_aliases", "cfg_aliases",
"libc", "libc",
@ -779,9 +779,9 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.86" version = "1.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@ -792,7 +792,7 @@ version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b"
dependencies = [ dependencies = [
"bitflags 2.6.0", "bitflags 2.5.0",
"getopts", "getopts",
"memchr", "memchr",
"unicase", "unicase",
@ -933,7 +933,7 @@ version = "0.38.34"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
dependencies = [ dependencies = [
"bitflags 2.6.0", "bitflags 2.5.0",
"errno", "errno",
"libc", "libc",
"linux-raw-sys", "linux-raw-sys",
@ -960,29 +960,29 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.204" version = "1.0.203"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.204" version = "1.0.203"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.69", "syn 2.0.66",
] ]
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.120" version = "1.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@ -1037,7 +1037,7 @@ dependencies = [
"heck 0.5.0", "heck 0.5.0",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.69", "syn 2.0.66",
] ]
[[package]] [[package]]
@ -1078,9 +1078,9 @@ dependencies = [
[[package]] [[package]]
name = "strum" name = "strum"
version = "0.26.3" version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29"
dependencies = [ dependencies = [
"strum_macros", "strum_macros",
] ]
@ -1095,7 +1095,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"rustversion", "rustversion",
"syn 2.0.69", "syn 2.0.66",
] ]
[[package]] [[package]]
@ -1111,9 +1111,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.69" version = "2.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201fcda3845c23e8212cd466bfebf0bd20694490fc0356ae8e428e0824a915a6" checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1183,7 +1183,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.69", "syn 2.0.66",
] ]
[[package]] [[package]]
@ -1240,9 +1240,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]] [[package]]
name = "uuid" name = "uuid"
version = "1.9.1" version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439" checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0"
dependencies = [ dependencies = [
"getrandom", "getrandom",
] ]
@ -1286,7 +1286,7 @@ dependencies = [
"once_cell", "once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.69", "syn 2.0.66",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -1308,7 +1308,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.69", "syn 2.0.66",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@ -1359,7 +1359,7 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [ dependencies = [
"windows-targets 0.52.6", "windows-targets 0.52.5",
] ]
[[package]] [[package]]
@ -1377,7 +1377,7 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [ dependencies = [
"windows-targets 0.52.6", "windows-targets 0.52.5",
] ]
[[package]] [[package]]
@ -1397,18 +1397,18 @@ dependencies = [
[[package]] [[package]]
name = "windows-targets" name = "windows-targets"
version = "0.52.6" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
dependencies = [ dependencies = [
"windows_aarch64_gnullvm 0.52.6", "windows_aarch64_gnullvm 0.52.5",
"windows_aarch64_msvc 0.52.6", "windows_aarch64_msvc 0.52.5",
"windows_i686_gnu 0.52.6", "windows_i686_gnu 0.52.5",
"windows_i686_gnullvm", "windows_i686_gnullvm",
"windows_i686_msvc 0.52.6", "windows_i686_msvc 0.52.5",
"windows_x86_64_gnu 0.52.6", "windows_x86_64_gnu 0.52.5",
"windows_x86_64_gnullvm 0.52.6", "windows_x86_64_gnullvm 0.52.5",
"windows_x86_64_msvc 0.52.6", "windows_x86_64_msvc 0.52.5",
] ]
[[package]] [[package]]
@ -1419,9 +1419,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]] [[package]]
name = "windows_aarch64_gnullvm" name = "windows_aarch64_gnullvm"
version = "0.52.6" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
@ -1431,9 +1431,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.52.6" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
@ -1443,15 +1443,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.52.6" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
[[package]] [[package]]
name = "windows_i686_gnullvm" name = "windows_i686_gnullvm"
version = "0.52.6" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
@ -1461,9 +1461,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.52.6" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
@ -1473,9 +1473,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.52.6" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
@ -1485,9 +1485,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.52.6" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
@ -1497,9 +1497,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.52.6" version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
[[package]] [[package]]
name = "winsafe" name = "winsafe"

View File

@ -1,6 +1,6 @@
[package] [package]
name = "just" name = "just"
version = "1.30.1" version = "1.29.1"
authors = ["Casey Rodarmor <casey@rodarmor.com>"] authors = ["Casey Rodarmor <casey@rodarmor.com>"]
autotests = false autotests = false
categories = ["command-line-utilities", "development-tools"] categories = ["command-line-utilities", "development-tools"]

View File

@ -379,11 +379,11 @@ There will never be a `just` 2.0. Any desirable backwards-incompatible changes
will be opt-in on a per-`justfile` basis, so users may migrate at their will be opt-in on a per-`justfile` basis, so users may migrate at their
leisure. leisure.
Features that aren't yet ready for stabilization are marked as unstable and may Features that aren't yet ready for stabilization are gated behind the
be changed or removed at any time. Using unstable features produces an error by `--unstable` flag. Features enabled by `--unstable` may change in backwards
default, which can be suppressed with by passing the `--unstable` flag, incompatible ways at any time. Unstable features can also be enabled by setting
`set unstable`, or setting the environment variable `JUST_UNSTABLE`, to any the environment variable `JUST_UNSTABLE` to any value other than `false`, `0`,
value other than `false`, `0`, or the empty string. or the empty string.
Editor Support Editor Support
-------------- --------------
@ -820,7 +820,6 @@ foo:
| `positional-arguments` | boolean | `false` | Pass positional arguments. | | `positional-arguments` | boolean | `false` | Pass positional arguments. |
| `shell` | `[COMMAND, ARGS…]` | - | Set the command used to invoke recipes and evaluate backticks. | | `shell` | `[COMMAND, ARGS…]` | - | Set the command used to invoke recipes and evaluate backticks. |
| `tempdir` | string | - | Create temporary directories in `tempdir` instead of the system default temporary directory. | | `tempdir` | string | - | Create temporary directories in `tempdir` instead of the system default temporary directory. |
| `unstable`<sup>master</sup> | boolean | `false` | Enable unstable features. |
| `windows-powershell` | boolean | `false` | Use PowerShell on Windows as default shell. (Deprecated. Use `windows-shell` instead. | | `windows-powershell` | boolean | `false` | Use PowerShell on Windows as default shell. (Deprecated. Use `windows-shell` instead. |
| `windows-shell` | `[COMMAND, ARGS…]` | - | Set the command used to invoke recipes and evaluate backticks. | | `windows-shell` | `[COMMAND, ARGS…]` | - | Set the command used to invoke recipes and evaluate backticks. |
@ -1350,11 +1349,6 @@ Done!
`just` provides a few built-in functions that might be useful when writing `just` provides a few built-in functions that might be useful when writing
recipes. recipes.
All functions ending in `_directory` can be abbreviated to `_dir`. So
`home_directory()` can also be written as `home_dir()`. In addition,
`invocation_directory_native()` can be abbreviated to
`invocation_dir_native()`.
#### System Information #### System Information
- `arch()` — Instruction set architecture. Possible values are: `"aarch64"`, - `arch()` — Instruction set architecture. Possible values are: `"aarch64"`,
@ -1651,8 +1645,8 @@ which will halt execution.
#### Datetime #### Datetime
- `datetime(format)`<sup>1.30.0</sup> - Return local time with `format`. - `datetime(format)`<sup>master</sup> - Return local time with `format`.
- `datetime_utc(format)`<sup>1.30.0</sup> - Return UTC time with `format`. - `datetime_utc(format)`<sup>master</sup> - Return UTC time with `format`.
The arguments to `datetime` and `datetime_utc` are `strftime`-style format The arguments to `datetime` and `datetime_utc` are `strftime`-style format
strings, see the strings, see the
@ -3155,8 +3149,8 @@ Missing source files for optional imports do not produce an error.
### Modules<sup>1.19.0</sup> ### Modules<sup>1.19.0</sup>
A `justfile` can declare modules using `mod` statements. `mod` statements are A `justfile` can declare modules using `mod` statements. `mod` statements are
currently unstable, so you'll need to use the `--unstable` flag, currently unstable, so you'll need to use the `--unstable` flag, or set the
`set unstable`, or set the `JUST_UNSTABLE` environment variable to use them. `JUST_UNSTABLE` environment variable to use them.
If you have the following `justfile`: If you have the following `justfile`:
@ -3204,10 +3198,7 @@ mod foo 'PATH'
Which loads the module's source file from `PATH`, instead of from the usual Which loads the module's source file from `PATH`, instead of from the usual
locations. A leading `~/` in `PATH` is replaced with the current user's home locations. A leading `~/` in `PATH` is replaced with the current user's home
directory. `PATH` may point to the module source file itself, or to a directory directory.
containing the module source file with the name `mod.just`, `justfile`, or
`.justfile`. In the latter two cases, the module file may have any
capitalization.
Environment files are only loaded for the root justfile, and loaded environment Environment files are only loaded for the root justfile, and loaded environment
variables are available in submodules. Settings in submodules that affect variables are available in submodules. Settings in submodules that affect
@ -3238,7 +3229,7 @@ mod? foo 'baz.just'
``` ```
Modules may be given doc comments which appear in `--list` Modules may be given doc comments which appear in `--list`
output<sup>1.30.0</sup>: output<sup>master</sup>:
```mf ```mf
# foo is a great module! # foo is a great module!
@ -3760,9 +3751,9 @@ binary from the outside by invoking `just` on a given `justfile` and set of
command-line arguments, and checking the output. command-line arguments, and checking the output.
You should write whichever type of tests are easiest to write for your feature You should write whichever type of tests are easiest to write for your feature
while still providing good test coverage. while still providing test good coverage.
Unit tests are useful for testing new Rust functions that are used internally Unit tests are useful for testing new Rust functions that are used internally,
and as an aid for development. A good example are the unit tests which cover and as an aid for development. A good example are the unit tests which cover
the the
[`unindent()` function](https://github.com/casey/just/blob/master/src/unindent.rs), [`unindent()` function](https://github.com/casey/just/blob/master/src/unindent.rs),
@ -3774,7 +3765,7 @@ Integration tests are useful for making sure that the final behavior of the
`just` binary is correct. `unindent()` is also covered by integration tests `just` binary is correct. `unindent()` is also covered by integration tests
which make sure that evaluating a triple-quoted string produces the correct which make sure that evaluating a triple-quoted string produces the correct
unindented value. However, there are not integration tests for all possible unindented value. However, there are not integration tests for all possible
cases. These are covered by faster, more concise unit tests that call cases, since these are covered by faster, more concise unit tests that call
`unindent()` directly. `unindent()` directly.
Existing integration tests are in two forms, those that use the `test!` macro Existing integration tests are in two forms, those that use the `test!` macro
@ -3826,7 +3817,8 @@ checking the program's stdout, stderr, and exit code .
9. Enjoy the sweet feeling of your PR getting merged! 9. Enjoy the sweet feeling of your PR getting merged!
Feel free to open a draft PR at any time for discussion and feedback. Feel free at any time to open a draft PR with your changes for discussion and
feedback.
### Hints ### Hints

View File

@ -37,8 +37,6 @@ impl<'src> Analyzer<'src> {
let mut warnings = Vec::new(); let mut warnings = Vec::new();
let mut unstable = BTreeSet::new();
let mut modules: Table<Justfile> = Table::new(); let mut modules: Table<Justfile> = Table::new();
let mut unexports: HashSet<String> = HashSet::new(); let mut unexports: HashSet<String> = HashSet::new();
@ -94,8 +92,6 @@ impl<'src> Analyzer<'src> {
doc, doc,
.. ..
} => { } => {
unstable.insert(Unstable::Modules);
if let Some(absolute) = absolute { if let Some(absolute) = absolute {
define(*name, "module", false)?; define(*name, "module", false)?;
modules.insert(Self::analyze( modules.insert(Self::analyze(
@ -198,7 +194,6 @@ impl<'src> Analyzer<'src> {
settings, settings,
source: root.into(), source: root.into(),
unexports, unexports,
unstable,
warnings, warnings,
}) })
} }

View File

@ -252,7 +252,7 @@ mod tests {
fs::write(&path, "mod foo").unwrap(); fs::write(&path, "mod foo").unwrap();
fs::create_dir(tempdir.path().join("foo")).unwrap(); fs::create_dir(tempdir.path().join("foo")).unwrap();
fs::write(tempdir.path().join("foo/mod.just"), "bar:").unwrap(); fs::write(tempdir.path().join("foo/mod.just"), "bar:").unwrap();
let compilation = Compiler::compile(&loader, &path).unwrap(); let compilation = Compiler::compile(true, &loader, &path).unwrap();
assert_eq!( assert_eq!(
ArgumentParser::parse_arguments(&compilation.justfile, &["foo", "bar"]).unwrap(), ArgumentParser::parse_arguments(&compilation.justfile, &["foo", "bar"]).unwrap(),
@ -271,7 +271,7 @@ mod tests {
fs::write(&path, "mod foo").unwrap(); fs::write(&path, "mod foo").unwrap();
fs::create_dir(tempdir.path().join("foo")).unwrap(); fs::create_dir(tempdir.path().join("foo")).unwrap();
fs::write(tempdir.path().join("foo/mod.just"), "bar:").unwrap(); fs::write(tempdir.path().join("foo/mod.just"), "bar:").unwrap();
let compilation = Compiler::compile(&loader, &path).unwrap(); let compilation = Compiler::compile(true, &loader, &path).unwrap();
assert_matches!( assert_matches!(
ArgumentParser::parse_arguments(&compilation.justfile, &["foo", "zzz"]).unwrap_err(), ArgumentParser::parse_arguments(&compilation.justfile, &["foo", "zzz"]).unwrap_err(),
@ -289,7 +289,7 @@ mod tests {
tempdir.write("foo.just", "bar:"); tempdir.write("foo.just", "bar:");
let loader = Loader::new(); let loader = Loader::new();
let compilation = Compiler::compile(&loader, &tempdir.path().join("justfile")).unwrap(); let compilation = Compiler::compile(true, &loader, &tempdir.path().join("justfile")).unwrap();
assert_matches!( assert_matches!(
ArgumentParser::parse_arguments(&compilation.justfile, &["foo::zzz"]).unwrap_err(), ArgumentParser::parse_arguments(&compilation.justfile, &["foo::zzz"]).unwrap_err(),
@ -307,7 +307,7 @@ mod tests {
tempdir.write("foo.just", "bar:"); tempdir.write("foo.just", "bar:");
let loader = Loader::new(); let loader = Loader::new();
let compilation = Compiler::compile(&loader, &tempdir.path().join("justfile")).unwrap(); let compilation = Compiler::compile(true, &loader, &tempdir.path().join("justfile")).unwrap();
assert_matches!( assert_matches!(
ArgumentParser::parse_arguments(&compilation.justfile, &["foo::bar::baz"]).unwrap_err(), ArgumentParser::parse_arguments(&compilation.justfile, &["foo::bar::baz"]).unwrap_err(),
@ -323,7 +323,7 @@ mod tests {
tempdir.write("justfile", ""); tempdir.write("justfile", "");
let loader = Loader::new(); let loader = Loader::new();
let compilation = Compiler::compile(&loader, &tempdir.path().join("justfile")).unwrap(); let compilation = Compiler::compile(true, &loader, &tempdir.path().join("justfile")).unwrap();
assert_matches!( assert_matches!(
ArgumentParser::parse_arguments(&compilation.justfile, &[]).unwrap_err(), ArgumentParser::parse_arguments(&compilation.justfile, &[]).unwrap_err(),
@ -337,7 +337,7 @@ mod tests {
tempdir.write("justfile", "foo bar:"); tempdir.write("justfile", "foo bar:");
let loader = Loader::new(); let loader = Loader::new();
let compilation = Compiler::compile(&loader, &tempdir.path().join("justfile")).unwrap(); let compilation = Compiler::compile(true, &loader, &tempdir.path().join("justfile")).unwrap();
assert_matches!( assert_matches!(
ArgumentParser::parse_arguments(&compilation.justfile, &[]).unwrap_err(), ArgumentParser::parse_arguments(&compilation.justfile, &[]).unwrap_err(),
@ -355,7 +355,7 @@ mod tests {
tempdir.write("foo.just", "bar:"); tempdir.write("foo.just", "bar:");
let loader = Loader::new(); let loader = Loader::new();
let compilation = Compiler::compile(&loader, &tempdir.path().join("justfile")).unwrap(); let compilation = Compiler::compile(true, &loader, &tempdir.path().join("justfile")).unwrap();
assert_matches!( assert_matches!(
ArgumentParser::parse_arguments(&compilation.justfile, &[]).unwrap_err(), ArgumentParser::parse_arguments(&compilation.justfile, &[]).unwrap_err(),

View File

@ -66,7 +66,7 @@ pub(crate) enum CompileErrorKind<'src> {
FunctionArgumentCountMismatch { FunctionArgumentCountMismatch {
function: &'src str, function: &'src str,
found: usize, found: usize,
expected: RangeInclusive<usize>, expected: Range<usize>,
}, },
Include, Include,
InconsistentLeadingWhitespace { InconsistentLeadingWhitespace {

View File

@ -4,13 +4,14 @@ pub(crate) struct Compiler;
impl Compiler { impl Compiler {
pub(crate) fn compile<'src>( pub(crate) fn compile<'src>(
unstable: bool,
loader: &'src Loader, loader: &'src Loader,
root: &Path, root: &Path,
) -> RunResult<'src, Compilation<'src>> { ) -> RunResult<'src, Compilation<'src>> {
let mut asts = HashMap::<PathBuf, Ast>::new(); let mut asts = HashMap::<PathBuf, Ast>::new();
let mut loaded = Vec::new();
let mut paths = HashMap::<PathBuf, PathBuf>::new(); let mut paths = HashMap::<PathBuf, PathBuf>::new();
let mut srcs = HashMap::<PathBuf, &str>::new(); let mut srcs = HashMap::<PathBuf, &str>::new();
let mut loaded = Vec::new();
let mut stack = Vec::new(); let mut stack = Vec::new();
stack.push(Source::root(root)); stack.push(Source::root(root));
@ -41,14 +42,25 @@ impl Compiler {
relative, relative,
.. ..
} => { } => {
if !unstable {
return Err(Error::Unstable {
message: "Modules are currently unstable.".into(),
});
}
let parent = current.path.parent().unwrap(); let parent = current.path.parent().unwrap();
let relative = relative let import = if let Some(relative) = relative {
.as_ref() let path = parent.join(Self::expand_tilde(&relative.cooked)?);
.map(|relative| Self::expand_tilde(&relative.cooked))
.transpose()?;
let import = Self::find_module_file(parent, *name, relative.as_deref())?; if path.is_file() {
Some(path)
} else {
None
}
} else {
Self::find_module_file(parent, *name)?
};
if let Some(import) = import { if let Some(import) = import {
if current.file_path.contains(&import) { if current.file_path.contains(&import) {
@ -100,69 +112,25 @@ impl Compiler {
Ok(Compilation { Ok(Compilation {
asts, asts,
srcs,
justfile, justfile,
root: root.into(), root: root.into(),
srcs,
}) })
} }
fn find_module_file<'src>( fn find_module_file<'src>(parent: &Path, module: Name<'src>) -> RunResult<'src, Option<PathBuf>> {
parent: &Path, let mut candidates = vec![format!("{module}.just"), format!("{module}/mod.just")]
module: Name<'src>, .into_iter()
path: Option<&Path>, .filter(|path| parent.join(path).is_file())
) -> RunResult<'src, Option<PathBuf>> { .collect::<Vec<String>>();
let mut candidates = Vec::new();
if let Some(path) = path { let directory = parent.join(module.lexeme());
let full = parent.join(path);
if full.is_file() { if directory.exists() {
return Ok(Some(full)); let entries = fs::read_dir(&directory).map_err(|io_error| SearchError::Io {
}
candidates.push((path.join("mod.just"), true));
for name in search::JUSTFILE_NAMES {
candidates.push((path.join(name), false));
}
} else {
candidates.push((format!("{module}.just").into(), true));
candidates.push((format!("{module}/mod.just").into(), true));
for name in search::JUSTFILE_NAMES {
candidates.push((format!("{module}/{name}").into(), false));
}
}
let mut grouped = BTreeMap::<PathBuf, Vec<(PathBuf, bool)>>::new();
for (candidate, case_sensitive) in candidates {
let candidate = parent.join(candidate).lexiclean();
grouped
.entry(candidate.parent().unwrap().into())
.or_default()
.push((candidate, case_sensitive));
}
let mut found = Vec::new();
for (directory, candidates) in grouped {
let entries = match fs::read_dir(&directory) {
Ok(entries) => entries,
Err(io_error) => {
if io_error.kind() == io::ErrorKind::NotFound {
continue;
}
return Err(
SearchError::Io {
io_error, io_error,
directory, directory: directory.clone(),
} })?;
.into(),
);
}
};
for entry in entries { for entry in entries {
let entry = entry.map_err(|io_error| SearchError::Io { let entry = entry.map_err(|io_error| SearchError::Io {
@ -171,34 +139,22 @@ impl Compiler {
})?; })?;
if let Some(name) = entry.file_name().to_str() { if let Some(name) = entry.file_name().to_str() {
for (candidate, case_sensitive) in &candidates { for justfile_name in search::JUSTFILE_NAMES {
let candidate_name = candidate.file_name().unwrap().to_str().unwrap(); if name.eq_ignore_ascii_case(justfile_name) {
candidates.push(format!("{module}/{name}"));
let eq = if *case_sensitive {
name == candidate_name
} else {
name.eq_ignore_ascii_case(candidate_name)
};
if eq {
found.push(candidate.parent().unwrap().join(name));
} }
} }
} }
} }
} }
if found.len() > 1 { match candidates.as_slice() {
found.sort(); [] => Ok(None),
Err(Error::AmbiguousModuleFile { [file] => Ok(Some(parent.join(file).lexiclean())),
found: found found => Err(Error::AmbiguousModuleFile {
.into_iter() found: found.into(),
.map(|found| found.strip_prefix(parent).unwrap().into())
.collect(),
module, module,
}) }),
} else {
Ok(found.into_iter().next())
} }
} }
@ -269,7 +225,7 @@ recipe_b: recipe_c
let loader = Loader::new(); let loader = Loader::new();
let justfile_a_path = tmp.path().join("justfile"); let justfile_a_path = tmp.path().join("justfile");
let compilation = Compiler::compile(&loader, &justfile_a_path).unwrap(); let compilation = Compiler::compile(false, &loader, &justfile_a_path).unwrap();
assert_eq!(compilation.root_src(), justfile_a); assert_eq!(compilation.root_src(), justfile_a);
} }
@ -286,91 +242,11 @@ recipe_b: recipe_c
let loader = Loader::new(); let loader = Loader::new();
let justfile_a_path = tmp.path().join("justfile"); let justfile_a_path = tmp.path().join("justfile");
let loader_output = Compiler::compile(&loader, &justfile_a_path).unwrap_err(); let loader_output = Compiler::compile(false, &loader, &justfile_a_path).unwrap_err();
assert_matches!(loader_output, Error::CircularImport { current, import } assert_matches!(loader_output, Error::CircularImport { current, import }
if current == tmp.path().join("subdir").join("b").lexiclean() && if current == tmp.path().join("subdir").join("b").lexiclean() &&
import == tmp.path().join("justfile").lexiclean() import == tmp.path().join("justfile").lexiclean()
); );
} }
#[test]
fn find_module_file() {
#[track_caller]
fn case(path: Option<&str>, files: &[&str], expected: Result<Option<&str>, &[&str]>) {
let module = Name {
token: Token {
column: 0,
kind: TokenKind::Identifier,
length: 3,
line: 0,
offset: 0,
path: Path::new(""),
src: "foo",
},
};
let tempdir = tempfile::tempdir().unwrap();
for file in files {
if let Some(parent) = Path::new(file).parent() {
fs::create_dir_all(tempdir.path().join(parent)).unwrap();
}
fs::write(tempdir.path().join(file), "").unwrap();
}
let actual = Compiler::find_module_file(tempdir.path(), module, path.map(Path::new));
match expected {
Err(expected) => match actual.unwrap_err() {
Error::AmbiguousModuleFile { found, .. } => {
assert_eq!(
found,
expected
.iter()
.map(|expected| expected.replace('/', std::path::MAIN_SEPARATOR_STR).into())
.collect::<Vec<PathBuf>>()
);
}
_ => panic!("unexpected error"),
},
Ok(Some(expected)) => assert_eq!(
actual.unwrap().unwrap(),
tempdir
.path()
.join(expected.replace('/', std::path::MAIN_SEPARATOR_STR))
),
Ok(None) => assert_eq!(actual.unwrap(), None),
}
}
case(None, &["foo.just"], Ok(Some("foo.just")));
case(None, &["FOO.just"], Ok(None));
case(None, &["foo/mod.just"], Ok(Some("foo/mod.just")));
case(None, &["foo/MOD.just"], Ok(None));
case(None, &["foo/justfile"], Ok(Some("foo/justfile")));
case(None, &["foo/JUSTFILE"], Ok(Some("foo/JUSTFILE")));
case(None, &["foo/.justfile"], Ok(Some("foo/.justfile")));
case(None, &["foo/.JUSTFILE"], Ok(Some("foo/.JUSTFILE")));
case(
None,
&["foo/.justfile", "foo/justfile"],
Err(&["foo/.justfile", "foo/justfile"]),
);
case(None, &["foo/JUSTFILE"], Ok(Some("foo/JUSTFILE")));
case(Some("bar"), &["bar"], Ok(Some("bar")));
case(Some("bar"), &["bar/mod.just"], Ok(Some("bar/mod.just")));
case(Some("bar"), &["bar/justfile"], Ok(Some("bar/justfile")));
case(Some("bar"), &["bar/JUSTFILE"], Ok(Some("bar/JUSTFILE")));
case(Some("bar"), &["bar/.justfile"], Ok(Some("bar/.justfile")));
case(Some("bar"), &["bar/.JUSTFILE"], Ok(Some("bar/.JUSTFILE")));
case(
Some("bar"),
&["bar/justfile", "bar/mod.just"],
Err(&["bar/justfile", "bar/mod.just"]),
);
}
} }

View File

@ -4,7 +4,7 @@ use super::*;
pub(crate) enum Error<'src> { pub(crate) enum Error<'src> {
AmbiguousModuleFile { AmbiguousModuleFile {
module: Name<'src>, module: Name<'src>,
found: Vec<PathBuf>, found: Vec<String>,
}, },
ArgumentCountMismatch { ArgumentCountMismatch {
recipe: &'src str, recipe: &'src str,
@ -262,7 +262,7 @@ impl<'src> ColorDisplay for Error<'src> {
AmbiguousModuleFile { module, found } => AmbiguousModuleFile { module, found } =>
write!(f, write!(f,
"Found multiple source files for module `{module}`: {}", "Found multiple source files for module `{module}`: {}",
List::and_ticked(found.iter().map(|path| path.display())), List::and_ticked(found),
)?, )?,
ArgumentCountMismatch { recipe, found, min, max, .. } => { ArgumentCountMismatch { recipe, found, min, max, .. } => {
let count = Count("argument", *found); let count = Count("argument", *found);
@ -460,7 +460,7 @@ impl<'src> ColorDisplay for Error<'src> {
} }
} }
Unstable { message } => { Unstable { message } => {
write!(f, "{message} Invoke `just` with `--unstable`, set the `JUST_UNSTABLE` environment variable, or add `set unstable` to your `justfile` to enable unstable features.")?; write!(f, "{message} Invoke `just` with the `--unstable` flag to enable unstable features.")?;
} }
WriteJustfile { justfile, io_error } => { WriteJustfile { justfile, io_error } => {
let justfile = justfile.display(); let justfile = justfile.display();

View File

@ -32,15 +32,7 @@ impl<'src: 'run, 'run> Context<'src, 'run> {
} }
pub(crate) fn get(name: &str) -> Option<Function> { pub(crate) fn get(name: &str) -> Option<Function> {
let name = if let Some(prefix) = name.strip_suffix("_dir") { let function = match name {
format!("{prefix}_directory")
} else if let Some(prefix) = name.strip_suffix("_dir_native") {
format!("{prefix}_directory_native")
} else {
name.into()
};
let function = match name.as_str() {
"absolute_path" => Unary(absolute_path), "absolute_path" => Unary(absolute_path),
"append" => Binary(append), "append" => Binary(append),
"arch" => Nullary(arch), "arch" => Nullary(arch),
@ -116,15 +108,15 @@ pub(crate) fn get(name: &str) -> Option<Function> {
} }
impl Function { impl Function {
pub(crate) fn argc(&self) -> RangeInclusive<usize> { pub(crate) fn argc(&self) -> Range<usize> {
match *self { match *self {
Nullary(_) => 0..=0, Nullary(_) => 0..0,
Unary(_) => 1..=1, Unary(_) => 1..1,
UnaryOpt(_) => 1..=2, UnaryOpt(_) => 1..2,
UnaryPlus(_) => 1..=usize::MAX, UnaryPlus(_) => 1..usize::MAX,
Binary(_) => 2..=2, Binary(_) => 2..2,
BinaryPlus(_) => 2..=usize::MAX, BinaryPlus(_) => 2..usize::MAX,
Ternary(_) => 3..=3, Ternary(_) => 3..3,
} }
} }
} }

View File

@ -13,7 +13,6 @@ pub(crate) enum Item<'src> {
relative: StringLiteral<'src>, relative: StringLiteral<'src>,
}, },
Module { Module {
attributes: BTreeSet<Attribute<'src>>,
absolute: Option<PathBuf>, absolute: Option<PathBuf>,
doc: Option<&'src str>, doc: Option<&'src str>,
name: Name<'src>, name: Name<'src>,

View File

@ -27,8 +27,6 @@ pub(crate) struct Justfile<'src> {
pub(crate) source: PathBuf, pub(crate) source: PathBuf,
pub(crate) unexports: HashSet<String>, pub(crate) unexports: HashSet<String>,
pub(crate) warnings: Vec<Warning>, pub(crate) warnings: Vec<Warning>,
#[serde(skip)]
pub(crate) unstable: BTreeSet<Unstable>,
} }
impl<'src> Justfile<'src> { impl<'src> Justfile<'src> {
@ -227,22 +225,6 @@ impl<'src> Justfile<'src> {
Ok(()) Ok(())
} }
pub(crate) fn check_unstable(&self, config: &Config) -> RunResult<'src> {
if !config.unstable && !self.settings.unstable {
if let Some(unstable) = self.unstable.iter().next() {
return Err(Error::Unstable {
message: unstable.message(),
});
}
}
for module in self.modules.values() {
module.check_unstable(config)?;
}
Ok(())
}
pub(crate) fn get_alias(&self, name: &str) -> Option<&Alias<'src>> { pub(crate) fn get_alias(&self, name: &str) -> Option<&Alias<'src>> {
self.aliases.get(name) self.aliases.get(name)
} }

View File

@ -26,7 +26,6 @@ pub(crate) enum Keyword {
Tempdir, Tempdir,
True, True,
Unexport, Unexport,
Unstable,
WindowsPowershell, WindowsPowershell,
WindowsShell, WindowsShell,
X, X,

View File

@ -42,8 +42,8 @@ pub(crate) use {
shell::Shell, show_whitespace::ShowWhitespace, source::Source, string_kind::StringKind, shell::Shell, show_whitespace::ShowWhitespace, source::Source, string_kind::StringKind,
string_literal::StringLiteral, subcommand::Subcommand, suggestion::Suggestion, table::Table, string_literal::StringLiteral, subcommand::Subcommand, suggestion::Suggestion, table::Table,
thunk::Thunk, token::Token, token_kind::TokenKind, unresolved_dependency::UnresolvedDependency, thunk::Thunk, token::Token, token_kind::TokenKind, unresolved_dependency::UnresolvedDependency,
unresolved_recipe::UnresolvedRecipe, unstable::Unstable, use_color::UseColor, unresolved_recipe::UnresolvedRecipe, use_color::UseColor, variables::Variables,
variables::Variables, verbosity::Verbosity, warning::Warning, verbosity::Verbosity, warning::Warning,
}, },
camino::Utf8Path, camino::Utf8Path,
clap::ValueEnum, clap::ValueEnum,
@ -204,7 +204,6 @@ mod token_kind;
mod unindent; mod unindent;
mod unresolved_dependency; mod unresolved_dependency;
mod unresolved_recipe; mod unresolved_recipe;
mod unstable;
mod use_color; mod use_color;
mod variables; mod variables;
mod verbosity; mod verbosity;

View File

@ -294,7 +294,6 @@ impl<'src> Node<'src> for Set<'src> {
| Setting::Fallback(value) | Setting::Fallback(value)
| Setting::PositionalArguments(value) | Setting::PositionalArguments(value)
| Setting::Quiet(value) | Setting::Quiet(value)
| Setting::Unstable(value)
| Setting::WindowsPowerShell(value) | Setting::WindowsPowerShell(value)
| Setting::IgnoreComments(value) => { | Setting::IgnoreComments(value) => {
set.push_mut(value.to_string()); set.push_mut(value.to_string());

View File

@ -373,7 +373,27 @@ impl<'run, 'src> Parser<'run, 'src> {
|| self.next_are(&[Identifier, QuestionMark]) => || self.next_are(&[Identifier, QuestionMark]) =>
{ {
let doc = pop_doc_comment(&mut items, eol_since_last_comment); let doc = pop_doc_comment(&mut items, eol_since_last_comment);
items.push(self.parse_module(BTreeSet::new(), doc)?);
self.presume_keyword(Keyword::Mod)?;
let optional = self.accepted(QuestionMark)?;
let name = self.parse_name()?;
let relative = if self.next_is(StringToken) || self.next_are(&[Identifier, StringToken])
{
Some(self.parse_string_literal()?)
} else {
None
};
items.push(Item::Module {
absolute: None,
doc,
name,
optional,
relative,
});
} }
Some(Keyword::Set) Some(Keyword::Set)
if self.next_are(&[Identifier, Identifier, ColonEquals]) if self.next_are(&[Identifier, Identifier, ColonEquals])
@ -410,17 +430,6 @@ impl<'run, 'src> Parser<'run, 'src> {
Some(Keyword::Alias) if self.next_are(&[Identifier, Identifier, ColonEquals]) => { Some(Keyword::Alias) if self.next_are(&[Identifier, Identifier, ColonEquals]) => {
items.push(Item::Alias(self.parse_alias(attributes)?)); items.push(Item::Alias(self.parse_alias(attributes)?));
} }
Some(Keyword::Mod)
if self.next_are(&[Identifier, Identifier, Comment])
|| self.next_are(&[Identifier, Identifier, Eof])
|| self.next_are(&[Identifier, Identifier, Eol])
|| self.next_are(&[Identifier, Identifier, Identifier, StringToken])
|| self.next_are(&[Identifier, Identifier, StringToken])
|| self.next_are(&[Identifier, QuestionMark]) =>
{
let doc = pop_doc_comment(&mut items, eol_since_last_comment);
items.push(self.parse_module(attributes, doc)?);
}
_ => { _ => {
let quiet = self.accepted(At)?; let quiet = self.accepted(At)?;
let doc = pop_doc_comment(&mut items, eol_since_last_comment); let doc = pop_doc_comment(&mut items, eol_since_last_comment);
@ -445,33 +454,6 @@ impl<'run, 'src> Parser<'run, 'src> {
} }
} }
fn parse_module(
&mut self,
attributes: BTreeSet<Attribute<'src>>,
doc: Option<&'src str>,
) -> CompileResult<'src, Item<'src>> {
self.presume_keyword(Keyword::Mod)?;
let optional = self.accepted(QuestionMark)?;
let name = self.parse_name()?;
let relative = if self.next_is(StringToken) || self.next_are(&[Identifier, StringToken]) {
Some(self.parse_string_literal()?)
} else {
None
};
Ok(Item::Module {
attributes,
absolute: None,
doc,
name,
optional,
relative,
})
}
/// Parse an alias, e.g `alias name := target` /// Parse an alias, e.g `alias name := target`
fn parse_alias( fn parse_alias(
&mut self, &mut self,
@ -954,7 +936,6 @@ impl<'run, 'src> Parser<'run, 'src> {
Keyword::IgnoreComments => Some(Setting::IgnoreComments(self.parse_set_bool()?)), Keyword::IgnoreComments => Some(Setting::IgnoreComments(self.parse_set_bool()?)),
Keyword::PositionalArguments => Some(Setting::PositionalArguments(self.parse_set_bool()?)), Keyword::PositionalArguments => Some(Setting::PositionalArguments(self.parse_set_bool()?)),
Keyword::Quiet => Some(Setting::Quiet(self.parse_set_bool()?)), Keyword::Quiet => Some(Setting::Quiet(self.parse_set_bool()?)),
Keyword::Unstable => Some(Setting::Unstable(self.parse_set_bool()?)),
Keyword::WindowsPowershell => Some(Setting::WindowsPowerShell(self.parse_set_bool()?)), Keyword::WindowsPowershell => Some(Setting::WindowsPowerShell(self.parse_set_bool()?)),
_ => None, _ => None,
}; };
@ -2587,7 +2568,7 @@ mod tests {
kind: FunctionArgumentCountMismatch { kind: FunctionArgumentCountMismatch {
function: "arch", function: "arch",
found: 1, found: 1,
expected: 0..=0, expected: 0..0,
}, },
} }
@ -2601,7 +2582,7 @@ mod tests {
kind: FunctionArgumentCountMismatch { kind: FunctionArgumentCountMismatch {
function: "env_var", function: "env_var",
found: 0, found: 0,
expected: 1..=1, expected: 1..1,
}, },
} }
@ -2615,7 +2596,7 @@ mod tests {
kind: FunctionArgumentCountMismatch { kind: FunctionArgumentCountMismatch {
function: "env", function: "env",
found: 3, found: 3,
expected: 1..=2, expected: 1..2,
}, },
} }
@ -2629,7 +2610,7 @@ mod tests {
kind: FunctionArgumentCountMismatch { kind: FunctionArgumentCountMismatch {
function: "env", function: "env",
found: 0, found: 0,
expected: 1..=2, expected: 1..2,
}, },
} }
@ -2643,7 +2624,7 @@ mod tests {
kind: FunctionArgumentCountMismatch { kind: FunctionArgumentCountMismatch {
function: "env_var_or_default", function: "env_var_or_default",
found: 1, found: 1,
expected: 2..=2, expected: 2..2,
}, },
} }
@ -2657,7 +2638,7 @@ mod tests {
kind: FunctionArgumentCountMismatch { kind: FunctionArgumentCountMismatch {
function: "join", function: "join",
found: 1, found: 1,
expected: 2..=usize::MAX, expected: 2..usize::MAX,
}, },
} }
@ -2671,7 +2652,7 @@ mod tests {
kind: FunctionArgumentCountMismatch { kind: FunctionArgumentCountMismatch {
function: "replace", function: "replace",
found: 1, found: 1,
expected: 3..=3, expected: 3..3,
}, },
} }
} }

View File

@ -10,14 +10,16 @@ pub(crate) trait RangeExt<T> {
pub(crate) struct DisplayRange<T>(T); pub(crate) struct DisplayRange<T>(T);
impl Display for DisplayRange<&RangeInclusive<usize>> { impl Display for DisplayRange<&Range<usize>> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
if self.0.start() == self.0.end() { if self.0.start == self.0.end {
write!(f, "{}", self.0.start())?; write!(f, "0")?;
} else if *self.0.end() == usize::MAX { } else if self.0.start == self.0.end - 1 {
write!(f, "{} or more", self.0.start())?; write!(f, "{}", self.0.start)?;
} else if self.0.end == usize::MAX {
write!(f, "{} or more", self.0.start)?;
} else { } else {
write!(f, "{} to {}", self.0.start(), self.0.end())?; write!(f, "{} to {}", self.0.start, self.0.end - 1)?;
} }
Ok(()) Ok(())
} }
@ -74,10 +76,10 @@ mod tests {
assert!(!(1..1).contains(&1)); assert!(!(1..1).contains(&1));
assert!((1..1).is_empty()); assert!((1..1).is_empty());
assert!((5..5).is_empty()); assert!((5..5).is_empty());
assert_eq!((0..=0).display().to_string(), "0"); assert_eq!((1..1).display().to_string(), "0");
assert_eq!((1..=1).display().to_string(), "1"); assert_eq!((1..2).display().to_string(), "1");
assert_eq!((5..=5).display().to_string(), "5"); assert_eq!((5..6).display().to_string(), "5");
assert_eq!((5..=9).display().to_string(), "5 to 9"); assert_eq!((5..10).display().to_string(), "5 to 9");
assert_eq!((1..=usize::MAX).display().to_string(), "1 or more"); assert_eq!((1..usize::MAX).display().to_string(), "1 or more");
} }
} }

View File

@ -4,7 +4,6 @@ const DEFAULT_JUSTFILE_NAME: &str = JUSTFILE_NAMES[0];
pub(crate) const JUSTFILE_NAMES: [&str; 2] = ["justfile", ".justfile"]; pub(crate) const JUSTFILE_NAMES: [&str; 2] = ["justfile", ".justfile"];
const PROJECT_ROOT_CHILDREN: &[&str] = &[".bzr", ".git", ".hg", ".svn", "_darcs"]; const PROJECT_ROOT_CHILDREN: &[&str] = &[".bzr", ".git", ".hg", ".svn", "_darcs"];
#[derive(Debug)]
pub(crate) struct Search { pub(crate) struct Search {
pub(crate) justfile: PathBuf, pub(crate) justfile: PathBuf,
pub(crate) working_directory: PathBuf, pub(crate) working_directory: PathBuf,

View File

@ -15,7 +15,6 @@ pub(crate) enum Setting<'src> {
Quiet(bool), Quiet(bool),
Shell(Shell<'src>), Shell(Shell<'src>),
Tempdir(String), Tempdir(String),
Unstable(bool),
WindowsPowerShell(bool), WindowsPowerShell(bool),
WindowsShell(Shell<'src>), WindowsShell(Shell<'src>),
} }
@ -32,7 +31,6 @@ impl<'src> Display for Setting<'src> {
| Self::IgnoreComments(value) | Self::IgnoreComments(value)
| Self::PositionalArguments(value) | Self::PositionalArguments(value)
| Self::Quiet(value) | Self::Quiet(value)
| Self::Unstable(value)
| Self::WindowsPowerShell(value) => write!(f, "{value}"), | Self::WindowsPowerShell(value) => write!(f, "{value}"),
Self::Shell(shell) | Self::WindowsShell(shell) => write!(f, "{shell}"), Self::Shell(shell) | Self::WindowsShell(shell) => write!(f, "{shell}"),
Self::DotenvFilename(value) | Self::DotenvPath(value) | Self::Tempdir(value) => { Self::DotenvFilename(value) | Self::DotenvPath(value) | Self::Tempdir(value) => {

View File

@ -20,7 +20,6 @@ pub(crate) struct Settings<'src> {
pub(crate) quiet: bool, pub(crate) quiet: bool,
pub(crate) shell: Option<Shell<'src>>, pub(crate) shell: Option<Shell<'src>>,
pub(crate) tempdir: Option<String>, pub(crate) tempdir: Option<String>,
pub(crate) unstable: bool,
pub(crate) windows_powershell: bool, pub(crate) windows_powershell: bool,
pub(crate) windows_shell: Option<Shell<'src>>, pub(crate) windows_shell: Option<Shell<'src>>,
} }
@ -67,9 +66,6 @@ impl<'src> Settings<'src> {
Setting::Shell(shell) => { Setting::Shell(shell) => {
settings.shell = Some(shell); settings.shell = Some(shell);
} }
Setting::Unstable(unstable) => {
settings.unstable = unstable;
}
Setting::WindowsPowerShell(windows_powershell) => { Setting::WindowsPowerShell(windows_powershell) => {
settings.windows_powershell = windows_powershell; settings.windows_powershell = windows_powershell;
} }

View File

@ -110,10 +110,9 @@ impl Subcommand {
) { ) {
let starting_path = match &config.search_config { let starting_path = match &config.search_config {
SearchConfig::FromInvocationDirectory => config.invocation_directory.clone(), SearchConfig::FromInvocationDirectory => config.invocation_directory.clone(),
SearchConfig::FromSearchDirectory { search_directory } => config SearchConfig::FromSearchDirectory { search_directory } => {
.invocation_directory env::current_dir().unwrap().join(search_directory)
.join(search_directory) }
.lexiclean(),
_ => unreachable!(), _ => unreachable!(),
}; };
@ -190,9 +189,7 @@ impl Subcommand {
loader: &'src Loader, loader: &'src Loader,
search: &Search, search: &Search,
) -> RunResult<'src, Compilation<'src>> { ) -> RunResult<'src, Compilation<'src>> {
let compilation = Compiler::compile(loader, &search.justfile)?; let compilation = Compiler::compile(config.unstable, loader, &search.justfile)?;
compilation.justfile.check_unstable(config)?;
if config.verbosity.loud() { if config.verbosity.loud() {
for warning in &compilation.justfile.warnings { for warning in &compilation.justfile.warnings {

View File

@ -28,7 +28,7 @@ mod full {
pub fn summary(path: &Path) -> io::Result<Result<Summary, String>> { pub fn summary(path: &Path) -> io::Result<Result<Summary, String>> {
let loader = Loader::new(); let loader = Loader::new();
match Compiler::compile(&loader, path) { match Compiler::compile(false, &loader, path) {
Ok(compilation) => Ok(Ok(Summary::new(&compilation.justfile))), Ok(compilation) => Ok(Ok(Summary::new(&compilation.justfile))),
Err(error) => Ok(Err(if let Error::Compile { compile_error } = error { Err(error) => Ok(Err(if let Error::Compile { compile_error } = error {
compile_error.to_string() compile_error.to_string()

View File

@ -1,12 +0,0 @@
#[derive(Copy, Clone, Debug, PartialEq, Ord, Eq, PartialOrd)]
pub(crate) enum Unstable {
Modules,
}
impl Unstable {
pub(crate) fn message(self) -> String {
match self {
Self::Modules => "Modules are currently unstable.".into(),
}
}
}

View File

@ -4,7 +4,10 @@ test! {
name: unstable_not_passed, name: unstable_not_passed,
justfile: "", justfile: "",
args: ("--fmt"), args: ("--fmt"),
stderr_regex: "error: The `--fmt` command is currently unstable..*", stderr: "
error: The `--fmt` command is currently unstable. \
Invoke `just` with the `--unstable` flag to enable unstable features.
",
status: EXIT_FAILURE, status: EXIT_FAILURE,
} }

View File

@ -1050,51 +1050,3 @@ fn is_dependency() {
.stdout("beta false\ngamma true\n") .stdout("beta false\ngamma true\n")
.run(); .run();
} }
#[test]
fn unary_argument_count_mismamatch_error_message() {
Test::new()
.justfile("x := datetime()")
.args(["--evaluate"])
.stderr(
"
error: Function `datetime` called with 0 arguments but takes 1
justfile:1:6
1 x := datetime()
^^^^^^^^
",
)
.status(EXIT_FAILURE)
.run();
}
#[test]
fn dir_abbreviations_are_accepted() {
Test::new()
.justfile(
"
abbreviated := justfile_dir()
unabbreviated := justfile_directory()
@foo:
# {{ assert(abbreviated == unabbreviated, 'fail') }}
",
)
.run();
}
#[test]
fn invocation_dir_native_abbreviation_is_accepted() {
Test::new()
.justfile(
"
abbreviated := invocation_directory_native()
unabbreviated := invocation_dir_native()
@foo:
# {{ assert(abbreviated == unabbreviated, 'fail') }}
",
)
.run();
}

View File

@ -56,9 +56,7 @@ fn alias() {
"quiet": false, "quiet": false,
"shell": null, "shell": null,
"tempdir" : null, "tempdir" : null,
"unstable": false,
"ignore_comments": false, "ignore_comments": false,
"unstable": false,
"windows_powershell": false, "windows_powershell": false,
"windows_shell": null, "windows_shell": null,
}, },
@ -100,7 +98,6 @@ fn assignment() {
"quiet": false, "quiet": false,
"shell": null, "shell": null,
"tempdir" : null, "tempdir" : null,
"unstable": false,
"windows_powershell": false, "windows_powershell": false,
"windows_shell": null, "windows_shell": null,
}, },
@ -156,7 +153,6 @@ fn body() {
"quiet": false, "quiet": false,
"shell": null, "shell": null,
"tempdir" : null, "tempdir" : null,
"unstable": false,
"windows_powershell": false, "windows_powershell": false,
"windows_shell": null, "windows_shell": null,
}, },
@ -224,7 +220,6 @@ fn dependencies() {
"quiet": false, "quiet": false,
"shell": null, "shell": null,
"tempdir" : null, "tempdir" : null,
"unstable": false,
"windows_powershell": false, "windows_powershell": false,
"windows_shell": null, "windows_shell": null,
}, },
@ -330,7 +325,6 @@ fn dependency_argument() {
"quiet": false, "quiet": false,
"shell": null, "shell": null,
"tempdir" : null, "tempdir" : null,
"unstable": false,
"windows_powershell": false, "windows_powershell": false,
"windows_shell": null, "windows_shell": null,
}, },
@ -398,7 +392,6 @@ fn duplicate_recipes() {
"quiet": false, "quiet": false,
"shell": null, "shell": null,
"tempdir" : null, "tempdir" : null,
"unstable": false,
"windows_powershell": false, "windows_powershell": false,
"windows_shell": null, "windows_shell": null,
}, },
@ -444,7 +437,6 @@ fn duplicate_variables() {
"quiet": false, "quiet": false,
"shell": null, "shell": null,
"tempdir" : null, "tempdir" : null,
"unstable": false,
"windows_powershell": false, "windows_powershell": false,
"windows_shell": null, "windows_shell": null,
}, },
@ -493,7 +485,6 @@ fn doc_comment() {
"quiet": false, "quiet": false,
"shell": null, "shell": null,
"tempdir" : null, "tempdir" : null,
"unstable": false,
"windows_powershell": false, "windows_powershell": false,
"windows_shell": null, "windows_shell": null,
}, },
@ -528,7 +519,6 @@ fn empty_justfile() {
"quiet": false, "quiet": false,
"shell": null, "shell": null,
"tempdir" : null, "tempdir" : null,
"unstable": false,
"windows_powershell": false, "windows_powershell": false,
"windows_shell": null, "windows_shell": null,
}, },
@ -684,7 +674,6 @@ fn parameters() {
"quiet": false, "quiet": false,
"shell": null, "shell": null,
"tempdir" : null, "tempdir" : null,
"unstable": false,
"windows_powershell": false, "windows_powershell": false,
"windows_shell": null, "windows_shell": null,
}, },
@ -773,7 +762,6 @@ fn priors() {
"quiet": false, "quiet": false,
"shell": null, "shell": null,
"tempdir" : null, "tempdir" : null,
"unstable": false,
"windows_powershell": false, "windows_powershell": false,
"windows_shell": null, "windows_shell": null,
}, },
@ -822,7 +810,6 @@ fn private() {
"quiet": false, "quiet": false,
"shell": null, "shell": null,
"tempdir" : null, "tempdir" : null,
"unstable": false,
"windows_powershell": false, "windows_powershell": false,
"windows_shell": null, "windows_shell": null,
}, },
@ -871,7 +858,6 @@ fn quiet() {
"quiet": false, "quiet": false,
"shell": null, "shell": null,
"tempdir" : null, "tempdir" : null,
"unstable": false,
"windows_powershell": false, "windows_powershell": false,
"windows_shell": null, "windows_shell": null,
}, },
@ -935,7 +921,6 @@ fn settings() {
"command": "a", "command": "a",
}, },
"tempdir": null, "tempdir": null,
"unstable": false,
"windows_powershell": false, "windows_powershell": false,
"windows_shell": null, "windows_shell": null,
}, },
@ -987,7 +972,6 @@ fn shebang() {
"quiet": false, "quiet": false,
"shell": null, "shell": null,
"tempdir": null, "tempdir": null,
"unstable": false,
"windows_powershell": false, "windows_powershell": false,
"windows_shell": null, "windows_shell": null,
}, },
@ -1036,7 +1020,6 @@ fn simple() {
"quiet": false, "quiet": false,
"shell": null, "shell": null,
"tempdir": null, "tempdir": null,
"unstable": false,
"windows_powershell": false, "windows_powershell": false,
"windows_shell": null, "windows_shell": null,
}, },
@ -1087,7 +1070,6 @@ fn attribute() {
"quiet": false, "quiet": false,
"shell": null, "shell": null,
"tempdir" : null, "tempdir" : null,
"unstable": false,
"ignore_comments": false, "ignore_comments": false,
"windows_powershell": false, "windows_powershell": false,
"windows_shell": null, "windows_shell": null,
@ -1154,7 +1136,6 @@ fn module() {
"quiet": false, "quiet": false,
"shell": null, "shell": null,
"tempdir" : null, "tempdir" : null,
"unstable": false,
"ignore_comments": false, "ignore_comments": false,
"windows_powershell": false, "windows_powershell": false,
"windows_shell": null, "windows_shell": null,
@ -1177,7 +1158,6 @@ fn module() {
"quiet": false, "quiet": false,
"shell": null, "shell": null,
"tempdir" : null, "tempdir" : null,
"unstable": false,
"ignore_comments": false, "ignore_comments": false,
"windows_powershell": false, "windows_powershell": false,
"windows_shell": null, "windows_shell": null,

View File

@ -19,7 +19,7 @@ pub(crate) use {
fs, fs,
io::Write, io::Write,
iter, iter,
path::{Path, PathBuf, MAIN_SEPARATOR, MAIN_SEPARATOR_STR}, path::{Path, PathBuf, MAIN_SEPARATOR},
process::{Command, Stdio}, process::{Command, Stdio},
str, str,
}, },

View File

@ -8,8 +8,10 @@ fn modules_are_unstable() {
mod foo mod foo
", ",
) )
.write("foo.just", "") .stderr(
.stderr_regex("error: Modules are currently unstable..*") "error: Modules are currently unstable. \
Invoke `just` with the `--unstable` flag to enable unstable features.\n",
)
.status(EXIT_FAILURE) .status(EXIT_FAILURE)
.run(); .run();
} }
@ -439,13 +441,12 @@ fn modules_require_unambiguous_file() {
.status(EXIT_FAILURE) .status(EXIT_FAILURE)
.stderr( .stderr(
" "
error: Found multiple source files for module `foo`: `foo/justfile` and `foo.just` error: Found multiple source files for module `foo`: `foo.just` and `foo/justfile`
justfile:1:5 justfile:1:5
1 mod foo 1 mod foo
^^^ ^^^
" ",
.replace('/', MAIN_SEPARATOR_STR),
) )
.run(); .run();
} }
@ -565,23 +566,6 @@ fn modules_may_specify_path() {
.run(); .run();
} }
#[test]
fn modules_may_specify_path_to_directory() {
Test::new()
.write("commands/bar/mod.just", "foo:\n @echo FOO")
.justfile(
"
mod foo 'commands/bar'
",
)
.test_round_trip(false)
.arg("--unstable")
.arg("foo")
.arg("foo")
.stdout("FOO\n")
.run();
}
#[test] #[test]
fn modules_with_paths_are_dumped_correctly() { fn modules_with_paths_are_dumped_correctly() {
Test::new() Test::new()

View File

@ -143,22 +143,6 @@ fn single_upwards() {
search_test(path, &["../"]); search_test(path, &["../"]);
} }
#[test]
fn double_upwards() {
let tmp = temptree! {
justfile: "default:\n\techo ok",
foo: {
bar: {
justfile: "default:\n\techo foo",
},
},
};
let path = tmp.path().join("foo/bar");
search_test(path, &["../default"]);
}
#[test] #[test]
fn find_dot_justfile() { fn find_dot_justfile() {
Test::new() Test::new()

View File

@ -150,7 +150,7 @@ impl Test {
} }
pub(crate) fn stderr_regex(mut self, stderr_regex: impl AsRef<str>) -> Self { pub(crate) fn stderr_regex(mut self, stderr_regex: impl AsRef<str>) -> Self {
self.stderr_regex = Some(Regex::new(&format!("^(?s){}$", stderr_regex.as_ref())).unwrap()); self.stderr_regex = Some(Regex::new(&format!("^{}$", stderr_regex.as_ref())).unwrap());
self self
} }

View File

@ -30,7 +30,7 @@ default:
.args(["--fmt"]) .args(["--fmt"])
.env("JUST_UNSTABLE", val) .env("JUST_UNSTABLE", val)
.status(EXIT_FAILURE) .status(EXIT_FAILURE)
.stderr_regex("error: The `--fmt` command is currently unstable.*") .stderr("error: The `--fmt` command is currently unstable. Invoke `just` with the `--unstable` flag to enable unstable features.\n")
.run(); .run();
} }
} }
@ -45,40 +45,6 @@ default:
.justfile(justfile) .justfile(justfile)
.args(["--fmt"]) .args(["--fmt"])
.status(EXIT_FAILURE) .status(EXIT_FAILURE)
.stderr_regex("error: The `--fmt` command is currently unstable.*") .stderr("error: The `--fmt` command is currently unstable. Invoke `just` with the `--unstable` flag to enable unstable features.\n")
.run();
}
#[test]
fn set_unstable_with_setting() {
Test::new()
.justfile(
"
set unstable
mod foo
",
)
.write("foo.just", "@bar:\n echo BAR")
.args(["foo", "bar"])
.stdout("BAR\n")
.run();
}
#[test]
fn unstable_setting_does_not_affect_submodules() {
Test::new()
.justfile(
"
set unstable
mod foo
",
)
.write("foo.just", "mod bar")
.write("bar.just", "baz:\n echo hello")
.args(["foo", "bar"])
.stderr_regex("error: Modules are currently unstable.*")
.status(EXIT_FAILURE)
.run(); .run();
} }