Add dotenv integration (#306)

This commit is contained in:
Casey Rodarmor 2018-03-05 13:21:35 -08:00 committed by GitHub
parent ec56336df7
commit 70234f6193
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 298 additions and 81 deletions

135
Cargo.lock generated
View File

@ -11,6 +11,14 @@ name = "ansi_term"
version = "0.10.2" version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "assert_matches" name = "assert_matches"
version = "1.1.0" version = "1.1.0"
@ -21,11 +29,32 @@ name = "atty"
version = "0.2.6" version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
"termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "backtrace"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "backtrace-sys"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.0.1" version = "1.0.1"
@ -40,6 +69,16 @@ dependencies = [
"tempdir 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "cc"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cfg-if"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "clap" name = "clap"
version = "2.30.0" version = "2.30.0"
@ -54,6 +93,25 @@ dependencies = [
"vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "derive-error-chain"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "dotenv"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"derive-error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "edit-distance" name = "edit-distance"
version = "2.0.1" version = "2.0.1"
@ -64,6 +122,14 @@ name = "either"
version = "1.4.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"
[[package]]
name = "error-chain"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "executable-path" name = "executable-path"
version = "1.0.0" version = "1.0.0"
@ -90,7 +156,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "itertools" name = "itertools"
version = "0.7.6" version = "0.7.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -100,16 +166,17 @@ dependencies = [
name = "just" name = "just"
version = "0.3.8" version = "0.3.8"
dependencies = [ dependencies = [
"ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"assert_matches 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "assert_matches 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"brev 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "brev 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.30.0 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
"dotenv 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"edit-distance 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "edit-distance 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"executable-path 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "executable-path 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"target 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "target 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -132,7 +199,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.36" version = "0.2.39"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
@ -140,16 +207,21 @@ name = "memchr"
version = "2.0.1" version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "quote"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "rand" name = "rand"
version = "0.4.2" version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -192,11 +264,34 @@ dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "rustc-demangle"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.7.0" version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "syn"
version = "0.11.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "synom"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "target" name = "target"
version = "1.0.0" version = "1.0.0"
@ -216,7 +311,7 @@ name = "termion"
version = "1.5.1" version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -243,6 +338,11 @@ name = "unicode-width"
version = "0.1.4" version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-xid"
version = "0.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "unreachable" name = "unreachable"
version = "1.0.0" version = "1.0.0"
@ -298,35 +398,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata] [metadata]
"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4"
"checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455" "checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum assert_matches 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e772942dccdf11b368c31e044e4fca9189f80a773d2f0808379de65894cbf57" "checksum assert_matches 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e772942dccdf11b368c31e044e4fca9189f80a773d2f0808379de65894cbf57"
"checksum atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8352656fd42c30a0c3c89d26dea01e3b77c0ab2af18230835c15e2e13cd51859" "checksum atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8352656fd42c30a0c3c89d26dea01e3b77c0ab2af18230835c15e2e13cd51859"
"checksum backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbbf59b1c43eefa8c3ede390fcc36820b4999f7914104015be25025e0d62af2"
"checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661"
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
"checksum brev 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "d85c3b7957223c752ff78ffd20a1806b0c7262d9aef85ed470546f16b56a5bb2" "checksum brev 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "d85c3b7957223c752ff78ffd20a1806b0c7262d9aef85ed470546f16b56a5bb2"
"checksum cc 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9be26b24e988625409b19736d130f0c7d224f01d06454b5f81d8d23d6c1a618f"
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
"checksum clap 2.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1c07b9257a00f3fc93b7f3c417fc15607ec7a56823bc2c37ec744e266387de5b" "checksum clap 2.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1c07b9257a00f3fc93b7f3c417fc15607ec7a56823bc2c37ec744e266387de5b"
"checksum derive-error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "92183014af72c63aea490e66526c712bf1066ac50f66c9f34824f02483ec1d98"
"checksum dotenv 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a70de3c590ce18df70743cace1cf12565637a0b26fd8b04ef10c7d33fdc66cdc"
"checksum edit-distance 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3bd26878c3d921f89797a4e1a1711919f999a9f6946bb6f5a4ffda126d297b7e" "checksum edit-distance 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3bd26878c3d921f89797a4e1a1711919f999a9f6946bb6f5a4ffda126d297b7e"
"checksum either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740178ddf48b1a9e878e6d6509a1442a2d42fd2928aae8e7a6f8a36fb01981b3" "checksum either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740178ddf48b1a9e878e6d6509a1442a2d42fd2928aae8e7a6f8a36fb01981b3"
"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
"checksum executable-path 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ebc5a6d89e3c90b84e8f33c8737933dda8f1c106b5415900b38b9d433841478" "checksum executable-path 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ebc5a6d89e3c90b84e8f33c8737933dda8f1c106b5415900b38b9d433841478"
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
"checksum itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b07332223953b5051bceb67e8c4700aa65291535568e1f12408c43c4a42c0394" "checksum itertools 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)" = "23d53b4c7394338044c3b9c8c5b2caaf7b40ae049ecd321578ebdc2e13738cd1"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
"checksum libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1e5d97d6708edaa407429faa671b942dc0f2727222fb6b6539bf1db936e4b121" "checksum libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)" = "f54263ad99207254cf58b5f701ecb432c717445ea2ee8af387334bdd1a03fdff"
"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5"
"checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" "checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd"
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
"checksum regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "5be5347bde0c48cfd8c3fdc0766cdfe9d8a755ef84d620d6794c778c91de8b2b" "checksum regex 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "5be5347bde0c48cfd8c3fdc0766cdfe9d8a755ef84d620d6794c778c91de8b2b"
"checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e" "checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e"
"checksum remove_dir_all 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5d2f806b0fcdabd98acd380dc8daef485e22bcb7cddc811d1337967f2528cf5" "checksum remove_dir_all 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5d2f806b0fcdabd98acd380dc8daef485e22bcb7cddc811d1337967f2528cf5"
"checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb"
"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
"checksum target 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "10000465bb0cc031c87a44668991b284fd84c0e6bd945f62d4af04e9e52a222a" "checksum target 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "10000465bb0cc031c87a44668991b284fd84c0e6bd945f62d4af04e9e52a222a"
"checksum tempdir 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f73eebdb68c14bcb24aef74ea96079830e7fa7b31a6106e42ea7ee887c1e134e" "checksum tempdir 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f73eebdb68c14bcb24aef74ea96079830e7fa7b31a6106e42ea7ee887c1e134e"
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963"
"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
"checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"

View File

@ -8,11 +8,12 @@ homepage = "https://github.com/casey/just"
readme = "crates-io-readme.md" readme = "crates-io-readme.md"
[dependencies] [dependencies]
ansi_term = "0.10" ansi_term = "0.11"
assert_matches = "1.1.0" assert_matches = "1.1.0"
atty = "0.2.1" atty = "0.2.1"
brev = "0.1.6" brev = "0.1.6"
clap = "2.0.0" clap = "2.0.0"
dotenv = "0.11.0"
edit-distance = "2.0.0" edit-distance = "2.0.0"
itertools = "0.7" itertools = "0.7"
lazy_static = "1.0.0" lazy_static = "1.0.0"

View File

@ -289,6 +289,34 @@ This is an x86_64 machine
- `env_var_or_default(key, default)` Retrieves the environment variable with name `key`, returning `default` if it is not present. - `env_var_or_default(key, default)` Retrieves the environment variable with name `key`, returning `default` if it is not present.
==== Dotenv Integration
`just` will load environment variables from a file named `.env`. This file can be located in the same directory as your justfile or in a parent directory. These variables are environment variables, not `just` variables, and so must be accessed using `$VARIABLE_NAME` in recipes and backticks.
For example, if your `.env` file contains:
```
# a comment, will be ignored
DATABASE_ADDRESS=localhost:6379
SERVER_PORT=1337
```
And your justfile contains:
```make
serve:
@echo "Starting server with database $DATABASE_ADDRESS on port $SERVER_PORT..."
./server --database $DATABASE_ADDRESS --port $SERVER_PORT
```
`just serve` will output:
```sh
$ just serve
Starting server with database localhost:6379 on port 1337...
./server --database $DATABASE_ADDRESS --port $SERVER_PORT
```
=== Command Evaluation Using Backticks === Command Evaluation Using Backticks
Backticks can be used to store the result of commands: Backticks can be used to store the result of commands:

View File

@ -4,32 +4,35 @@ use brev;
pub struct AssignmentEvaluator<'a: 'b, 'b> { pub struct AssignmentEvaluator<'a: 'b, 'b> {
pub assignments: &'b Map<&'a str, Expression<'a>>, pub assignments: &'b Map<&'a str, Expression<'a>>,
pub dotenv: &'b Map<String, String>,
pub dry_run: bool,
pub evaluated: Map<&'a str, String>, pub evaluated: Map<&'a str, String>,
pub exports: &'b Set<&'a str>, pub exports: &'b Set<&'a str>,
pub overrides: &'b Map<&'b str, &'b str>, pub overrides: &'b Map<&'b str, &'b str>,
pub quiet: bool, pub quiet: bool,
pub scope: &'b Map<&'a str, String>, pub scope: &'b Map<&'a str, String>,
pub shell: &'b str, pub shell: &'b str,
pub dry_run: bool,
} }
impl<'a, 'b> AssignmentEvaluator<'a, 'b> { impl<'a, 'b> AssignmentEvaluator<'a, 'b> {
pub fn evaluate_assignments( pub fn evaluate_assignments(
assignments: &Map<&'a str, Expression<'a>>, assignments: &Map<&'a str, Expression<'a>>,
dotenv: &'b Map<String, String>,
overrides: &Map<&str, &str>, overrides: &Map<&str, &str>,
quiet: bool, quiet: bool,
shell: &'a str, shell: &'a str,
dry_run: bool, dry_run: bool,
) -> RunResult<'a, Map<&'a str, String>> { ) -> RunResult<'a, Map<&'a str, String>> {
let mut evaluator = AssignmentEvaluator { let mut evaluator = AssignmentEvaluator {
assignments: assignments, evaluated: empty(),
evaluated: empty(), exports: &empty(),
exports: &empty(), scope: &empty(),
overrides: overrides, assignments,
quiet: quiet, dotenv,
scope: &empty(), dry_run,
shell: shell, overrides,
dry_run: dry_run, quiet,
shell,
}; };
for name in assignments.keys() { for name in assignments.keys() {
@ -110,7 +113,7 @@ impl<'a, 'b> AssignmentEvaluator<'a, 'b> {
if self.dry_run { if self.dry_run {
Ok(format!("`{}`", raw)) Ok(format!("`{}`", raw))
} else { } else {
Ok(self.run_backtick(raw, token)?) Ok(self.run_backtick(self.dotenv, raw, token)?)
} }
} }
Expression::Concatination{ref lhs, ref rhs} => { Expression::Concatination{ref lhs, ref rhs} => {
@ -125,12 +128,13 @@ impl<'a, 'b> AssignmentEvaluator<'a, 'b> {
fn run_backtick( fn run_backtick(
&self, &self,
dotenv: &Map<String, String>,
raw: &str, raw: &str,
token: &Token<'a>, token: &Token<'a>,
) -> RunResult<'a, String> { ) -> RunResult<'a, String> {
let mut cmd = Command::new(self.shell); let mut cmd = Command::new(self.shell);
cmd.export_environment_variables(self.scope, self.exports)?; cmd.export_environment_variables(self.scope, dotenv, self.exports)?;
cmd.arg("-cu") cmd.arg("-cu")
.arg(raw); .arg(raw);

View File

@ -17,11 +17,11 @@ impl<'a: 'b, 'b> AssignmentResolver<'a, 'b> {
) -> CompilationResult<'a, ()> { ) -> CompilationResult<'a, ()> {
let mut resolver = AssignmentResolver { let mut resolver = AssignmentResolver {
assignments: assignments, stack: empty(),
assignment_tokens: assignment_tokens, seen: empty(),
stack: empty(), evaluated: empty(),
seen: empty(), assignments,
evaluated: empty(), assignment_tokens,
}; };
for name in assignments.keys() { for name in assignments.keys() {

View File

@ -35,7 +35,7 @@ impl Default for Color {
impl Color { impl Color {
fn restyle(self, style: Style) -> Color { fn restyle(self, style: Style) -> Color {
Color { Color {
style: style, style,
..self ..self
} }
} }

View File

@ -3,7 +3,8 @@ use common::*;
pub trait CommandExt { pub trait CommandExt {
fn export_environment_variables<'a>( fn export_environment_variables<'a>(
&mut self, &mut self,
scope: &Map<&'a str, String>, scope: &Map<&'a str, String>,
dotenv: &Map<String, String>,
exports: &Set<&'a str> exports: &Set<&'a str>
) -> RunResult<'a, ()>; ) -> RunResult<'a, ()>;
} }
@ -11,9 +12,13 @@ pub trait CommandExt {
impl CommandExt for Command { impl CommandExt for Command {
fn export_environment_variables<'a>( fn export_environment_variables<'a>(
&mut self, &mut self,
scope: &Map<&'a str, String>, scope: &Map<&'a str, String>,
dotenv: &Map<String, String>,
exports: &Set<&'a str> exports: &Set<&'a str>
) -> RunResult<'a, ()> { ) -> RunResult<'a, ()> {
for (name, value) in dotenv {
self.env(name, value);
}
for name in exports { for name in exports {
if let Some(value) = scope.get(name) { if let Some(value) = scope.get(name) {
self.env(name, value); self.env(name, value);

View File

@ -11,7 +11,7 @@ impl<'a> CookedString<'a> {
let raw = &token.lexeme[1..token.lexeme.len()-1]; let raw = &token.lexeme[1..token.lexeme.len()-1];
if let TokenKind::RawString = token.kind { if let TokenKind::RawString = token.kind {
Ok(CookedString{raw: raw, cooked: raw.to_string()}) Ok(CookedString{cooked: raw.to_string(), raw})
} else if let TokenKind::StringToken = token.kind { } else if let TokenKind::StringToken = token.kind {
let mut cooked = String::new(); let mut cooked = String::new();
let mut escape = false; let mut escape = false;
@ -36,7 +36,7 @@ impl<'a> CookedString<'a> {
} }
cooked.push(c); cooked.push(c);
} }
Ok(CookedString{raw: raw, cooked: cooked}) Ok(CookedString{raw, cooked})
} else { } else {
Err(token.error(CompilationErrorKind::Internal { Err(token.error(CompilationErrorKind::Internal {
message: "cook_string() called on non-string token".to_string() message: "cook_string() called on non-string token".to_string()

View File

@ -53,8 +53,11 @@ impl<'a, 'b> Justfile<'a> where 'a: 'b {
return Err(RuntimeError::UnknownOverrides{overrides: unknown_overrides}); return Err(RuntimeError::UnknownOverrides{overrides: unknown_overrides});
} }
let dotenv = load_dotenv()?;
let scope = AssignmentEvaluator::evaluate_assignments( let scope = AssignmentEvaluator::evaluate_assignments(
&self.assignments, &self.assignments,
&dotenv,
&configuration.overrides, &configuration.overrides,
configuration.quiet, configuration.quiet,
configuration.shell, configuration.shell,
@ -107,12 +110,12 @@ impl<'a, 'b> Justfile<'a> where 'a: 'b {
} else { } else {
None None
}; };
return Err(RuntimeError::UnknownRecipes{recipes: missing, suggestion: suggestion}); return Err(RuntimeError::UnknownRecipes{recipes: missing, suggestion});
} }
let mut ran = empty(); let mut ran = empty();
for (recipe, arguments) in grouped { for (recipe, arguments) in grouped {
self.run_recipe(recipe, arguments, &scope, &mut ran, configuration)? self.run_recipe(recipe, arguments, &scope, &dotenv, configuration, &mut ran)?
} }
Ok(()) Ok(())
@ -123,15 +126,16 @@ impl<'a, 'b> Justfile<'a> where 'a: 'b {
recipe: &Recipe<'a>, recipe: &Recipe<'a>,
arguments: &[&'a str], arguments: &[&'a str],
scope: &Map<&'c str, String>, scope: &Map<&'c str, String>,
ran: &mut Set<&'a str>, dotenv: &Map<String, String>,
configuration: &Configuration<'a>, configuration: &Configuration<'a>,
ran: &mut Set<&'a str>,
) -> RunResult<()> { ) -> RunResult<()> {
for dependency_name in &recipe.dependencies { for dependency_name in &recipe.dependencies {
if !ran.contains(dependency_name) { if !ran.contains(dependency_name) {
self.run_recipe(&self.recipes[dependency_name], &[], scope, ran, configuration)?; self.run_recipe(&self.recipes[dependency_name], &[], scope, dotenv, configuration, ran)?;
} }
} }
recipe.run(arguments, scope, &self.exports, configuration)?; recipe.run(arguments, scope, dotenv, &self.exports, configuration)?;
ran.insert(recipe.name); ran.insert(recipe.name);
Ok(()) Ok(())
} }

View File

@ -41,12 +41,12 @@ impl<'a> Lexer<'a> {
pub fn lex(text: &'a str) -> CompilationResult<Vec<Token<'a>>> { pub fn lex(text: &'a str) -> CompilationResult<Vec<Token<'a>>> {
let lexer = Lexer{ let lexer = Lexer{
tokens: vec![], tokens: vec![],
text: text,
rest: text, rest: text,
index: 0, index: 0,
line: 0, line: 0,
column: 0, column: 0,
state: vec![State::Start], state: vec![State::Start],
text,
}; };
lexer.inner() lexer.inner()
@ -59,7 +59,7 @@ impl<'a> Lexer<'a> {
line: self.line, line: self.line,
column: self.column, column: self.column,
width: None, width: None,
kind: kind, kind,
} }
} }
@ -69,9 +69,9 @@ impl<'a> Lexer<'a> {
line: self.line, line: self.line,
column: self.column, column: self.column,
text: self.text, text: self.text,
prefix: prefix, prefix,
lexeme: lexeme, lexeme,
kind: kind, kind,
} }
} }

17
src/load_dotenv.rs Normal file
View File

@ -0,0 +1,17 @@
use common::*;
use dotenv;
pub fn load_dotenv() -> RunResult<'static, Map<String, String>> {
match dotenv::dotenv_iter() {
Ok(iter) => {
let result: dotenv::Result<Map<String, String>> = iter.collect();
result.map_err(|dotenv_error| RuntimeError::Dotenv{dotenv_error})
}
Err(dotenv_error) => if dotenv_error.not_found() {
Ok(Map::new())
} else {
Err(RuntimeError::Dotenv{dotenv_error})
}
}
}

View File

@ -3,6 +3,7 @@ extern crate lazy_static;
extern crate ansi_term; extern crate ansi_term;
extern crate brev; extern crate brev;
extern crate clap; extern crate clap;
extern crate dotenv;
extern crate edit_distance; extern crate edit_distance;
extern crate itertools; extern crate itertools;
extern crate libc; extern crate libc;
@ -22,6 +23,7 @@ mod command_ext;
mod compilation_error; mod compilation_error;
mod configuration; mod configuration;
mod cooked_string; mod cooked_string;
mod load_dotenv;
mod expression; mod expression;
mod fragment; mod fragment;
mod functions; mod functions;
@ -63,6 +65,8 @@ mod common {
pub use expression::Expression; pub use expression::Expression;
pub use fragment::Fragment; pub use fragment::Fragment;
pub use justfile::Justfile; pub use justfile::Justfile;
pub use lexer::Lexer;
pub use load_dotenv::load_dotenv;
pub use misc::{default, empty}; pub use misc::{default, empty};
pub use parameter::Parameter; pub use parameter::Parameter;
pub use parser::Parser; pub use parser::Parser;
@ -70,7 +74,6 @@ mod common {
pub use recipe::Recipe; pub use recipe::Recipe;
pub use recipe_resolver::RecipeResolver; pub use recipe_resolver::RecipeResolver;
pub use runtime_error::{RuntimeError, RunResult}; pub use runtime_error::{RuntimeError, RunResult};
pub use lexer::Lexer;
pub use shebang::Shebang; pub use shebang::Shebang;
pub use token::{Token, TokenKind}; pub use token::{Token, TokenKind};
} }

View File

@ -22,12 +22,12 @@ impl<'a> Parser<'a> {
pub fn new(text: &'a str, tokens: Vec<Token<'a>>) -> Parser<'a> { pub fn new(text: &'a str, tokens: Vec<Token<'a>>) -> Parser<'a> {
Parser { Parser {
text: text,
tokens: itertools::put_back(tokens), tokens: itertools::put_back(tokens),
recipes: empty(), recipes: empty(),
assignments: empty(), assignments: empty(),
assignment_tokens: empty(), assignment_tokens: empty(),
exports: empty(), exports: empty(),
text,
} }
} }
@ -151,10 +151,10 @@ impl<'a> Parser<'a> {
parsed_variadic_parameter = variadic; parsed_variadic_parameter = variadic;
parameters.push(Parameter { parameters.push(Parameter {
default: default,
name: parameter.lexeme, name: parameter.lexeme,
token: parameter, token: parameter,
variadic: variadic, default,
variadic,
}); });
} }
@ -237,13 +237,13 @@ impl<'a> Parser<'a> {
line_number: name.line, line_number: name.line,
name: name.lexeme, name: name.lexeme,
doc: doc.map(|t| t.lexeme[1..].trim()), doc: doc.map(|t| t.lexeme[1..].trim()),
dependencies: dependencies,
dependency_tokens: dependency_tokens,
parameters: parameters,
private: &name.lexeme[0..1] == "_", private: &name.lexeme[0..1] == "_",
lines: lines, dependencies,
shebang: shebang, dependency_tokens,
quiet: quiet, lines,
parameters,
quiet,
shebang,
}); });
Ok(()) Ok(())

View File

@ -12,8 +12,8 @@ fn error_from_signal(
exit_status: ExitStatus exit_status: ExitStatus
) -> RuntimeError { ) -> RuntimeError {
match Platform::signal_from_exit_status(exit_status) { match Platform::signal_from_exit_status(exit_status) {
Some(signal) => RuntimeError::Signal{recipe: recipe, line_number: line_number, signal: signal}, Some(signal) => RuntimeError::Signal{recipe, line_number, signal},
None => RuntimeError::Unknown{recipe: recipe, line_number: line_number}, None => RuntimeError::Unknown{recipe, line_number},
} }
} }
@ -52,6 +52,7 @@ impl<'a> Recipe<'a> {
&self, &self,
arguments: &[&'a str], arguments: &[&'a str],
scope: &Map<&'a str, String>, scope: &Map<&'a str, String>,
dotenv: &Map<String, String>,
exports: &Set<&'a str>, exports: &Set<&'a str>,
configuration: &Configuration, configuration: &Configuration,
) -> RunResult<'a, ()> { ) -> RunResult<'a, ()> {
@ -84,14 +85,15 @@ impl<'a> Recipe<'a> {
} }
let mut evaluator = AssignmentEvaluator { let mut evaluator = AssignmentEvaluator {
evaluated: empty(),
scope: scope,
exports: exports,
assignments: &empty(), assignments: &empty(),
dry_run: configuration.dry_run,
evaluated: empty(),
overrides: &empty(), overrides: &empty(),
quiet: configuration.quiet, quiet: configuration.quiet,
shell: configuration.shell, shell: configuration.shell,
dry_run: configuration.dry_run, dotenv,
exports,
scope,
}; };
if self.shebang { if self.shebang {
@ -153,13 +155,13 @@ impl<'a> Recipe<'a> {
let mut command = Platform::make_shebang_command(&path, interpreter, argument) let mut command = Platform::make_shebang_command(&path, interpreter, argument)
.map_err(|output_error| RuntimeError::Cygpath{recipe: self.name, output_error})?; .map_err(|output_error| RuntimeError::Cygpath{recipe: self.name, output_error})?;
command.export_environment_variables(scope, exports)?; command.export_environment_variables(scope, dotenv, exports)?;
// run it! // run it!
match command.status() { match command.status() {
Ok(exit_status) => if let Some(code) = exit_status.code() { Ok(exit_status) => if let Some(code) = exit_status.code() {
if code != 0 { if code != 0 {
return Err(RuntimeError::Code{recipe: self.name, line_number: None, code: code}) return Err(RuntimeError::Code{recipe: self.name, line_number: None, code})
} }
} else { } else {
return Err(error_from_signal(self.name, None, exit_status)) return Err(error_from_signal(self.name, None, exit_status))
@ -168,7 +170,7 @@ impl<'a> Recipe<'a> {
recipe: self.name, recipe: self.name,
command: interpreter.to_string(), command: interpreter.to_string(),
argument: argument.map(String::from), argument: argument.map(String::from),
io_error: io_error io_error,
}) })
}; };
} else { } else {
@ -228,20 +230,22 @@ impl<'a> Recipe<'a> {
cmd.stdout(Stdio::null()); cmd.stdout(Stdio::null());
} }
cmd.export_environment_variables(scope, exports)?; cmd.export_environment_variables(scope, dotenv, exports)?;
match cmd.status() { match cmd.status() {
Ok(exit_status) => if let Some(code) = exit_status.code() { Ok(exit_status) => if let Some(code) = exit_status.code() {
if code != 0 { if code != 0 {
return Err(RuntimeError::Code{ return Err(RuntimeError::Code{
recipe: self.name, line_number: Some(line_number), code: code recipe: self.name, line_number: Some(line_number), code,
}); });
} }
} else { } else {
return Err(error_from_signal(self.name, Some(line_number), exit_status)); return Err(error_from_signal(self.name, Some(line_number), exit_status));
}, },
Err(io_error) => return Err(RuntimeError::IoError{ Err(io_error) => return Err(RuntimeError::IoError{
recipe: self.name, io_error: io_error}), recipe: self.name,
io_error,
}),
}; };
} }
} }

View File

@ -16,10 +16,10 @@ impl<'a, 'b> RecipeResolver<'a, 'b> {
text: &'a str, text: &'a str,
) -> CompilationResult<'a, ()> { ) -> CompilationResult<'a, ()> {
let mut resolver = RecipeResolver { let mut resolver = RecipeResolver {
seen: empty(), seen: empty(),
stack: empty(), stack: empty(),
resolved: empty(), resolved: empty(),
recipes: recipes, recipes,
}; };
for recipe in recipes.values() { for recipe in recipes.values() {
@ -44,14 +44,14 @@ impl<'a, 'b> RecipeResolver<'a, 'b> {
for (function, argc) in expression.functions() { for (function, argc) in expression.functions() {
if let Err(error) = ::functions::resolve_function(function, argc) { if let Err(error) = ::functions::resolve_function(function, argc) {
return Err(CompilationError { return Err(CompilationError {
text: text,
index: error.index, index: error.index,
line: error.line, line: error.line,
column: error.column, column: error.column,
width: error.width, width: error.width,
kind: UnknownFunction { kind: UnknownFunction {
function: &text[error.index..error.index + error.width.unwrap()], function: &text[error.index..error.index + error.width.unwrap()],
} },
text,
}); });
} }
} }
@ -62,14 +62,14 @@ impl<'a, 'b> RecipeResolver<'a, 'b> {
if undefined { if undefined {
let error = variable.error(UndefinedVariable{variable: name}); let error = variable.error(UndefinedVariable{variable: name});
return Err(CompilationError { return Err(CompilationError {
text: text,
index: error.index, index: error.index,
line: error.line, line: error.line,
column: error.column, column: error.column,
width: error.width, width: error.width,
kind: UndefinedVariable { kind: UndefinedVariable {
variable: &text[error.index..error.index + error.width.unwrap()], variable: &text[error.index..error.index + error.width.unwrap()],
} },
text,
}); });
} }
} }

View File

@ -349,11 +349,11 @@ pub fn run() {
dry_run: matches.is_present("DRY-RUN"), dry_run: matches.is_present("DRY-RUN"),
evaluate: matches.is_present("EVALUATE"), evaluate: matches.is_present("EVALUATE"),
highlight: matches.is_present("HIGHLIGHT"), highlight: matches.is_present("HIGHLIGHT"),
overrides: overrides,
quiet: matches.is_present("QUIET"), quiet: matches.is_present("QUIET"),
shell: matches.value_of("SHELL").unwrap(), shell: matches.value_of("SHELL").unwrap(),
color: color,
verbose: matches.is_present("VERBOSE"), verbose: matches.is_present("VERBOSE"),
color,
overrides,
}; };
if let Err(run_error) = justfile.run(&arguments, &configuration) { if let Err(run_error) = justfile.run(&arguments, &configuration) {

View File

@ -1,5 +1,7 @@
use common::*; use common::*;
use dotenv;
use brev::OutputError; use brev::OutputError;
use misc::{And, Or, maybe_s, Tick, ticks, write_error_context}; use misc::{And, Or, maybe_s, Tick, ticks, write_error_context};
@ -25,6 +27,7 @@ pub enum RuntimeError<'a> {
Backtick{token: Token<'a>, output_error: OutputError}, Backtick{token: Token<'a>, output_error: OutputError},
Code{recipe: &'a str, line_number: Option<usize>, code: i32}, Code{recipe: &'a str, line_number: Option<usize>, code: i32},
Cygpath{recipe: &'a str, output_error: OutputError}, Cygpath{recipe: &'a str, output_error: OutputError},
Dotenv{dotenv_error: dotenv::Error},
FunctionCall{token: Token<'a>, message: String}, FunctionCall{token: Token<'a>, message: String},
Internal{message: String}, Internal{message: String},
IoError{recipe: &'a str, io_error: io::Error}, IoError{recipe: &'a str, io_error: io::Error},
@ -118,6 +121,9 @@ impl<'a> Display for RuntimeError<'a> {
but output was not utf8: {}", recipe, utf8_error)?; but output was not utf8: {}", recipe, utf8_error)?;
} }
}, },
Dotenv{ref dotenv_error} => {
write!(f, "Failed to load .env: {}\n", dotenv_error)?;
}
FunctionCall{ref token, ref message} => { FunctionCall{ref token, ref message} => {
write!(f, "Call to function `{}` failed: {}\n", token.lexeme, message)?; write!(f, "Call to function `{}` failed: {}\n", token.lexeme, message)?;
error_token = Some(token); error_token = Some(token);

View File

@ -14,12 +14,12 @@ pub struct Token<'a> {
impl<'a> Token<'a> { impl<'a> Token<'a> {
pub fn error(&self, kind: CompilationErrorKind<'a>) -> CompilationError<'a> { pub fn error(&self, kind: CompilationErrorKind<'a>) -> CompilationError<'a> {
CompilationError { CompilationError {
text: self.text, column: self.column + self.prefix.len(),
index: self.index + self.prefix.len(), index: self.index + self.prefix.len(),
line: self.line, line: self.line,
column: self.column + self.prefix.len(), text: self.text,
width: Some(self.lexeme.len()), width: Some(self.lexeme.len()),
kind: kind, kind,
} }
} }
} }

View File

@ -51,9 +51,14 @@ fn integration_test(
let tmp = TempDir::new("just-integration") let tmp = TempDir::new("just-integration")
.unwrap_or_else( .unwrap_or_else(
|err| panic!("integration test: failed to create temporary directory: {}", err)); |err| panic!("integration test: failed to create temporary directory: {}", err));
let mut path = tmp.path().to_path_buf();
path.push("justfile"); let mut justfile_path = tmp.path().to_path_buf();
brev::dump(path, justfile); justfile_path.push("justfile");
brev::dump(justfile_path, justfile);
let mut dotenv_path = tmp.path().to_path_buf();
dotenv_path.push(".env");
brev::dump(dotenv_path, "DOTENV_KEY=dotenv-value");
let output = process::Command::new(&executable_path("just")) let output = process::Command::new(&executable_path("just"))
.current_dir(tmp.path()) .current_dir(tmp.path())
@ -1739,3 +1744,30 @@ echo:
stderr: "echo 1\n", stderr: "echo 1\n",
status: EXIT_SUCCESS, status: EXIT_SUCCESS,
} }
integration_test! {
name: dotenv_variable_in_recipe,
justfile: "
#
echo:
echo $DOTENV_KEY
",
args: (),
stdout: "dotenv-value\n",
stderr: "echo $DOTENV_KEY\n",
status: EXIT_SUCCESS,
}
integration_test! {
name: dotenv_variable_in_backtick,
justfile: "
#
X=`echo $DOTENV_KEY`
echo:
echo {{X}}
",
args: (),
stdout: "dotenv-value\n",
stderr: "echo dotenv-value\n",
status: EXIT_SUCCESS,
}