Add dotenv integration (#306)
This commit is contained in:
parent
ec56336df7
commit
70234f6193
135
Cargo.lock
generated
135
Cargo.lock
generated
@ -11,6 +11,14 @@ name = "ansi_term"
|
||||
version = "0.10.2"
|
||||
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]]
|
||||
name = "assert_matches"
|
||||
version = "1.1.0"
|
||||
@ -21,11 +29,32 @@ name = "atty"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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)",
|
||||
"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]]
|
||||
name = "bitflags"
|
||||
version = "1.0.1"
|
||||
@ -40,6 +69,16 @@ dependencies = [
|
||||
"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]]
|
||||
name = "clap"
|
||||
version = "2.30.0"
|
||||
@ -54,6 +93,25 @@ dependencies = [
|
||||
"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]]
|
||||
name = "edit-distance"
|
||||
version = "2.0.1"
|
||||
@ -64,6 +122,14 @@ name = "either"
|
||||
version = "1.4.0"
|
||||
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]]
|
||||
name = "executable-path"
|
||||
version = "1.0.0"
|
||||
@ -90,7 +156,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.7.6"
|
||||
version = "0.7.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -100,16 +166,17 @@ dependencies = [
|
||||
name = "just"
|
||||
version = "0.3.8"
|
||||
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)",
|
||||
"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)",
|
||||
"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)",
|
||||
"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)",
|
||||
"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)",
|
||||
"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)",
|
||||
@ -132,7 +199,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.36"
|
||||
version = "0.2.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
@ -140,16 +207,21 @@ name = "memchr"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "rand"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"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)",
|
||||
]
|
||||
|
||||
@ -192,11 +264,34 @@ dependencies = [
|
||||
"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]]
|
||||
name = "strsim"
|
||||
version = "0.7.0"
|
||||
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]]
|
||||
name = "target"
|
||||
version = "1.0.0"
|
||||
@ -216,7 +311,7 @@ name = "termion"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -243,6 +338,11 @@ name = "unicode-width"
|
||||
version = "0.1.4"
|
||||
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]]
|
||||
name = "unreachable"
|
||||
version = "1.0.0"
|
||||
@ -298,35 +398,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
[metadata]
|
||||
"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.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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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"
|
||||
|
@ -8,11 +8,12 @@ homepage = "https://github.com/casey/just"
|
||||
readme = "crates-io-readme.md"
|
||||
|
||||
[dependencies]
|
||||
ansi_term = "0.10"
|
||||
ansi_term = "0.11"
|
||||
assert_matches = "1.1.0"
|
||||
atty = "0.2.1"
|
||||
brev = "0.1.6"
|
||||
clap = "2.0.0"
|
||||
dotenv = "0.11.0"
|
||||
edit-distance = "2.0.0"
|
||||
itertools = "0.7"
|
||||
lazy_static = "1.0.0"
|
||||
|
28
README.adoc
28
README.adoc
@ -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.
|
||||
|
||||
==== 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
|
||||
|
||||
Backticks can be used to store the result of commands:
|
||||
|
@ -4,32 +4,35 @@ use brev;
|
||||
|
||||
pub struct AssignmentEvaluator<'a: 'b, 'b> {
|
||||
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 exports: &'b Set<&'a str>,
|
||||
pub overrides: &'b Map<&'b str, &'b str>,
|
||||
pub quiet: bool,
|
||||
pub scope: &'b Map<&'a str, String>,
|
||||
pub shell: &'b str,
|
||||
pub dry_run: bool,
|
||||
}
|
||||
|
||||
impl<'a, 'b> AssignmentEvaluator<'a, 'b> {
|
||||
pub fn evaluate_assignments(
|
||||
assignments: &Map<&'a str, Expression<'a>>,
|
||||
dotenv: &'b Map<String, String>,
|
||||
overrides: &Map<&str, &str>,
|
||||
quiet: bool,
|
||||
shell: &'a str,
|
||||
dry_run: bool,
|
||||
) -> RunResult<'a, Map<&'a str, String>> {
|
||||
let mut evaluator = AssignmentEvaluator {
|
||||
assignments: assignments,
|
||||
evaluated: empty(),
|
||||
exports: &empty(),
|
||||
overrides: overrides,
|
||||
quiet: quiet,
|
||||
scope: &empty(),
|
||||
shell: shell,
|
||||
dry_run: dry_run,
|
||||
evaluated: empty(),
|
||||
exports: &empty(),
|
||||
scope: &empty(),
|
||||
assignments,
|
||||
dotenv,
|
||||
dry_run,
|
||||
overrides,
|
||||
quiet,
|
||||
shell,
|
||||
};
|
||||
|
||||
for name in assignments.keys() {
|
||||
@ -110,7 +113,7 @@ impl<'a, 'b> AssignmentEvaluator<'a, 'b> {
|
||||
if self.dry_run {
|
||||
Ok(format!("`{}`", raw))
|
||||
} else {
|
||||
Ok(self.run_backtick(raw, token)?)
|
||||
Ok(self.run_backtick(self.dotenv, raw, token)?)
|
||||
}
|
||||
}
|
||||
Expression::Concatination{ref lhs, ref rhs} => {
|
||||
@ -125,12 +128,13 @@ impl<'a, 'b> AssignmentEvaluator<'a, 'b> {
|
||||
|
||||
fn run_backtick(
|
||||
&self,
|
||||
dotenv: &Map<String, String>,
|
||||
raw: &str,
|
||||
token: &Token<'a>,
|
||||
) -> RunResult<'a, String> {
|
||||
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")
|
||||
.arg(raw);
|
||||
|
@ -17,11 +17,11 @@ impl<'a: 'b, 'b> AssignmentResolver<'a, 'b> {
|
||||
) -> CompilationResult<'a, ()> {
|
||||
|
||||
let mut resolver = AssignmentResolver {
|
||||
assignments: assignments,
|
||||
assignment_tokens: assignment_tokens,
|
||||
stack: empty(),
|
||||
seen: empty(),
|
||||
evaluated: empty(),
|
||||
stack: empty(),
|
||||
seen: empty(),
|
||||
evaluated: empty(),
|
||||
assignments,
|
||||
assignment_tokens,
|
||||
};
|
||||
|
||||
for name in assignments.keys() {
|
||||
|
@ -35,7 +35,7 @@ impl Default for Color {
|
||||
impl Color {
|
||||
fn restyle(self, style: Style) -> Color {
|
||||
Color {
|
||||
style: style,
|
||||
style,
|
||||
..self
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,8 @@ use common::*;
|
||||
pub trait CommandExt {
|
||||
fn export_environment_variables<'a>(
|
||||
&mut self,
|
||||
scope: &Map<&'a str, String>,
|
||||
scope: &Map<&'a str, String>,
|
||||
dotenv: &Map<String, String>,
|
||||
exports: &Set<&'a str>
|
||||
) -> RunResult<'a, ()>;
|
||||
}
|
||||
@ -11,9 +12,13 @@ pub trait CommandExt {
|
||||
impl CommandExt for Command {
|
||||
fn export_environment_variables<'a>(
|
||||
&mut self,
|
||||
scope: &Map<&'a str, String>,
|
||||
scope: &Map<&'a str, String>,
|
||||
dotenv: &Map<String, String>,
|
||||
exports: &Set<&'a str>
|
||||
) -> RunResult<'a, ()> {
|
||||
for (name, value) in dotenv {
|
||||
self.env(name, value);
|
||||
}
|
||||
for name in exports {
|
||||
if let Some(value) = scope.get(name) {
|
||||
self.env(name, value);
|
||||
|
@ -11,7 +11,7 @@ impl<'a> CookedString<'a> {
|
||||
let raw = &token.lexeme[1..token.lexeme.len()-1];
|
||||
|
||||
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 {
|
||||
let mut cooked = String::new();
|
||||
let mut escape = false;
|
||||
@ -36,7 +36,7 @@ impl<'a> CookedString<'a> {
|
||||
}
|
||||
cooked.push(c);
|
||||
}
|
||||
Ok(CookedString{raw: raw, cooked: cooked})
|
||||
Ok(CookedString{raw, cooked})
|
||||
} else {
|
||||
Err(token.error(CompilationErrorKind::Internal {
|
||||
message: "cook_string() called on non-string token".to_string()
|
||||
|
@ -53,8 +53,11 @@ impl<'a, 'b> Justfile<'a> where 'a: 'b {
|
||||
return Err(RuntimeError::UnknownOverrides{overrides: unknown_overrides});
|
||||
}
|
||||
|
||||
let dotenv = load_dotenv()?;
|
||||
|
||||
let scope = AssignmentEvaluator::evaluate_assignments(
|
||||
&self.assignments,
|
||||
&dotenv,
|
||||
&configuration.overrides,
|
||||
configuration.quiet,
|
||||
configuration.shell,
|
||||
@ -107,12 +110,12 @@ impl<'a, 'b> Justfile<'a> where 'a: 'b {
|
||||
} else {
|
||||
None
|
||||
};
|
||||
return Err(RuntimeError::UnknownRecipes{recipes: missing, suggestion: suggestion});
|
||||
return Err(RuntimeError::UnknownRecipes{recipes: missing, suggestion});
|
||||
}
|
||||
|
||||
let mut ran = empty();
|
||||
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(())
|
||||
@ -123,15 +126,16 @@ impl<'a, 'b> Justfile<'a> where 'a: 'b {
|
||||
recipe: &Recipe<'a>,
|
||||
arguments: &[&'a str],
|
||||
scope: &Map<&'c str, String>,
|
||||
ran: &mut Set<&'a str>,
|
||||
dotenv: &Map<String, String>,
|
||||
configuration: &Configuration<'a>,
|
||||
ran: &mut Set<&'a str>,
|
||||
) -> RunResult<()> {
|
||||
for dependency_name in &recipe.dependencies {
|
||||
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);
|
||||
Ok(())
|
||||
}
|
||||
|
10
src/lexer.rs
10
src/lexer.rs
@ -41,12 +41,12 @@ impl<'a> Lexer<'a> {
|
||||
pub fn lex(text: &'a str) -> CompilationResult<Vec<Token<'a>>> {
|
||||
let lexer = Lexer{
|
||||
tokens: vec![],
|
||||
text: text,
|
||||
rest: text,
|
||||
index: 0,
|
||||
line: 0,
|
||||
column: 0,
|
||||
state: vec![State::Start],
|
||||
text,
|
||||
};
|
||||
|
||||
lexer.inner()
|
||||
@ -59,7 +59,7 @@ impl<'a> Lexer<'a> {
|
||||
line: self.line,
|
||||
column: self.column,
|
||||
width: None,
|
||||
kind: kind,
|
||||
kind,
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,9 +69,9 @@ impl<'a> Lexer<'a> {
|
||||
line: self.line,
|
||||
column: self.column,
|
||||
text: self.text,
|
||||
prefix: prefix,
|
||||
lexeme: lexeme,
|
||||
kind: kind,
|
||||
prefix,
|
||||
lexeme,
|
||||
kind,
|
||||
}
|
||||
}
|
||||
|
||||
|
17
src/load_dotenv.rs
Normal file
17
src/load_dotenv.rs
Normal 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})
|
||||
}
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ extern crate lazy_static;
|
||||
extern crate ansi_term;
|
||||
extern crate brev;
|
||||
extern crate clap;
|
||||
extern crate dotenv;
|
||||
extern crate edit_distance;
|
||||
extern crate itertools;
|
||||
extern crate libc;
|
||||
@ -22,6 +23,7 @@ mod command_ext;
|
||||
mod compilation_error;
|
||||
mod configuration;
|
||||
mod cooked_string;
|
||||
mod load_dotenv;
|
||||
mod expression;
|
||||
mod fragment;
|
||||
mod functions;
|
||||
@ -63,6 +65,8 @@ mod common {
|
||||
pub use expression::Expression;
|
||||
pub use fragment::Fragment;
|
||||
pub use justfile::Justfile;
|
||||
pub use lexer::Lexer;
|
||||
pub use load_dotenv::load_dotenv;
|
||||
pub use misc::{default, empty};
|
||||
pub use parameter::Parameter;
|
||||
pub use parser::Parser;
|
||||
@ -70,7 +74,6 @@ mod common {
|
||||
pub use recipe::Recipe;
|
||||
pub use recipe_resolver::RecipeResolver;
|
||||
pub use runtime_error::{RuntimeError, RunResult};
|
||||
pub use lexer::Lexer;
|
||||
pub use shebang::Shebang;
|
||||
pub use token::{Token, TokenKind};
|
||||
}
|
||||
|
@ -22,12 +22,12 @@ impl<'a> Parser<'a> {
|
||||
|
||||
pub fn new(text: &'a str, tokens: Vec<Token<'a>>) -> Parser<'a> {
|
||||
Parser {
|
||||
text: text,
|
||||
tokens: itertools::put_back(tokens),
|
||||
recipes: empty(),
|
||||
assignments: empty(),
|
||||
assignment_tokens: empty(),
|
||||
exports: empty(),
|
||||
text,
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,10 +151,10 @@ impl<'a> Parser<'a> {
|
||||
parsed_variadic_parameter = variadic;
|
||||
|
||||
parameters.push(Parameter {
|
||||
default: default,
|
||||
name: parameter.lexeme,
|
||||
token: parameter,
|
||||
variadic: variadic,
|
||||
default,
|
||||
variadic,
|
||||
});
|
||||
}
|
||||
|
||||
@ -237,13 +237,13 @@ impl<'a> Parser<'a> {
|
||||
line_number: name.line,
|
||||
name: name.lexeme,
|
||||
doc: doc.map(|t| t.lexeme[1..].trim()),
|
||||
dependencies: dependencies,
|
||||
dependency_tokens: dependency_tokens,
|
||||
parameters: parameters,
|
||||
private: &name.lexeme[0..1] == "_",
|
||||
lines: lines,
|
||||
shebang: shebang,
|
||||
quiet: quiet,
|
||||
dependencies,
|
||||
dependency_tokens,
|
||||
lines,
|
||||
parameters,
|
||||
quiet,
|
||||
shebang,
|
||||
});
|
||||
|
||||
Ok(())
|
||||
|
@ -12,8 +12,8 @@ fn error_from_signal(
|
||||
exit_status: ExitStatus
|
||||
) -> RuntimeError {
|
||||
match Platform::signal_from_exit_status(exit_status) {
|
||||
Some(signal) => RuntimeError::Signal{recipe: recipe, line_number: line_number, signal: signal},
|
||||
None => RuntimeError::Unknown{recipe: recipe, line_number: line_number},
|
||||
Some(signal) => RuntimeError::Signal{recipe, line_number, signal},
|
||||
None => RuntimeError::Unknown{recipe, line_number},
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,6 +52,7 @@ impl<'a> Recipe<'a> {
|
||||
&self,
|
||||
arguments: &[&'a str],
|
||||
scope: &Map<&'a str, String>,
|
||||
dotenv: &Map<String, String>,
|
||||
exports: &Set<&'a str>,
|
||||
configuration: &Configuration,
|
||||
) -> RunResult<'a, ()> {
|
||||
@ -84,14 +85,15 @@ impl<'a> Recipe<'a> {
|
||||
}
|
||||
|
||||
let mut evaluator = AssignmentEvaluator {
|
||||
evaluated: empty(),
|
||||
scope: scope,
|
||||
exports: exports,
|
||||
assignments: &empty(),
|
||||
dry_run: configuration.dry_run,
|
||||
evaluated: empty(),
|
||||
overrides: &empty(),
|
||||
quiet: configuration.quiet,
|
||||
shell: configuration.shell,
|
||||
dry_run: configuration.dry_run,
|
||||
dotenv,
|
||||
exports,
|
||||
scope,
|
||||
};
|
||||
|
||||
if self.shebang {
|
||||
@ -153,13 +155,13 @@ impl<'a> Recipe<'a> {
|
||||
let mut command = Platform::make_shebang_command(&path, interpreter, argument)
|
||||
.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!
|
||||
match command.status() {
|
||||
Ok(exit_status) => if let Some(code) = exit_status.code() {
|
||||
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 {
|
||||
return Err(error_from_signal(self.name, None, exit_status))
|
||||
@ -168,7 +170,7 @@ impl<'a> Recipe<'a> {
|
||||
recipe: self.name,
|
||||
command: interpreter.to_string(),
|
||||
argument: argument.map(String::from),
|
||||
io_error: io_error
|
||||
io_error,
|
||||
})
|
||||
};
|
||||
} else {
|
||||
@ -228,20 +230,22 @@ impl<'a> Recipe<'a> {
|
||||
cmd.stdout(Stdio::null());
|
||||
}
|
||||
|
||||
cmd.export_environment_variables(scope, exports)?;
|
||||
cmd.export_environment_variables(scope, dotenv, exports)?;
|
||||
|
||||
match cmd.status() {
|
||||
Ok(exit_status) => if let Some(code) = exit_status.code() {
|
||||
if code != 0 {
|
||||
return Err(RuntimeError::Code{
|
||||
recipe: self.name, line_number: Some(line_number), code: code
|
||||
recipe: self.name, line_number: Some(line_number), code,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return Err(error_from_signal(self.name, Some(line_number), exit_status));
|
||||
},
|
||||
Err(io_error) => return Err(RuntimeError::IoError{
|
||||
recipe: self.name, io_error: io_error}),
|
||||
recipe: self.name,
|
||||
io_error,
|
||||
}),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -16,10 +16,10 @@ impl<'a, 'b> RecipeResolver<'a, 'b> {
|
||||
text: &'a str,
|
||||
) -> CompilationResult<'a, ()> {
|
||||
let mut resolver = RecipeResolver {
|
||||
seen: empty(),
|
||||
stack: empty(),
|
||||
resolved: empty(),
|
||||
recipes: recipes,
|
||||
seen: empty(),
|
||||
stack: empty(),
|
||||
resolved: empty(),
|
||||
recipes,
|
||||
};
|
||||
|
||||
for recipe in recipes.values() {
|
||||
@ -44,14 +44,14 @@ impl<'a, 'b> RecipeResolver<'a, 'b> {
|
||||
for (function, argc) in expression.functions() {
|
||||
if let Err(error) = ::functions::resolve_function(function, argc) {
|
||||
return Err(CompilationError {
|
||||
text: text,
|
||||
index: error.index,
|
||||
line: error.line,
|
||||
column: error.column,
|
||||
width: error.width,
|
||||
kind: UnknownFunction {
|
||||
function: &text[error.index..error.index + error.width.unwrap()],
|
||||
}
|
||||
},
|
||||
text,
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -62,14 +62,14 @@ impl<'a, 'b> RecipeResolver<'a, 'b> {
|
||||
if undefined {
|
||||
let error = variable.error(UndefinedVariable{variable: name});
|
||||
return Err(CompilationError {
|
||||
text: text,
|
||||
index: error.index,
|
||||
line: error.line,
|
||||
column: error.column,
|
||||
width: error.width,
|
||||
kind: UndefinedVariable {
|
||||
variable: &text[error.index..error.index + error.width.unwrap()],
|
||||
}
|
||||
},
|
||||
text,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -349,11 +349,11 @@ pub fn run() {
|
||||
dry_run: matches.is_present("DRY-RUN"),
|
||||
evaluate: matches.is_present("EVALUATE"),
|
||||
highlight: matches.is_present("HIGHLIGHT"),
|
||||
overrides: overrides,
|
||||
quiet: matches.is_present("QUIET"),
|
||||
shell: matches.value_of("SHELL").unwrap(),
|
||||
color: color,
|
||||
verbose: matches.is_present("VERBOSE"),
|
||||
color,
|
||||
overrides,
|
||||
};
|
||||
|
||||
if let Err(run_error) = justfile.run(&arguments, &configuration) {
|
||||
|
@ -1,5 +1,7 @@
|
||||
use common::*;
|
||||
|
||||
use dotenv;
|
||||
|
||||
use brev::OutputError;
|
||||
|
||||
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},
|
||||
Code{recipe: &'a str, line_number: Option<usize>, code: i32},
|
||||
Cygpath{recipe: &'a str, output_error: OutputError},
|
||||
Dotenv{dotenv_error: dotenv::Error},
|
||||
FunctionCall{token: Token<'a>, message: String},
|
||||
Internal{message: String},
|
||||
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)?;
|
||||
}
|
||||
},
|
||||
Dotenv{ref dotenv_error} => {
|
||||
write!(f, "Failed to load .env: {}\n", dotenv_error)?;
|
||||
}
|
||||
FunctionCall{ref token, ref message} => {
|
||||
write!(f, "Call to function `{}` failed: {}\n", token.lexeme, message)?;
|
||||
error_token = Some(token);
|
||||
|
@ -14,12 +14,12 @@ pub struct Token<'a> {
|
||||
impl<'a> Token<'a> {
|
||||
pub fn error(&self, kind: CompilationErrorKind<'a>) -> CompilationError<'a> {
|
||||
CompilationError {
|
||||
text: self.text,
|
||||
column: self.column + self.prefix.len(),
|
||||
index: self.index + self.prefix.len(),
|
||||
line: self.line,
|
||||
column: self.column + self.prefix.len(),
|
||||
text: self.text,
|
||||
width: Some(self.lexeme.len()),
|
||||
kind: kind,
|
||||
kind,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -51,9 +51,14 @@ fn integration_test(
|
||||
let tmp = TempDir::new("just-integration")
|
||||
.unwrap_or_else(
|
||||
|err| panic!("integration test: failed to create temporary directory: {}", err));
|
||||
let mut path = tmp.path().to_path_buf();
|
||||
path.push("justfile");
|
||||
brev::dump(path, justfile);
|
||||
|
||||
let mut justfile_path = tmp.path().to_path_buf();
|
||||
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"))
|
||||
.current_dir(tmp.path())
|
||||
@ -1739,3 +1744,30 @@ echo:
|
||||
stderr: "echo 1\n",
|
||||
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,
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user