settingspec 0.5.0__tar.gz → 0.5.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {settingspec-0.5.0 → settingspec-0.5.1}/Cargo.lock +67 -1
- {settingspec-0.5.0 → settingspec-0.5.1}/Cargo.toml +2 -1
- {settingspec-0.5.0 → settingspec-0.5.1}/PKG-INFO +26 -9
- {settingspec-0.5.0 → settingspec-0.5.1}/README.md +25 -8
- {settingspec-0.5.0 → settingspec-0.5.1}/src/cli.rs +74 -44
- {settingspec-0.5.0 → settingspec-0.5.1}/LICENSE-APACHE +0 -0
- {settingspec-0.5.0 → settingspec-0.5.1}/LICENSE-MIT +0 -0
- {settingspec-0.5.0 → settingspec-0.5.1}/pyproject.toml +0 -0
- {settingspec-0.5.0 → settingspec-0.5.1}/src/envfile.rs +0 -0
- {settingspec-0.5.0 → settingspec-0.5.1}/src/error.rs +0 -0
- {settingspec-0.5.0 → settingspec-0.5.1}/src/filter.rs +0 -0
- {settingspec-0.5.0 → settingspec-0.5.1}/src/generator/common.rs +0 -0
- {settingspec-0.5.0 → settingspec-0.5.1}/src/generator/env.rs +0 -0
- {settingspec-0.5.0 → settingspec-0.5.1}/src/generator/javascript.rs +0 -0
- {settingspec-0.5.0 → settingspec-0.5.1}/src/generator/json.rs +0 -0
- {settingspec-0.5.0 → settingspec-0.5.1}/src/generator/lua.rs +0 -0
- {settingspec-0.5.0 → settingspec-0.5.1}/src/generator/mod.rs +0 -0
- {settingspec-0.5.0 → settingspec-0.5.1}/src/generator/python.rs +0 -0
- {settingspec-0.5.0 → settingspec-0.5.1}/src/generator/toml.rs +0 -0
- {settingspec-0.5.0 → settingspec-0.5.1}/src/generator/tree.rs +0 -0
- {settingspec-0.5.0 → settingspec-0.5.1}/src/generator/typescript.rs +0 -0
- {settingspec-0.5.0 → settingspec-0.5.1}/src/generator/yaml.rs +0 -0
- {settingspec-0.5.0 → settingspec-0.5.1}/src/lib.rs +0 -0
- {settingspec-0.5.0 → settingspec-0.5.1}/src/main.rs +0 -0
- {settingspec-0.5.0 → settingspec-0.5.1}/src/model.rs +0 -0
- {settingspec-0.5.0 → settingspec-0.5.1}/src/parser.rs +0 -0
- {settingspec-0.5.0 → settingspec-0.5.1}/src/profile.rs +0 -0
- {settingspec-0.5.0 → settingspec-0.5.1}/src/resolver.rs +0 -0
|
@@ -282,6 +282,15 @@ dependencies = [
|
|
|
282
282
|
"generic-array",
|
|
283
283
|
]
|
|
284
284
|
|
|
285
|
+
[[package]]
|
|
286
|
+
name = "block2"
|
|
287
|
+
version = "0.6.2"
|
|
288
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
289
|
+
checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5"
|
|
290
|
+
dependencies = [
|
|
291
|
+
"objc2",
|
|
292
|
+
]
|
|
293
|
+
|
|
285
294
|
[[package]]
|
|
286
295
|
name = "blowfish"
|
|
287
296
|
version = "0.9.1"
|
|
@@ -324,6 +333,12 @@ version = "1.0.5"
|
|
|
324
333
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
325
334
|
checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600"
|
|
326
335
|
|
|
336
|
+
[[package]]
|
|
337
|
+
name = "cfg_aliases"
|
|
338
|
+
version = "0.2.2"
|
|
339
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
340
|
+
checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527"
|
|
341
|
+
|
|
327
342
|
[[package]]
|
|
328
343
|
name = "chacha20"
|
|
329
344
|
version = "0.9.1"
|
|
@@ -519,6 +534,17 @@ dependencies = [
|
|
|
519
534
|
"cipher",
|
|
520
535
|
]
|
|
521
536
|
|
|
537
|
+
[[package]]
|
|
538
|
+
name = "ctrlc"
|
|
539
|
+
version = "3.5.2"
|
|
540
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
541
|
+
checksum = "e0b1fab2ae45819af2d0731d60f2afe17227ebb1a1538a236da84c93e9a60162"
|
|
542
|
+
dependencies = [
|
|
543
|
+
"dispatch2",
|
|
544
|
+
"nix",
|
|
545
|
+
"windows-sys",
|
|
546
|
+
]
|
|
547
|
+
|
|
522
548
|
[[package]]
|
|
523
549
|
name = "curve25519-dalek"
|
|
524
550
|
version = "4.1.3"
|
|
@@ -584,6 +610,18 @@ dependencies = [
|
|
|
584
610
|
"crypto-common 0.2.2",
|
|
585
611
|
]
|
|
586
612
|
|
|
613
|
+
[[package]]
|
|
614
|
+
name = "dispatch2"
|
|
615
|
+
version = "0.3.1"
|
|
616
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
617
|
+
checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38"
|
|
618
|
+
dependencies = [
|
|
619
|
+
"bitflags",
|
|
620
|
+
"block2",
|
|
621
|
+
"libc",
|
|
622
|
+
"objc2",
|
|
623
|
+
]
|
|
624
|
+
|
|
587
625
|
[[package]]
|
|
588
626
|
name = "displaydoc"
|
|
589
627
|
version = "0.2.7"
|
|
@@ -1180,6 +1218,18 @@ dependencies = [
|
|
|
1180
1218
|
"sha3",
|
|
1181
1219
|
]
|
|
1182
1220
|
|
|
1221
|
+
[[package]]
|
|
1222
|
+
name = "nix"
|
|
1223
|
+
version = "0.31.3"
|
|
1224
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1225
|
+
checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d"
|
|
1226
|
+
dependencies = [
|
|
1227
|
+
"bitflags",
|
|
1228
|
+
"cfg-if",
|
|
1229
|
+
"cfg_aliases",
|
|
1230
|
+
"libc",
|
|
1231
|
+
]
|
|
1232
|
+
|
|
1183
1233
|
[[package]]
|
|
1184
1234
|
name = "nom"
|
|
1185
1235
|
version = "8.0.0"
|
|
@@ -1240,6 +1290,21 @@ dependencies = [
|
|
|
1240
1290
|
"libm",
|
|
1241
1291
|
]
|
|
1242
1292
|
|
|
1293
|
+
[[package]]
|
|
1294
|
+
name = "objc2"
|
|
1295
|
+
version = "0.6.4"
|
|
1296
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1297
|
+
checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f"
|
|
1298
|
+
dependencies = [
|
|
1299
|
+
"objc2-encode",
|
|
1300
|
+
]
|
|
1301
|
+
|
|
1302
|
+
[[package]]
|
|
1303
|
+
name = "objc2-encode"
|
|
1304
|
+
version = "4.1.0"
|
|
1305
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1306
|
+
checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
|
|
1307
|
+
|
|
1243
1308
|
[[package]]
|
|
1244
1309
|
name = "once_cell"
|
|
1245
1310
|
version = "1.21.4"
|
|
@@ -1758,7 +1823,7 @@ dependencies = [
|
|
|
1758
1823
|
|
|
1759
1824
|
[[package]]
|
|
1760
1825
|
name = "settingspec"
|
|
1761
|
-
version = "0.5.
|
|
1826
|
+
version = "0.5.1"
|
|
1762
1827
|
dependencies = [
|
|
1763
1828
|
"age",
|
|
1764
1829
|
"anyhow",
|
|
@@ -1766,6 +1831,7 @@ dependencies = [
|
|
|
1766
1831
|
"assert_fs",
|
|
1767
1832
|
"clap",
|
|
1768
1833
|
"clap_complete",
|
|
1834
|
+
"ctrlc",
|
|
1769
1835
|
"dotenvy",
|
|
1770
1836
|
"indexmap",
|
|
1771
1837
|
"predicates",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "settingspec"
|
|
3
|
-
version = "0.5.
|
|
3
|
+
version = "0.5.1"
|
|
4
4
|
edition = "2024"
|
|
5
5
|
description = "One file for all environments, all languages, all submodules."
|
|
6
6
|
readme = "README.md"
|
|
@@ -40,6 +40,7 @@ serde_yaml = "0.9"
|
|
|
40
40
|
indexmap = { version = "2", features = ["serde"] }
|
|
41
41
|
dotenvy = "0.15.7"
|
|
42
42
|
age = { version = "0.12.1", features = ["armor", "ssh"] }
|
|
43
|
+
ctrlc = "3.5.2"
|
|
43
44
|
|
|
44
45
|
[dev-dependencies]
|
|
45
46
|
assert_fs = "1.1.4"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: settingspec
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.1
|
|
4
4
|
Classifier: Programming Language :: Rust
|
|
5
5
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
6
6
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
@@ -30,14 +30,15 @@ Project-URL: Source Code, https://github.com/sayanarijit/settingspec
|
|
|
30
30
|
|
|
31
31
|
# SettingSpec
|
|
32
32
|
|
|
33
|
-
1.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
33
|
+
1. [Concepts](#concepts)
|
|
34
|
+
1. [Single file convenience](#single-file-convenience)
|
|
35
|
+
2. [Declarative profiles as environments](#declarative-profiles-as-environments)
|
|
36
|
+
3. [Language independent](#language-independent)
|
|
37
|
+
4. [Easy secrets](#easy-secrets)
|
|
38
|
+
1. [SecretSpec](#secretspec)
|
|
39
|
+
2. [Dotenv](#dotenv)
|
|
40
|
+
3. [Cottage or agebox](#cottage-or-agebox)
|
|
41
|
+
2. [Learn more](#learn-more)
|
|
41
42
|
|
|
42
43
|
## Concepts
|
|
43
44
|
|
|
@@ -188,6 +189,22 @@ envfile.prod = "-" # Read from stdin, encrypted or not
|
|
|
188
189
|
secret1.default.env = "SECRET1" # Load value from $SECRET1
|
|
189
190
|
```
|
|
190
191
|
|
|
192
|
+
#### Cottage or agebox
|
|
193
|
+
|
|
194
|
+
Too simple? Use [Cottage](https://cottage-cli.pages.dev) or [agebox](https://github.com/slok/agebox).
|
|
195
|
+
|
|
196
|
+
```toml
|
|
197
|
+
[spec]
|
|
198
|
+
envfile.default = ".env.cott.age"
|
|
199
|
+
|
|
200
|
+
# decryption.key.env = "AGEBOX_PRIVATE_KEYS"
|
|
201
|
+
# decryption.key.env = "COTTAGE_IDENTITY"
|
|
202
|
+
decryption.key.path = "~/.config/cottage/identity:~/.ssh"
|
|
203
|
+
|
|
204
|
+
[settings]
|
|
205
|
+
secret.default.env = "SECRET"
|
|
206
|
+
```
|
|
207
|
+
|
|
191
208
|
## Learn more
|
|
192
209
|
|
|
193
210
|
Check out the [settingspec.toml](./settingspec.toml) example file and [full specification](./SPECIFICATION.md) for more details.
|
|
@@ -13,14 +13,15 @@
|
|
|
13
13
|
|
|
14
14
|
# SettingSpec
|
|
15
15
|
|
|
16
|
-
1.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
16
|
+
1. [Concepts](#concepts)
|
|
17
|
+
1. [Single file convenience](#single-file-convenience)
|
|
18
|
+
2. [Declarative profiles as environments](#declarative-profiles-as-environments)
|
|
19
|
+
3. [Language independent](#language-independent)
|
|
20
|
+
4. [Easy secrets](#easy-secrets)
|
|
21
|
+
1. [SecretSpec](#secretspec)
|
|
22
|
+
2. [Dotenv](#dotenv)
|
|
23
|
+
3. [Cottage or agebox](#cottage-or-agebox)
|
|
24
|
+
2. [Learn more](#learn-more)
|
|
24
25
|
|
|
25
26
|
## Concepts
|
|
26
27
|
|
|
@@ -171,6 +172,22 @@ envfile.prod = "-" # Read from stdin, encrypted or not
|
|
|
171
172
|
secret1.default.env = "SECRET1" # Load value from $SECRET1
|
|
172
173
|
```
|
|
173
174
|
|
|
175
|
+
#### Cottage or agebox
|
|
176
|
+
|
|
177
|
+
Too simple? Use [Cottage](https://cottage-cli.pages.dev) or [agebox](https://github.com/slok/agebox).
|
|
178
|
+
|
|
179
|
+
```toml
|
|
180
|
+
[spec]
|
|
181
|
+
envfile.default = ".env.cott.age"
|
|
182
|
+
|
|
183
|
+
# decryption.key.env = "AGEBOX_PRIVATE_KEYS"
|
|
184
|
+
# decryption.key.env = "COTTAGE_IDENTITY"
|
|
185
|
+
decryption.key.path = "~/.config/cottage/identity:~/.ssh"
|
|
186
|
+
|
|
187
|
+
[settings]
|
|
188
|
+
secret.default.env = "SECRET"
|
|
189
|
+
```
|
|
190
|
+
|
|
174
191
|
## Learn more
|
|
175
192
|
|
|
176
193
|
Check out the [settingspec.toml](./settingspec.toml) example file and [full specification](./SPECIFICATION.md) for more details.
|
|
@@ -7,12 +7,30 @@ use crate::parser::parse_config_str;
|
|
|
7
7
|
use crate::profile::resolve_active_profile;
|
|
8
8
|
use crate::resolver::resolve_settings;
|
|
9
9
|
use clap::{Parser, Subcommand};
|
|
10
|
-
use std::collections::HashMap;
|
|
10
|
+
use std::collections::{HashMap, HashSet};
|
|
11
11
|
use std::io::Write;
|
|
12
12
|
use std::path::{Path, PathBuf};
|
|
13
13
|
use std::sync::mpsc;
|
|
14
14
|
use std::time::Duration;
|
|
15
15
|
|
|
16
|
+
#[derive(Default)]
|
|
17
|
+
struct CleanupGuard {
|
|
18
|
+
keep: bool,
|
|
19
|
+
paths: HashSet<PathBuf>,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
impl Drop for CleanupGuard {
|
|
23
|
+
fn drop(&mut self) {
|
|
24
|
+
if !self.keep {
|
|
25
|
+
self.paths.iter().for_each(|path| {
|
|
26
|
+
if std::fs::exists(path).unwrap_or(false) {
|
|
27
|
+
let _ = std::fs::remove_file(path);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
16
34
|
#[derive(Parser, Debug)]
|
|
17
35
|
#[command(
|
|
18
36
|
name = "settingspec",
|
|
@@ -156,35 +174,66 @@ pub fn run_cli() -> Result<()> {
|
|
|
156
174
|
|
|
157
175
|
fn run_watch() -> Result<()> {
|
|
158
176
|
let ctx = load_and_resolve()?;
|
|
159
|
-
perform_export(&ctx)?;
|
|
160
|
-
|
|
161
177
|
let config_path = ctx.project_root.join("settingspec.toml");
|
|
178
|
+
let mut guard = CleanupGuard::default();
|
|
162
179
|
|
|
163
180
|
let (tx, rx) = mpsc::channel();
|
|
181
|
+
let (txsig, rxsig) = mpsc::channel();
|
|
182
|
+
|
|
183
|
+
ctrlc::set_handler(move || txsig.send(()).expect("Could not send signal on channel."))
|
|
184
|
+
.expect("Error setting Ctrl-C handler");
|
|
164
185
|
|
|
165
186
|
std::thread::spawn(move || {
|
|
187
|
+
let _ = tx.send(true); // Trigger initial export
|
|
188
|
+
|
|
166
189
|
let mut modified = std::fs::metadata(&config_path)
|
|
167
190
|
.ok()
|
|
168
191
|
.and_then(|m| m.modified().ok());
|
|
192
|
+
|
|
169
193
|
loop {
|
|
170
194
|
std::thread::sleep(Duration::from_secs(1));
|
|
171
|
-
|
|
172
|
-
.
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
195
|
+
if rxsig.try_recv().is_ok() {
|
|
196
|
+
let _ = tx.send(false);
|
|
197
|
+
break;
|
|
198
|
+
} else {
|
|
199
|
+
let new_modified = std::fs::metadata(&config_path)
|
|
200
|
+
.ok()
|
|
201
|
+
.and_then(|m| m.modified().ok());
|
|
202
|
+
if new_modified != modified {
|
|
203
|
+
modified = new_modified;
|
|
204
|
+
let _ = tx.send(true);
|
|
205
|
+
}
|
|
177
206
|
}
|
|
178
207
|
}
|
|
179
208
|
});
|
|
180
209
|
|
|
181
|
-
while rx.recv().
|
|
182
|
-
println!("Detected change in settingspec.toml, reloading...");
|
|
210
|
+
while rx.recv().unwrap_or(false) {
|
|
183
211
|
match load_and_resolve() {
|
|
184
|
-
Ok(ctx) => {
|
|
212
|
+
Ok(mut ctx) => {
|
|
213
|
+
guard.keep = ctx.doc.spec.export.keep;
|
|
214
|
+
if ctx.doc.spec.export.file.is_empty() {
|
|
215
|
+
eprintln!("No export files configured, skipping export.");
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
ctx.doc.spec.export.stdout = None;
|
|
219
|
+
ctx.doc.spec.export.stdin = None;
|
|
220
|
+
ctx.doc.spec.export.env = None;
|
|
221
|
+
|
|
222
|
+
eprintln!("Exporting files...");
|
|
185
223
|
if let Err(e) = perform_export(&ctx) {
|
|
186
224
|
eprintln!("Error during export: {}", e);
|
|
187
225
|
}
|
|
226
|
+
ctx.doc
|
|
227
|
+
.spec
|
|
228
|
+
.export
|
|
229
|
+
.file
|
|
230
|
+
.iter()
|
|
231
|
+
.for_each(|(file_path_str, filter)| {
|
|
232
|
+
if !matches!(filter, ExportFilter::Disabled) {
|
|
233
|
+
guard.paths.insert(PathBuf::from(file_path_str));
|
|
234
|
+
println!("{file_path_str}");
|
|
235
|
+
}
|
|
236
|
+
});
|
|
188
237
|
}
|
|
189
238
|
Err(e) => {
|
|
190
239
|
eprintln!("Error loading configuration: {}", e);
|
|
@@ -192,6 +241,7 @@ fn run_watch() -> Result<()> {
|
|
|
192
241
|
}
|
|
193
242
|
}
|
|
194
243
|
|
|
244
|
+
eprintln!("Exiting watch mode.");
|
|
195
245
|
Ok(())
|
|
196
246
|
}
|
|
197
247
|
|
|
@@ -236,28 +286,10 @@ fn execute_run(ctx: &ExecutionContext, command_args: &[String]) -> Result<()> {
|
|
|
236
286
|
}
|
|
237
287
|
|
|
238
288
|
// Export all files
|
|
239
|
-
let
|
|
240
|
-
|
|
241
|
-
// Setup cleanup guard
|
|
242
|
-
struct CleanupGuard {
|
|
243
|
-
files: Vec<PathBuf>,
|
|
244
|
-
keep: bool,
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
impl Drop for CleanupGuard {
|
|
248
|
-
fn drop(&mut self) {
|
|
249
|
-
if !self.keep {
|
|
250
|
-
for f in &self.files {
|
|
251
|
-
let _ = std::fs::remove_file(f);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
let _guard = CleanupGuard {
|
|
258
|
-
files: generated_files,
|
|
289
|
+
let _guard = perform_export(ctx).map(|files| CleanupGuard {
|
|
259
290
|
keep: ctx.doc.spec.export.keep,
|
|
260
|
-
|
|
291
|
+
paths: files.into_iter().collect(),
|
|
292
|
+
})?;
|
|
261
293
|
|
|
262
294
|
let stdin_payload = if let Some(ref stdin_fmt) = ctx.doc.spec.export.stdin {
|
|
263
295
|
Some(generate_by_format(stdin_fmt, &ctx.resolved_settings)?)
|
|
@@ -418,16 +450,14 @@ pub fn auto_append_gitignore(ctx: &ExecutionContext) -> Result<()> {
|
|
|
418
450
|
return Ok(());
|
|
419
451
|
}
|
|
420
452
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
None => return Ok(()),
|
|
425
|
-
};
|
|
453
|
+
if find_git_root(&ctx.project_root).is_none() {
|
|
454
|
+
return Ok(());
|
|
455
|
+
}
|
|
426
456
|
|
|
427
|
-
let
|
|
428
|
-
let
|
|
457
|
+
let project_root = &ctx.project_root;
|
|
458
|
+
let project_root_canon = project_root
|
|
429
459
|
.canonicalize()
|
|
430
|
-
.unwrap_or_else(|_|
|
|
460
|
+
.unwrap_or_else(|_| project_root.clone());
|
|
431
461
|
|
|
432
462
|
let mut entries_to_add = Vec::new();
|
|
433
463
|
|
|
@@ -438,13 +468,13 @@ pub fn auto_append_gitignore(ctx: &ExecutionContext) -> Result<()> {
|
|
|
438
468
|
|
|
439
469
|
let target_path = Path::new(file_path_str);
|
|
440
470
|
let full_target = if target_path.is_relative() {
|
|
441
|
-
|
|
471
|
+
project_root_canon.join(target_path)
|
|
442
472
|
} else {
|
|
443
473
|
target_path.to_path_buf()
|
|
444
474
|
};
|
|
445
475
|
|
|
446
476
|
let normalized = normalize_path(&full_target);
|
|
447
|
-
let rel_path = match normalized.strip_prefix(&
|
|
477
|
+
let rel_path = match normalized.strip_prefix(&project_root_canon) {
|
|
448
478
|
Ok(rel) => rel,
|
|
449
479
|
Err(_) => continue,
|
|
450
480
|
};
|
|
@@ -468,7 +498,7 @@ pub fn auto_append_gitignore(ctx: &ExecutionContext) -> Result<()> {
|
|
|
468
498
|
return Ok(());
|
|
469
499
|
}
|
|
470
500
|
|
|
471
|
-
let gitignore_path =
|
|
501
|
+
let gitignore_path = project_root.join(".gitignore");
|
|
472
502
|
let existing_content = if gitignore_path.exists() {
|
|
473
503
|
std::fs::read_to_string(&gitignore_path)?
|
|
474
504
|
} else {
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|