Skip to content

Commit 8167994

Browse files
committed
feat: add ability to globally work with environment variables
1 parent a5af494 commit 8167994

File tree

5 files changed

+307
-26
lines changed

5 files changed

+307
-26
lines changed

Cargo.lock

+19
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ similar-string = "1.4.3"
2020
subprocess = "0.2.9"
2121
# Parsing dotenv-style files
2222
dotenv-parser = "0.1.3"
23+
# Globally setting variables
24+
globalenv = "0.4.2"
2325

2426
[dev-dependencies]
2527
# Asserting CLI programs

README.md

+4-9
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,9 @@
1515
- [x] Print all environment variables
1616
- [x] Get value of variable by name
1717
- [x] Show similar variables if variable not found
18-
- [x] Set variable
19-
- [x] Delete variable
20-
- [x] Load variables from dotenv-style file
21-
- [ ] Globally set variables
22-
- [ ] Globally delete variables
23-
- [ ] Globally load variables from dotenv-style file
18+
- [x] Set variable (temporary and permanent)
19+
- [x] Delete variable (temporary and permanent)
20+
- [x] Load variables from dotenv-style file (temporary and permanent)
2421
- [ ] Set and delete multiple variables at once
2522
# Get started
2623
## Installing
@@ -42,11 +39,9 @@ You can run `envfetch help` to see help message or `envfetch --version` to see p
4239
### Command list
4340
#### Set
4441
Set environment variable and run process.
45-
> [!NOTE]
46-
> Now variable sets only for one run
4742

4843
Usage:
49-
`envfetch set <KEY> <VALUE> <PROCESS>`, where:
44+
`envfetch set <KEY> <VALUE> [PROCESS]`, where:
5045
- `KEY` - name of environment variable
5146
- `VALUE` - value of environment variable
5247
- `PROCESS` - name of process which you want to run

src/main.rs

+69-17
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,12 @@ pub struct GetArgs {
6363

6464
#[derive(Args, Debug)]
6565
pub struct LoadArgs {
66-
/// Process to start
67-
#[arg(required = true)]
68-
process: String,
66+
/// Globally set variable
67+
#[arg(required = false, long, short)]
68+
global: bool,
69+
/// Process to start, not required if --global flag is set
70+
#[arg(required_unless_present = "global")]
71+
process: Option<String>,
6972
/// Relative or absolute path to file to read variables from.
7073
/// Note that it must in .env format
7174
#[arg(long, short, default_value = ".env")]
@@ -81,9 +84,12 @@ pub struct SetArgs {
8184
/// Value for environment variable
8285
#[arg(required = true)]
8386
value: String,
84-
/// Process to start
85-
#[arg(required = true)]
86-
process: String,
87+
/// Globally set variable
88+
#[arg(required = false, long, short)]
89+
global: bool,
90+
/// Process to start, not required if --global flag is set
91+
#[arg(required_unless_present = "global")]
92+
process: Option<String>,
8793
}
8894

8995
/// Args for delete command
@@ -92,9 +98,19 @@ pub struct DeleteArgs {
9298
/// Environment variable name
9399
#[arg(required = true)]
94100
key: String,
95-
/// Process to start
96-
#[arg(required = true)]
97-
process: String,
101+
/// Globally set variable
102+
#[arg(required = false, long, short)]
103+
global: bool,
104+
/// Process to start, not required if --global flag is set
105+
#[arg(required_unless_present = "global")]
106+
process: Option<String>,
107+
}
108+
109+
fn validate_var_name(name: &str) -> Result<(), String> {
110+
if name.contains(' ') {
111+
return Err("Variable name cannot contain spaces".into());
112+
}
113+
Ok(())
98114
}
99115

100116
fn main() {
@@ -151,37 +167,73 @@ fn main() {
151167
match dotenv_parser::parse_dotenv(&content) {
152168
Ok(variables) => {
153169
for (key, value) in variables.into_iter() {
154-
unsafe { env::set_var(key, value) };
170+
if opt.global {
171+
if let Err(err) = globalenv::set_var(&key, &value) {
172+
error(&format!("can't globally set variables: {}", err), cli.exit_on_error);
173+
}
174+
} else {
175+
unsafe { env::set_var(key, value) };
176+
}
177+
}
178+
if let Some(process) = opt.process {
179+
run(process, cli.exit_on_error);
155180
}
156-
run(opt.process, cli.exit_on_error);
157181
}
158182
Err(err) => {
159183
error(err.to_string().as_str(), cli.exit_on_error);
160-
run(opt.process, cli.exit_on_error);
184+
if let Some(process) = opt.process {
185+
run(process, cli.exit_on_error);
186+
}
161187
process::exit(1);
162188
}
163189
}
164190
}
165191
Err(err) => {
166192
error(err.to_string().as_str(), cli.exit_on_error);
167-
run(opt.process, cli.exit_on_error);
193+
if let Some(process) = opt.process {
194+
run(process, cli.exit_on_error);
195+
}
168196
process::exit(1);
169197
}
170198
}
171199
}
172200
// Set command handler
173201
Commands::Set(opt) => {
174-
unsafe { env::set_var(opt.key, opt.value) };
175-
run(opt.process, cli.exit_on_error);
202+
if let Err(err) = validate_var_name(&opt.key) {
203+
error(&err, cli.exit_on_error);
204+
process::exit(1);
205+
}
206+
207+
if opt.global {
208+
if let Err(err) = globalenv::set_var(&opt.key, &opt.value) {
209+
error(&format!("can't globally set variable: {}", err), cli.exit_on_error);
210+
process::exit(1);
211+
}
212+
} else {
213+
unsafe { env::set_var(opt.key, opt.value) };
214+
}
215+
if let Some(process) = opt.process {
216+
run(process, cli.exit_on_error);
217+
}
176218
}
177219
// Delete command handler
178220
Commands::Delete(opt) => {
179221
// Check if variable exists
180222
match env::var(&opt.key) {
181-
Ok(_) => unsafe { env::remove_var(&opt.key) },
223+
Ok(_) => {
224+
if opt.global {
225+
if let Err(err) = globalenv::unset_var(&opt.key) {
226+
error(&format!("can't globally delete variable: {}", err), cli.exit_on_error);
227+
}
228+
} else {
229+
unsafe { env::remove_var(&opt.key) }
230+
}
231+
},
182232
_ => warning("variable doesn't exists"),
183233
}
184-
run(opt.process, cli.exit_on_error);
234+
if let Some(process) = opt.process {
235+
run(process, cli.exit_on_error);
236+
}
185237
}
186238
}
187239
}

0 commit comments

Comments
 (0)