Compare commits
10 Commits
8186992340
...
b81d106c91
Author | SHA1 | Date | |
---|---|---|---|
|
b81d106c91 | ||
|
458805e283 | ||
|
d6669e0b97 | ||
|
564814208f | ||
|
f1020b4e6a | ||
|
5e9f46e855 | ||
|
241e7b46a5 | ||
|
0c9b159aa4 | ||
|
d2f66815da | ||
|
50e8874e0e |
50
CHANGELOG.md
50
CHANGELOG.md
@ -1,6 +1,56 @@
|
|||||||
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
158
Cargo.lock
generated
@ -121,9 +121,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.5.0"
|
version = "2.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "blake3"
|
name = "blake3"
|
||||||
@ -174,9 +174,9 @@ checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.99"
|
version = "1.0.104"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695"
|
checksum = "74b6a57f98764a267ff415d50a25e6e166f3831a5071af4995296ea97d210490"
|
||||||
|
|
||||||
[[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.5",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -221,9 +221,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.5.7"
|
version = "4.5.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f"
|
checksum = "84b3edb18336f4df585bc9aa31dd99c036dfa5dc5e9a2939a722a188f3a8970d"
|
||||||
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.7"
|
version = "4.5.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f"
|
checksum = "c1c09dd5ada6c6c78075d6fd0da3f90d8080651e2d6cc8eb2f1aaa4034ced708"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstream",
|
"anstream",
|
||||||
"anstyle",
|
"anstyle",
|
||||||
@ -244,23 +244,23 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_complete"
|
name = "clap_complete"
|
||||||
version = "4.5.5"
|
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 = "d2020fa13af48afc65a9a87335bda648309ab3d154cd03c7ff95b378c7ed39c4"
|
checksum = "1d598e88f6874d4b888ed40c71efbcbf4076f1dfbae128a08a8c9e45f710605d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap 4.5.7",
|
"clap 4.5.8",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_derive"
|
name = "clap_derive"
|
||||||
version = "4.5.5"
|
version = "4.5.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6"
|
checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck 0.5.0",
|
"heck 0.5.0",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.66",
|
"syn 2.0.69",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -271,11 +271,11 @@ checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_mangen"
|
name = "clap_mangen"
|
||||||
version = "0.2.21"
|
version = "0.2.22"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "74b70fc13e60c0e1d490dc50eb73a749be6d81f4ef03783df1d9b7b0c62bc937"
|
checksum = "f50dde5bc0c853d6248de457e5eb6e5a674a54b93810a34ded88d882ca1fe2de"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap 4.5.7",
|
"clap 4.5.8",
|
||||||
"roff",
|
"roff",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -407,15 +407,15 @@ checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "edit-distance"
|
name = "edit-distance"
|
||||||
version = "2.1.0"
|
version = "2.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bbbaaaf38131deb9ca518a274a45bfdb8771f139517b073b16c2d3d32ae5037b"
|
checksum = "853fc7035888bd1c9320f3a05bfe7f344f49b8766a4bb4209b1ac5f0503d9577"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.12.0"
|
version = "1.13.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b"
|
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "env_filter"
|
name = "env_filter"
|
||||||
@ -591,13 +591,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "just"
|
name = "just"
|
||||||
version = "1.29.1"
|
version = "1.30.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term",
|
"ansi_term",
|
||||||
"blake3",
|
"blake3",
|
||||||
"camino",
|
"camino",
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap 4.5.7",
|
"clap 4.5.8",
|
||||||
"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.4.0"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||||
|
|
||||||
[[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.5.0",
|
"bitflags 2.6.0",
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -669,9 +669,9 @@ checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.21"
|
version = "0.4.22"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
||||||
|
|
||||||
[[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.5.0",
|
"bitflags 2.6.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.85"
|
version = "1.0.86"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23"
|
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
|
||||||
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.5.0",
|
"bitflags 2.6.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.5.0",
|
"bitflags 2.6.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.203"
|
version = "1.0.204"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
|
checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.203"
|
version = "1.0.204"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
|
checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.66",
|
"syn 2.0.69",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.117"
|
version = "1.0.120"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
|
checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5"
|
||||||
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.66",
|
"syn 2.0.69",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1078,9 +1078,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strum"
|
name = "strum"
|
||||||
version = "0.26.2"
|
version = "0.26.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29"
|
checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"strum_macros",
|
"strum_macros",
|
||||||
]
|
]
|
||||||
@ -1095,7 +1095,7 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"rustversion",
|
"rustversion",
|
||||||
"syn 2.0.66",
|
"syn 2.0.69",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1111,9 +1111,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.66"
|
version = "2.0.69"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5"
|
checksum = "201fcda3845c23e8212cd466bfebf0bd20694490fc0356ae8e428e0824a915a6"
|
||||||
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.66",
|
"syn 2.0.69",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1240,9 +1240,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "1.8.0"
|
version = "1.9.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0"
|
checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom",
|
||||||
]
|
]
|
||||||
@ -1286,7 +1286,7 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.66",
|
"syn 2.0.69",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1308,7 +1308,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.66",
|
"syn 2.0.69",
|
||||||
"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.5",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[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.5",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1397,18 +1397,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-targets"
|
name = "windows-targets"
|
||||||
version = "0.52.5"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
|
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows_aarch64_gnullvm 0.52.5",
|
"windows_aarch64_gnullvm 0.52.6",
|
||||||
"windows_aarch64_msvc 0.52.5",
|
"windows_aarch64_msvc 0.52.6",
|
||||||
"windows_i686_gnu 0.52.5",
|
"windows_i686_gnu 0.52.6",
|
||||||
"windows_i686_gnullvm",
|
"windows_i686_gnullvm",
|
||||||
"windows_i686_msvc 0.52.5",
|
"windows_i686_msvc 0.52.6",
|
||||||
"windows_x86_64_gnu 0.52.5",
|
"windows_x86_64_gnu 0.52.6",
|
||||||
"windows_x86_64_gnullvm 0.52.5",
|
"windows_x86_64_gnullvm 0.52.6",
|
||||||
"windows_x86_64_msvc 0.52.5",
|
"windows_x86_64_msvc 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1419,9 +1419,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_gnullvm"
|
name = "windows_aarch64_gnullvm"
|
||||||
version = "0.52.5"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
|
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||||
|
|
||||||
[[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.5"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
|
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||||
|
|
||||||
[[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.5"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
|
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnullvm"
|
name = "windows_i686_gnullvm"
|
||||||
version = "0.52.5"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
|
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||||
|
|
||||||
[[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.5"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
|
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||||
|
|
||||||
[[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.5"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
|
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||||
|
|
||||||
[[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.5"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
|
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||||
|
|
||||||
[[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.5"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winsafe"
|
name = "winsafe"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "just"
|
name = "just"
|
||||||
version = "1.29.1"
|
version = "1.30.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"]
|
||||||
|
40
README.md
40
README.md
@ -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 gated behind the
|
Features that aren't yet ready for stabilization are marked as unstable and may
|
||||||
`--unstable` flag. Features enabled by `--unstable` may change in backwards
|
be changed or removed at any time. Using unstable features produces an error by
|
||||||
incompatible ways at any time. Unstable features can also be enabled by setting
|
default, which can be suppressed with by passing the `--unstable` flag,
|
||||||
the environment variable `JUST_UNSTABLE` to any value other than `false`, `0`,
|
`set unstable`, or setting the environment variable `JUST_UNSTABLE`, to any
|
||||||
or the empty string.
|
value other than `false`, `0`, or the empty string.
|
||||||
|
|
||||||
Editor Support
|
Editor Support
|
||||||
--------------
|
--------------
|
||||||
@ -820,6 +820,7 @@ 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. |
|
||||||
|
|
||||||
@ -1349,6 +1350,11 @@ 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"`,
|
||||||
@ -1645,8 +1651,8 @@ which will halt execution.
|
|||||||
|
|
||||||
#### Datetime
|
#### Datetime
|
||||||
|
|
||||||
- `datetime(format)`<sup>master</sup> - Return local time with `format`.
|
- `datetime(format)`<sup>1.30.0</sup> - Return local time with `format`.
|
||||||
- `datetime_utc(format)`<sup>master</sup> - Return UTC time with `format`.
|
- `datetime_utc(format)`<sup>1.30.0</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
|
||||||
@ -3149,8 +3155,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, or set the
|
currently unstable, so you'll need to use the `--unstable` flag,
|
||||||
`JUST_UNSTABLE` environment variable to use them.
|
`set unstable`, or set the `JUST_UNSTABLE` environment variable to use them.
|
||||||
|
|
||||||
If you have the following `justfile`:
|
If you have the following `justfile`:
|
||||||
|
|
||||||
@ -3198,7 +3204,10 @@ 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.
|
directory. `PATH` may point to the module source file itself, or to a 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
|
||||||
@ -3229,7 +3238,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>master</sup>:
|
output<sup>1.30.0</sup>:
|
||||||
|
|
||||||
```mf
|
```mf
|
||||||
# foo is a great module!
|
# foo is a great module!
|
||||||
@ -3751,9 +3760,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 test good coverage.
|
while still providing good test 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),
|
||||||
@ -3765,7 +3774,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, since these are covered by faster, more concise unit tests that call
|
cases. 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
|
||||||
@ -3817,8 +3826,7 @@ 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 at any time to open a draft PR with your changes for discussion and
|
Feel free to open a draft PR at any time for discussion and feedback.
|
||||||
feedback.
|
|
||||||
|
|
||||||
### Hints
|
### Hints
|
||||||
|
|
||||||
|
@ -37,6 +37,8 @@ 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();
|
||||||
@ -92,6 +94,8 @@ 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(
|
||||||
@ -194,6 +198,7 @@ impl<'src> Analyzer<'src> {
|
|||||||
settings,
|
settings,
|
||||||
source: root.into(),
|
source: root.into(),
|
||||||
unexports,
|
unexports,
|
||||||
|
unstable,
|
||||||
warnings,
|
warnings,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -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(true, &loader, &path).unwrap();
|
let compilation = Compiler::compile(&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(true, &loader, &path).unwrap();
|
let compilation = Compiler::compile(&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(true, &loader, &tempdir.path().join("justfile")).unwrap();
|
let compilation = Compiler::compile(&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(true, &loader, &tempdir.path().join("justfile")).unwrap();
|
let compilation = Compiler::compile(&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(true, &loader, &tempdir.path().join("justfile")).unwrap();
|
let compilation = Compiler::compile(&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(true, &loader, &tempdir.path().join("justfile")).unwrap();
|
let compilation = Compiler::compile(&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(true, &loader, &tempdir.path().join("justfile")).unwrap();
|
let compilation = Compiler::compile(&loader, &tempdir.path().join("justfile")).unwrap();
|
||||||
|
|
||||||
assert_matches!(
|
assert_matches!(
|
||||||
ArgumentParser::parse_arguments(&compilation.justfile, &[]).unwrap_err(),
|
ArgumentParser::parse_arguments(&compilation.justfile, &[]).unwrap_err(),
|
||||||
|
@ -66,7 +66,7 @@ pub(crate) enum CompileErrorKind<'src> {
|
|||||||
FunctionArgumentCountMismatch {
|
FunctionArgumentCountMismatch {
|
||||||
function: &'src str,
|
function: &'src str,
|
||||||
found: usize,
|
found: usize,
|
||||||
expected: Range<usize>,
|
expected: RangeInclusive<usize>,
|
||||||
},
|
},
|
||||||
Include,
|
Include,
|
||||||
InconsistentLeadingWhitespace {
|
InconsistentLeadingWhitespace {
|
||||||
|
206
src/compiler.rs
206
src/compiler.rs
@ -4,14 +4,13 @@ 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));
|
||||||
@ -42,25 +41,14 @@ 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 import = if let Some(relative) = relative {
|
let relative = relative
|
||||||
let path = parent.join(Self::expand_tilde(&relative.cooked)?);
|
.as_ref()
|
||||||
|
.map(|relative| Self::expand_tilde(&relative.cooked))
|
||||||
|
.transpose()?;
|
||||||
|
|
||||||
if path.is_file() {
|
let import = Self::find_module_file(parent, *name, relative.as_deref())?;
|
||||||
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) {
|
||||||
@ -112,25 +100,69 @@ impl Compiler {
|
|||||||
|
|
||||||
Ok(Compilation {
|
Ok(Compilation {
|
||||||
asts,
|
asts,
|
||||||
srcs,
|
|
||||||
justfile,
|
justfile,
|
||||||
root: root.into(),
|
root: root.into(),
|
||||||
|
srcs,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_module_file<'src>(parent: &Path, module: Name<'src>) -> RunResult<'src, Option<PathBuf>> {
|
fn find_module_file<'src>(
|
||||||
let mut candidates = vec![format!("{module}.just"), format!("{module}/mod.just")]
|
parent: &Path,
|
||||||
.into_iter()
|
module: Name<'src>,
|
||||||
.filter(|path| parent.join(path).is_file())
|
path: Option<&Path>,
|
||||||
.collect::<Vec<String>>();
|
) -> RunResult<'src, Option<PathBuf>> {
|
||||||
|
let mut candidates = Vec::new();
|
||||||
|
|
||||||
let directory = parent.join(module.lexeme());
|
if let Some(path) = path {
|
||||||
|
let full = parent.join(path);
|
||||||
|
|
||||||
if directory.exists() {
|
if full.is_file() {
|
||||||
let entries = fs::read_dir(&directory).map_err(|io_error| SearchError::Io {
|
return Ok(Some(full));
|
||||||
io_error,
|
}
|
||||||
directory: directory.clone(),
|
|
||||||
})?;
|
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,
|
||||||
|
directory,
|
||||||
|
}
|
||||||
|
.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 {
|
||||||
@ -139,22 +171,34 @@ impl Compiler {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
if let Some(name) = entry.file_name().to_str() {
|
if let Some(name) = entry.file_name().to_str() {
|
||||||
for justfile_name in search::JUSTFILE_NAMES {
|
for (candidate, case_sensitive) in &candidates {
|
||||||
if name.eq_ignore_ascii_case(justfile_name) {
|
let candidate_name = candidate.file_name().unwrap().to_str().unwrap();
|
||||||
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match candidates.as_slice() {
|
if found.len() > 1 {
|
||||||
[] => Ok(None),
|
found.sort();
|
||||||
[file] => Ok(Some(parent.join(file).lexiclean())),
|
Err(Error::AmbiguousModuleFile {
|
||||||
found => Err(Error::AmbiguousModuleFile {
|
found: found
|
||||||
found: found.into(),
|
.into_iter()
|
||||||
|
.map(|found| found.strip_prefix(parent).unwrap().into())
|
||||||
|
.collect(),
|
||||||
module,
|
module,
|
||||||
}),
|
})
|
||||||
|
} else {
|
||||||
|
Ok(found.into_iter().next())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,7 +269,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(false, &loader, &justfile_a_path).unwrap();
|
let compilation = Compiler::compile(&loader, &justfile_a_path).unwrap();
|
||||||
|
|
||||||
assert_eq!(compilation.root_src(), justfile_a);
|
assert_eq!(compilation.root_src(), justfile_a);
|
||||||
}
|
}
|
||||||
@ -242,11 +286,91 @@ 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(false, &loader, &justfile_a_path).unwrap_err();
|
let loader_output = Compiler::compile(&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"]),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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<String>,
|
found: Vec<PathBuf>,
|
||||||
},
|
},
|
||||||
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),
|
List::and_ticked(found.iter().map(|path| path.display())),
|
||||||
)?,
|
)?,
|
||||||
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 the `--unstable` flag to enable unstable features.")?;
|
write!(f, "{message} Invoke `just` with `--unstable`, set the `JUST_UNSTABLE` environment variable, or add `set unstable` to your `justfile` to enable unstable features.")?;
|
||||||
}
|
}
|
||||||
WriteJustfile { justfile, io_error } => {
|
WriteJustfile { justfile, io_error } => {
|
||||||
let justfile = justfile.display();
|
let justfile = justfile.display();
|
||||||
|
@ -32,7 +32,15 @@ impl<'src: 'run, 'run> Context<'src, 'run> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get(name: &str) -> Option<Function> {
|
pub(crate) fn get(name: &str) -> Option<Function> {
|
||||||
let function = match name {
|
let name = if let Some(prefix) = name.strip_suffix("_dir") {
|
||||||
|
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),
|
||||||
@ -108,15 +116,15 @@ pub(crate) fn get(name: &str) -> Option<Function> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Function {
|
impl Function {
|
||||||
pub(crate) fn argc(&self) -> Range<usize> {
|
pub(crate) fn argc(&self) -> RangeInclusive<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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ 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>,
|
||||||
|
@ -27,6 +27,8 @@ 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> {
|
||||||
@ -225,6 +227,22 @@ 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)
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ pub(crate) enum Keyword {
|
|||||||
Tempdir,
|
Tempdir,
|
||||||
True,
|
True,
|
||||||
Unexport,
|
Unexport,
|
||||||
|
Unstable,
|
||||||
WindowsPowershell,
|
WindowsPowershell,
|
||||||
WindowsShell,
|
WindowsShell,
|
||||||
X,
|
X,
|
||||||
|
@ -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, use_color::UseColor, variables::Variables,
|
unresolved_recipe::UnresolvedRecipe, unstable::Unstable, use_color::UseColor,
|
||||||
verbosity::Verbosity, warning::Warning,
|
variables::Variables, verbosity::Verbosity, warning::Warning,
|
||||||
},
|
},
|
||||||
camino::Utf8Path,
|
camino::Utf8Path,
|
||||||
clap::ValueEnum,
|
clap::ValueEnum,
|
||||||
@ -204,6 +204,7 @@ 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;
|
||||||
|
@ -294,6 +294,7 @@ 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());
|
||||||
|
@ -373,27 +373,7 @@ 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])
|
||||||
@ -430,6 +410,17 @@ 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);
|
||||||
@ -454,6 +445,33 @@ 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,
|
||||||
@ -936,6 +954,7 @@ 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,
|
||||||
};
|
};
|
||||||
@ -2568,7 +2587,7 @@ mod tests {
|
|||||||
kind: FunctionArgumentCountMismatch {
|
kind: FunctionArgumentCountMismatch {
|
||||||
function: "arch",
|
function: "arch",
|
||||||
found: 1,
|
found: 1,
|
||||||
expected: 0..0,
|
expected: 0..=0,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2582,7 +2601,7 @@ mod tests {
|
|||||||
kind: FunctionArgumentCountMismatch {
|
kind: FunctionArgumentCountMismatch {
|
||||||
function: "env_var",
|
function: "env_var",
|
||||||
found: 0,
|
found: 0,
|
||||||
expected: 1..1,
|
expected: 1..=1,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2596,7 +2615,7 @@ mod tests {
|
|||||||
kind: FunctionArgumentCountMismatch {
|
kind: FunctionArgumentCountMismatch {
|
||||||
function: "env",
|
function: "env",
|
||||||
found: 3,
|
found: 3,
|
||||||
expected: 1..2,
|
expected: 1..=2,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2610,7 +2629,7 @@ mod tests {
|
|||||||
kind: FunctionArgumentCountMismatch {
|
kind: FunctionArgumentCountMismatch {
|
||||||
function: "env",
|
function: "env",
|
||||||
found: 0,
|
found: 0,
|
||||||
expected: 1..2,
|
expected: 1..=2,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2624,7 +2643,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,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2638,7 +2657,7 @@ mod tests {
|
|||||||
kind: FunctionArgumentCountMismatch {
|
kind: FunctionArgumentCountMismatch {
|
||||||
function: "join",
|
function: "join",
|
||||||
found: 1,
|
found: 1,
|
||||||
expected: 2..usize::MAX,
|
expected: 2..=usize::MAX,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2652,7 +2671,7 @@ mod tests {
|
|||||||
kind: FunctionArgumentCountMismatch {
|
kind: FunctionArgumentCountMismatch {
|
||||||
function: "replace",
|
function: "replace",
|
||||||
found: 1,
|
found: 1,
|
||||||
expected: 3..3,
|
expected: 3..=3,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,16 +10,14 @@ pub(crate) trait RangeExt<T> {
|
|||||||
|
|
||||||
pub(crate) struct DisplayRange<T>(T);
|
pub(crate) struct DisplayRange<T>(T);
|
||||||
|
|
||||||
impl Display for DisplayRange<&Range<usize>> {
|
impl Display for DisplayRange<&RangeInclusive<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, "0")?;
|
write!(f, "{}", self.0.start())?;
|
||||||
} else if self.0.start == self.0.end - 1 {
|
} else if *self.0.end() == usize::MAX {
|
||||||
write!(f, "{}", self.0.start)?;
|
write!(f, "{} or more", 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 - 1)?;
|
write!(f, "{} to {}", self.0.start(), self.0.end())?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -76,10 +74,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!((1..1).display().to_string(), "0");
|
assert_eq!((0..=0).display().to_string(), "0");
|
||||||
assert_eq!((1..2).display().to_string(), "1");
|
assert_eq!((1..=1).display().to_string(), "1");
|
||||||
assert_eq!((5..6).display().to_string(), "5");
|
assert_eq!((5..=5).display().to_string(), "5");
|
||||||
assert_eq!((5..10).display().to_string(), "5 to 9");
|
assert_eq!((5..=9).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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ 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,
|
||||||
|
@ -15,6 +15,7 @@ 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>),
|
||||||
}
|
}
|
||||||
@ -31,6 +32,7 @@ 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) => {
|
||||||
|
@ -20,6 +20,7 @@ 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>>,
|
||||||
}
|
}
|
||||||
@ -66,6 +67,9 @@ 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;
|
||||||
}
|
}
|
||||||
|
@ -110,9 +110,10 @@ 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 } => {
|
SearchConfig::FromSearchDirectory { search_directory } => config
|
||||||
env::current_dir().unwrap().join(search_directory)
|
.invocation_directory
|
||||||
}
|
.join(search_directory)
|
||||||
|
.lexiclean(),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -189,7 +190,9 @@ impl Subcommand {
|
|||||||
loader: &'src Loader,
|
loader: &'src Loader,
|
||||||
search: &Search,
|
search: &Search,
|
||||||
) -> RunResult<'src, Compilation<'src>> {
|
) -> RunResult<'src, Compilation<'src>> {
|
||||||
let compilation = Compiler::compile(config.unstable, loader, &search.justfile)?;
|
let compilation = Compiler::compile(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 {
|
||||||
|
@ -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(false, &loader, path) {
|
match Compiler::compile(&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()
|
||||||
|
12
src/unstable.rs
Normal file
12
src/unstable.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#[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(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,10 +4,7 @@ test! {
|
|||||||
name: unstable_not_passed,
|
name: unstable_not_passed,
|
||||||
justfile: "",
|
justfile: "",
|
||||||
args: ("--fmt"),
|
args: ("--fmt"),
|
||||||
stderr: "
|
stderr_regex: "error: The `--fmt` command is currently unstable..*",
|
||||||
error: The `--fmt` command is currently unstable. \
|
|
||||||
Invoke `just` with the `--unstable` flag to enable unstable features.
|
|
||||||
",
|
|
||||||
status: EXIT_FAILURE,
|
status: EXIT_FAILURE,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1050,3 +1050,51 @@ 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();
|
||||||
|
}
|
||||||
|
@ -56,7 +56,9 @@ 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,
|
||||||
},
|
},
|
||||||
@ -98,6 +100,7 @@ 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,
|
||||||
},
|
},
|
||||||
@ -153,6 +156,7 @@ 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,
|
||||||
},
|
},
|
||||||
@ -220,6 +224,7 @@ 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,
|
||||||
},
|
},
|
||||||
@ -325,6 +330,7 @@ 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,
|
||||||
},
|
},
|
||||||
@ -392,6 +398,7 @@ 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,
|
||||||
},
|
},
|
||||||
@ -437,6 +444,7 @@ 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,
|
||||||
},
|
},
|
||||||
@ -485,6 +493,7 @@ 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,
|
||||||
},
|
},
|
||||||
@ -519,6 +528,7 @@ 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,
|
||||||
},
|
},
|
||||||
@ -674,6 +684,7 @@ 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,
|
||||||
},
|
},
|
||||||
@ -762,6 +773,7 @@ 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,
|
||||||
},
|
},
|
||||||
@ -810,6 +822,7 @@ 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,
|
||||||
},
|
},
|
||||||
@ -858,6 +871,7 @@ 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,
|
||||||
},
|
},
|
||||||
@ -921,6 +935,7 @@ fn settings() {
|
|||||||
"command": "a",
|
"command": "a",
|
||||||
},
|
},
|
||||||
"tempdir": null,
|
"tempdir": null,
|
||||||
|
"unstable": false,
|
||||||
"windows_powershell": false,
|
"windows_powershell": false,
|
||||||
"windows_shell": null,
|
"windows_shell": null,
|
||||||
},
|
},
|
||||||
@ -972,6 +987,7 @@ 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,
|
||||||
},
|
},
|
||||||
@ -1020,6 +1036,7 @@ 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,
|
||||||
},
|
},
|
||||||
@ -1070,6 +1087,7 @@ 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,
|
||||||
@ -1136,6 +1154,7 @@ 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,
|
||||||
@ -1158,6 +1177,7 @@ 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,
|
||||||
|
@ -19,7 +19,7 @@ pub(crate) use {
|
|||||||
fs,
|
fs,
|
||||||
io::Write,
|
io::Write,
|
||||||
iter,
|
iter,
|
||||||
path::{Path, PathBuf, MAIN_SEPARATOR},
|
path::{Path, PathBuf, MAIN_SEPARATOR, MAIN_SEPARATOR_STR},
|
||||||
process::{Command, Stdio},
|
process::{Command, Stdio},
|
||||||
str,
|
str,
|
||||||
},
|
},
|
||||||
|
@ -8,10 +8,8 @@ fn modules_are_unstable() {
|
|||||||
mod foo
|
mod foo
|
||||||
",
|
",
|
||||||
)
|
)
|
||||||
.stderr(
|
.write("foo.just", "")
|
||||||
"error: Modules are currently unstable. \
|
.stderr_regex("error: Modules are currently unstable..*")
|
||||||
Invoke `just` with the `--unstable` flag to enable unstable features.\n",
|
|
||||||
)
|
|
||||||
.status(EXIT_FAILURE)
|
.status(EXIT_FAILURE)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
@ -441,12 +439,13 @@ fn modules_require_unambiguous_file() {
|
|||||||
.status(EXIT_FAILURE)
|
.status(EXIT_FAILURE)
|
||||||
.stderr(
|
.stderr(
|
||||||
"
|
"
|
||||||
error: Found multiple source files for module `foo`: `foo.just` and `foo/justfile`
|
error: Found multiple source files for module `foo`: `foo/justfile` and `foo.just`
|
||||||
——▶ justfile:1:5
|
——▶ justfile:1:5
|
||||||
│
|
│
|
||||||
1 │ mod foo
|
1 │ mod foo
|
||||||
│ ^^^
|
│ ^^^
|
||||||
",
|
"
|
||||||
|
.replace('/', MAIN_SEPARATOR_STR),
|
||||||
)
|
)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
@ -566,6 +565,23 @@ 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()
|
||||||
|
@ -143,6 +143,22 @@ 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()
|
||||||
|
@ -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!("^{}$", stderr_regex.as_ref())).unwrap());
|
self.stderr_regex = Some(Regex::new(&format!("^(?s){}$", stderr_regex.as_ref())).unwrap());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,12 +26,12 @@ default:
|
|||||||
"#;
|
"#;
|
||||||
for val in ["0", "", "false"] {
|
for val in ["0", "", "false"] {
|
||||||
Test::new()
|
Test::new()
|
||||||
.justfile(justfile)
|
.justfile(justfile)
|
||||||
.args(["--fmt"])
|
.args(["--fmt"])
|
||||||
.env("JUST_UNSTABLE", val)
|
.env("JUST_UNSTABLE", val)
|
||||||
.status(EXIT_FAILURE)
|
.status(EXIT_FAILURE)
|
||||||
.stderr("error: The `--fmt` command is currently unstable. Invoke `just` with the `--unstable` flag to enable unstable features.\n")
|
.stderr_regex("error: The `--fmt` command is currently unstable.*")
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,6 +45,40 @@ default:
|
|||||||
.justfile(justfile)
|
.justfile(justfile)
|
||||||
.args(["--fmt"])
|
.args(["--fmt"])
|
||||||
.status(EXIT_FAILURE)
|
.status(EXIT_FAILURE)
|
||||||
.stderr("error: The `--fmt` command is currently unstable. Invoke `just` with the `--unstable` flag to enable unstable features.\n")
|
.stderr_regex("error: The `--fmt` command is currently unstable.*")
|
||||||
|
.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();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user