-
Notifications
You must be signed in to change notification settings - Fork 44
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add more contextual informations to actions #242
Comments
Does this mean the current version installed, or the latest compatible version? Unfortunately both are not feasible, I've discussed the former in #138 and the latter is just way too slow. These are great suggestions! I will have to think about some of these, and some features are just not worth the effort (e.g. dependency listing). They are waaay more complicated to implement than it might seem, and it might not be worth it for such a small improvement. |
I was thinking about currently installed version, which is almost always present in the filename. Currently the output is of the form:
but the
So I think it would be beneficial to print just that - the filename of the latest mod, which helps in identifying the version easily:
This is the most straightforward way, in my opinion, but additional work could be done to provide a RegExp for extracting the version from the mod name using some most common patterns. This would on the other hand require you to sometimes update the regex if some new format is reported. Some example formats from the top of my head could fit the following regex: Which should match any of the following:
|
What you're describing is actually a huge problem that this program has had to deal with since the very beginning. (see #17, yes that old) The main issue is that using the filename to determine the mod version is unreliable because naming conventions differ quite a bit between authors, mod loaders, etc. |
Note, that my main proposal is to simply display the filename, and depend on human eyes to read the version number. Using the filename to determine the mod version, on the other hand, would be problematic, and it probably would be a dirty solution with a long cycle of proposing another pattern matcher and adapting it, while also never being sure, that ALL versioning schemes used in the wild are handled. While thinking about that I came up with yet another solution. Mods written for forge, fabric or quilt all have some kind of file, which has some mod metadata inside of them:
Commands I use to extract version information:
This approach would be the most correct one, as it depends on a common, standardized by mod-loaders mod structure. Versions would have to be extracted using appropriate json and toml parsers for fabric/quilt and forge respectively. It would be that simple, because jar files are just zip files with different extension name, so any tool and library that can peek inside the zip file could read mod's version. What's more, this approach could be useful to parse additional mod information that is included in the mod's config files, such as description, author, dependencies (as listed in |
Yes that would be a solution, I think PrismMC uses this. I was thinking that getting the files, unzipping them, and reading the manifests would be too slow, but I guess I should try it out one day. |
I had to check to be sure, but according to wikipedia the zip file doesn't need to be decompressed as a whole to access separate file. Zip file is capable of storing multiple files each compressed using different method, as well as decompressing a part of the whole archive — in this case, the There is a zip crate probably capable of doing that. |
Here is a concept that solves just that, written with my very basic knowledge of Rust. First, dependencies: # Cargo.toml
[dependencies]
zip = "0.6"
serde = "1.0"
serde_json = "1.0"
toml = "0.5"
regex = "1.7" and here is the script: use serde_json::{Result as JsonRes, Value as JsonVal};
use std::{fs::File, io::Read};
use toml::Value as TomlVal;
use zip::{read::ZipFile, ZipArchive};
use regex::Regex;
fn main() {
let jar_path = std::env::args().nth(1).expect("pass *.jar file path");
let t = get_version(jar_path);
println!("{}", t);
}
fn get_version(jar_path: String) -> String {
let jar_file = File::open(jar_path).expect("File not found");
let mut jar_archive = ZipArchive::new(jar_file).expect("Can't open .jar file");
match jar_archive
.by_name("fabric.mod.json")
.map(get_version_string_from_json)
{
Ok(ver) => return ver,
Err(e) => e,
};
match jar_archive
.by_name("quilt.mod.json")
.map(get_version_string_from_json)
{
Ok(ver) => return ver,
Err(e) => e,
};
match jar_archive
.by_name("META-INF/mods.toml")
.map(get_version_string_from_toml)
{
Ok(ver) => {
return if ver != "${file.jarVersion}" {
ver
} else {
jar_archive
.by_name("META-INF/MANIFEST.MF")
.map(get_version_string_from_manifest)
.expect("cannot determine version")
}
}
Err(_) => panic!("cannot determine version"),
};
}
fn read_zip_file_content(mut zip_file: ZipFile<'_>) -> String {
let mut content = String::new();
let _n = zip_file
.read_to_string(&mut content)
.expect("couldn't read file");
return content;
}
fn get_version_string_from_json(zip_file: ZipFile<'_>) -> String {
let content = read_zip_file_content(zip_file);
let config: JsonRes<JsonVal> = serde_json::from_str(content.as_str());
return String::from(
config.expect("couldn't read json")["version"]
.as_str()
.expect("missing version string in json"),
);
}
fn get_version_string_from_toml(zip_file: ZipFile<'_>) -> String {
let content = read_zip_file_content(zip_file);
let config: TomlVal = toml::from_str(content.as_str()).expect("can't read toml");
// println!("{:?}", config["mods"][0]["version"].as_str());
return String::from(config["mods"][0]["version"].as_str().expect("missing version string in toml"));
}
fn get_version_string_from_manifest(zip_file: ZipFile<'_>) -> String {
let content = read_zip_file_content(zip_file);
let re = Regex::new(r"Implementation-Version: (?P<version>.*)").unwrap();
let caps = re.captures(content.as_str());
return String::from(&caps.unwrap()["version"]);
} It requires a thorough check, of course, but it is capable of extracting version info from fabric, quilt(probably, untested) and forge mods when given mod *.jar file. It doesn't decompress whole file, just extracts a single file from the zip. The important part is using I wanted it to be more concise, but I for the love of god don't know how to chain results and deal with lifetime problems of ZipArchive. |
Oh yeah I do remember now, it would be possible to access only the manifest. In fact I do already use the |
Alright well there is still the issue of linking the mod file and the mod entry within ferium, how can that be done? This is the reason I had refused to implement #138 |
I've moved your recommendations about the CLI to #250. I've updated your initial comment to collapse those and link to the new issue. The 2 points we discussed here are left outside, which are unfortunately not feasible at the moment. |
I would need some more context. For now, the most straightforward I can imagine is storing the path to the file jar along with the SHA256 hash of a mod jar in the profile for the project ID. This way you can have both quick access to jar file, as well as validation that the file you point to is the actual file in question. If the file doesn't exist OR the SHA256 of jar is invalid, appropriate message should be displayed. |
The problem
There are some actions that produce output on terminal, which would be a lot more helpful if it included some additional info.
My solutions
Moved to #250
ferium add
results in "project/repository is not compatible":ferium profile
should print current profile first, then a simple text saying "Useferium profile -h
for more info about this command"ferium list
should print first a header with profile name, loader and MC version and only then list of mods.ferium modpack
should show current modpack, then a simple prompt with "Useferium modpack -h
for more info about this command"ferium profile switch
should print in a row profile name, mc version, loader and number of modsferium profiles
should be an alias toferium profile list
ferium modpacks
should be an alias toferium modpack list
ferium mods
should be an alias toferium list
(because thelist
is the only unscoped subcommand which doesn't align withprofiles list
andmodpacks list
).ferium info
should be added and show currently set profile and modpackferium remove
should printremoved <Mod name> <projectID>
There should be some kind of dependency listing showing which mods depend on which, for example
ferium dependencies
would print which mods were pulled as required dependencies of other modsThe mod list should include a version of the mod
The text was updated successfully, but these errors were encountered: