Fix how processor arguments are generated in app (#4919)

This commit is contained in:
aecsocket
2025-12-16 20:03:37 +00:00
committed by GitHub
parent 21fad12a21
commit e123e51c66

View File

@@ -452,35 +452,64 @@ where
Ok(()) Ok(())
} }
pub fn get_processor_arguments<T: AsRef<str>>( pub fn get_processor_arguments(
libraries_path: &Path, libraries_path: &Path,
arguments: &[T], arguments: &[impl AsRef<str>],
data: &HashMap<String, SidedDataEntry>, data: &HashMap<String, SidedDataEntry>,
) -> crate::Result<Vec<String>> { ) -> crate::Result<Vec<String>> {
let mut new_arguments = Vec::new(); // We use iterator combinators to make sure that 1 input argument maps
// to exactly 1 output argument. Otherwise you might get issues that take
// days to debug *sigh*
//
// Arguments can be enclosed in square brackets [] if they are not taken
// literally, but are actually resolved to the path of a library we
// previously downloaded.
// For example, `[net.neoforged:neoform:1.21.10-20251010.172816:mappings@tsrg.lzma]`.
//
// Otherwise, arguments may contain `{KEY}` variable placeholders, which
// must be replaced with the corresponding value from `data`.
// Importantly, variables might not *just* be `{KEY}`, but may also be
// e.g. `{KEY}/some more values`. For example, `{ROOT}/libraries/`.
// Therefore, it is important that we don't just check if the variable is
// enclosed in `{}`s, but actually do a find-and-replace with all variables.
//
// Currently, we do it in a naive way where we iterate over every `data`
// entry and just `.replace()`, which is not efficient, but we shouldn't
// have a lot of entries in `data`, and this code is not run often anyway.
for argument in arguments { arguments
let trimmed_arg = &argument.as_ref()[1..argument.as_ref().len() - 1]; .iter()
if argument.as_ref().starts_with('{') { .map(|arg| {
if let Some(entry) = data.get(trimmed_arg) { let arg = arg.as_ref();
new_arguments.push(if entry.client.starts_with('[') { if let Some(arg) = arg.strip_prefix('[')
get_lib_path( && let Some(lib_key) = arg.strip_suffix(']')
libraries_path, {
&entry.client[1..entry.client.len() - 1], // this should resolve to the path of a library
true, get_lib_path(libraries_path, lib_key, true)
)? } else {
} else { let mut arg = arg.to_string();
entry.client.clone()
}) // replace variables like `{PATH}` to their real values
for (key, entry) in data {
let replacement = if let Some(arg) =
entry.client.strip_prefix('[')
&& let Some(lib_key) = arg.strip_suffix(']')
{
// if the value of `PATH` in `data` is also a library key,
// it'll be enclosed in `[]`s, and we resolve it to a real lib path
get_lib_path(libraries_path, lib_key, true)?
} else {
// otherwise we just take the value in `data` literally
entry.client.clone()
};
arg = arg.replace(&format!("{{{key}}}"), &replacement);
}
Ok(arg)
} }
} else if argument.as_ref().starts_with('[') { })
new_arguments.push(get_lib_path(libraries_path, trimmed_arg, true)?) .collect::<crate::Result<Vec<_>>>()
} else {
new_arguments.push(argument.as_ref().to_string())
}
}
Ok(new_arguments)
} }
pub async fn get_processor_main_class( pub async fn get_processor_main_class(