diff --git a/app/src/main/java/io/github/wiiznokes/gitnote/data/room/Dao.kt b/app/src/main/java/io/github/wiiznokes/gitnote/data/room/Dao.kt index 74fd2c6c..09f275f2 100644 --- a/app/src/main/java/io/github/wiiznokes/gitnote/data/room/Dao.kt +++ b/app/src/main/java/io/github/wiiznokes/gitnote/data/room/Dao.kt @@ -11,7 +11,7 @@ import androidx.sqlite.db.SimpleSQLiteQuery import androidx.sqlite.db.SupportSQLiteQuery import io.github.wiiznokes.gitnote.data.platform.NodeFs import io.github.wiiznokes.gitnote.manager.Progress -import io.github.wiiznokes.gitnote.manager.isExtensionSupported +import io.github.wiiznokes.gitnote.manager.isExtensionSupportedLib import io.github.wiiznokes.gitnote.ui.model.GridNote import io.github.wiiznokes.gitnote.ui.model.SortOrder import io.github.wiiznokes.gitnote.ui.screen.app.DrawerFolderModel @@ -52,7 +52,7 @@ interface RepoDatabaseDao { when (nodeFs) { is NodeFs.File -> { - if (!isExtensionSupported(nodeFs.extension.text)) { + if (!isExtensionSupportedLib(nodeFs.extension.text)) { //Log.d(TAG, "skipped ${nodeFs.path} because extension not supported") return@forEachNodeFs } diff --git a/app/src/main/java/io/github/wiiznokes/gitnote/manager/MimeTypeManager.kt b/app/src/main/java/io/github/wiiznokes/gitnote/manager/MimeTypeManager.kt index d88aa6f0..ef210282 100644 --- a/app/src/main/java/io/github/wiiznokes/gitnote/manager/MimeTypeManager.kt +++ b/app/src/main/java/io/github/wiiznokes/gitnote/manager/MimeTypeManager.kt @@ -21,4 +21,4 @@ private fun extensionTypeFromNumber(num: Int): ExtensionType? = private external fun extensionTypeLib(extension: String): Int -external fun isExtensionSupported(extension: String): Boolean \ No newline at end of file +external fun isExtensionSupportedLib(extension: String): Boolean \ No newline at end of file diff --git a/app/src/main/rust/Cargo.lock b/app/src/main/rust/Cargo.lock index a9bbd1d7..fcac4e09 100644 --- a/app/src/main/rust/Cargo.lock +++ b/app/src/main/rust/Cargo.lock @@ -84,12 +84,6 @@ dependencies = [ "shlex", ] -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - [[package]] name = "cfg-if" version = "1.0.4" @@ -309,7 +303,7 @@ dependencies = [ "bstr", "gix-trace", "gix-validate", - "thiserror 2.0.18", + "thiserror", ] [[package]] @@ -327,7 +321,7 @@ dependencies = [ "bstr", "gix-path", "percent-encoding", - "thiserror 2.0.18", + "thiserror", ] [[package]] @@ -471,25 +465,52 @@ dependencies = [ [[package]] name = "jni" -version = "0.21.1" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" dependencies = [ - "cesu8", "cfg-if", "combine", + "jni-macros", "jni-sys", "log", - "thiserror 1.0.69", + "simd_cesu8", + "thiserror", "walkdir", - "windows-sys 0.45.0", + "windows-link", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.111", ] [[package]] name = "jni-sys" -version = "0.3.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.111", +] [[package]] name = "jobserver" @@ -761,6 +782,22 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +[[package]] +name = "simd_cesu8" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "smallvec" version = "1.15.1" @@ -849,33 +886,13 @@ dependencies = [ "syn 2.0.111", ] -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl 1.0.69", -] - [[package]] name = "thiserror" version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.18", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.111", + "thiserror-impl", ] [[package]] @@ -972,7 +989,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys", ] [[package]] @@ -981,15 +998,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets", -] - [[package]] name = "windows-sys" version = "0.61.2" @@ -999,63 +1007,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "wit-bindgen" version = "0.46.0" diff --git a/app/src/main/rust/Cargo.toml b/app/src/main/rust/Cargo.toml index ff850593..5c791d88 100644 --- a/app/src/main/rust/Cargo.toml +++ b/app/src/main/rust/Cargo.toml @@ -11,7 +11,7 @@ git2 = { version = "0.20.2", features = [ "vendored-libgit2", "vendored-openssl", ] } -jni = "0.21" +jni = "0.22" android_logger = "0.15" log = "0.4" rand_core = { version = "0.6", features = ["std"] } diff --git a/app/src/main/rust/justfile b/app/src/main/rust/justfile index 91727526..7429459c 100644 --- a/app/src/main/rust/justfile +++ b/app/src/main/rust/justfile @@ -5,27 +5,22 @@ zip_openssl_build arch: cp -r target/{{ arch }}-linux-android/release/build/openssl-sys-*/out/openssl-build/install openssl-prebuild/{{ arch }} zip -r install.zip openssl-prebuild/{{ arch }}/install mv install.zip openssl-prebuild/{{ arch }} - pull: prettier fix fix: fmt fmt-just cargo clippy --workspace --all-features --fix --allow-dirty --allow-staged - fmt: cargo fmt --all - fmt-just: just --fmt --unstable - prettier: # install on Debian: sudo snap install node --classic # npx is the command to run npm package, node is the runtime npx prettier -w . - sortext: #!/usr/bin/env bash extension_dir=supported_extensions for f in $(ls $extension_dir 2>/dev/null); do sort $extension_dir/$f -o $extension_dir/$f echo sorted $f - done \ No newline at end of file + done diff --git a/app/src/main/rust/src/lib.rs b/app/src/main/rust/src/lib.rs index 5ba3c959..499fada4 100644 --- a/app/src/main/rust/src/lib.rs +++ b/app/src/main/rust/src/lib.rs @@ -2,9 +2,9 @@ use std::fmt::{Debug, Display}; use anyhow::anyhow; use git2::Signature; -use jni::JNIEnv; use jni::objects::{JClass, JObject, JString, JValue}; -use jni::sys::{jboolean, jint, jobject, jstring}; +use jni::sys::{jboolean, jint}; +use jni::{Env, NativeMethod, jni_sig, jni_str, native_method}; use crate::callback::ProgressCB; use crate::key_gen::gen_keys; @@ -71,17 +71,104 @@ impl Display for Error { } } -#[unsafe(no_mangle)] -pub extern "C" fn Java_io_github_wiiznokes_gitnote_manager_GitManagerKt_initLib<'local>( - mut env: JNIEnv<'local>, +const _INIT_LIB_METHOD: NativeMethod = native_method! { + java_type = "io.github.wiiznokes.gitnote.manager.GitManagerKt", + static extern fn init_lib(home_path: JString) -> jint, +}; + +const _CREATE_REPO_LIB_METHOD: NativeMethod = native_method! { + java_type = "io.github.wiiznokes.gitnote.manager.GitManagerKt", + static extern fn create_repo_lib(repo_path: JString) -> jint, +}; + +const _OPEN_REPO_LIB_METHOD: NativeMethod = native_method! { + java_type = "io.github.wiiznokes.gitnote.manager.GitManagerKt", + static extern fn open_repo_lib(repo_path: JString) -> jint, +}; + +const _CLONE_REPO_LIB_METHOD: NativeMethod = native_method! { + java_type = "io.github.wiiznokes.gitnote.manager.GitManagerKt", + export = "Java_io_github_wiiznokes_gitnote_manager_GitManagerKt_cloneRepoLib", + static extern fn clone_repo_lib(repo_path: JString, remote_url: JString, cred: JObject, progress_callback: JObject) -> jint, +}; + +const _LAST_COMMIT_LIB_METHOD: NativeMethod = native_method! { + java_type = "io.github.wiiznokes.gitnote.manager.GitManagerKt", + static extern fn last_commit_lib() -> JString, +}; + +const _COMMIT_ALL_LIB_METHOD: NativeMethod = native_method! { + java_type = "io.github.wiiznokes.gitnote.manager.GitManagerKt", + static extern fn commit_all_lib(name: JString, email: JString, message: JString) -> jint, +}; + +const _CURRENT_SIGNATURE_LIB_METHOD: NativeMethod = native_method! { + java_type = "io.github.wiiznokes.gitnote.manager.GitManagerKt", + export = "Java_io_github_wiiznokes_gitnote_manager_GitManagerKt_currentSignatureLib", + static extern fn current_signature_lib() -> JObject, +}; + +const _PUSH_LIB_METHOD: NativeMethod = native_method! { + java_type = "io.github.wiiznokes.gitnote.manager.GitManagerKt", + export = "Java_io_github_wiiznokes_gitnote_manager_GitManagerKt_pushLib", + static extern fn push_lib(cred: JObject) -> jint, +}; + +const _PULL_LIB_METHOD: NativeMethod = native_method! { + java_type = "io.github.wiiznokes.gitnote.manager.GitManagerKt", + export = "Java_io_github_wiiznokes_gitnote_manager_GitManagerKt_pullLib", + static extern fn pull_lib(cred: JObject, name: JString, email: JString) -> jint, +}; + +const _FREE_LIB_METHOD: NativeMethod = native_method! { + java_type = "io.github.wiiznokes.gitnote.manager.GitManagerKt", + static extern fn free_lib(), +}; + +const _CLOSE_REPO_LIB_METHOD: NativeMethod = native_method! { + java_type = "io.github.wiiznokes.gitnote.manager.GitManagerKt", + static extern fn close_repo_lib(), +}; + +const _IS_CHANGE_LIB_LIB_METHOD: NativeMethod = native_method! { + java_type = "io.github.wiiznokes.gitnote.manager.GitManagerKt", + static extern fn is_change_lib() -> jint, +}; + +const _GET_TIMESTAMPS_LIB_METHOD: NativeMethod = native_method! { + java_type = "io.github.wiiznokes.gitnote.manager.GitManagerKt", + export = "Java_io_github_wiiznokes_gitnote_manager_GitManagerKt_getTimestampsLib", + static extern fn get_timestamps_lib(j_map: JObject) -> jint, +}; + +const _GENERATE_SSH_KEYS_LIB_METHOD: NativeMethod = native_method! { + java_type = "io.github.wiiznokes.gitnote.manager.GitManagerKt", + export = "Java_io_github_wiiznokes_gitnote_manager_GitManagerKt_generateSshKeysLib", + static extern fn generate_ssh_keys_lib() -> JObject, +}; + +const _EXTENSION_TYPE_LIB_METHOD: NativeMethod = native_method! { + java_type = "io.github.wiiznokes.gitnote.manager.MimeTypeManagerKt", + static extern fn extension_type_lib(extension: JString) -> jint, +}; + +const _IS_EXTENSION_SUPPORTED_LIB_METHOD: NativeMethod = native_method! { + java_type = "io.github.wiiznokes.gitnote.manager.MimeTypeManagerKt", + static extern fn is_extension_supported_lib(extension: JString) -> jboolean, +}; + +const _GET_URL_INFO_LIB_METHOD: NativeMethod = native_method! { + java_type = "io.github.wiiznokes.gitnote.manager.GitManagerKt", + export = "Java_io_github_wiiznokes_gitnote_manager_GitManagerKt_getUrlInfoLib", + static extern fn get_url_info_lib(url: JString) -> JObject, +}; + +fn init_lib<'local>( + env: &mut Env<'local>, _class: JClass<'local>, home_path: JString<'local>, -) -> jint { - let home_path: String = env - .get_string(&home_path) - .expect("Couldn't get java string!") - .into(); - +) -> Result { + let home_path = home_path.try_to_string(env).unwrap(); libgit2::init_lib(home_path); install_panic_hook(); @@ -97,38 +184,30 @@ pub extern "C" fn Java_io_github_wiiznokes_gitnote_manager_GitManagerKt_initLib< ), ); - OK + Ok(OK) } -#[unsafe(no_mangle)] -pub extern "C" fn Java_io_github_wiiznokes_gitnote_manager_GitManagerKt_createRepoLib<'local>( - mut env: JNIEnv<'local>, +fn create_repo_lib<'local>( + env: &mut Env<'local>, _class: JClass<'local>, repo_path: JString<'local>, -) -> jint { - let repo_path: String = env - .get_string(&repo_path) - .expect("Couldn't get java string!") - .into(); +) -> Result { + let repo_path = repo_path.try_to_string(env).unwrap(); unwrap_or_log!(libgit2::create_repo(&repo_path), "create_repo"); - OK + Ok(OK) } -#[unsafe(no_mangle)] -pub extern "C" fn Java_io_github_wiiznokes_gitnote_manager_GitManagerKt_openRepoLib<'local>( - mut env: JNIEnv<'local>, +fn open_repo_lib<'local>( + env: &mut Env<'local>, _class: JClass<'local>, repo_path: JString<'local>, -) -> jint { - let repo_path: String = env - .get_string(&repo_path) - .expect("Couldn't get java string!") - .into(); +) -> Result { + let repo_path = repo_path.try_to_string(env).unwrap(); unwrap_or_log!(libgit2::open_repo(&repo_path), "open_repo"); - OK + Ok(OK) } pub enum Cred { @@ -182,63 +261,67 @@ impl Debug for Cred { } } +macro_rules! jstring_field { + ($env:expr, $obj:expr, $field:literal) => {{ + let obj = $env + .get_field($obj, jni_str!($field), jni_sig!(JString))? + .l()?; + + $env.as_cast::(&obj)? + .mutf8_chars($env)? + .to_string() + }}; +} + +macro_rules! jstring_field_nullable { + ($env:expr, $obj:expr, $field:literal) => {{ + let obj = $env + .get_field($obj, jni_str!($field), jni_sig!(JString))? + .l()?; + + if obj.is_null() { + None + } else { + Some( + $env.as_cast::(&obj)? + .mutf8_chars($env)? + .to_string(), + ) + } + }}; +} + impl Cred { - pub fn from_jni(env: &mut JNIEnv, cred_obj: &JObject) -> anyhow::Result> { + pub fn from_jni(env: &mut Env, cred_obj: &JObject) -> anyhow::Result> { if cred_obj.is_null() { return Ok(None); } - let class = env.get_object_class(cred_obj)?; - let class_name_jstring: JString = env - .call_method(class, "getName", "()Ljava/lang/String;", &[])? - .l()? - .into(); - let class_name: String = env.get_string(&class_name_jstring)?.into(); + let class_name = { + let class = env.get_object_class(cred_obj)?; + + let obj = env + .call_method(class, jni_str!("getName"), jni_sig!(() -> JString), &[])? + .l()?; + + let jstring = env.as_cast::(&obj)?; + + jstring.mutf8_chars(env)?.to_string() + }; match class_name.as_str() { "io.github.wiiznokes.gitnote.ui.model.Cred$UserPassPlainText" => { - let username_obj: JString = env - .get_field(cred_obj, "username", "Ljava/lang/String;")? - .l()? - .into(); - let password_obj: JString = env - .get_field(cred_obj, "password", "Ljava/lang/String;")? - .l()? - .into(); - - let username: String = env.get_string(&username_obj)?.into(); - let password: String = env.get_string(&password_obj)?.into(); + let username = jstring_field!(env, cred_obj, "username"); + let password = jstring_field!(env, cred_obj, "username"); Ok(Some(Cred::UserPassPlainText { username, password })) } "io.github.wiiznokes.gitnote.ui.model.Cred$Ssh" => { - let username_key_obj: JString = env - .get_field(cred_obj, "username", "Ljava/lang/String;")? - .l()? - .into(); - - let public_key_obj: JString = env - .get_field(cred_obj, "publicKey", "Ljava/lang/String;")? - .l()? - .into(); - - let private_key_obj: JString = env - .get_field(cred_obj, "privateKey", "Ljava/lang/String;")? - .l()? - .into(); - - let passphrase_obj = env - .get_field(cred_obj, "passphrase", "Ljava/lang/String;")? - .l()?; - - let username: String = env.get_string(&username_key_obj)?.into(); - let public_key: String = env.get_string(&public_key_obj)?.into(); - let private_key: String = env.get_string(&private_key_obj)?.into(); - let passphrase: Option = if passphrase_obj.is_null() { - None - } else { - Some(env.get_string(&JString::from(passphrase_obj))?.into()) - }; + let username = jstring_field!(env, cred_obj, "username"); + let public_key = jstring_field!(env, cred_obj, "publicKey"); + + let private_key = jstring_field!(env, cred_obj, "privateKey"); + let passphrase = jstring_field_nullable!(env, cred_obj, "passphrase"); Ok(Some(Cred::Ssh { username, @@ -253,49 +336,47 @@ impl Cred { } mod callback { - use jni::{JNIEnv, objects::JObject}; + use jni::{Env, jni_sig, jni_str, objects::JObject}; - pub struct ProgressCB<'a, 'b> { - env: &'b mut JNIEnv<'a>, - callback_class: JObject<'a>, + pub struct ProgressCB<'ptr, 'local> { + env: &'ptr mut Env<'local>, + callback_class: JObject<'local>, } - impl<'a, 'b> ProgressCB<'a, 'b> { - pub fn new(env: &'b mut JNIEnv<'a>, callback_class: JObject<'a>) -> Self { + impl<'ptr, 'local> ProgressCB<'ptr, 'local> { + pub fn new(env: &'ptr mut Env<'local>, callback_class: JObject<'local>) -> Self { Self { env, callback_class, } } pub fn progress(&mut self, progress: i32) -> bool { - match self.env.call_method( - &self.callback_class, - "progressCb", - "(I)Z", - &[progress.into()], - ) { - Ok(res) => res.z().unwrap(), - Err(e) => { - error!("{e}"); - true - } - } + let res = self + .env + .call_method( + &self.callback_class, + jni_str!("progressCb"), + jni_sig!((jint) -> jboolean), + &[progress.into()], + ) + .unwrap(); + + res.z().unwrap() } } } -#[unsafe(no_mangle)] -pub extern "C" fn Java_io_github_wiiznokes_gitnote_manager_GitManagerKt_cloneRepoLib<'local>( - mut env: JNIEnv<'local>, +fn clone_repo_lib<'local>( + env: &mut Env<'local>, _class: JClass<'local>, repo_path: JString<'local>, remote_url: JString<'local>, - cred: JString<'local>, + cred: JObject<'local>, progress_callback: JObject<'local>, -) -> jint { - let repo_path: String = env.get_string(&repo_path).unwrap().into(); - let remote_url: String = env.get_string(&remote_url).unwrap().into(); +) -> Result { + let repo_path = repo_path.try_to_string(env).unwrap(); + let remote_url = remote_url.try_to_string(env).unwrap(); - let cred = match Cred::from_jni(&mut env, &cred) { + let cred = match Cred::from_jni(env, &cred) { Ok(cred) => cred, Err(e) => { error!("Cred::from_jni: {e}"); @@ -303,154 +384,147 @@ pub extern "C" fn Java_io_github_wiiznokes_gitnote_manager_GitManagerKt_cloneRep } }; - let cb = ProgressCB::new(&mut env, progress_callback); + let cb = ProgressCB::new(env, progress_callback); unwrap_or_log!( libgit2::clone_repo(&repo_path, &remote_url, cred, cb), "clone_repo" ); - OK + Ok(OK) } -#[unsafe(no_mangle)] -pub extern "C" fn Java_io_github_wiiznokes_gitnote_manager_GitManagerKt_lastCommitLib( - env: JNIEnv, - _class: JClass, -) -> jstring { +fn last_commit_lib<'local>( + env: &mut Env<'local>, + _class: JClass<'local>, +) -> Result, jni::errors::Error> { let commit = match libgit2::last_commit() { Some(commit) => commit, - None => return std::ptr::null_mut(), + None => return Ok(JString::null()), }; - env.new_string(commit) - .expect("Couldn't create Java string!") - .into_raw() + let s = env + .new_string(commit) + .expect("Couldn't create Java string!"); + + Ok(s) } -#[unsafe(no_mangle)] -pub extern "C" fn Java_io_github_wiiznokes_gitnote_manager_GitManagerKt_commitAllLib<'local>( - mut env: JNIEnv<'local>, +fn commit_all_lib<'local>( + env: &mut Env<'local>, _class: JClass<'local>, name: JString<'local>, email: JString<'local>, message: JString<'local>, -) -> jint { - let name: String = env.get_string(&name).unwrap().into(); - let email: String = env.get_string(&email).unwrap().into(); - let message: String = env.get_string(&message).unwrap().into(); +) -> Result { + let name = name.try_to_string(env).unwrap(); + let email = email.try_to_string(env).unwrap(); + let message = message.try_to_string(env).unwrap(); unwrap_or_log!(libgit2::commit_all(&name, &email, &message), "commit_all"); - OK + Ok(OK) } -#[unsafe(no_mangle)] -pub extern "C" fn Java_io_github_wiiznokes_gitnote_manager_GitManagerKt_currentSignatureLib< - 'local, ->( - mut env: JNIEnv<'local>, +fn current_signature_lib<'local>( + env: &mut Env<'local>, _class: JClass<'local>, -) -> jobject { +) -> Result, jni::errors::Error> { let signature = match libgit2::signature() { Some(signature) => signature, - None => return std::ptr::null_mut(), + None => return Ok(JObject::null()), }; let name_jstring = env.new_string(&signature.0).unwrap(); let email_jstring = env.new_string(&signature.1).unwrap(); - let pair_class = env.find_class("kotlin/Pair").unwrap(); + let pair_class = env.find_class(jni_str!("kotlin/Pair")).unwrap(); let pair_obj = env .new_object( &pair_class, - "(Ljava/lang/Object;Ljava/lang/Object;)V", + jni_sig!((JObject, JObject)), &[(&name_jstring).into(), (&email_jstring).into()], ) .unwrap(); - pair_obj.into_raw() + Ok(pair_obj) } -#[unsafe(no_mangle)] -pub extern "C" fn Java_io_github_wiiznokes_gitnote_manager_GitManagerKt_pushLib<'local>( - mut env: JNIEnv<'local>, +fn push_lib<'local>( + env: &mut Env<'local>, _class: JClass<'local>, - cred: JString<'local>, -) -> jint { - let cred = Cred::from_jni(&mut env, &cred).unwrap(); + cred: JObject<'local>, +) -> Result { + let cred = Cred::from_jni(env, &cred).unwrap(); unwrap_or_log!(libgit2::push(cred), "push"); - OK + Ok(OK) } -#[unsafe(no_mangle)] -pub extern "C" fn Java_io_github_wiiznokes_gitnote_manager_GitManagerKt_pullLib<'local>( - mut env: JNIEnv<'local>, +fn pull_lib<'local>( + env: &mut Env<'local>, _class: JClass<'local>, - cred: JString<'local>, + cred: JObject<'local>, name: JString<'local>, email: JString<'local>, -) -> jint { - let cred = Cred::from_jni(&mut env, &cred).unwrap(); - let name: String = env.get_string(&name).unwrap().into(); - let email: String = env.get_string(&email).unwrap().into(); +) -> Result { + let cred = Cred::from_jni(env, &cred).unwrap(); + let name: String = name.try_to_string(env).unwrap(); + let email: String = email.try_to_string(env).unwrap(); let author = GitAuthor { name, email }; unwrap_or_log!(libgit2::pull(cred, &author), "pull"); - OK + Ok(OK) } -#[unsafe(no_mangle)] -pub extern "C" fn Java_io_github_wiiznokes_gitnote_manager_GitManagerKt_freeLib( - _env: JNIEnv, - _class: JClass, -) { +fn free_lib<'local>( + _env: &mut Env<'local>, + _class: JClass<'local>, +) -> Result<(), jni::errors::Error> { + Ok(()) } -#[unsafe(no_mangle)] -pub extern "C" fn Java_io_github_wiiznokes_gitnote_manager_GitManagerKt_closeRepoLib( - _env: JNIEnv, - _class: JClass, -) { +fn close_repo_lib<'local>( + _env: &mut Env<'local>, + _class: JClass<'local>, +) -> Result<(), jni::errors::Error> { libgit2::close(); + Ok(()) } -#[unsafe(no_mangle)] -pub extern "C" fn Java_io_github_wiiznokes_gitnote_manager_GitManagerKt_isChangeLib( - _env: JNIEnv, - _class: JClass, -) -> jint { +fn is_change_lib<'local>( + _env: &mut Env<'local>, + _class: JClass<'local>, +) -> Result { let is_change = unwrap_or_log!(libgit2::is_change(), "is_change"); - is_change as jint + Ok(is_change as jint) } -#[unsafe(no_mangle)] -pub extern "C" fn Java_io_github_wiiznokes_gitnote_manager_GitManagerKt_getTimestampsLib<'local>( - mut env: JNIEnv<'local>, +fn get_timestamps_lib<'local>( + env: &mut Env<'local>, _class: JClass<'local>, j_map: JObject<'local>, -) -> jint { +) -> Result { let timestamps = unwrap_or_log!(libgit2::get_timestamps(), "get_timestamps"); - if let Err(e) = get_timestamps_jni(&mut env, &j_map, timestamps.iter()) { + if let Err(e) = get_timestamps_jni(env, &j_map, timestamps.iter()) { error!("get_timestamps_jni: {e}"); - return -1; + return Ok(-1); } - OK + Ok(OK) } fn get_timestamps_jni<'local, 'a>( - env: &mut JNIEnv<'local>, + env: &mut Env<'local>, j_map: &JObject<'local>, timestamps: impl Iterator, ) -> Result<(), Box> { let map_class = env.get_object_class(j_map)?; let put_method = env.get_method_id( map_class, - "put", - "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", + jni_str!("put"), + jni_sig!((JObject, JObject) -> JObject), )?; - let long_class = env.find_class("java/lang/Long")?; - let long_ctor = env.get_method_id(&long_class, "", "(J)V")?; + let long_class = env.find_class(jni_str!("java/lang/Long"))?; + let long_ctor = env.get_method_id(&long_class, jni_str!(""), jni_sig!((jlong)))?; for (path, timestamp) in timestamps { let j_key: JString = env.new_string(path)?; @@ -477,93 +551,82 @@ fn get_timestamps_jni<'local, 'a>( Ok(()) } -#[unsafe(no_mangle)] -pub extern "C" fn Java_io_github_wiiznokes_gitnote_manager_GitManagerKt_generateSshKeysLib< - 'local, ->( - mut env: JNIEnv<'local>, +fn generate_ssh_keys_lib<'local>( + env: &mut Env<'local>, _class: JClass<'local>, -) -> jobject { +) -> Result, jni::errors::Error> { let keys = match gen_keys() { Ok(keys) => keys, Err(e) => { error!("can't gen keys: {e}"); - return std::ptr::null_mut(); + return Ok(JObject::null()); } }; let public_jstring = env.new_string(&keys.public).unwrap(); let private_jstring = env.new_string(&keys.private).unwrap(); - let pair_class = env.find_class("kotlin/Pair").unwrap(); + let pair_class = env.find_class(jni_str!("kotlin/Pair")).unwrap(); let pair_obj = env .new_object( &pair_class, - "(Ljava/lang/Object;Ljava/lang/Object;)V", + jni_sig!((JObject, JObject)), &[(&public_jstring).into(), (&private_jstring).into()], ) .unwrap(); - pair_obj.into_raw() + Ok(pair_obj) } -#[unsafe(no_mangle)] -pub extern "C" fn Java_io_github_wiiznokes_gitnote_manager_MimeTypeManagerKt_extensionTypeLib< - 'local, ->( - mut env: JNIEnv<'local>, +fn extension_type_lib<'local>( + env: &mut Env<'local>, _class: JClass<'local>, extension: JString<'local>, -) -> jint { - let extension: String = env.get_string(&extension).unwrap().into(); +) -> Result { + let extension = extension.try_to_string(env).unwrap(); - match mime_types::extension_type(extension.as_str()) { + let res = match mime_types::extension_type(extension.as_str()) { Some(ext_type) => ext_type as jint, None => 0, - } + }; + + Ok(res) } -#[unsafe(no_mangle)] -pub extern "C" fn Java_io_github_wiiznokes_gitnote_manager_MimeTypeManagerKt_isExtensionSupported< - 'local, ->( - mut env: JNIEnv<'local>, +fn is_extension_supported_lib<'local>( + env: &mut Env<'local>, _class: JClass<'local>, extension: JString<'local>, -) -> jboolean { - let extension: String = env.get_string(&extension).unwrap().into(); +) -> Result { + let extension = extension.try_to_string(env).unwrap(); - mime_types::is_extension_supported(extension.as_str()).into() + let res = mime_types::is_extension_supported(extension.as_str()); + Ok(res) } -#[unsafe(no_mangle)] -pub extern "C" fn Java_io_github_wiiznokes_gitnote_manager_GitManagerKt_getUrlInfoLib<'local>( - mut env: JNIEnv<'local>, +fn get_url_info_lib<'local>( + env: &mut Env<'local>, _class: JClass<'local>, url: JString<'local>, -) -> jobject { - let url: String = env.get_string(&url).unwrap().into(); +) -> Result, jni::errors::Error> { + let url = url.try_to_string(env).unwrap(); let url_info = match url::parse_url(&url) { Ok(info) => info, Err(e) => { error!("{e}"); - return std::ptr::null_mut(); + return Ok(JObject::null()); } }; let is_ssh = url_info.kind == url::UrlKind::Ssh; - let boolean_class = env.find_class("java/lang/Boolean").unwrap(); + let boolean_class = env.find_class(jni_str!("java/lang/Boolean")).unwrap(); let obj = env - .new_object( - boolean_class, - "(Z)V", - &[JValue::Bool(if is_ssh { 1 } else { 0 })], - ) + .new_object(boolean_class, jni_sig!((jboolean)), &[JValue::Bool(is_ssh)]) .unwrap(); - obj.into_raw() + Ok(obj) } diff --git a/app/src/main/rust/src/utils.rs b/app/src/main/rust/src/utils.rs index 4fed6b11..8519c8db 100644 --- a/app/src/main/rust/src/utils.rs +++ b/app/src/main/rust/src/utils.rs @@ -27,7 +27,7 @@ macro_rules! unwrap_or_log { Ok(v) => v, Err(e) => { error!("{}: {}", $name, e); - return e.into(); + return Ok(e.into()); } } };