Skip to content

Commit 85aa458

Browse files
committed
feat: set process as last argument in all commands (related to #18)
1 parent 6771b94 commit 85aa458

File tree

4 files changed

+36
-37
lines changed

4 files changed

+36
-37
lines changed

README.md

+10-11
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ This will start TUI, where you will be able to work with environment variables.
8888
Set environment variable and optionally run process.
8989

9090
Usage:
91-
`envfetch set <KEY> <VALUE> [PROCESS]`, where:
91+
`envfetch set <KEY> <VALUE> [-- <PROCESS>]`, where:
9292
- `KEY` - name of environment variable
9393
- `VALUE` - value of environment variable
9494
- `PROCESS` - name of process which you want to run (optional if --global is used)
@@ -101,14 +101,14 @@ Options:
101101

102102
For example:
103103
```shell
104-
$ envfetch set MY_VAR "Hello" "npm run" # temporary for process
105-
$ envfetch set MY_VAR "Hello" --global # permanent system-wide
104+
$ envfetch set MY_VAR "Hello" -- "npm run" # temporary for process
105+
$ envfetch set MY_VAR "Hello" --global # permanent system-wide
106106
```
107107
#### Add
108108
Add value to the end of environment variable and optionally run the process
109109

110110
Usage:
111-
`envfetch add <KEY> <VALUE> [PROCESS]`, where:
111+
`envfetch add <KEY> <VALUE> [-- <PROCESS>]`, where:
112112
- `KEY` - name of environment variable
113113
- `VALUE` - value of environment variable to add
114114
- `PROCESS` - name of process which you want to run (optional if --global is used)
@@ -121,8 +121,8 @@ Options:
121121

122122
For example:
123123
```shell
124-
$ envfetch add PATH "../hello.exe" "crago run" # temporary for process
125-
$ envfetch add MY_VAR "Hello" --global # permanent system-wide
124+
$ envfetch add PATH "../hello.exe" -- "cargo run" # temporary for process
125+
$ envfetch add MY_VAR "Hello" --global # permanent system-wide
126126
```
127127
#### Print
128128
Print all environment variables
@@ -164,7 +164,7 @@ It will print value of specified variable.
164164
Delete variable and optionally start process.
165165

166166
Usage:
167-
`envfetch delete <KEY> [PROCESS]`, where:
167+
`envfetch delete <KEY> [-- <PROCESS>]`, where:
168168
- `KEY` - name of environment variable
169169
- `PROCESS` - name of command to run (optional if --global is used)
170170

@@ -174,8 +174,8 @@ Options:
174174

175175
For example:
176176
```shell
177-
$ envfetch delete MY_VAR "npm run" # temporary for process
178-
$ envfetch delete MY_VAR --global # permanent system-wide
177+
$ envfetch delete MY_VAR -- "npm run" # temporary for process
178+
$ envfetch delete MY_VAR --global # permanent system-wide
179179
```
180180

181181
#### Load
@@ -193,7 +193,7 @@ By default, program loads variables from `.env` file in current directory.
193193

194194
For example:
195195
```shell
196-
$ envfetch load "npm run" # temporary for process
196+
$ envfetch load -- "npm run" # temporary for process
197197
$ envfetch load --global # permanent system-wide
198198
$ envfetch load --global --file .env.prod # permanent from specific file
199199
```
@@ -223,7 +223,6 @@ $ cd envfetch
223223
$ cargo run -- <COMMAND> <ARGS>
224224
```
225225
# See Also
226-
227226
- [codewars-api-rs](https://github.com/ankddev/codewars-api-rs) - Rust library for Codewars API
228227
- [conemu-progressbar-go](https://github.com/ankddev/conemu-progressbar-go) - Progress bar for ConEmu for Go
229228
- [terminal-go](https://github.com/ankddev/terminal-go) - Go library for working with ANSI/VT terminal sequences

src/main.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ mod tests {
6868

6969
#[test]
7070
fn test_set_command_simple() {
71-
let args = Cli::parse_from(["envfetch", "set", "VAR", "VALUE", "npm run"]);
71+
let args = Cli::parse_from(["envfetch", "set", "VAR", "VALUE", "--", "npm run"]);
7272
assert_eq!(
7373
args.command,
7474
Commands::Set(SetArgs {
@@ -96,7 +96,7 @@ mod tests {
9696

9797
#[test]
9898
fn test_set_command_with_global_flag_and_process() {
99-
let args = Cli::parse_from(["envfetch", "set", "VAR", "VALUE", "npm run", "--global"]);
99+
let args = Cli::parse_from(["envfetch", "set", "VAR", "VALUE", "--global", "--", "npm run"]);
100100
assert_eq!(
101101
args.command,
102102
Commands::Set(SetArgs {
@@ -110,7 +110,7 @@ mod tests {
110110

111111
#[test]
112112
fn test_add_command_simple() {
113-
let args = Cli::parse_from(["envfetch", "add", "PATH", "./executable", "npm run"]);
113+
let args = Cli::parse_from(["envfetch", "add", "PATH", "./executable", "--", "npm run"]);
114114
assert_eq!(
115115
args.command,
116116
Commands::Add(AddArgs {
@@ -143,8 +143,9 @@ mod tests {
143143
"add",
144144
"PATH",
145145
"./executable",
146-
"npm run",
147146
"--global",
147+
"--",
148+
"npm run",
148149
]);
149150
assert_eq!(
150151
args.command,
@@ -159,7 +160,7 @@ mod tests {
159160

160161
#[test]
161162
fn test_delete_command_simple() {
162-
let args = Cli::parse_from(["envfetch", "delete", "VAR", "npm run"]);
163+
let args = Cli::parse_from(["envfetch", "delete", "VAR", "--", "npm run"]);
163164
assert_eq!(
164165
args.command,
165166
Commands::Delete(DeleteArgs {
@@ -185,7 +186,7 @@ mod tests {
185186

186187
#[test]
187188
fn test_delete_command_with_global_flag_and_process() {
188-
let args = Cli::parse_from(["envfetch", "delete", "VAR", "npm run", "--global"]);
189+
let args = Cli::parse_from(["envfetch", "delete", "VAR", "--global", "--", "npm run"]);
189190
assert_eq!(
190191
args.command,
191192
Commands::Delete(DeleteArgs {

src/models.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ pub struct LoadArgs {
5858
#[arg(required = false, long, short)]
5959
pub global: bool,
6060
/// Process to start, not required if --global flag is set
61-
#[arg(required_unless_present = "global")]
61+
#[arg(last = true, required_unless_present = "global")]
6262
pub process: Option<String>,
6363
/// Relative or absolute path to file to read variables from.
6464
/// Note that it must be in .env format
@@ -79,7 +79,7 @@ pub struct SetArgs {
7979
#[arg(required = false, long, short)]
8080
pub global: bool,
8181
/// Process to start, not required if --global flag is set
82-
#[arg(required_unless_present = "global")]
82+
#[arg(last = true, required_unless_present = "global")]
8383
pub process: Option<String>,
8484
}
8585

@@ -96,7 +96,7 @@ pub struct AddArgs {
9696
#[arg(required = false, long, short)]
9797
pub global: bool,
9898
/// Process to start, not required if --global flag is set
99-
#[arg(required_unless_present = "global")]
99+
#[arg(last = true, required_unless_present = "global")]
100100
pub process: Option<String>,
101101
}
102102

@@ -110,7 +110,7 @@ pub struct DeleteArgs {
110110
#[arg(required = false, long, short)]
111111
pub global: bool,
112112
/// Process to start, not required if --global flag is set
113-
#[arg(required_unless_present = "global")]
113+
#[arg(last = true, required_unless_present = "global")]
114114
pub process: Option<String>,
115115
}
116116

tests/cli.rs

+15-16
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ fn set_command_success() -> Result<(), Box<dyn std::error::Error>> {
1515
cmd.arg("set").arg("MY_VAR").arg("Hello");
1616
// Windows
1717
#[cfg(target_os = "windows")]
18-
cmd.arg("echo %MY_VAR%")
18+
cmd.arg("--").arg("echo %MY_VAR%")
1919
.assert()
2020
.success()
2121
.stdout(predicate::str::contains("Hello"));
2222

2323
// Linux and macOS
2424
#[cfg(not(target_os = "windows"))]
25-
cmd.arg("echo $MY_VAR")
25+
cmd.arg("--").arg("echo $MY_VAR")
2626
.assert()
2727
.success()
2828
.stdout(predicate::str::contains("Hello"));
@@ -36,15 +36,14 @@ fn set_command_failure() -> Result<(), Box<dyn std::error::Error>> {
3636
let mut cmd = Command::cargo_bin("envfetch")?;
3737
cmd.arg("set").arg("MY_VARR").arg("Hello");
3838
// We can use only Windows command here because it should fail
39-
cmd.arg("%MY_VARIABLE%").assert().failure();
39+
cmd.arg("--").arg("%MY_VARIABLE%").assert().failure();
4040
Ok(())
4141
}
4242

4343
#[test]
4444
/// Test for get command if specified variable exists
4545
fn get_variable_exists() -> Result<(), Box<dyn std::error::Error>> {
4646
let mut cmd = Command::cargo_bin("envfetch")?;
47-
// TODO: Audit that the environment access only happens in single-threaded code.
4847
unsafe { env::set_var("MY_VAR", "Hello") };
4948
cmd.arg("get").arg("MY_VAR");
5049
cmd.assert()
@@ -67,7 +66,6 @@ fn get_variable_doesnt_exists() -> Result<(), Box<dyn std::error::Error>> {
6766
#[test]
6867
/// Test for get command if specified variable doesn't exist and showing similar variables is enabled
6968
fn get_variable_doesnt_exists_similar_enabled() -> Result<(), Box<dyn std::error::Error>> {
70-
// TODO: Audit that the environment access only happens in single-threaded code.
7169
unsafe { env::set_var("MY_VARIABLEE", "Hello") };
7270
let mut cmd = Command::cargo_bin("envfetch")?;
7371
cmd.arg("get").arg("MY_VARIABLE");
@@ -85,7 +83,6 @@ fn get_variable_doesnt_exists_similar_enabled() -> Result<(), Box<dyn std::error
8583
/// Test for get command if specified variable doesn't exist and showing similar variables is disabled
8684
fn get_variable_doesnt_exists_similar_disabled() -> Result<(), Box<dyn std::error::Error>> {
8785
let mut cmd = Command::cargo_bin("envfetch")?;
88-
// TODO: Audit that the environment access only happens in single-threaded code.
8986
unsafe { env::set_var("MY_VARIABLEE", "Hello") };
9087
cmd.arg("get").arg("MY_VARIABLE").arg("--no-similar-names");
9188
cmd.assert().failure();
@@ -96,7 +93,6 @@ fn get_variable_doesnt_exists_similar_disabled() -> Result<(), Box<dyn std::erro
9693
/// Test for print command
9794
fn print_success() -> Result<(), Box<dyn std::error::Error>> {
9895
let mut cmd = Command::cargo_bin("envfetch")?;
99-
// TODO: Audit that the environment access only happens in single-threaded code.
10096
unsafe { env::set_var("PRINT_TEST", "Print") };
10197
cmd.arg("print")
10298
.assert()
@@ -109,12 +105,11 @@ fn print_success() -> Result<(), Box<dyn std::error::Error>> {
109105
/// Test for delete command if specified process is successful
110106
fn delete_command_success() -> Result<(), Box<dyn std::error::Error>> {
111107
let mut cmd = Command::cargo_bin("envfetch")?;
112-
// TODO: Audit that the environment access only happens in single-threaded code.
113108
unsafe { env::set_var("MY_VAR", "Hello") };
114109
cmd.arg("delete").arg("MY_VAR");
115110
// Windows
116111
#[cfg(target_os = "windows")]
117-
cmd.arg("echo 'Hello'")
112+
cmd.arg("--").arg("echo 'Hello'")
118113
.assert()
119114
.success()
120115
.stdout(predicate::str::contains("Hello"));
@@ -137,14 +132,14 @@ fn load_custom_file_exists() -> Result<(), Box<dyn std::error::Error>> {
137132
cmd.arg("load").arg("--file").arg(file.path());
138133
// Windows
139134
#[cfg(target_os = "windows")]
140-
cmd.arg("echo %MY_ENV_VAR%")
135+
cmd.arg("--").arg("echo %MY_ENV_VAR%")
141136
.assert()
142137
.success()
143138
.stdout(predicate::str::contains("TEST"));
144139

145140
// Linux and macOS
146141
#[cfg(not(target_os = "windows"))]
147-
cmd.arg("echo $MY_ENV_VAR")
142+
cmd.arg("--").arg("echo $MY_ENV_VAR")
148143
.assert()
149144
.success()
150145
.stdout(predicate::str::contains("TEST"));
@@ -163,14 +158,14 @@ fn load_custom_file_exists_command_failed() -> Result<(), Box<dyn std::error::Er
163158
cmd.arg("load").arg("--file").arg(file.path());
164159
// Windows
165160
#[cfg(target_os = "windows")]
166-
cmd.arg("echo %MY_ENV_VAR_TEST%")
161+
cmd.arg("--").arg("echo %MY_ENV_VAR_TEST%")
167162
.assert()
168163
.success()
169164
.stdout(predicate::str::contains("%MY_ENV_VAR_TEST%"));
170165

171166
// Linux and macOS
172167
#[cfg(not(target_os = "windows"))]
173-
cmd.arg("(exit 1)").assert().failure();
168+
cmd.arg("--").arg("(exit 1)").assert().failure();
174169
// Close file after test
175170
file.close().unwrap();
176171
Ok(())
@@ -183,11 +178,11 @@ fn load_custom_file_doesnt_exists() -> Result<(), Box<dyn std::error::Error>> {
183178
cmd.arg("load").arg("--file").arg(".env.production");
184179
// Windows
185180
#[cfg(target_os = "windows")]
186-
cmd.arg("echo %MY_ENV_VAR%").assert().failure();
181+
cmd.arg("--").arg("echo %MY_ENV_VAR%").assert().failure();
187182

188183
// Linux and macOS
189184
#[cfg(not(target_os = "windows"))]
190-
cmd.arg("echo $MY_VARIABLE").assert().failure();
185+
cmd.arg("--").arg("echo $MY_VARIABLE").assert().failure();
191186
Ok(())
192187
}
193188

@@ -203,6 +198,7 @@ fn test_add_local_variable() -> Result<(), Box<dyn std::error::Error>> {
203198
"add",
204199
"TEST_VAR",
205200
"test_value",
201+
"--",
206202
&format!("{} get TEST_VAR", envfetch),
207203
])
208204
.assert()
@@ -224,6 +220,7 @@ fn test_add_variable_with_special_characters() -> Result<(), Box<dyn std::error:
224220
"add",
225221
"SPECIAL_VAR",
226222
"test@#$%^&*",
223+
"--",
227224
&format!("{} get SPECIAL_VAR", envfetch),
228225
])
229226
.assert()
@@ -245,6 +242,7 @@ fn test_add_empty_value() -> Result<(), Box<dyn std::error::Error>> {
245242
"add",
246243
"EMPTY_VAR",
247244
"",
245+
"--",
248246
&format!("{} get EMPTY_VAR", envfetch),
249247
])
250248
.assert()
@@ -257,7 +255,7 @@ fn test_add_empty_value() -> Result<(), Box<dyn std::error::Error>> {
257255
#[test]
258256
fn test_add_invalid_variable_name() -> Result<(), Box<dyn std::error::Error>> {
259257
let mut cmd = Command::cargo_bin("envfetch")?;
260-
cmd.args(["add", "INVALID NAME", "test_value", "echo test"])
258+
cmd.args(["add", "INVALID NAME", "test_value", "--", "echo test"])
261259
.assert()
262260
.failure()
263261
.stderr(predicates::str::contains(
@@ -285,6 +283,7 @@ fn test_add_with_process() -> Result<(), Box<dyn std::error::Error>> {
285283
"add",
286284
"PROCESS_VAR",
287285
"test_value",
286+
"--",
288287
&format!("{} get PROCESS_VAR", envfetch),
289288
])
290289
.assert()

0 commit comments

Comments
 (0)