@repokit/core 3.0.6 → 4.0.0
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.
- package/Cargo.lock +96 -11
- package/Cargo.toml +2 -2
- package/installation/install.sh +39 -28
- package/internals/caches/crawl_cache.rs +124 -0
- package/internals/caches/file_cache.rs +104 -0
- package/internals/caches/mod.rs +5 -0
- package/internals/caches/repokit_version_resolver.rs +50 -0
- package/internals/caches/settings_cache.rs +73 -0
- package/internals/caches/version_cache.rs +128 -0
- package/internals/context/cache_scope.rs +76 -0
- package/internals/context/file_system.rs +66 -0
- package/internals/context/git_scope.rs +55 -0
- package/internals/context/mod.rs +5 -0
- package/internals/context/node_scope.rs +133 -0
- package/internals/context/typescript_bridge.rs +68 -0
- package/internals/executables/internal_executable.rs +8 -2
- package/internals/executables/internal_executable_definition.rs +0 -8
- package/internals/executor/executor.rs +13 -0
- package/internals/file_walker/file_walker.rs +59 -0
- package/internals/file_walker/mod.rs +1 -0
- package/internals/internal_commands/help.rs +4 -3
- package/internals/internal_commands/internal_registry.rs +14 -20
- package/internals/internal_commands/list_commands.rs +7 -16
- package/internals/internal_commands/list_owners.rs +3 -16
- package/internals/internal_commands/list_themes.rs +11 -10
- package/internals/internal_commands/list_version.rs +17 -18
- package/internals/internal_commands/locate_command.rs +11 -17
- package/internals/internal_commands/onboarder.rs +5 -16
- package/internals/internal_commands/register_command.rs +12 -20
- package/internals/internal_commands/search_commands.rs +29 -20
- package/internals/internal_commands/upgrade_repokit.rs +19 -30
- package/internals/internal_filesystem/file_builder.rs +4 -9
- package/internals/internal_filesystem/mod.rs +0 -1
- package/internals/logger/logger.rs +19 -6
- package/internals/main.rs +8 -11
- package/internals/repokit/mod.rs +1 -1
- package/internals/repokit/repokit.rs +49 -57
- package/internals/repokit/repokit_command.rs +69 -38
- package/internals/repokit/repokit_config.rs +42 -18
- package/internals/repokit/repokit_construct_validator.rs +1 -4
- package/internals/repokit/repokit_runtime.rs +43 -0
- package/internals/themes/theme_registry.rs +5 -7
- package/internals/validations/command_validations.rs +39 -62
- package/package.json +3 -3
- package/internals/configuration/configuration.rs +0 -45
- package/internals/configuration/mod.rs +0 -3
- package/internals/configuration/recovery.rs +0 -42
- package/internals/configuration/typescript_command.rs +0 -65
- package/internals/internal_filesystem/internal_filesystem.rs +0 -308
- package/internals/repokit/runtime_compiler.rs +0 -62
package/Cargo.lock
CHANGED
|
@@ -293,6 +293,94 @@ dependencies = [
|
|
|
293
293
|
"num",
|
|
294
294
|
]
|
|
295
295
|
|
|
296
|
+
[[package]]
|
|
297
|
+
name = "futures"
|
|
298
|
+
version = "0.3.32"
|
|
299
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
300
|
+
checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d"
|
|
301
|
+
dependencies = [
|
|
302
|
+
"futures-channel",
|
|
303
|
+
"futures-core",
|
|
304
|
+
"futures-executor",
|
|
305
|
+
"futures-io",
|
|
306
|
+
"futures-sink",
|
|
307
|
+
"futures-task",
|
|
308
|
+
"futures-util",
|
|
309
|
+
]
|
|
310
|
+
|
|
311
|
+
[[package]]
|
|
312
|
+
name = "futures-channel"
|
|
313
|
+
version = "0.3.32"
|
|
314
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
315
|
+
checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d"
|
|
316
|
+
dependencies = [
|
|
317
|
+
"futures-core",
|
|
318
|
+
"futures-sink",
|
|
319
|
+
]
|
|
320
|
+
|
|
321
|
+
[[package]]
|
|
322
|
+
name = "futures-core"
|
|
323
|
+
version = "0.3.32"
|
|
324
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
325
|
+
checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
|
|
326
|
+
|
|
327
|
+
[[package]]
|
|
328
|
+
name = "futures-executor"
|
|
329
|
+
version = "0.3.32"
|
|
330
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
331
|
+
checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d"
|
|
332
|
+
dependencies = [
|
|
333
|
+
"futures-core",
|
|
334
|
+
"futures-task",
|
|
335
|
+
"futures-util",
|
|
336
|
+
]
|
|
337
|
+
|
|
338
|
+
[[package]]
|
|
339
|
+
name = "futures-io"
|
|
340
|
+
version = "0.3.32"
|
|
341
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
342
|
+
checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718"
|
|
343
|
+
|
|
344
|
+
[[package]]
|
|
345
|
+
name = "futures-macro"
|
|
346
|
+
version = "0.3.32"
|
|
347
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
348
|
+
checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b"
|
|
349
|
+
dependencies = [
|
|
350
|
+
"proc-macro2",
|
|
351
|
+
"quote",
|
|
352
|
+
"syn",
|
|
353
|
+
]
|
|
354
|
+
|
|
355
|
+
[[package]]
|
|
356
|
+
name = "futures-sink"
|
|
357
|
+
version = "0.3.32"
|
|
358
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
359
|
+
checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893"
|
|
360
|
+
|
|
361
|
+
[[package]]
|
|
362
|
+
name = "futures-task"
|
|
363
|
+
version = "0.3.32"
|
|
364
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
365
|
+
checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393"
|
|
366
|
+
|
|
367
|
+
[[package]]
|
|
368
|
+
name = "futures-util"
|
|
369
|
+
version = "0.3.32"
|
|
370
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
371
|
+
checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
|
|
372
|
+
dependencies = [
|
|
373
|
+
"futures-channel",
|
|
374
|
+
"futures-core",
|
|
375
|
+
"futures-io",
|
|
376
|
+
"futures-macro",
|
|
377
|
+
"futures-sink",
|
|
378
|
+
"futures-task",
|
|
379
|
+
"memchr",
|
|
380
|
+
"pin-project-lite",
|
|
381
|
+
"slab",
|
|
382
|
+
]
|
|
383
|
+
|
|
296
384
|
[[package]]
|
|
297
385
|
name = "getrandom"
|
|
298
386
|
version = "0.2.17"
|
|
@@ -900,10 +988,11 @@ checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c"
|
|
|
900
988
|
|
|
901
989
|
[[package]]
|
|
902
990
|
name = "repokit"
|
|
903
|
-
version = "
|
|
991
|
+
version = "4.0.0"
|
|
904
992
|
dependencies = [
|
|
905
993
|
"alphanumeric-sort",
|
|
906
994
|
"colored",
|
|
995
|
+
"futures",
|
|
907
996
|
"ignore",
|
|
908
997
|
"jsonschema",
|
|
909
998
|
"normalize-path",
|
|
@@ -913,7 +1002,6 @@ dependencies = [
|
|
|
913
1002
|
"serde_json",
|
|
914
1003
|
"shellexpand",
|
|
915
1004
|
"terminal-spinners",
|
|
916
|
-
"tokio",
|
|
917
1005
|
]
|
|
918
1006
|
|
|
919
1007
|
[[package]]
|
|
@@ -1056,6 +1144,12 @@ dependencies = [
|
|
|
1056
1144
|
"libc",
|
|
1057
1145
|
]
|
|
1058
1146
|
|
|
1147
|
+
[[package]]
|
|
1148
|
+
name = "slab"
|
|
1149
|
+
version = "0.4.12"
|
|
1150
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1151
|
+
checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
|
|
1152
|
+
|
|
1059
1153
|
[[package]]
|
|
1060
1154
|
name = "smallvec"
|
|
1061
1155
|
version = "1.15.1"
|
|
@@ -1173,15 +1267,6 @@ dependencies = [
|
|
|
1173
1267
|
"zerovec",
|
|
1174
1268
|
]
|
|
1175
1269
|
|
|
1176
|
-
[[package]]
|
|
1177
|
-
name = "tokio"
|
|
1178
|
-
version = "1.50.0"
|
|
1179
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1180
|
-
checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d"
|
|
1181
|
-
dependencies = [
|
|
1182
|
-
"pin-project-lite",
|
|
1183
|
-
]
|
|
1184
|
-
|
|
1185
1270
|
[[package]]
|
|
1186
1271
|
name = "unicode-general-category"
|
|
1187
1272
|
version = "1.1.0"
|
package/Cargo.toml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "repokit"
|
|
3
|
-
version = "
|
|
3
|
+
version = "4.0.0"
|
|
4
4
|
edition = "2024"
|
|
5
5
|
|
|
6
6
|
[[bin]]
|
|
@@ -14,9 +14,9 @@ serde_json = "1.0"
|
|
|
14
14
|
colored = "3"
|
|
15
15
|
normalize-path = "0.2.1"
|
|
16
16
|
alphanumeric-sort = "1.5.5"
|
|
17
|
-
tokio = "1.50.0"
|
|
18
17
|
ignore = "0.4.25"
|
|
19
18
|
regex = { version = "1.12.3", features = ["std", "unicode"] }
|
|
20
19
|
shellexpand = "3.1.2"
|
|
21
20
|
schemars = "1.2.1"
|
|
22
21
|
terminal-spinners = "0.3.2"
|
|
22
|
+
futures = "0.3.32"
|
package/installation/install.sh
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
CURRENT_VERSION="
|
|
1
|
+
CURRENT_VERSION="4.0.0"
|
|
2
2
|
CWD=$(pwd)
|
|
3
3
|
|
|
4
4
|
REPLACEMENT="/node_modules"
|
|
5
5
|
FALLBACK_ROOT="${CWD%${REPLACEMENT}*}"
|
|
6
6
|
|
|
7
|
-
GIT_ROOT=$(git rev-parse --show-toplevel
|
|
7
|
+
GIT_ROOT=$(git rev-parse --show-toplevel)
|
|
8
8
|
REPO_ROOT=${GIT_ROOT:-$FALLBACK_ROOT}
|
|
9
9
|
|
|
10
10
|
if [[ "$CWD" != *"$REPLACEMENT"* ]]; then
|
|
@@ -31,39 +31,50 @@ ROOT_COMMIT=$(git rev-list --parents HEAD | tail -1) || ROOT_COMMIT=""
|
|
|
31
31
|
|
|
32
32
|
cd
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
OLD_CACHE_FILE=".repokit";
|
|
35
35
|
CACHE_DIRECTORY=".repokit_cache";
|
|
36
|
-
|
|
36
|
+
VERSION_FILE=".version"
|
|
37
|
+
SETTINGS_FILE=".settings"
|
|
37
38
|
REPO_CACHE_DIRECTORY="$CACHE_DIRECTORY/$ROOT_COMMIT"
|
|
38
|
-
LAST_THEME_USED=""
|
|
39
|
-
BACK_PORTING=0
|
|
40
|
-
|
|
41
|
-
if [ -n "$ROOT_COMMIT" ] && [ -f "$REPO_CACHE_DIRECTORY/$NEW_SETTINGS_FILE" ]; then
|
|
42
|
-
BACK_PORTING=1
|
|
43
|
-
cd "$REPO_CACHE_DIRECTORY"
|
|
44
|
-
read -r LAST_THEME_USED < "$NEW_SETTINGS_FILE"
|
|
45
|
-
rm "$NEW_SETTINGS_FILE"
|
|
46
|
-
cd
|
|
47
|
-
fi
|
|
48
39
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
40
|
+
CACHED_THEME=""
|
|
41
|
+
|
|
42
|
+
if [ -f "$OLD_CACHE_FILE" ] && [ -n "$ROOT_COMMIT" ] && [ ! -f "$REPO_CACHE_DIRECTORY/$SETTINGS_FILE" ]; then
|
|
43
|
+
{
|
|
44
|
+
read -r
|
|
45
|
+
read -r CACHED_THEME
|
|
46
|
+
} < "$OLD_CACHE_FILE"
|
|
47
|
+
echo "CACHED THEME $CACHED_THEME"
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
if [ ! -d "$CACHE_DIRECTORY" ]; then
|
|
51
|
+
mkdir "$CACHE_DIRECTORY"
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
cd "$CACHE_DIRECTORY"
|
|
55
|
+
|
|
56
|
+
if [ -n "$ROOT_COMMIT" ]; then
|
|
57
|
+
if [ ! -d "$ROOT_COMMIT" ]; then
|
|
58
|
+
mkdir "$ROOT_COMMIT"
|
|
55
59
|
fi
|
|
60
|
+
cd $ROOT_COMMIT;
|
|
61
|
+
if [ -n "$CACHED_THEME" ] && [ ! -f "$SETTINGS_FILE" ]; then
|
|
62
|
+
touch "$SETTINGS_FILE"
|
|
63
|
+
echo "$CACHED_THEME\n" > "$SETTINGS_FILE"
|
|
64
|
+
fi
|
|
65
|
+
cd "../"
|
|
56
66
|
fi
|
|
57
67
|
|
|
58
|
-
if [ -
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
fi
|
|
68
|
+
if [ -f $VERSION_FILE ]; then
|
|
69
|
+
read -r CACHED_VERSION < "$VERSION_FILE"
|
|
70
|
+
if [ "$CACHED_VERSION" == "$CURRENT_VERSION" ]; then
|
|
71
|
+
exit 0;
|
|
72
|
+
fi
|
|
73
|
+
else
|
|
74
|
+
touch "$VERSION_FILE"
|
|
75
|
+
fi
|
|
66
76
|
|
|
77
|
+
echo "$CURRENT_VERSION\n" > "$VERSION_FILE"
|
|
67
78
|
|
|
68
79
|
cd $CWD
|
|
69
80
|
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
use std::{
|
|
2
|
+
collections::HashSet,
|
|
3
|
+
path::{Path, PathBuf},
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
use regex::Regex;
|
|
7
|
+
|
|
8
|
+
use crate::{
|
|
9
|
+
caches::file_cache::FileCache, context::git_scope::GitScope, executor::executor::Executor,
|
|
10
|
+
logger::logger::Logger, post_processing::post_processor::PostProcessor,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
#[derive(Clone)]
|
|
14
|
+
pub struct CrawlCache {
|
|
15
|
+
pub cache_directory: Option<PathBuf>,
|
|
16
|
+
pub files_to_crawl: Option<Vec<String>>,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
impl CrawlCache {
|
|
20
|
+
pub fn new(cache_directory: &Option<PathBuf>) -> Self {
|
|
21
|
+
CrawlCache {
|
|
22
|
+
files_to_crawl: None,
|
|
23
|
+
cache_directory: cache_directory.clone(),
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
pub async fn initialize(&mut self, git_scope: &GitScope) {
|
|
28
|
+
let head_commit = git_scope
|
|
29
|
+
.head_commit_hash
|
|
30
|
+
.to_owned()
|
|
31
|
+
.unwrap_or("".to_string());
|
|
32
|
+
if let Some((mut lines, path)) = self.read() {
|
|
33
|
+
let commit_hash = self.unwrap_line(lines.nth(0), "non_existent_hash");
|
|
34
|
+
if commit_hash != head_commit {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
let mut lines = self.line_buffer_to_vec(lines);
|
|
38
|
+
if lines.is_empty() {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
let (git_ignore_changed, mut changed_files) = self.get_changed_files(&git_scope.root);
|
|
42
|
+
if git_ignore_changed {
|
|
43
|
+
CrawlCache::clear_cache_file(path.to_owned(), false);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
for line in &lines {
|
|
47
|
+
if changed_files.contains(line) {
|
|
48
|
+
changed_files.remove(line);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
for line in changed_files {
|
|
52
|
+
lines.push(line);
|
|
53
|
+
}
|
|
54
|
+
self.files_to_crawl = Some(lines);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
pub fn crawl_cache_enabled(&self) -> bool {
|
|
59
|
+
self.files_to_crawl.is_some()
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
pub fn cache_crawl_results(&self, results: String) {
|
|
63
|
+
self.write(&results, |_| {
|
|
64
|
+
self.on_crawl_cache_storage_error();
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
fn on_crawl_cache_storage_error(&self) {
|
|
69
|
+
if let Some(storage_path) = self.storage_path() {
|
|
70
|
+
PostProcessor::get().register_task(move || {
|
|
71
|
+
Logger::info(
|
|
72
|
+
"I attempted to cache the results of a file crawl, but couldn't write to disk",
|
|
73
|
+
);
|
|
74
|
+
CrawlCache::log_cache_write_error();
|
|
75
|
+
Logger::info(
|
|
76
|
+
"To avoid issues with stale caches I'm going to delete what's currently on disk",
|
|
77
|
+
);
|
|
78
|
+
CrawlCache::clear_cache_file(storage_path.clone(), true);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
fn get_changed_files(&self, git_root: &str) -> (bool, HashSet<String>) {
|
|
84
|
+
let mut contains_git_ignore = false;
|
|
85
|
+
let file_path_matcher = Regex::new(r#"^.*\s(.*\.ts)$"#).unwrap();
|
|
86
|
+
let stdout = Executor::exec("git status --porcelain -uall", |cmd| cmd);
|
|
87
|
+
let git_root_path = Path::new(git_root);
|
|
88
|
+
let files: HashSet<String> = stdout
|
|
89
|
+
.split("\n")
|
|
90
|
+
.filter_map(|file| {
|
|
91
|
+
if !contains_git_ignore && file.ends_with(".gitignore") {
|
|
92
|
+
contains_git_ignore = true;
|
|
93
|
+
return None;
|
|
94
|
+
}
|
|
95
|
+
let matches: Vec<&str> = file_path_matcher
|
|
96
|
+
.captures_iter(file)
|
|
97
|
+
.filter_map(|entry| {
|
|
98
|
+
if let Some(match_result) = entry.get(1) {
|
|
99
|
+
return Some(match_result.as_str());
|
|
100
|
+
}
|
|
101
|
+
None
|
|
102
|
+
})
|
|
103
|
+
.collect();
|
|
104
|
+
if let Some(file_path) = matches.first()
|
|
105
|
+
&& git_root_path.join(file_path).exists()
|
|
106
|
+
{
|
|
107
|
+
return Some(file_path.to_string());
|
|
108
|
+
}
|
|
109
|
+
None
|
|
110
|
+
})
|
|
111
|
+
.collect();
|
|
112
|
+
(contains_git_ignore, files)
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
impl FileCache for CrawlCache {
|
|
117
|
+
fn cache_file(&self) -> &str {
|
|
118
|
+
".crawl_cache"
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
fn cache_directory(&self) -> &Option<PathBuf> {
|
|
122
|
+
&self.cache_directory
|
|
123
|
+
}
|
|
124
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
use std::{
|
|
2
|
+
fs::{File, write},
|
|
3
|
+
io::{BufRead, BufReader, Error, Lines},
|
|
4
|
+
path::PathBuf,
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
use normalize_path::NormalizePath;
|
|
8
|
+
|
|
9
|
+
use crate::{logger::logger::Logger, post_processing::post_processor::PostProcessor};
|
|
10
|
+
|
|
11
|
+
pub trait FileCache {
|
|
12
|
+
fn cache_file(&self) -> &str;
|
|
13
|
+
|
|
14
|
+
fn cache_directory(&self) -> &Option<PathBuf>;
|
|
15
|
+
|
|
16
|
+
fn storage_path(&self) -> Option<PathBuf> {
|
|
17
|
+
if let Some(storage_path) = self.perspective_path()
|
|
18
|
+
&& storage_path.exists()
|
|
19
|
+
{
|
|
20
|
+
return Some(storage_path);
|
|
21
|
+
}
|
|
22
|
+
None
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
fn perspective_path(&self) -> Option<PathBuf> {
|
|
26
|
+
if let Some(cache_dir) = &self.cache_directory() {
|
|
27
|
+
return Some(cache_dir.join(self.cache_file()).normalize());
|
|
28
|
+
}
|
|
29
|
+
None
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async fn create_cache_file_if_not_exists(&self) -> Option<PathBuf> {
|
|
33
|
+
if let Some(storage_path) = self.perspective_path()
|
|
34
|
+
&& !&storage_path.exists()
|
|
35
|
+
&& write(&storage_path, "").is_ok()
|
|
36
|
+
{
|
|
37
|
+
return Some(storage_path);
|
|
38
|
+
}
|
|
39
|
+
None
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
fn read(&self) -> Option<(Lines<BufReader<File>>, PathBuf)> {
|
|
43
|
+
if let Some(path) = self.storage_path()
|
|
44
|
+
&& let Ok(file) = File::open(&path)
|
|
45
|
+
{
|
|
46
|
+
return Some((BufReader::new(file).lines(), path));
|
|
47
|
+
}
|
|
48
|
+
None
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
fn write(&self, content: &str, on_error: impl Fn(Error)) {
|
|
52
|
+
if let Some(path) = self.storage_path()
|
|
53
|
+
&& let Err(error) = write(path, content)
|
|
54
|
+
{
|
|
55
|
+
on_error(error);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
fn line_buffer_to_vec(&self, lines: Lines<BufReader<File>>) -> Vec<String> {
|
|
60
|
+
lines.filter_map(Result::ok).collect()
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
fn insert_as_first_line(&self, lines: Lines<BufReader<File>>, value: String) -> Vec<String> {
|
|
64
|
+
let mut lines: Vec<String> = self.line_buffer_to_vec(lines);
|
|
65
|
+
if !lines.is_empty() {
|
|
66
|
+
lines[0] = value;
|
|
67
|
+
} else {
|
|
68
|
+
lines.push(value);
|
|
69
|
+
}
|
|
70
|
+
lines
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
fn unwrap_line(&self, line_result: Option<Result<String, Error>>, fallback: &str) -> String {
|
|
74
|
+
line_result
|
|
75
|
+
.and_then(|r| r.ok())
|
|
76
|
+
.unwrap_or(fallback.to_string())
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
fn clear_cache_file(path: PathBuf, notify: bool) {
|
|
80
|
+
// This is post-processed so it doesn't block the command the user is executing
|
|
81
|
+
PostProcessor::get().register_task(move || {
|
|
82
|
+
if write(&path, "").is_err() {
|
|
83
|
+
Logger::error("I was unable to remove a cache on disk");
|
|
84
|
+
Logger::error("To correct this, please run");
|
|
85
|
+
Logger::log_file_path(format!("rm {}", path.to_string_lossy()).as_str())
|
|
86
|
+
} else if notify {
|
|
87
|
+
Logger::info("Cache deleted!");
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
fn log_cache_write_error() {
|
|
93
|
+
Logger::info("This is typically a permission-related issue on the operating system");
|
|
94
|
+
Logger::info(
|
|
95
|
+
format!(
|
|
96
|
+
"If you believe this to be a bug within {}",
|
|
97
|
+
Logger::with_theme(|theme| theme.highlight("Repokit"))
|
|
98
|
+
)
|
|
99
|
+
.as_str(),
|
|
100
|
+
);
|
|
101
|
+
Logger::info("Please file an issue here");
|
|
102
|
+
Logger::log_issue_link();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
use std::env::args;
|
|
2
|
+
|
|
3
|
+
use terminal_spinners::{BOUNCING_BALL, SpinnerBuilder};
|
|
4
|
+
|
|
5
|
+
use crate::{
|
|
6
|
+
context::file_system::FileSystem, executor::executor::Executor, logger::logger::Logger,
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
pub struct RepoKitVersionResolver;
|
|
10
|
+
|
|
11
|
+
impl RepoKitVersionResolver {
|
|
12
|
+
pub fn hop_to_installed_version(files: &FileSystem) {
|
|
13
|
+
if files.install_script_path.is_absolute() && files.install_script_path.exists() {
|
|
14
|
+
if let Some(errors) = RepoKitVersionResolver::run_post_install(files) {
|
|
15
|
+
println!("{errors}");
|
|
16
|
+
Logger::error("My installer failed");
|
|
17
|
+
RepoKitVersionResolver::on_error();
|
|
18
|
+
} else {
|
|
19
|
+
RepoKitVersionResolver::re_run_command();
|
|
20
|
+
}
|
|
21
|
+
} else {
|
|
22
|
+
Logger::error("I couldn't find my installer");
|
|
23
|
+
RepoKitVersionResolver::on_error();
|
|
24
|
+
}
|
|
25
|
+
panic!();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
fn run_post_install(files: &FileSystem) -> Option<String> {
|
|
29
|
+
let handle = SpinnerBuilder::new()
|
|
30
|
+
.spinner(&BOUNCING_BALL)
|
|
31
|
+
.text(" Installing")
|
|
32
|
+
.start();
|
|
33
|
+
let result =
|
|
34
|
+
Executor::exec_with_errors(format!("./{}", files.install_script_location), |cmd| {
|
|
35
|
+
cmd.current_dir(&files.package_directory)
|
|
36
|
+
});
|
|
37
|
+
handle.done();
|
|
38
|
+
result
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
fn re_run_command() {
|
|
42
|
+
let args: Vec<String> = args().collect();
|
|
43
|
+
Executor::with_stdio(args.join(" "), |cmd| cmd);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
fn on_error() {
|
|
47
|
+
Logger::info("Please file a bug here");
|
|
48
|
+
Logger::log_issue_link();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
use std::path::PathBuf;
|
|
2
|
+
|
|
3
|
+
use crate::{
|
|
4
|
+
caches::file_cache::FileCache, logger::logger::Logger,
|
|
5
|
+
post_processing::post_processor::PostProcessor,
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
#[derive(Clone)]
|
|
9
|
+
pub struct SettingsCache {
|
|
10
|
+
pub cache_directory: Option<PathBuf>,
|
|
11
|
+
pub theme_preference: String,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
impl SettingsCache {
|
|
15
|
+
pub fn new(cache_directory: &Option<PathBuf>) -> Self {
|
|
16
|
+
SettingsCache {
|
|
17
|
+
cache_directory: cache_directory.clone(),
|
|
18
|
+
theme_preference: Logger::with_registry(|registry| registry.default_theme.to_owned()),
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
pub async fn initialize(&mut self) {
|
|
23
|
+
if let Some((mut lines, _)) = self.read()
|
|
24
|
+
&& let Some(result) = lines.nth(0)
|
|
25
|
+
&& let Ok(theme) = result
|
|
26
|
+
{
|
|
27
|
+
self.theme_preference = theme;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
pub fn store_theme_preference(&self, theme: &str) {
|
|
32
|
+
self.write(format!("{theme}\n").as_str(), |_| {
|
|
33
|
+
self.on_theme_storage_error(theme);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
fn on_theme_storage_error(&self, theme: &str) {
|
|
38
|
+
if let Some(storage_path) = self.storage_path() {
|
|
39
|
+
let theme_clone = theme.to_string();
|
|
40
|
+
PostProcessor::get().register_task(move || {
|
|
41
|
+
Logger::info("I failed to write your theme preference to the file system");
|
|
42
|
+
Logger::info(
|
|
43
|
+
format!(
|
|
44
|
+
"This usually indicates a bug within {}",
|
|
45
|
+
Logger::with_theme(|theme| theme.highlight("Repokit"))
|
|
46
|
+
)
|
|
47
|
+
.as_str(),
|
|
48
|
+
);
|
|
49
|
+
Logger::info("Please file an issue here");
|
|
50
|
+
Logger::log_issue_link();
|
|
51
|
+
Logger::info("To repair this manually you can run");
|
|
52
|
+
Logger::log_file_path(
|
|
53
|
+
format!(
|
|
54
|
+
"printf \"{}\n\" > {}",
|
|
55
|
+
theme_clone,
|
|
56
|
+
storage_path.to_string_lossy(),
|
|
57
|
+
)
|
|
58
|
+
.as_str(),
|
|
59
|
+
);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
impl FileCache for SettingsCache {
|
|
66
|
+
fn cache_file(&self) -> &str {
|
|
67
|
+
".settings"
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
fn cache_directory(&self) -> &Option<PathBuf> {
|
|
71
|
+
&self.cache_directory
|
|
72
|
+
}
|
|
73
|
+
}
|