diff options
-rw-r--r-- | src-tauri/Cargo.lock | 44 | ||||
-rw-r--r-- | src-tauri/Cargo.toml | 4 | ||||
-rw-r--r-- | src-tauri/src/development/mod.rs | 78 | ||||
-rw-r--r-- | src-tauri/src/main.rs | 1 | ||||
-rw-r--r-- | src-vue/src/views/DeveloperView.vue | 59 |
5 files changed, 183 insertions, 3 deletions
diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index e8ac30cc..dca74714 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -87,6 +87,7 @@ dependencies = [ "async-recursion", "chrono", "const_format", + "crypto-hash", "dirs", "glob", "json5", @@ -108,6 +109,7 @@ dependencies = [ "tauri-plugin-store", "tokio", "ts-rs", + "walkdir", "winapi", "winreg 0.11.0", "zip", @@ -596,6 +598,24 @@ dependencies = [ ] [[package]] +name = "commoncrypto" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d056a8586ba25a1e4d61cb090900e495952c7886786fc55f909ab2f819b69007" +dependencies = [ + "commoncrypto-sys", +] + +[[package]] +name = "commoncrypto-sys" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fed34f46747aa73dfaa578069fd8279d2818ade2b55f38f22a9401c7f4083e2" +dependencies = [ + "libc", +] + +[[package]] name = "concurrent-queue" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -748,6 +768,18 @@ dependencies = [ ] [[package]] +name = "crypto-hash" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a77162240fd97248d19a564a565eb563a3f592b386e4136fb300909e67dddca" +dependencies = [ + "commoncrypto", + "hex 0.3.2", + "openssl", + "winapi", +] + +[[package]] name = "cssparser" version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1598,6 +1630,12 @@ checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[package]] name = "hex" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" + +[[package]] +name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" @@ -3465,7 +3503,7 @@ checksum = "360ee3270f7a4a1eee6c667f7d38360b995431598a73b740dfe420da548d9cc9" dependencies = [ "debugid", "getrandom 0.2.10", - "hex", + "hex 0.4.3", "serde", "serde_json", "thiserror", @@ -3545,7 +3583,7 @@ checksum = "21e47d95bc83ed33b2ecf84f4187ad1ab9685d18ff28db000c99deac8ce180e3" dependencies = [ "base64 0.21.2", "chrono", - "hex", + "hex 0.4.3", "indexmap 1.9.3", "serde", "serde_json", @@ -5331,7 +5369,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "hex", + "hex 0.4.3", "nix", "once_cell", "ordered-stream", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index d2f1e87e..50e75987 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -65,6 +65,10 @@ semver = "1.0" # simplified filesystem access glob = "0.3.1" dirs = "5" +# Walk directories +walkdir = "2.3" +# Crypto stuff like checksum calculation +crypto-hash = "0.3" [target.'cfg(windows)'.dependencies] # Windows API stuff diff --git a/src-tauri/src/development/mod.rs b/src-tauri/src/development/mod.rs index be02966d..cb2aeec9 100644 --- a/src-tauri/src/development/mod.rs +++ b/src-tauri/src/development/mod.rs @@ -3,6 +3,9 @@ use crate::github::{ pull_requests::{check_github_api, download_zip_into_memory, get_launcher_download_link}, CommitInfo, }; +use crate::GameInstall; +use serde::{Deserialize, Serialize}; +use std::io::Read; #[tauri::command] pub async fn install_git_main(game_install_path: &str) -> Result<String, String> { @@ -82,3 +85,78 @@ pub async fn install_git_main(game_install_path: &str) -> Result<String, String> ); Ok(latest_commit_sha) } + +#[derive(Serialize, Deserialize, Debug)] +pub struct Checksum { + path: String, + checksum: String, +} + +impl ToString for Checksum { + fn to_string(&self) -> String { + format!("{} {}", self.checksum, self.path) + } +} + +/// Computes the checksum of a given file +fn compute_checksum<P: AsRef<std::path::Path>>( + path: P, +) -> Result<Checksum, Box<dyn std::error::Error>> { + dbg!(path.as_ref().to_string_lossy().into_owned()); + let mut file = std::fs::File::open(&path)?; + let mut buffer = Vec::new(); + file.read_to_end(&mut buffer)?; + + let checksum = crypto_hash::hex_digest(crypto_hash::Algorithm::SHA256, &buffer); + Ok(Checksum { + path: path.as_ref().to_string_lossy().into_owned(), + checksum, + }) +} + +fn convert_to_string(checksums: Vec<Checksum>) -> String { + let mut result = String::new(); + + for entry in checksums { + result.push_str(&entry.to_string()); + result.push('\n'); + } + result +} + +#[tauri::command] +/// Calculates checksums over the passed game_install folder and returns results +pub async fn calculate_checksums_gameinstall(game_install: GameInstall) -> Result<String, String> { + log::info!("Computing checksums"); + + let path = game_install.game_path; + let mut checksums = Vec::new(); + + // Iterate over folder + for entry in walkdir::WalkDir::new(path.clone()) { + let entry = entry.unwrap(); + if !entry.file_type().is_file() { + continue; + } + + match compute_checksum(entry.path()) { + Ok(mut checksum) => { + checksum.path = checksum + .path + .strip_prefix(&path.clone()) + .unwrap() + .to_string(); + checksums.push(checksum) + } + Err(err) => log::warn!("Failed to compute checksum for {:?}: {:?}", entry, err), + } + } + + for checksum in &checksums { + println!("{:?}", checksum); + } + + log::info!("Done calculating"); + let s = convert_to_string(checksums); + Ok(s) +} diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 1067f5d3..db0fd3bd 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -156,6 +156,7 @@ fn main() { github::pull_requests::get_launcher_download_link, close_application, development::install_git_main, + development::calculate_checksums_gameinstall, get_available_northstar_versions, ]) .run(tauri::generate_context!()) diff --git a/src-vue/src/views/DeveloperView.vue b/src-vue/src/views/DeveloperView.vue index 28ab3892..ce91af8c 100644 --- a/src-vue/src/views/DeveloperView.vue +++ b/src-vue/src/views/DeveloperView.vue @@ -50,6 +50,24 @@ <br /> <br /> + <el-button type="primary" @click="computeChecksumsGameInstallFolder"> + Compute checksums + </el-button> + <el-button type="primary" @click="copyToClipboard"> + Copy to clipboard + </el-button> + + + <el-input + v-model="checksum_results" + type="textarea" + :rows="1" + placeholder="Output" + /> + + <br /> + <br /> + <el-button type="primary" @click="getAvailableNorthstarVersions"> Get available versions </el-button> @@ -130,6 +148,7 @@ </template> <script lang="ts"> +import { Checksum } from "../../../src-tauri/bindings/Checksum"; import { defineComponent } from "vue"; import { invoke } from "@tauri-apps/api"; import { GameInstall } from "../utils/GameInstall"; @@ -148,6 +167,7 @@ export default defineComponent({ return { mod_to_install_field_string: "", release_notes_text: "", + checksum_results: "", first_tag: { label: '', value: { name: '' } }, second_tag: { label: '', value: { name: '' } }, ns_release_tags: [] as TagWrapper[], @@ -336,6 +356,45 @@ export default defineComponent({ .then((message) => { showNotification(`NSProton Version`, message as string); }) .catch((error) => { showNotification(`Error`, error, "error"); }) }, + async computeChecksumsGameInstallFolder() { + let game_install = { + game_path: this.$store.state.game_path, + install_type: this.$store.state.install_type + } as GameInstall; + + // Send notification telling the user to wait for the process to finish + const notification = showNotification( + "Calculating checksums", + "Please wait", + 'info', + 0 + ); + + let checksum_calc_result = invoke<string>("calculate_checksums_gameinstall", { gameInstall: game_install }); + await checksum_calc_result + .then((message) => { + // Send notification + this.checksum_results = message; + showNotification("Done calculating checksums"); + }) + .catch((error) => { + showErrorNotification(error); + console.error(error); + }) + .finally(() => { + // Clear old notification + notification.close(); + }); + }, + async copyToClipboard() { + navigator.clipboard.writeText(this.checksum_results) + .then(() => { + showNotification("Copied to clipboard"); + }) + .catch(() => { + showErrorNotification("Failed copying to clipboard"); + }); + } } }); </script> |