@repokit/core 3.0.6 → 4.0.1
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 +49 -26
- package/internals/caches/crawl_cache.rs +124 -0
- package/internals/caches/file_cache.rs +104 -0
- package/internals/caches/mod.rs +6 -0
- package/internals/caches/old_cache.rs +35 -0
- package/internals/caches/repokit_version_resolver.rs +50 -0
- package/internals/caches/settings_cache.rs +73 -0
- package/internals/caches/version_cache.rs +142 -0
- package/internals/context/cache_scope.rs +71 -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 +70 -39
- 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
|
@@ -6,24 +6,21 @@ use crate::{
|
|
|
6
6
|
executables::{
|
|
7
7
|
internal_executable::InternalExecutable,
|
|
8
8
|
internal_executable_definition::{
|
|
9
|
-
InternalExecutableDefinition, InternalExecutableDefinitionInput,
|
|
9
|
+
InternalExecutableDefinition, InternalExecutableDefinitionInput,
|
|
10
10
|
},
|
|
11
11
|
},
|
|
12
12
|
executor::executor::Executor,
|
|
13
|
-
internal_commands::help::Help,
|
|
14
|
-
internal_filesystem::internal_filesystem::InternalFileSystem,
|
|
15
13
|
logger::logger::Logger,
|
|
14
|
+
repokit::repokit_runtime::RepoKitRuntime,
|
|
16
15
|
};
|
|
17
16
|
|
|
18
17
|
pub struct UpgradeRepoKit {
|
|
19
|
-
pub scope: RepoKitScope,
|
|
20
18
|
pub definition: InternalExecutableDefinition,
|
|
21
19
|
}
|
|
22
20
|
|
|
23
21
|
impl UpgradeRepoKit {
|
|
24
|
-
pub fn new(
|
|
22
|
+
pub fn new() -> UpgradeRepoKit {
|
|
25
23
|
UpgradeRepoKit {
|
|
26
|
-
scope: scope.clone(),
|
|
27
24
|
definition: InternalExecutableDefinition::define(InternalExecutableDefinitionInput {
|
|
28
25
|
name: "upgrade",
|
|
29
26
|
description: "Upgrades your installation of repokit to the latest stable version",
|
|
@@ -32,50 +29,42 @@ impl UpgradeRepoKit {
|
|
|
32
29
|
}
|
|
33
30
|
}
|
|
34
31
|
|
|
35
|
-
pub fn static_execute(
|
|
32
|
+
pub fn static_execute(&self) {
|
|
36
33
|
Logger::info("Upgrading installation");
|
|
37
34
|
let handle = SpinnerBuilder::new()
|
|
38
35
|
.spinner(&BOUNCING_BALL)
|
|
39
36
|
.text(" Installing")
|
|
40
37
|
.start();
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
38
|
+
RepoKitRuntime::with_runtime(|runtime| {
|
|
39
|
+
Executor::exec(
|
|
40
|
+
format!("{} @repokit/core@latest", runtime.node.install_command).as_str(),
|
|
41
|
+
|cmd| cmd.current_dir(&runtime.git.root),
|
|
42
|
+
)
|
|
43
|
+
});
|
|
46
44
|
handle.done();
|
|
45
|
+
Logger::info("Upgrade Complete!");
|
|
47
46
|
}
|
|
48
47
|
}
|
|
49
48
|
|
|
50
49
|
impl InternalExecutable for UpgradeRepoKit {
|
|
51
50
|
fn run(&self, _: Vec<String>, _: &HashMap<String, Box<dyn InternalExecutable>>) {
|
|
52
|
-
|
|
53
|
-
let
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
.installed_repokit_version()
|
|
60
|
-
.unwrap_or(fallback.to_string());
|
|
61
|
-
if runtime_version != installed_version {
|
|
62
|
-
Logger::info("Upgrade Complete!");
|
|
51
|
+
self.static_execute();
|
|
52
|
+
if let Some(new_version) = RepoKitRuntime::with_runtime(|runtime| {
|
|
53
|
+
runtime
|
|
54
|
+
.caches
|
|
55
|
+
.version_cache
|
|
56
|
+
.refresh_installed_version(&runtime.files)
|
|
57
|
+
}) {
|
|
63
58
|
Logger::info(
|
|
64
59
|
format!(
|
|
65
60
|
"The currently installed version is {}",
|
|
66
|
-
Logger::with_theme(|theme| theme.highlight(&
|
|
61
|
+
Logger::with_theme(|theme| theme.highlight(&new_version))
|
|
67
62
|
)
|
|
68
63
|
.as_str(),
|
|
69
64
|
);
|
|
70
|
-
} else {
|
|
71
|
-
Logger::info("The latest version is already installed");
|
|
72
65
|
}
|
|
73
66
|
}
|
|
74
67
|
|
|
75
|
-
fn help(&self) {
|
|
76
|
-
Help::log_internal_command(&self.definition);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
68
|
fn get_definition(&self) -> &InternalExecutableDefinition {
|
|
80
69
|
&self.definition
|
|
81
70
|
}
|
|
@@ -1,22 +1,19 @@
|
|
|
1
|
-
use crate::post_processing::post_processor::PostProcessor;
|
|
2
1
|
use std::{
|
|
3
2
|
fs::{File, create_dir_all},
|
|
4
3
|
io::{Error, copy},
|
|
5
4
|
path::Path,
|
|
6
|
-
process::exit,
|
|
7
5
|
};
|
|
8
6
|
|
|
9
7
|
pub struct FileBuilder;
|
|
10
8
|
|
|
11
9
|
impl FileBuilder {
|
|
12
|
-
pub fn open(source:
|
|
10
|
+
pub fn open<P: AsRef<Path>>(source: P, on_error: impl Fn(Error)) -> File {
|
|
13
11
|
let source = File::open(source);
|
|
14
12
|
match source {
|
|
15
13
|
Ok(file) => file,
|
|
16
14
|
Err(error) => {
|
|
17
15
|
on_error(error);
|
|
18
|
-
|
|
19
|
-
exit(0);
|
|
16
|
+
panic!();
|
|
20
17
|
}
|
|
21
18
|
}
|
|
22
19
|
}
|
|
@@ -27,8 +24,7 @@ impl FileBuilder {
|
|
|
27
24
|
Ok(file) => file,
|
|
28
25
|
Err(error) => {
|
|
29
26
|
on_error(error);
|
|
30
|
-
|
|
31
|
-
exit(0);
|
|
27
|
+
panic!();
|
|
32
28
|
}
|
|
33
29
|
}
|
|
34
30
|
}
|
|
@@ -53,8 +49,7 @@ impl FileBuilder {
|
|
|
53
49
|
Ok(result) => result,
|
|
54
50
|
Err(error) => {
|
|
55
51
|
on_error(error);
|
|
56
|
-
|
|
57
|
-
exit(0);
|
|
52
|
+
panic!();
|
|
58
53
|
}
|
|
59
54
|
}
|
|
60
55
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
use core::panic;
|
|
1
2
|
use std::sync::LazyLock;
|
|
2
3
|
use std::sync::Mutex;
|
|
3
4
|
use std::sync::MutexGuard;
|
|
4
5
|
|
|
5
6
|
use colored::{ColoredString, Colorize};
|
|
6
7
|
|
|
7
|
-
use crate::
|
|
8
|
+
use crate::repokit::repokit_runtime::RepoKitRuntime;
|
|
8
9
|
use crate::themes::theme::Theme;
|
|
9
10
|
use crate::themes::theme_registry::ThemeRegistry;
|
|
10
11
|
|
|
@@ -16,8 +17,16 @@ static THEMES: LazyLock<Mutex<ThemeRegistry>> = LazyLock::new(|| Mutex::new(Them
|
|
|
16
17
|
pub struct Logger;
|
|
17
18
|
|
|
18
19
|
impl Logger {
|
|
19
|
-
pub fn
|
|
20
|
-
|
|
20
|
+
pub fn initialize() {
|
|
21
|
+
RepoKitRuntime::with_runtime(|runtime| {
|
|
22
|
+
Logger::set_name(&runtime.configuration.project);
|
|
23
|
+
for theme in &runtime.configuration.themes {
|
|
24
|
+
Logger::with_registry(|mut registry| registry.register_user_theme(theme))
|
|
25
|
+
}
|
|
26
|
+
Logger::with_registry(|mut registry| {
|
|
27
|
+
registry.set_theme(&runtime.caches.settings_cache.theme_preference)
|
|
28
|
+
});
|
|
29
|
+
});
|
|
21
30
|
}
|
|
22
31
|
|
|
23
32
|
pub fn info(message: &str) {
|
|
@@ -30,12 +39,12 @@ impl Logger {
|
|
|
30
39
|
|
|
31
40
|
pub fn exit_with_info(message: &str) {
|
|
32
41
|
Logger::info(message);
|
|
33
|
-
|
|
42
|
+
panic!();
|
|
34
43
|
}
|
|
35
44
|
|
|
36
45
|
pub fn exit_with_error(message: &str) {
|
|
37
46
|
Logger::error(message);
|
|
38
|
-
|
|
47
|
+
panic!();
|
|
39
48
|
}
|
|
40
49
|
|
|
41
50
|
pub fn list(items: &[&str], indentation: Option<i32>) {
|
|
@@ -121,7 +130,7 @@ impl Logger {
|
|
|
121
130
|
Logger::info(format!("I was unable to {operation} in your repository").as_str());
|
|
122
131
|
Logger::error("Please verify the permissions on your working directory or file a bug here");
|
|
123
132
|
Logger::log_issue_link();
|
|
124
|
-
|
|
133
|
+
panic!();
|
|
125
134
|
}
|
|
126
135
|
|
|
127
136
|
fn info_prefix() -> String {
|
|
@@ -133,4 +142,8 @@ impl Logger {
|
|
|
133
142
|
format!("{}: ", theme.error_prefix(®ISTERED_NAME.lock().unwrap()))
|
|
134
143
|
})
|
|
135
144
|
}
|
|
145
|
+
|
|
146
|
+
fn set_name(value: &str) {
|
|
147
|
+
*REGISTERED_NAME.lock().unwrap() = value.to_string();
|
|
148
|
+
}
|
|
136
149
|
}
|
package/internals/main.rs
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
use
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
repokit::{repokit::RepoKit, runtime_compiler::RuntimeCompiler},
|
|
5
|
-
};
|
|
1
|
+
use std::panic;
|
|
2
|
+
|
|
3
|
+
use crate::{post_processing::post_processor::PostProcessor, repokit::repokit::RepoKit};
|
|
6
4
|
|
|
7
5
|
mod argv;
|
|
8
|
-
mod
|
|
6
|
+
mod caches;
|
|
7
|
+
mod context;
|
|
9
8
|
mod executables;
|
|
10
9
|
mod executor;
|
|
11
10
|
mod file_walker;
|
|
@@ -18,9 +17,7 @@ mod themes;
|
|
|
18
17
|
mod validations;
|
|
19
18
|
|
|
20
19
|
fn main() {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
let kit = RepoKit::new(&root, config);
|
|
25
|
-
kit.invoke();
|
|
20
|
+
panic::set_hook(Box::new(|_| PostProcessor::get().flush()));
|
|
21
|
+
RepoKit::new().invoke();
|
|
22
|
+
PostProcessor::get().flush();
|
|
26
23
|
}
|
package/internals/repokit/mod.rs
CHANGED
|
@@ -1,77 +1,52 @@
|
|
|
1
1
|
use std::{collections::HashMap, env::args, path::Path};
|
|
2
2
|
|
|
3
3
|
use crate::{
|
|
4
|
-
executables::
|
|
5
|
-
internal_executable::InternalExecutable, internal_executable_definition::RepoKitScope,
|
|
6
|
-
},
|
|
4
|
+
executables::internal_executable::InternalExecutable,
|
|
7
5
|
executor::executor::Executor,
|
|
8
6
|
internal_commands::help::Help,
|
|
9
|
-
internal_filesystem::internal_filesystem::InternalFileSystem,
|
|
10
7
|
logger::logger::Logger,
|
|
11
|
-
|
|
12
|
-
repokit::{repokit_command::RepoKitCommand, repokit_config::RepoKitConfig},
|
|
8
|
+
repokit::{repokit_command::RepoKitCommand, repokit_runtime::RepoKitRuntime},
|
|
13
9
|
validations::command_validations::CommandValidations,
|
|
14
10
|
};
|
|
15
11
|
|
|
16
|
-
pub struct RepoKit {
|
|
17
|
-
pub scope: RepoKitScope,
|
|
18
|
-
}
|
|
12
|
+
pub struct RepoKit {}
|
|
19
13
|
|
|
20
14
|
impl RepoKit {
|
|
21
|
-
pub fn new(
|
|
22
|
-
Logger::
|
|
23
|
-
|
|
24
|
-
Logger::with_registry(|mut registry| registry.register_user_theme(theme))
|
|
25
|
-
}
|
|
26
|
-
let theme = InternalFileSystem::new(root).read_theme_preference();
|
|
27
|
-
Logger::with_registry(|mut registry| registry.set_theme(root, &theme));
|
|
28
|
-
RepoKit {
|
|
29
|
-
scope: RepoKitScope {
|
|
30
|
-
configuration,
|
|
31
|
-
root: root.to_string(),
|
|
32
|
-
},
|
|
33
|
-
}
|
|
15
|
+
pub fn new() -> RepoKit {
|
|
16
|
+
Logger::initialize();
|
|
17
|
+
RepoKit {}
|
|
34
18
|
}
|
|
35
19
|
|
|
36
20
|
pub fn invoke(&self) {
|
|
37
21
|
let (command, args) = self.parse();
|
|
38
|
-
let
|
|
39
|
-
let
|
|
40
|
-
|
|
41
|
-
let interface = internals.get(&command).expect("known command");
|
|
42
|
-
return interface.run(args, &internals);
|
|
43
|
-
}
|
|
44
|
-
if self.scope.configuration.commands.contains_key(&command) {
|
|
45
|
-
let root_script = self
|
|
46
|
-
.scope
|
|
47
|
-
.configuration
|
|
48
|
-
.commands
|
|
49
|
-
.get(&command)
|
|
50
|
-
.expect("Unknown command");
|
|
51
|
-
return Executor::with_stdio(
|
|
52
|
-
format!("{} {}", root_script.command, &args.join(" ")),
|
|
53
|
-
|cmd| cmd.current_dir(Path::new(&self.scope.root)),
|
|
54
|
-
);
|
|
22
|
+
let internals = CommandValidations::collect_and_validate_internals();
|
|
23
|
+
if let Some(internal_command) = internals.get(&command) {
|
|
24
|
+
return internal_command.run(args, &internals);
|
|
55
25
|
}
|
|
56
|
-
|
|
26
|
+
RepoKitRuntime::with_runtime(|runtime| {
|
|
27
|
+
if let Some(root_script) = runtime.configuration.commands.get(&command) {
|
|
28
|
+
Executor::with_stdio(
|
|
29
|
+
format!("{} {}", root_script.command, &args.join(" ")),
|
|
30
|
+
|cmd| cmd.current_dir(&runtime.files.git_root_path),
|
|
31
|
+
);
|
|
32
|
+
panic!();
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
let externals = CommandValidations::collect_and_validate_externals();
|
|
57
36
|
CommandValidations::detect_collisions_between_internals_and_externals(
|
|
58
37
|
&internals, &externals,
|
|
59
38
|
);
|
|
60
|
-
if externals.
|
|
61
|
-
let interface = externals.get(&command).expect("Unknown command");
|
|
39
|
+
if let Some(interface) = externals.get(&command) {
|
|
62
40
|
if args.is_empty() {
|
|
63
41
|
return self.log_external_command(interface);
|
|
64
42
|
}
|
|
65
43
|
let sub_command = &args[0];
|
|
66
|
-
if interface.commands.
|
|
67
|
-
let
|
|
68
|
-
let working_dir = Path::new(&interface.location)
|
|
69
|
-
.
|
|
70
|
-
|
|
71
|
-
return
|
|
72
|
-
format!("{} {}", &script.command, &args[1..].join(" ")),
|
|
73
|
-
|cmd| cmd.current_dir(working_dir),
|
|
74
|
-
);
|
|
44
|
+
if let Some(script) = interface.commands.get(sub_command) {
|
|
45
|
+
let executable = format!("{} {}", &script.command, &args[1..].join(" "));
|
|
46
|
+
if let Some(working_dir) = Path::new(&interface.location).parent() {
|
|
47
|
+
return Executor::with_stdio(executable, |cmd| cmd.current_dir(working_dir));
|
|
48
|
+
}
|
|
49
|
+
return self.working_directory_not_found(interface, &executable);
|
|
75
50
|
}
|
|
76
51
|
return self.subcommand_not_found(interface, sub_command);
|
|
77
52
|
}
|
|
@@ -82,8 +57,8 @@ impl RepoKit {
|
|
|
82
57
|
let argv: Vec<String> = args().collect();
|
|
83
58
|
if argv.len() < 2 {
|
|
84
59
|
let (internals, externals) = self.collect_and_validate();
|
|
85
|
-
Help::list_all(&
|
|
86
|
-
|
|
60
|
+
Help::list_all(&internals, &externals);
|
|
61
|
+
panic!();
|
|
87
62
|
}
|
|
88
63
|
let command = &argv[1];
|
|
89
64
|
let args = &(&argv)[2..];
|
|
@@ -96,9 +71,8 @@ impl RepoKit {
|
|
|
96
71
|
HashMap<String, Box<dyn InternalExecutable>>,
|
|
97
72
|
HashMap<String, RepoKitCommand>,
|
|
98
73
|
) {
|
|
99
|
-
let
|
|
100
|
-
let
|
|
101
|
-
let externals = validator.collect_and_validate_externals();
|
|
74
|
+
let internals = CommandValidations::collect_and_validate_internals();
|
|
75
|
+
let externals = CommandValidations::collect_and_validate_externals();
|
|
102
76
|
CommandValidations::detect_collisions_between_internals_and_externals(
|
|
103
77
|
&internals, &externals,
|
|
104
78
|
);
|
|
@@ -111,7 +85,7 @@ impl RepoKit {
|
|
|
111
85
|
internals: &HashMap<String, Box<dyn InternalExecutable>>,
|
|
112
86
|
externals: &HashMap<String, RepoKitCommand>,
|
|
113
87
|
) {
|
|
114
|
-
Help::list_all(
|
|
88
|
+
Help::list_all(internals, externals);
|
|
115
89
|
Logger::info(
|
|
116
90
|
format!(
|
|
117
91
|
"I'm not aware of a command named {}",
|
|
@@ -151,4 +125,22 @@ impl RepoKit {
|
|
|
151
125
|
Help::log_external_subcommands(&command.commands, 3);
|
|
152
126
|
println!();
|
|
153
127
|
}
|
|
128
|
+
|
|
129
|
+
fn working_directory_not_found(&self, interface: &RepoKitCommand, executable: &str) {
|
|
130
|
+
Logger::info("I was unable to determine the working directory for this command");
|
|
131
|
+
Logger::info(
|
|
132
|
+
format!(
|
|
133
|
+
"This typically indicates a bug within {}",
|
|
134
|
+
Logger::with_theme(|theme| theme.highlight("Repokit"))
|
|
135
|
+
)
|
|
136
|
+
.as_str(),
|
|
137
|
+
);
|
|
138
|
+
Logger::info("Please file an issue at");
|
|
139
|
+
Logger::log_issue_link();
|
|
140
|
+
Logger::info("To run this command from your terminal, you can run:");
|
|
141
|
+
Logger::log_file_path(executable);
|
|
142
|
+
Logger::info("From the parent directory of");
|
|
143
|
+
Logger::log_file_path(&interface.location);
|
|
144
|
+
panic!();
|
|
145
|
+
}
|
|
154
146
|
}
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
use std::{
|
|
2
|
-
collections::HashMap,
|
|
3
|
-
sync::LazyLock,
|
|
4
|
-
};
|
|
1
|
+
use std::{collections::HashMap, sync::LazyLock};
|
|
5
2
|
|
|
6
3
|
use jsonschema::Validator;
|
|
7
4
|
use schemars::JsonSchema;
|
|
@@ -9,12 +6,11 @@ use serde::Deserialize;
|
|
|
9
6
|
use serde_json::{Value, from_value, to_value};
|
|
10
7
|
|
|
11
8
|
use crate::{
|
|
12
|
-
configuration::recovery::Recovery,
|
|
13
9
|
logger::logger::Logger,
|
|
14
10
|
post_processing::post_processor::PostProcessor,
|
|
15
11
|
repokit::{
|
|
16
12
|
command_definition::CommandDefinition,
|
|
17
|
-
repokit_construct_validator::RepoKitConstructValidator,
|
|
13
|
+
repokit_construct_validator::RepoKitConstructValidator, repokit_runtime::RepoKitRuntime,
|
|
18
14
|
},
|
|
19
15
|
};
|
|
20
16
|
|
|
@@ -31,37 +27,14 @@ static REPOKIT_COMMAND_VALIDATOR: LazyLock<Validator> = LazyLock::new(|| {
|
|
|
31
27
|
Validator::new(&to_value(schemars::schema_for!(RepoKitCommand)).unwrap()).unwrap()
|
|
32
28
|
});
|
|
33
29
|
|
|
34
|
-
impl RepoKitCommand {
|
|
35
|
-
fn register_encountered_errors(root: &str, failed_paths: Vec<String>) {
|
|
36
|
-
let root_clone = root.to_string();
|
|
37
|
-
PostProcessor::get().register_task(move || {
|
|
38
|
-
println!();
|
|
39
|
-
if !failed_paths.is_empty() {
|
|
40
|
-
let appendage = if failed_paths.len() != 1 { "s" } else { "" };
|
|
41
|
-
Logger::error(
|
|
42
|
-
format!(
|
|
43
|
-
"I encountered an error in the following command{}",
|
|
44
|
-
appendage
|
|
45
|
-
)
|
|
46
|
-
.as_str(),
|
|
47
|
-
);
|
|
48
|
-
Logger::list_file_paths(&failed_paths);
|
|
49
|
-
} else {
|
|
50
|
-
Logger::info("There was an error parsing one or more of your commands");
|
|
51
|
-
}
|
|
52
|
-
Logger::info("You can validate a command file's syntactical correctness by running");
|
|
53
|
-
Logger::log_file_path(
|
|
54
|
-
&Recovery::new(&root_clone).get_typecheck_command("<optional-path-to-file>"),
|
|
55
|
-
);
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
}
|
|
30
|
+
impl RepoKitConstructValidator for RepoKitCommand {}
|
|
59
31
|
|
|
60
|
-
impl
|
|
61
|
-
fn from_input(
|
|
32
|
+
impl RepoKitCommand {
|
|
33
|
+
pub fn from_input(input: Vec<Value>) -> Vec<RepoKitCommand> {
|
|
62
34
|
let mut result: Vec<RepoKitCommand> = Vec::new();
|
|
63
35
|
let mut failures = 0;
|
|
64
36
|
let mut failed_paths: Vec<String> = Vec::new();
|
|
37
|
+
let git_root = RepoKitRuntime::with_runtime(|runtime| runtime.git.root.clone());
|
|
65
38
|
for command in input {
|
|
66
39
|
let repokit_command: Result<RepoKitCommand, serde_json::Error> =
|
|
67
40
|
from_value(command.clone());
|
|
@@ -69,28 +42,86 @@ impl RepoKitConstructValidator<Vec<Value>, Vec<RepoKitCommand>> for RepoKitComma
|
|
|
69
42
|
|| repokit_command.is_err()
|
|
70
43
|
{
|
|
71
44
|
failures += 1;
|
|
72
|
-
if let Some(path) = RepoKitCommand::on_parsing_error(
|
|
45
|
+
if let Some(path) = RepoKitCommand::on_parsing_error(command) {
|
|
73
46
|
failed_paths.push(path);
|
|
74
47
|
}
|
|
75
48
|
} else {
|
|
76
|
-
let mut valid_command = repokit_command.expect("
|
|
77
|
-
valid_command.location = format!("{}/{}",
|
|
49
|
+
let mut valid_command = repokit_command.expect("parse success");
|
|
50
|
+
valid_command.location = format!("{}/{}", git_root, valid_command.location);
|
|
78
51
|
result.push(valid_command);
|
|
79
52
|
}
|
|
80
53
|
}
|
|
81
54
|
if failures != 0 {
|
|
82
|
-
RepoKitCommand::register_encountered_errors(
|
|
55
|
+
RepoKitCommand::register_encountered_errors(failed_paths);
|
|
83
56
|
}
|
|
84
57
|
result
|
|
85
58
|
}
|
|
86
59
|
|
|
87
|
-
fn on_parsing_error(
|
|
60
|
+
pub fn on_parsing_error(command: Value) -> Option<String> {
|
|
88
61
|
let location = command.get("location");
|
|
89
62
|
println!();
|
|
90
63
|
if location.is_some_and(|v| v.is_string()) {
|
|
91
|
-
let path =
|
|
64
|
+
let path = RepoKitRuntime::with_runtime(|runtime| {
|
|
65
|
+
format!(
|
|
66
|
+
"{}/{}",
|
|
67
|
+
runtime.git.root,
|
|
68
|
+
location.unwrap().as_str().unwrap()
|
|
69
|
+
)
|
|
70
|
+
});
|
|
92
71
|
return Some(path);
|
|
93
72
|
}
|
|
94
73
|
None
|
|
95
74
|
}
|
|
75
|
+
|
|
76
|
+
pub fn full_blown_crash() {
|
|
77
|
+
Logger::error("I hit a snag parsing your commands");
|
|
78
|
+
Logger::error(
|
|
79
|
+
format!(
|
|
80
|
+
"This kind of error is indicative of a bug within {}",
|
|
81
|
+
Logger::with_theme(|theme| theme.highlight("Repokit"))
|
|
82
|
+
)
|
|
83
|
+
.as_str(),
|
|
84
|
+
);
|
|
85
|
+
println!();
|
|
86
|
+
Logger::info("Let's blaim the AI's for this one");
|
|
87
|
+
let version = RepoKitRuntime::with_runtime(|runtime| {
|
|
88
|
+
runtime.caches.version_cache.installed_version.clone()
|
|
89
|
+
});
|
|
90
|
+
Logger::info(
|
|
91
|
+
format!(
|
|
92
|
+
"In the interim, please file a bug here and downgrade to the most recent version behind {}",
|
|
93
|
+
Logger::with_theme(|theme| theme.highlight(&version))
|
|
94
|
+
)
|
|
95
|
+
.as_str(),
|
|
96
|
+
);
|
|
97
|
+
Logger::log_issue_link();
|
|
98
|
+
Logger::info("We'll get a hotfix out asap!");
|
|
99
|
+
panic!();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
fn register_encountered_errors(failed_paths: Vec<String>) {
|
|
103
|
+
PostProcessor::get().register_task(move || {
|
|
104
|
+
println!();
|
|
105
|
+
if !failed_paths.is_empty() {
|
|
106
|
+
let appendage = if failed_paths.len() != 1 { "s" } else { "" };
|
|
107
|
+
Logger::error(
|
|
108
|
+
format!(
|
|
109
|
+
"I encountered an error in the following command{}",
|
|
110
|
+
appendage
|
|
111
|
+
)
|
|
112
|
+
.as_str(),
|
|
113
|
+
);
|
|
114
|
+
Logger::list_file_paths(&failed_paths);
|
|
115
|
+
} else {
|
|
116
|
+
Logger::info("There was an error parsing one or more of your commands");
|
|
117
|
+
}
|
|
118
|
+
Logger::info("You can validate a command file's syntactical correctness by running");
|
|
119
|
+
let type_check_command = RepoKitRuntime::with_runtime(|mut runtime| {
|
|
120
|
+
runtime
|
|
121
|
+
.node
|
|
122
|
+
.get_typecheck_command("<optional-path-to-file>")
|
|
123
|
+
});
|
|
124
|
+
Logger::log_file_path(&type_check_command);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
96
127
|
}
|
|
@@ -1,19 +1,14 @@
|
|
|
1
|
-
use
|
|
2
|
-
collections::HashMap,
|
|
3
|
-
path::Path,
|
|
4
|
-
process::exit,
|
|
5
|
-
sync::LazyLock,
|
|
6
|
-
};
|
|
7
|
-
|
|
1
|
+
use core::panic;
|
|
8
2
|
use jsonschema::Validator;
|
|
9
3
|
use schemars::JsonSchema;
|
|
10
4
|
use serde::Deserialize;
|
|
11
5
|
use serde_json::{Value, from_value, to_value};
|
|
6
|
+
use std::{collections::HashMap, path::Path, sync::LazyLock};
|
|
12
7
|
|
|
13
8
|
use crate::{
|
|
14
|
-
|
|
9
|
+
context::{file_system::FileSystem, node_scope::NodeScope},
|
|
10
|
+
internal_filesystem::file_builder::FileBuilder,
|
|
15
11
|
logger::logger::Logger,
|
|
16
|
-
post_processing::post_processor::PostProcessor,
|
|
17
12
|
repokit::{
|
|
18
13
|
command_definition::CommandDefinition, repokit_command::RepoKitCommand,
|
|
19
14
|
repokit_construct_validator::RepoKitConstructValidator,
|
|
@@ -52,24 +47,53 @@ static REPOKIT_CONFIG_VALIDATOR: LazyLock<Validator> = LazyLock::new(|| {
|
|
|
52
47
|
Validator::new(&to_value(schemars::schema_for!(RepoKitConfig)).unwrap()).unwrap()
|
|
53
48
|
});
|
|
54
49
|
|
|
55
|
-
impl RepoKitConstructValidator
|
|
56
|
-
|
|
50
|
+
impl RepoKitConstructValidator for RepoKitConfig {}
|
|
51
|
+
|
|
52
|
+
impl RepoKitConfig {
|
|
53
|
+
pub fn from_input(root: &str, node: &mut NodeScope, input: Value) -> RepoKitConfig {
|
|
57
54
|
let repokit_config: Result<RepoKitConfig, serde_json::Error> = from_value(input.clone());
|
|
58
55
|
if !RepoKitConfig::is_valid(&REPOKIT_CONFIG_VALIDATOR, &input) || repokit_config.is_err() {
|
|
59
|
-
RepoKitConfig::on_parsing_error(root, Value::Null);
|
|
56
|
+
RepoKitConfig::on_parsing_error(root, node, Value::Null);
|
|
60
57
|
}
|
|
61
58
|
repokit_config.expect("assertions succeeded")
|
|
62
59
|
}
|
|
63
60
|
|
|
64
|
-
fn on_parsing_error(root: &str, _: Value) -> Option<String> {
|
|
61
|
+
pub fn on_parsing_error(root: &str, node: &mut NodeScope, _: Value) -> Option<String> {
|
|
65
62
|
let path_buf = Path::new(&root).join("repokit.ts");
|
|
66
63
|
let path = path_buf.to_str().expect("exists");
|
|
67
|
-
|
|
68
|
-
recovery.run(path);
|
|
64
|
+
node.type_check_file(path);
|
|
69
65
|
println!();
|
|
70
66
|
Logger::info("There was an error parsing your configuration");
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
67
|
+
NodeScope::prompt_to_fix_errors(path);
|
|
68
|
+
panic!();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
pub fn create(files: &FileSystem) {
|
|
72
|
+
let file_path = format!("{}/repokit.ts", &files.git_root);
|
|
73
|
+
let path = Path::new(&file_path);
|
|
74
|
+
if path.exists() {
|
|
75
|
+
Logger::info(
|
|
76
|
+
format!(
|
|
77
|
+
"I found a Repokit configuration without an exported {} instance",
|
|
78
|
+
Logger::with_theme(|theme| theme.highlight("RepokitConfig"))
|
|
79
|
+
)
|
|
80
|
+
.as_str(),
|
|
81
|
+
);
|
|
82
|
+
return Logger::exit_with_info("Please create an instance and export it");
|
|
83
|
+
}
|
|
84
|
+
Logger::info("Welcome to Repokit! Let's get you setup");
|
|
85
|
+
Logger::info("Creating your configuration file:");
|
|
86
|
+
let mut source = files.resolve_template("configuration_template.txt");
|
|
87
|
+
let mut target = FileBuilder::create(path, |_| Logger::file_create_error());
|
|
88
|
+
FileBuilder::copy_to(&mut source, &mut target, |_| Logger::file_write_error());
|
|
89
|
+
Logger::info(
|
|
90
|
+
format!(
|
|
91
|
+
"Please fill out this file with your desired settings. Then run {}",
|
|
92
|
+
Logger::with_theme(|theme| theme.highlight("repokit onboard"))
|
|
93
|
+
)
|
|
94
|
+
.as_str(),
|
|
95
|
+
);
|
|
96
|
+
Logger::log_file_path(file_path.as_str());
|
|
97
|
+
panic!();
|
|
74
98
|
}
|
|
75
99
|
}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
use jsonschema::Validator;
|
|
2
2
|
use serde_json::Value;
|
|
3
3
|
|
|
4
|
-
pub trait RepoKitConstructValidator
|
|
5
|
-
fn from_input(root: &str, input: T) -> V;
|
|
6
|
-
fn on_parsing_error(root: &str, value: Value) -> Option<String>;
|
|
7
|
-
|
|
4
|
+
pub trait RepoKitConstructValidator {
|
|
8
5
|
fn is_valid(validator: &Validator, input: &Value) -> bool {
|
|
9
6
|
if validator.validate(input).is_err() {
|
|
10
7
|
return false;
|