Various final backend fixes (#117)

* Various final backend fixes

* Add FS watching

* run lint

* Autodetect installed jars
This commit is contained in:
Geometrically 2023-05-16 15:30:04 -07:00 committed by GitHub
parent 5cb54b44be
commit 3fa0e99de2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 941 additions and 529 deletions

378
Cargo.lock generated
View File

@ -17,6 +17,18 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aes"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"
dependencies = [
"cfg-if",
"cipher",
"cpufeatures",
"opaque-debug",
]
[[package]]
name = "aho-corasick"
version = "0.7.20"
@ -95,9 +107,9 @@ checksum = "64cb94155d965e3d37ffbbe7cc5b82c3dd79dd33bd48e536f73d2cfb8d85506f"
[[package]]
name = "async-compression"
version = "0.3.10"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00461f243d703f6999c8e7494f077799f1362720a55ae49a90ffe6214032fc0b"
checksum = "942c7cd7ae39e91bde4820d74132e9862e62c2f386c3aa90ccf55949f5bad63a"
dependencies = [
"bzip2",
"flate2",
@ -112,9 +124,9 @@ dependencies = [
[[package]]
name = "async-tungstenite"
version = "0.20.0"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e0388bb7a400072bbb41ceb75d65c3baefb2ea99672fa22e85278452cd9b58b"
checksum = "6a48bf42ab2178374a79853bceef600e279258c75049b20481b022d73c908882"
dependencies = [
"futures-io",
"futures-util",
@ -200,6 +212,12 @@ version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
[[package]]
name = "base64ct"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
[[package]]
name = "bincode"
version = "2.0.0-rc.2"
@ -424,6 +442,15 @@ dependencies = [
"winapi",
]
[[package]]
name = "cipher"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"
dependencies = [
"generic-array",
]
[[package]]
name = "cocoa"
version = "0.24.1"
@ -521,6 +548,12 @@ dependencies = [
"windows-sys 0.42.0",
]
[[package]]
name = "constant_time_eq"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
[[package]]
name = "convert_case"
version = "0.4.0"
@ -698,9 +731,9 @@ dependencies = [
[[package]]
name = "daedalus"
version = "0.1.20"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab1ff8f873475996ff3d755659e5e0fbe5a2d02d6fc84ff2b625874a8c446973"
checksum = "2a66b666b316919af243d8684f225b56aed72a83db52a93d61da89e2f588a7c7"
dependencies = [
"bincode",
"bytes",
@ -748,6 +781,12 @@ dependencies = [
"syn 1.0.109",
]
[[package]]
name = "data-encoding"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23d8666cb01533c39dde32bcbab8e227b4ed6679b2c925eba05feabea39508fb"
[[package]]
name = "derive_more"
version = "0.99.17"
@ -790,6 +829,7 @@ checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
dependencies = [
"block-buffer 0.10.4",
"crypto-common",
"subtle",
]
[[package]]
@ -798,7 +838,16 @@ version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
dependencies = [
"dirs-sys",
"dirs-sys 0.3.7",
]
[[package]]
name = "dirs"
version = "5.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
dependencies = [
"dirs-sys 0.4.1",
]
[[package]]
@ -822,6 +871,18 @@ dependencies = [
"winapi",
]
[[package]]
name = "dirs-sys"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
dependencies = [
"libc",
"option-ext",
"redox_users",
"windows-sys 0.48.0",
]
[[package]]
name = "dirs-sys-next"
version = "0.1.2"
@ -883,13 +944,13 @@ dependencies = [
[[package]]
name = "errno"
version = "0.2.8"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
dependencies = [
"errno-dragonfly",
"libc",
"winapi",
"windows-sys 0.48.0",
]
[[package]]
@ -939,7 +1000,7 @@ checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"redox_syscall 0.2.16",
"windows-sys 0.45.0",
]
@ -983,6 +1044,15 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "fsevent-sys"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2"
dependencies = [
"libc",
]
[[package]]
name = "futf"
version = "0.1.5"
@ -1429,6 +1499,15 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
[[package]]
name = "hmac"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
"digest 0.10.6",
]
[[package]]
name = "html5ever"
version = "0.25.2"
@ -1638,6 +1717,26 @@ dependencies = [
"cfb",
]
[[package]]
name = "inotify"
version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff"
dependencies = [
"bitflags",
"inotify-sys",
"libc",
]
[[package]]
name = "inotify-sys"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
dependencies = [
"libc",
]
[[package]]
name = "instant"
version = "0.1.12"
@ -1762,6 +1861,26 @@ dependencies = [
"treediff",
]
[[package]]
name = "kqueue"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98"
dependencies = [
"kqueue-sys",
"libc",
]
[[package]]
name = "kqueue-sys"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587"
dependencies = [
"bitflags",
"libc",
]
[[package]]
name = "kuchiki"
version = "0.8.1"
@ -1806,9 +1925,9 @@ dependencies = [
[[package]]
name = "linux-raw-sys"
version = "0.1.4"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f"
[[package]]
name = "lock_api"
@ -1841,7 +1960,7 @@ dependencies = [
"serde",
"serde_json",
"tracing",
"tracing-subscriber 0.3.16",
"tracing-subscriber 0.3.17",
]
[[package]]
@ -2036,6 +2155,33 @@ version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
[[package]]
name = "notify"
version = "5.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58ea850aa68a06e48fdb069c0ec44d0d64c8dbffa49bf3b6f7f0a901fdea1ba9"
dependencies = [
"bitflags",
"crossbeam-channel",
"filetime",
"fsevent-sys",
"inotify",
"kqueue",
"libc",
"mio",
"walkdir",
"windows-sys 0.42.0",
]
[[package]]
name = "notify-debouncer-mini"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e23e9fa24f094b143c1eb61f90ac6457de87be6987bc70746e0179f7dbc9007b"
dependencies = [
"notify",
]
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
@ -2228,6 +2374,12 @@ dependencies = [
"vcpkg",
]
[[package]]
name = "option-ext"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
name = "os_info"
version = "3.7.0"
@ -2309,11 +2461,22 @@ checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"redox_syscall 0.2.16",
"smallvec",
"windows-sys 0.45.0",
]
[[package]]
name = "password-hash"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700"
dependencies = [
"base64ct",
"rand_core 0.6.4",
"subtle",
]
[[package]]
name = "paste"
version = "1.0.12"
@ -2326,6 +2489,18 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
[[package]]
name = "pbkdf2"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917"
dependencies = [
"digest 0.10.6",
"hmac",
"password-hash",
"sha2 0.10.6",
]
[[package]]
name = "percent-encoding"
version = "2.2.0"
@ -2675,6 +2850,15 @@ dependencies = [
"bitflags",
]
[[package]]
name = "redox_syscall"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
dependencies = [
"bitflags",
]
[[package]]
name = "redox_users"
version = "0.4.3"
@ -2682,7 +2866,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
dependencies = [
"getrandom 0.2.8",
"redox_syscall",
"redox_syscall 0.2.16",
"thiserror",
]
@ -2792,9 +2976,9 @@ dependencies = [
[[package]]
name = "rustix"
version = "0.36.11"
version = "0.37.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db4165c9963ab29e422d6c26fbc1d37f15bace6b2810221f9d925023480fcf0e"
checksum = "2aae838e49b3d63e9274e1c01833cc8139d3fec468c3b84688c628f44b1ae11d"
dependencies = [
"bitflags",
"errno",
@ -3207,6 +3391,12 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "subtle"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]]
name = "syn"
version = "1.0.109"
@ -3517,15 +3707,15 @@ dependencies = [
[[package]]
name = "tempfile"
version = "3.4.0"
version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af18f7ae1acd354b992402e9ec5864359d693cd8a79dcbef59f76891701c1e95"
checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998"
dependencies = [
"cfg-if",
"fastrand",
"redox_syscall",
"redox_syscall 0.3.5",
"rustix",
"windows-sys 0.42.0",
"windows-sys 0.45.0",
]
[[package]]
@ -3557,11 +3747,13 @@ dependencies = [
"bytes",
"chrono",
"daedalus",
"dirs",
"dirs 5.0.1",
"dunce",
"futures",
"indicatif",
"lazy_static",
"notify",
"notify-debouncer-mini",
"paste",
"regex",
"reqwest",
@ -3571,16 +3763,17 @@ dependencies = [
"sha2 0.9.9",
"sys-info",
"tauri",
"tempfile",
"thiserror",
"tokio",
"tokio-stream",
"toml 0.7.3",
"tracing",
"tracing-error 0.1.2",
"tracing-subscriber 0.2.25",
"tracing-error 0.2.0",
"tracing-subscriber 0.3.17",
"url",
"uuid 1.3.0",
"winreg 0.11.0",
"winreg 0.50.0",
"zip",
]
@ -3592,7 +3785,7 @@ dependencies = [
"color-eyre",
"daedalus",
"dialoguer",
"dirs",
"dirs 4.0.0",
"dunce",
"eyre",
"futures",
@ -3604,7 +3797,7 @@ dependencies = [
"tracing",
"tracing-error 0.2.0",
"tracing-futures",
"tracing-subscriber 0.3.16",
"tracing-subscriber 0.3.17",
"url",
"uuid 1.3.0",
"webbrowser",
@ -3910,7 +4103,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e"
dependencies = [
"tracing",
"tracing-subscriber 0.3.16",
"tracing-subscriber 0.3.17",
]
[[package]]
@ -3968,9 +4161,9 @@ dependencies = [
[[package]]
name = "tracing-subscriber"
version = "0.3.16"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70"
checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77"
dependencies = [
"matchers 0.1.0",
"nu-ansi-term",
@ -4001,13 +4194,13 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
[[package]]
name = "tungstenite"
version = "0.18.0"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30ee6ab729cd4cf0fd55218530c4522ed30b7b6081752839b68fcec8d0960788"
checksum = "15fba1a6d6bb030745759a9a2a588bfe8490fc8b4751a277db3a0be1c9ebbf67"
dependencies = [
"base64 0.13.1",
"byteorder",
"bytes",
"data-encoding",
"http",
"httparse",
"log",
@ -4424,7 +4617,7 @@ version = "0.44.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e745dab35a0c4c77aa3ce42d595e13d2003d6902d6b08c9ef5fc326d08da12b"
dependencies = [
"windows-targets",
"windows-targets 0.42.2",
]
[[package]]
@ -4433,7 +4626,7 @@ version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdacb41e6a96a052c6cb63a144f24900236121c6f63f4f8219fef5977ecb0c25"
dependencies = [
"windows-targets",
"windows-targets 0.42.2",
]
[[package]]
@ -4468,12 +4661,12 @@ version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_gnullvm 0.42.2",
"windows_aarch64_msvc 0.42.2",
"windows_i686_gnu 0.42.2",
"windows_i686_msvc 0.42.2",
"windows_x86_64_gnu 0.42.2",
"windows_x86_64_gnullvm",
"windows_x86_64_gnullvm 0.42.2",
"windows_x86_64_msvc 0.42.2",
]
@ -4483,7 +4676,16 @@ version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
dependencies = [
"windows-targets",
"windows-targets 0.42.2",
]
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.0",
]
[[package]]
@ -4492,15 +4694,30 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_gnullvm 0.42.2",
"windows_aarch64_msvc 0.42.2",
"windows_i686_gnu 0.42.2",
"windows_i686_msvc 0.42.2",
"windows_x86_64_gnu 0.42.2",
"windows_x86_64_gnullvm",
"windows_x86_64_gnullvm 0.42.2",
"windows_x86_64_msvc 0.42.2",
]
[[package]]
name = "windows-targets"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
dependencies = [
"windows_aarch64_gnullvm 0.48.0",
"windows_aarch64_msvc 0.48.0",
"windows_i686_gnu 0.48.0",
"windows_i686_msvc 0.48.0",
"windows_x86_64_gnu 0.48.0",
"windows_x86_64_gnullvm 0.48.0",
"windows_x86_64_msvc 0.48.0",
]
[[package]]
name = "windows-tokens"
version = "0.39.0"
@ -4513,6 +4730,12 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.37.0"
@ -4531,6 +4754,12 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
[[package]]
name = "windows_i686_gnu"
version = "0.37.0"
@ -4549,6 +4778,12 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
[[package]]
name = "windows_i686_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
[[package]]
name = "windows_i686_msvc"
version = "0.37.0"
@ -4567,6 +4802,12 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]]
name = "windows_i686_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
[[package]]
name = "windows_x86_64_gnu"
version = "0.37.0"
@ -4585,12 +4826,24 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
[[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_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
[[package]]
name = "windows_x86_64_msvc"
version = "0.37.0"
@ -4609,6 +4862,12 @@ version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
[[package]]
name = "winnow"
version = "0.4.1"
@ -4637,6 +4896,16 @@ dependencies = [
"winapi",
]
[[package]]
name = "winreg"
version = "0.50.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
dependencies = [
"cfg-if",
"windows-sys 0.48.0",
]
[[package]]
name = "winres"
version = "0.1.12"
@ -4731,32 +5000,38 @@ checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"
[[package]]
name = "zip"
version = "0.5.13"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93ab48844d61251bb3835145c521d88aa4031d7139e8485990f60ca911fa0815"
checksum = "7e92305c174683d78035cbf1b70e18db6329cc0f1b9cae0a52ca90bf5bfe7125"
dependencies = [
"aes",
"byteorder",
"bzip2",
"constant_time_eq",
"crc32fast",
"crossbeam-utils",
"flate2",
"thiserror",
"time 0.1.45",
"hmac",
"pbkdf2",
"sha1 0.10.5",
"time 0.3.20",
"zstd",
]
[[package]]
name = "zstd"
version = "0.9.2+zstd.1.5.1"
version = "0.11.2+zstd.1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2390ea1bf6c038c39674f22d95f0564725fc06034a47129179810b2fc58caa54"
checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4"
dependencies = [
"zstd-safe",
]
[[package]]
name = "zstd-safe"
version = "4.1.3+zstd.1.5.1"
version = "5.0.2+zstd.1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e99d81b99fb3c2c2c794e3fe56c305c63d5173a16a46b5850b07c935ffc7db79"
checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db"
dependencies = [
"libc",
"zstd-sys",
@ -4764,10 +5039,11 @@ dependencies = [
[[package]]
name = "zstd-sys"
version = "1.6.2+zstd.1.5.1"
version = "2.0.8+zstd.1.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2daf2f248d9ea44454bfcb2516534e8b8ad2fc91bf818a1885495fc42bc8ac9f"
checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c"
dependencies = [
"cc",
"libc",
"pkg-config",
]

View File

@ -15,36 +15,40 @@ sha1 = { version = "0.6.1", features = ["std"]}
sha2 = "0.9.9"
url = "2.2"
uuid = { version = "1.1", features = ["serde", "v4"] }
zip = "0.5"
zip = "0.6.5"
async_zip = { version = "0.0.13", features = ["full"] }
tempfile = "3.5.0"
chrono = { version = "0.4.19", features = ["serde"] }
daedalus = { version = "0.1.20" }
dirs = "4.0"
daedalus = { version = "0.1.21" }
dirs = "5.0.1"
regex = "1.5"
sys-info = "0.9.0"
thiserror = "1.0"
tracing = "0.1.37"
tracing-subscriber = "0.2"
tracing-error = "0.1"
tracing-subscriber = "0.3.17"
tracing-error = "0.2.0"
paste = { version = "1.0"}
tauri = { version = "1.2", optional = true}
indicatif = { version = "0.17.3", optional = true }
async-tungstenite = { version = "0.20.0", features = ["tokio-runtime", "tokio-native-tls"] }
async-tungstenite = { version = "0.22.1", features = ["tokio-runtime", "tokio-native-tls"] }
futures = "0.3"
reqwest = { version = "0.11", features = ["json", "stream"] }
tokio = { version = "1", features = ["full"] }
tokio-stream = { version = "0.1", features = ["fs"] }
notify = { version = "5.1.0", default-features = false }
notify-debouncer-mini = { version = "0.2.1", default-features = false }
lazy_static = "1.4.0"
dunce = "1.0.3"
[target.'cfg(windows)'.dependencies]
winreg = "0.11.0"
winreg = "0.50.0"
[features]
tauri = ["dep:tauri"]

Binary file not shown.

View File

@ -0,0 +1,22 @@
public final class JavaInfo {
private static final String[] CHECKED_PROPERTIES = new String[] {
"os.arch",
"java.version"
};
public static void main(String[] args) {
int returnCode = 0;
for (String key : CHECKED_PROPERTIES) {
String property = System.getProperty(key);
if (property != null) {
System.out.println(key + "=" + property);
} else {
returnCode = 1;
}
}
System.exit(returnCode);
}
}

View File

@ -1,12 +1,16 @@
//! Authentication flow interface
use reqwest::Method;
use serde::Deserialize;
use std::path::PathBuf;
use crate::event::emit::{emit_loading, init_loading};
use crate::util::fetch::{fetch_advanced, fetch_json};
use crate::{
launcher::download,
prelude::Profile,
state::JavaGlobals,
util::jre::{self, extract_java_majorminor_version, JavaVersion},
State,
LoadingBarType, State,
};
pub const JAVA_8_KEY: &str = "JAVA_8";
@ -133,6 +137,87 @@ pub async fn find_java17_jres() -> crate::Result<Vec<JavaVersion>> {
.collect())
}
pub async fn auto_install_java(java_version: u32) -> crate::Result<PathBuf> {
let state = State::get().await?;
let loading_bar = init_loading(
LoadingBarType::JavaDownload {
version: java_version,
},
100.0,
"Downloading java version",
)
.await?;
#[derive(Deserialize)]
struct Package {
pub download_url: String,
pub name: PathBuf,
}
emit_loading(&loading_bar, 0.0, Some("Fetching java version")).await?;
let packages = fetch_json::<Vec<Package>>(
Method::GET,
&format!(
"https://api.azul.com/metadata/v1/zulu/packages?arch={}&java_version={}&os={}&archive_type=zip&javafx_bundled=false&java_package_type=jre&page_size=1",
std::env::consts::ARCH, java_version, std::env::consts::OS
),
None,
None,
&state.fetch_semaphore,
).await?;
emit_loading(&loading_bar, 10.0, Some("Downloading java version")).await?;
if let Some(download) = packages.first() {
let file = fetch_advanced(
Method::GET,
&download.download_url,
None,
None,
None,
Some((&loading_bar, 80.0)),
&state.fetch_semaphore,
)
.await?;
let path = state.directories.java_versions_dir();
if path.exists() {
tokio::fs::remove_dir_all(&path).await?;
}
let mut archive = zip::ZipArchive::new(std::io::Cursor::new(file))
.map_err(|_| {
crate::Error::from(crate::ErrorKind::InputError(
"Failed to read java zip".to_string(),
))
})?;
emit_loading(&loading_bar, 0.0, Some("Extracting java")).await?;
archive.extract(&path).map_err(|_| {
crate::Error::from(crate::ErrorKind::InputError(
"Failed to extract java zip".to_string(),
))
})?;
emit_loading(&loading_bar, 100.0, Some("Done extracting java")).await?;
Ok(path
.join(
download
.name
.file_stem()
.unwrap_or_default()
.to_string_lossy()
.to_string(),
)
.join(format!("zulu-{}.jre/Contents/Home/bin/java", java_version)))
} else {
Err(crate::ErrorKind::LauncherError(format!(
"No Java Version found for Java version {}, OS {}, and Architecture {}",
java_version, std::env::consts::OS, std::env::consts::ARCH,
)).into())
}
}
// Get all JREs that exist on the system
pub async fn get_all_jre() -> crate::Result<Vec<JavaVersion>> {
Ok(jre::get_all_jre().await?)
@ -148,3 +233,14 @@ pub async fn validate_globals() -> crate::Result<bool> {
pub async fn check_jre(path: PathBuf) -> crate::Result<Option<JavaVersion>> {
Ok(jre::check_java_at_filepath(&path).await)
}
// Gets maximum memory in KiB.
pub async fn get_max_memory() -> crate::Result<u64> {
Ok(sys_info::mem_info()
.map_err(|_| {
crate::Error::from(crate::ErrorKind::LauncherError(
"Unable to get computer memory".to_string(),
))
})?
.total)
}

View File

@ -6,8 +6,7 @@ use crate::event::emit::{
};
use crate::event::{LoadingBarId, LoadingBarType};
use crate::state::{
LinkedData, ModrinthProject, ModrinthVersion, Profile, ProfileInstallStage,
SideType,
LinkedData, ModrinthProject, ModrinthVersion, ProfileInstallStage, SideType,
};
use crate::util::fetch::{
fetch, fetch_advanced, fetch_json, fetch_mirrors, write, write_cached_icon,
@ -478,7 +477,6 @@ async fn install_pack(
if let Some(profile_val) =
crate::api::profile::get(&profile, None).await?
{
Profile::sync_projects_task(profile.clone());
crate::launcher::install_minecraft(
&profile_val,
Some(loading_bar),

View File

@ -5,7 +5,6 @@ use crate::state::ProjectMetadata;
use crate::{
auth::{self, refresh},
event::{emit::emit_profile, ProfilePayloadType},
launcher::download,
state::MinecraftChild,
};
pub use crate::{
@ -109,40 +108,10 @@ pub async fn list(
.collect())
}
/// Query + sync profile's projects with the UI from the FS
#[tracing::instrument]
pub async fn sync(path: &Path) -> crate::Result<()> {
Box::pin({
async move {
let state = State::get().await?;
let result = {
let mut profiles: tokio::sync::RwLockWriteGuard<
crate::state::Profiles,
> = state.profiles.write().await;
if let Some(profile) = profiles.0.get_mut(path) {
profile.sync_projects().await?;
Ok(())
} else {
Err(crate::ErrorKind::UnmanagedProfileError(
path.display().to_string(),
)
.as_error())
}
};
State::sync().await?;
result
}
})
.await
}
/// Installs/Repairs a profile
#[tracing::instrument]
pub async fn install(path: &Path) -> crate::Result<()> {
let profile = get(path, None).await?;
if let Some(profile) = profile {
if let Some(profile) = get(path, None).await? {
crate::launcher::install_minecraft(&profile, None).await?;
} else {
return Err(crate::ErrorKind::UnmanagedProfileError(
@ -155,11 +124,8 @@ pub async fn install(path: &Path) -> crate::Result<()> {
}
pub async fn update_all(profile_path: &Path) -> crate::Result<()> {
let state = State::get().await?;
Box::pin(async move {
let mut profiles = state.profiles.write().await;
if let Some(profile) = profiles.0.get_mut(profile_path) {
if let Some(profile) = get(profile_path, None).await? {
let loading_bar = init_loading(
LoadingBarType::ProfileUpdate {
profile_path: profile.path.clone(),
@ -187,8 +153,6 @@ pub async fn update_all(profile_path: &Path) -> crate::Result<()> {
)
.await?;
profile.sync_projects().await?;
Ok(())
} else {
Err(crate::ErrorKind::UnmanagedProfileError(
@ -204,10 +168,7 @@ pub async fn update_project(
profile_path: &Path,
project_path: &Path,
) -> crate::Result<PathBuf> {
let state = State::get().await?;
let mut profiles = state.profiles.write().await;
if let Some(profile) = profiles.0.get_mut(profile_path) {
if let Some(profile) = get(profile_path, None).await? {
if let Some(project) = profile.projects.get(project_path) {
if let ProjectMetadata::Modrinth {
update_version: Some(update_version),
@ -222,15 +183,20 @@ pub async fn update_project(
profile.remove_project(project_path, Some(true)).await?;
}
let value = profile.projects.remove(project_path);
if let Some(mut project) = value {
if let ProjectMetadata::Modrinth {
ref mut version, ..
} = project.metadata
{
*version = Box::new(new_version);
let state = State::get().await?;
let mut profiles = state.profiles.write().await;
if let Some(profile) = profiles.0.get_mut(project_path) {
let value = profile.projects.remove(project_path);
if let Some(mut project) = value {
if let ProjectMetadata::Modrinth {
ref mut version,
..
} = project.metadata
{
*version = Box::new(new_version);
}
profile.projects.insert(path.clone(), project);
}
profile.projects.insert(path.clone(), project);
}
return Ok(path);
@ -249,57 +215,15 @@ pub async fn update_project(
}
}
/// Replaces a project given a new version ID
pub async fn replace_project(
profile_path: &Path,
project: &Path,
version_id: String,
) -> crate::Result<PathBuf> {
let state = State::get().await?;
let mut profiles = state.profiles.write().await;
if let Some(profile) = profiles.0.get_mut(profile_path) {
let (path, new_version) =
profile.add_project_version(version_id).await?;
if path != project {
profile.remove_project(project, Some(true)).await?;
}
let value = profile.projects.remove(project);
if let Some(mut project) = value {
if let ProjectMetadata::Modrinth {
ref mut version, ..
} = project.metadata
{
*version = Box::new(new_version);
}
profile.projects.insert(path.clone(), project);
}
Ok(path)
} else {
Err(crate::ErrorKind::UnmanagedProfileError(
profile_path.display().to_string(),
)
.as_error())
}
}
/// Add a project from a version
#[tracing::instrument]
pub async fn add_project_from_version(
profile_path: &Path,
version_id: String,
) -> crate::Result<PathBuf> {
let state = State::get().await?;
let mut profiles = state.profiles.write().await;
if let Some(profile) = profiles.0.get_mut(profile_path) {
if let Some(profile) = get(profile_path, None).await? {
let (path, _) = profile.add_project_version(version_id).await?;
Profile::sync_projects_task(profile.path.clone());
Ok(path)
} else {
Err(crate::ErrorKind::UnmanagedProfileError(
@ -316,10 +240,7 @@ pub async fn add_project_from_path(
path: &Path,
project_type: Option<String>,
) -> crate::Result<PathBuf> {
let state = State::get().await?;
let mut profiles = state.profiles.write().await;
if let Some(profile) = profiles.0.get_mut(profile_path) {
if let Some(profile) = get(profile_path, None).await? {
let file = fs::read(path).await?;
let file_name = path
.file_name()
@ -335,8 +256,6 @@ pub async fn add_project_from_path(
)
.await?;
Profile::sync_projects_task(profile.path.clone());
Ok(path)
} else {
Err(crate::ErrorKind::UnmanagedProfileError(
@ -352,10 +271,7 @@ pub async fn toggle_disable_project(
profile: &Path,
project: &Path,
) -> crate::Result<()> {
let state = State::get().await?;
let mut profiles = state.profiles.write().await;
if let Some(profile) = profiles.0.get_mut(profile) {
if let Some(profile) = get(profile, None).await? {
profile.toggle_disable_project(project).await?;
Ok(())
@ -373,10 +289,7 @@ pub async fn remove_project(
profile: &Path,
project: &Path,
) -> crate::Result<()> {
let state = State::get().await?;
let mut profiles = state.profiles.write().await;
if let Some(profile) = profiles.0.get_mut(profile) {
if let Some(profile) = get(profile, None).await? {
profile.remove_project(project, None).await?;
Ok(())
@ -423,7 +336,6 @@ pub async fn run_credentials(
Box::pin(async move {
let state = State::get().await?;
let settings = state.settings.read().await;
let metadata = state.metadata.read().await;
let profile = get(path, None).await?.ok_or_else(|| {
crate::ErrorKind::OtherError(format!(
"Tried to run a nonexistent or unloaded profile at path {}!",
@ -431,25 +343,6 @@ pub async fn run_credentials(
))
})?;
let version = metadata
.minecraft
.versions
.iter()
.find(|it| it.id == profile.metadata.game_version)
.ok_or_else(|| {
crate::ErrorKind::LauncherError(format!(
"Invalid or unknown Minecraft version: {}",
profile.metadata.game_version
))
})?;
let version_info = download::download_version_info(
&state,
version,
profile.metadata.loader_version.as_ref(),
None,
None,
)
.await?;
let pre_launch_hooks =
&profile.hooks.as_ref().unwrap_or(&settings.hooks).pre_launch;
if let Some(hook) = pre_launch_hooks {
@ -473,49 +366,6 @@ pub async fn run_credentials(
}
}
let java_version = match profile.java {
// Load profile-specific Java implementation choice
// (This defaults to Daedalus-decided key on init, but can be changed by the user)
Some(JavaSettings {
jre_key: Some(ref jre_key),
..
}) => settings.java_globals.get(jre_key),
// Fall back to Daedalus-decided key if no profile-specific key is set
_ => {
match version_info
.java_version
.as_ref()
.map(|it| it.major_version)
.unwrap_or(0)
{
0..=16 => settings
.java_globals
.get(&crate::jre::JAVA_8_KEY.to_string()),
17 => settings
.java_globals
.get(&crate::jre::JAVA_17_KEY.to_string()),
_ => settings
.java_globals
.get(&crate::jre::JAVA_18PLUS_KEY.to_string()),
}
}
};
let java_version = java_version.as_ref().ok_or_else(|| {
crate::ErrorKind::LauncherError(format!(
"No Java stored for version {}",
version_info.java_version.map_or(8, |it| it.major_version),
))
})?;
// Get the path to the Java executable from the chosen Java implementation key
let java_install: &Path = &PathBuf::from(&java_version.path);
if !java_install.exists() {
return Err(crate::ErrorKind::LauncherError(format!(
"Could not find Java install: {}",
java_install.display()
))
.as_error());
}
let java_args = profile
.java
.as_ref()
@ -550,7 +400,6 @@ pub async fn run_credentials(
};
let mc_process = crate::launcher::launch_minecraft(
java_install,
java_args,
env_args,
wrapper,

View File

@ -1,9 +1,7 @@
//! Theseus profile management interface
use crate::event::emit::emit_warning;
use crate::state::LinkedData;
use crate::{
event::{emit::emit_profile, ProfilePayloadType},
jre,
prelude::ModLoader,
};
pub use crate::{
@ -84,7 +82,12 @@ pub async fn profile_create(
&canonicalize(&path)?.display()
);
let loader = if modloader != ModLoader::Vanilla {
get_loader_version_from_loader(game_version.clone(), modloader, loader_version).await?
get_loader_version_from_loader(
game_version.clone(),
modloader,
loader_version,
)
.await?
} else {
None
};
@ -112,19 +115,6 @@ pub async fn profile_create(
profile.metadata.linked_data = linked_data;
// Attempts to find optimal JRE for the profile from the JavaGlobals
// Finds optimal key, and see if key has been set in JavaGlobals
let settings = state.settings.read().await;
let optimal_version_key = jre::get_optimal_jre_key(&profile).await?;
if settings.java_globals.get(&optimal_version_key).is_some() {
profile.java = Some(JavaSettings {
jre_key: Some(optimal_version_key),
extra_arguments: None,
});
} else {
emit_warning(&format!("Could not detect optimal JRE: {optimal_version_key}, falling back to system default.")).await?;
}
emit_profile(
uuid,
path.clone(),
@ -144,7 +134,8 @@ pub async fn profile_create(
State::sync().await?;
Ok(path)
}).await
})
.await
}
pub(crate) async fn get_loader_version_from_loader(

View File

@ -84,6 +84,9 @@ pub enum ErrorKind {
#[error("Error: {0}")]
OtherError(String),
#[error("File watching error: {0}")]
NotifyError(#[from] notify::Error),
}
#[derive(Debug)]

View File

@ -149,6 +149,9 @@ impl Drop for LoadingBar {
#[serde(rename_all = "snake_case")]
pub enum LoadingBarType {
StateInit,
JavaDownload {
version: u32,
},
PackFileDownload {
profile_path: PathBuf,
pack_name: String,

View File

@ -22,12 +22,13 @@ pub fn get_class_paths(
libraries_path: &Path,
libraries: &[Library],
client_path: &Path,
java_arch: &str,
) -> crate::Result<String> {
let mut cps = libraries
.iter()
.filter_map(|library| {
if let Some(rules) = &library.rules {
if !rules.iter().all(parse_rule) {
if !rules.iter().any(|x| parse_rule(x, java_arch)) {
return None;
}
}
@ -53,19 +54,20 @@ pub fn get_class_paths(
.to_string(),
);
Ok(cps.join(classpath_separator()))
Ok(cps.join(classpath_separator(java_arch)))
}
pub fn get_class_paths_jar<T: AsRef<str>>(
libraries_path: &Path,
libraries: &[T],
java_arch: &str,
) -> crate::Result<String> {
let cps = libraries
.iter()
.map(|library| get_lib_path(libraries_path, library.as_ref(), false))
.collect::<Result<Vec<_>, _>>()?;
Ok(cps.join(classpath_separator()))
Ok(cps.join(classpath_separator(java_arch)))
}
pub fn get_lib_path(
@ -91,6 +93,8 @@ pub fn get_lib_path(
Ok(path.to_string_lossy().to_string())
}
#[allow(clippy::too_many_arguments)]
pub fn get_jvm_arguments(
arguments: Option<&[Argument]>,
natives_path: &Path,
@ -99,19 +103,26 @@ pub fn get_jvm_arguments(
version_name: &str,
memory: MemorySettings,
custom_args: Vec<String>,
java_arch: &str,
) -> crate::Result<Vec<String>> {
let mut parsed_arguments = Vec::new();
if let Some(args) = arguments {
parse_arguments(args, &mut parsed_arguments, |arg| {
parse_jvm_argument(
arg.to_string(),
natives_path,
libraries_path,
class_paths,
version_name,
)
})?;
parse_arguments(
args,
&mut parsed_arguments,
|arg| {
parse_jvm_argument(
arg.to_string(),
natives_path,
libraries_path,
class_paths,
version_name,
java_arch,
)
},
java_arch,
)?;
} else {
parsed_arguments.push(format!(
"-Djava.library.path={}",
@ -147,6 +158,7 @@ fn parse_jvm_argument(
libraries_path: &Path,
class_paths: &str,
version_name: &str,
java_arch: &str,
) -> crate::Result<String> {
argument.retain(|c| !c.is_whitespace());
Ok(argument
@ -174,7 +186,7 @@ fn parse_jvm_argument(
})?
.to_string_lossy(),
)
.replace("${classpath_separator}", classpath_separator())
.replace("${classpath_separator}", classpath_separator(java_arch))
.replace("${launcher_name}", "theseus")
.replace("${launcher_version}", env!("CARGO_PKG_VERSION"))
.replace("${version_name}", version_name)
@ -192,13 +204,37 @@ pub fn get_minecraft_arguments(
assets_directory: &Path,
version_type: &VersionType,
resolution: WindowSize,
java_arch: &str,
) -> crate::Result<Vec<String>> {
if let Some(arguments) = arguments {
let mut parsed_arguments = Vec::new();
parse_arguments(arguments, &mut parsed_arguments, |arg| {
parse_minecraft_argument(
arg,
parse_arguments(
arguments,
&mut parsed_arguments,
|arg| {
parse_minecraft_argument(
arg,
&credentials.access_token,
&credentials.username,
&credentials.id,
version,
asset_index_name,
game_directory,
assets_directory,
version_type,
resolution,
)
},
java_arch,
)?;
Ok(parsed_arguments)
} else if let Some(legacy_arguments) = legacy_arguments {
let mut parsed_arguments = Vec::new();
for x in legacy_arguments.split(' ') {
parsed_arguments.push(parse_minecraft_argument(
&x.replace(' ', TEMPORARY_REPLACE_CHAR),
&credentials.access_token,
&credentials.username,
&credentials.id,
@ -208,26 +244,9 @@ pub fn get_minecraft_arguments(
assets_directory,
version_type,
resolution,
)
})?;
)?);
}
Ok(parsed_arguments)
} else if let Some(legacy_arguments) = legacy_arguments {
Ok(parse_minecraft_argument(
&legacy_arguments.replace(' ', TEMPORARY_REPLACE_CHAR),
&credentials.access_token,
&credentials.username,
&credentials.id,
version,
asset_index_name,
game_directory,
assets_directory,
version_type,
resolution,
)?
.split(' ')
.map(|x| x.to_string())
.collect())
} else {
Ok(Vec::new())
}
@ -300,6 +319,7 @@ fn parse_arguments<F>(
arguments: &[Argument],
parsed_arguments: &mut Vec<String>,
parse_function: F,
java_arch: &str,
) -> crate::Result<()>
where
F: Fn(&str) -> crate::Result<String>,
@ -314,7 +334,7 @@ where
}
}
Argument::Ruled { rules, value } => {
if rules.iter().all(parse_rule) {
if rules.iter().any(|x| parse_rule(x, java_arch)) {
match value {
ArgumentValue::Single(arg) => {
parsed_arguments.push(parse_function(

View File

@ -24,6 +24,7 @@ pub async fn download_minecraft(
st: &State,
version: &GameVersionInfo,
loading_bar: &LoadingBarId,
java_arch: &str,
) -> crate::Result<()> {
tracing::info!("Downloading Minecraft version {}", version.id);
// 5
@ -45,7 +46,7 @@ pub async fn download_minecraft(
// Total loading sums to 90/60
download_client(st, version, Some(loading_bar)), // 10
download_assets(st, version.assets == "legacy", &assets_index, Some(loading_bar), amount), // 40
download_libraries(st, version.libraries.as_slice(), &version.id, Some(loading_bar), amount) // 40
download_libraries(st, version.libraries.as_slice(), &version.id, Some(loading_bar), amount, java_arch) // 40
}?;
tracing::info!("Done downloading Minecraft!");
@ -247,6 +248,7 @@ pub async fn download_libraries(
version: &str,
loading_bar: Option<&LoadingBarId>,
loading_amount: f64,
java_arch: &str,
) -> crate::Result<()> {
Box::pin(async move {
tracing::debug!("Loading libraries");
@ -260,10 +262,12 @@ pub async fn download_libraries(
stream::iter(libraries.iter())
.map(Ok::<&Library, crate::Error>), None, loading_bar,loading_amount,num_files, None,|library| async move {
if let Some(rules) = &library.rules {
if !rules.iter().all(super::parse_rule) {
if !rules.iter().any(|x| super::parse_rule(x, java_arch)) {
tracing::trace!("Skipped library {}", &library.name);
return Ok(());
}
}
tokio::try_join! {
async {
let artifact_path = d::get_path_from_artifact(&library.name)?;
@ -278,24 +282,23 @@ pub async fn download_libraries(
let bytes = fetch(&artifact.url, Some(&artifact.sha1), &st.fetch_semaphore)
.await?;
write(&path, &bytes, &st.io_semaphore).await?;
tracing::trace!("Fetched library {}", &library.name);
tracing::trace!("Fetched library {} to path {:?}", &library.name, &path);
Ok::<_, crate::Error>(())
}
None => {
_ => {
let url = [
library
.url
.as_deref()
.unwrap_or("https://libraries.minecraft.net"),
.unwrap_or("https://libraries.minecraft.net/"),
&artifact_path
].concat();
let bytes = fetch(&url, None, &st.fetch_semaphore).await?;
write(&path, &bytes, &st.io_semaphore).await?;
tracing::trace!("Fetched library {}", &library.name);
tracing::trace!("Fetched library {} to path {:?}", &library.name, &path);
Ok::<_, crate::Error>(())
}
_ => Ok(())
}
},
async {
@ -304,7 +307,7 @@ pub async fn download_libraries(
library
.natives
.as_ref()?
.get(&Os::native_arch())?,
.get(&Os::native_arch(java_arch))?,
library
.downloads
.as_ref()?

View File

@ -1,6 +1,8 @@
//! Logic for launching Minecraft
use crate::event::emit::{emit_loading, init_or_edit_loading};
use crate::event::{LoadingBarId, LoadingBarType};
use crate::jre::{JAVA_17_KEY, JAVA_18PLUS_KEY, JAVA_8_KEY};
use crate::prelude::JavaVersion;
use crate::state::ProfileInstallStage;
use crate::{
process,
@ -8,10 +10,11 @@ use crate::{
State,
};
use daedalus as d;
use daedalus::minecraft::VersionInfo;
use dunce::canonicalize;
use st::Profile;
use std::fs;
use std::{path::Path, process::Stdio, sync::Arc};
use std::{process::Stdio, sync::Arc};
use tokio::process::Command;
use uuid::Uuid;
@ -21,18 +24,18 @@ pub mod auth;
pub mod download;
#[tracing::instrument]
pub fn parse_rule(rule: &d::minecraft::Rule) -> bool {
pub fn parse_rule(rule: &d::minecraft::Rule, java_version: &str) -> bool {
use d::minecraft::{Rule, RuleAction};
let res = match rule {
Rule {
os: Some(ref os), ..
} => crate::util::platform::os_rule(os),
} => crate::util::platform::os_rule(os, java_version),
Rule {
features: Some(ref features),
..
} => features.has_demo_resolution.unwrap_or(false),
_ => true,
_ => false,
};
match rule.action {
@ -54,6 +57,40 @@ macro_rules! processor_rules {
}
}
async fn get_java_version_from_profile(
profile: &Profile,
version_info: &VersionInfo,
) -> crate::Result<JavaVersion> {
if let Some(java) = profile.java.clone().and_then(|x| x.override_version) {
Ok(java)
} else {
let optimal_keys = match version_info
.java_version
.as_ref()
.map(|it| it.major_version)
.unwrap_or(8)
{
0..=15 => vec![JAVA_8_KEY, JAVA_17_KEY, JAVA_18PLUS_KEY],
16..=17 => vec![JAVA_17_KEY, JAVA_18PLUS_KEY],
_ => vec![JAVA_18PLUS_KEY],
};
let state = State::get().await?;
let settings = state.settings.read().await;
for key in optimal_keys {
if let Some(java) = settings.java_globals.get(&key.to_string()) {
return Ok(java.clone());
}
}
Err(crate::ErrorKind::LauncherError(
"No available java installation".to_string(),
)
.into())
}
}
#[tracing::instrument(skip(profile))]
pub async fn install_minecraft(
profile: &Profile,
@ -112,8 +149,10 @@ pub async fn install_minecraft(
)
.await?;
let java_version = get_java_version_from_profile(profile, &version_info).await?;
// Download minecraft (5-90)
download::download_minecraft(&state, &version_info, &loading_bar).await?;
download::download_minecraft(&state, &version_info, &loading_bar, &java_version.architecture).await?;
if let Some(processors) = &version_info.processors {
let client_path = state
@ -157,11 +196,12 @@ pub async fn install_minecraft(
cp.push(processor.jar.clone())
});
let child = Command::new("java")
let child = Command::new(&java_version.path)
.arg("-cp")
.arg(args::get_class_paths_jar(
&state.directories.libraries_dir(),
&cp,
&java_version.architecture
)?)
.arg(
args::get_processor_main_class(args::get_lib_path(
@ -231,7 +271,6 @@ pub async fn install_minecraft(
#[allow(clippy::too_many_arguments)]
pub async fn launch_minecraft(
java_install: &Path,
java_args: &[String],
env_args: &[(String, String)],
wrapper: &Option<String>,
@ -286,6 +325,8 @@ pub async fn launch_minecraft(
)
.await?;
let java_version = get_java_version_from_profile(profile, &version_info).await?;
let client_path = state
.directories
.version_dir(&version_jar)
@ -294,9 +335,9 @@ pub async fn launch_minecraft(
let args = version_info.arguments.clone().unwrap_or_default();
let mut command = match wrapper {
Some(hook) => {
wrap_ref_builder!(it = Command::new(hook) => {it.arg(java_install)})
wrap_ref_builder!(it = Command::new(hook) => {it.arg(&java_version.path)})
}
None => Command::new(String::from(java_install.to_string_lossy())),
None => Command::new(&java_version.path),
};
let env_args = Vec::from(env_args);
@ -324,10 +365,12 @@ pub async fn launch_minecraft(
&state.directories.libraries_dir(),
version_info.libraries.as_slice(),
&client_path,
&java_version.architecture
)?,
&version_jar,
*memory,
Vec::from(java_args),
&java_version.architecture
)?
.into_iter()
.collect::<Vec<_>>(),
@ -345,6 +388,7 @@ pub async fn launch_minecraft(
&state.directories.assets_dir(),
&version.type_,
*resolution,
&java_version.architecture
)?
.into_iter()
.collect::<Vec<_>>(),
@ -362,7 +406,7 @@ pub async fn launch_minecraft(
// Get Modrinth logs directories
let datetime_string =
chrono::Local::now().format("%Y%m%y_%H%M%S").to_string();
chrono::Local::now().format("%Y%m%d_%H%M%S").to_string();
let logs_dir = {
let st = State::get().await?;
st.directories

View File

@ -44,6 +44,12 @@ impl DirectoryInfo {
self.config_dir.join("meta")
}
/// Get the Minecraft java versions metadata directory
#[inline]
pub fn java_versions_dir(&self) -> PathBuf {
self.metadata_dir().join("java_versions")
}
/// Get the Minecraft versions metadata directory
#[inline]
pub fn versions_dir(&self) -> PathBuf {

View File

@ -1,5 +1,6 @@
//! Theseus state management system
use crate::event::emit::emit_loading;
use std::path::PathBuf;
use crate::event::emit::init_loading;
use crate::event::LoadingBarType;
@ -7,9 +8,14 @@ use crate::loading_join;
use crate::state::users::Users;
use crate::util::fetch::{FetchSemaphore, IoSemaphore};
use notify::RecommendedWatcher;
use notify_debouncer_mini::{new_debouncer, DebounceEventResult, Debouncer};
use std::sync::Arc;
use std::time::Duration;
use tokio::sync::{OnceCell, RwLock, Semaphore};
use futures::{channel::mpsc::channel, SinkExt, StreamExt};
// Submodules
mod dirs;
pub use self::dirs::*;
@ -69,6 +75,9 @@ pub struct State {
pub(crate) users: RwLock<Users>,
/// Launcher tags
pub(crate) tags: RwLock<Tags>,
/// File watcher debouncer
pub(crate) file_watcher: RwLock<Debouncer<RecommendedWatcher>>,
}
impl State {
@ -84,6 +93,8 @@ impl State {
)
.await?;
let mut file_watcher = init_watcher().await?;
let directories = DirectoryInfo::init().await?;
emit_loading(&loading_bar, 10.0, None).await?;
@ -100,7 +111,8 @@ impl State {
let metadata_fut =
Metadata::init(&directories, &io_semaphore);
let profiles_fut = Profiles::init(&directories);
let profiles_fut =
Profiles::init(&directories, &mut file_watcher);
let tags_fut = Tags::init(
&directories,
&io_semaphore,
@ -137,6 +149,7 @@ impl State {
children: RwLock::new(children),
auth_flow: RwLock::new(auth_flow),
tags: RwLock::new(tags),
file_watcher: RwLock::new(file_watcher),
}))
}
})
@ -220,3 +233,51 @@ impl State {
*io_semaphore = Semaphore::new(settings.max_concurrent_downloads);
}
}
async fn init_watcher() -> crate::Result<Debouncer<RecommendedWatcher>> {
let (mut tx, mut rx) = channel(1);
let file_watcher = new_debouncer(
Duration::from_secs(2),
None,
move |res: DebounceEventResult| {
futures::executor::block_on(async {
tx.send(res).await.unwrap();
})
},
)?;
tokio::task::spawn(async move {
while let Some(res) = rx.next().await {
match res {
Ok(events) => {
let mut visited_paths = Vec::new();
events.iter().for_each(|e| {
let mut new_path = PathBuf::new();
let mut found = false;
for component in e.path.components() {
new_path.push(component);
if found {
break;
}
if component.as_os_str() == "profiles" {
found = true;
}
}
if !visited_paths.contains(&new_path) {
Profile::sync_projects_task(new_path.clone());
visited_paths.push(new_path);
}
});
}
Err(errors) => errors.iter().for_each(|err| {
tracing::warn!("Unable to watch file: {err}")
}),
}
}
});
Ok(file_watcher)
}

View File

@ -3,6 +3,7 @@ use crate::config::MODRINTH_API_URL;
use crate::data::DirectoryInfo;
use crate::event::emit::emit_profile;
use crate::event::ProfilePayloadType;
use crate::prelude::JavaVersion;
use crate::state::projects::Project;
use crate::state::{ModrinthVersion, ProjectMetadata, ProjectType};
use crate::util::fetch::{
@ -13,6 +14,8 @@ use daedalus::get_hash;
use daedalus::modded::LoaderVersion;
use dunce::canonicalize;
use futures::prelude::*;
use notify::{RecommendedWatcher, RecursiveMode};
use notify_debouncer_mini::Debouncer;
use reqwest::Method;
use serde::{Deserialize, Serialize};
use std::io::Cursor;
@ -124,7 +127,7 @@ impl ModLoader {
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct JavaSettings {
#[serde(skip_serializing_if = "Option::is_none")]
pub jre_key: Option<String>,
pub override_version: Option<JavaVersion>,
#[serde(skip_serializing_if = "Option::is_none")]
pub extra_arguments: Option<Vec<String>>,
}
@ -173,36 +176,10 @@ impl Profile {
semaphore: &IoSemaphore,
icon: bytes::Bytes,
file_name: &str,
) -> crate::Result<&'a mut Self> {
) -> crate::Result<()> {
let file =
write_cached_icon(file_name, cache_dir, icon, semaphore).await?;
self.metadata.icon = Some(file);
Ok(self)
}
pub async fn sync_projects(&mut self) -> crate::Result<()> {
let state = State::get().await?;
let paths = self.get_profile_project_paths()?;
let projects = crate::state::infer_data_from_files(
self.clone(),
paths,
state.directories.caches_dir(),
&state.io_semaphore,
&state.fetch_semaphore,
)
.await?;
self.projects = projects;
emit_profile(
self.uuid,
self.path.clone(),
&self.metadata.name,
ProfilePayloadType::Synced,
)
.await?;
Ok(())
}
@ -228,6 +205,10 @@ impl Profile {
if let Some(profile) = new_profiles.0.get_mut(&path) {
profile.projects = projects;
}
} else {
tracing::warn!(
"Unable to fetch single profile projects: path {path:?} invalid",
);
}
Ok::<(), crate::Error>(())
@ -268,8 +249,44 @@ impl Profile {
Ok(files)
}
pub async fn watch_fs(
profile_path: &Path,
watcher: &mut Debouncer<RecommendedWatcher>,
) -> crate::Result<()> {
async fn watch_path(
profile_path: &Path,
watcher: &mut Debouncer<RecommendedWatcher>,
path: &str,
) -> crate::Result<()> {
let path = profile_path.join(path);
fs::create_dir_all(&path).await?;
watcher
.watcher()
.watch(&profile_path.join(path), RecursiveMode::Recursive)?;
Ok(())
}
watch_path(profile_path, watcher, ProjectType::Mod.get_folder())
.await?;
watch_path(profile_path, watcher, ProjectType::ShaderPack.get_folder())
.await?;
watch_path(
profile_path,
watcher,
ProjectType::ResourcePack.get_folder(),
)
.await?;
watch_path(profile_path, watcher, ProjectType::DataPack.get_folder())
.await?;
Ok(())
}
pub async fn add_project_version(
&mut self,
&self,
version_id: String,
) -> crate::Result<(PathBuf, ModrinthVersion)> {
let state = State::get().await?;
@ -314,7 +331,7 @@ impl Profile {
}
pub async fn add_project_bytes(
&mut self,
&self,
file_name: &str,
bytes: bytes::Bytes,
project_type: Option<ProjectType>,
@ -354,16 +371,22 @@ impl Profile {
write(&path, &bytes, &state.io_semaphore).await?;
let hash = get_hash(bytes).await?;
{
let mut profiles = state.profiles.write().await;
if let Some(profile) = profiles.0.get_mut(&self.path) {
profile.projects.insert(
path.clone(),
Project {
sha512: hash,
disabled: false,
metadata: ProjectMetadata::Unknown,
file_name: file_name.to_string(),
},
);
}
}
self.projects.insert(
path.clone(),
Project {
sha512: hash,
disabled: false,
metadata: ProjectMetadata::Unknown,
file_name: file_name.to_string(),
},
);
emit_profile(
self.uuid,
self.path.clone(),
@ -376,10 +399,19 @@ impl Profile {
}
pub async fn toggle_disable_project(
&mut self,
&self,
path: &Path,
) -> crate::Result<()> {
if let Some(mut project) = self.projects.remove(path) {
let state = State::get().await?;
if let Some(mut project) = {
let mut profiles = state.profiles.write().await;
if let Some(profile) = profiles.0.get_mut(&self.path) {
profile.projects.remove(path)
} else {
None
}
} {
let path = path.to_path_buf();
let mut new_path = path.clone();
@ -395,7 +427,10 @@ impl Profile {
fs::rename(path, &new_path).await?;
self.projects.insert(new_path, project);
let mut profiles = state.profiles.write().await;
if let Some(profile) = profiles.0.get_mut(&self.path) {
profile.projects.insert(new_path, project);
}
} else {
return Err(crate::ErrorKind::InputError(format!(
"Project path does not exist: {:?}",
@ -408,14 +443,19 @@ impl Profile {
}
pub async fn remove_project(
&mut self,
&self,
path: &Path,
dont_remove_arr: Option<bool>,
) -> crate::Result<()> {
let state = State::get().await?;
if self.projects.contains_key(path) {
fs::remove_file(path).await?;
if !dont_remove_arr.unwrap_or(false) {
self.projects.remove(path);
let mut profiles = state.profiles.write().await;
if let Some(profile) = profiles.0.get_mut(&self.path) {
profile.projects.remove(path);
}
}
} else {
return Err(crate::ErrorKind::InputError(format!(
@ -430,8 +470,11 @@ impl Profile {
}
impl Profiles {
#[tracing::instrument]
pub async fn init(dirs: &DirectoryInfo) -> crate::Result<Self> {
#[tracing::instrument(skip(file_watcher))]
pub async fn init(
dirs: &DirectoryInfo,
file_watcher: &mut Debouncer<RecommendedWatcher>,
) -> crate::Result<Self> {
let mut profiles = HashMap::new();
fs::create_dir_all(dirs.profiles_dir()).await?;
let mut entries = fs::read_dir(dirs.profiles_dir()).await?;
@ -449,6 +492,7 @@ impl Profiles {
};
if let Some(profile) = prof {
let path = canonicalize(path)?;
Profile::watch_fs(&path, file_watcher).await?;
profiles.insert(path, profile);
}
}
@ -517,6 +561,11 @@ impl Profiles {
ProfilePayloadType::Added,
)
.await?;
let state = State::get().await?;
let mut file_watcher = state.file_watcher.write().await;
Profile::watch_fs(&profile.path, &mut file_watcher).await?;
self.0.insert(
canonicalize(&profile.path)?
.to_str()
@ -529,15 +578,6 @@ impl Profiles {
Ok(self)
}
#[tracing::instrument(skip(self))]
pub async fn insert_from<'a>(
&'a mut self,
path: &'a Path,
) -> crate::Result<&Self> {
self.insert(Self::read_profile_from_dir(&canonicalize(path)?).await?)
.await
}
#[tracing::instrument(skip(self))]
pub async fn remove(
&mut self,

View File

@ -1,14 +1,15 @@
use dunce::canonicalize;
use futures::prelude::*;
use lazy_static::lazy_static;
use regex::Regex;
use serde::{Deserialize, Serialize};
use std::env;
use std::io::Write;
use std::path::PathBuf;
use std::process::Command;
use std::{collections::HashSet, path::Path};
use tempfile::NamedTempFile;
use tokio::task::JoinError;
use crate::State;
#[cfg(target_os = "windows")]
use winreg::{
enums::{HKEY_LOCAL_MACHINE, KEY_READ, KEY_WOW64_32KEY, KEY_WOW64_64KEY},
@ -19,6 +20,7 @@ use winreg::{
pub struct JavaVersion {
pub path: String,
pub version: String,
pub architecture: String,
}
// Entrypoint function (Windows)
@ -30,6 +32,7 @@ pub async fn get_all_jre() -> Result<Vec<JavaVersion>, JREError> {
// Add JRES directly on PATH
jre_paths.extend(get_all_jre_path().await?);
jre_paths.extend(get_all_autoinstalled_jre_path().await?);
// Hard paths for locations for commonly installed .exes
let java_paths = [r"C:/Program Files/Java", r"C:/Program Files (x86)/Java"];
@ -110,6 +113,7 @@ pub async fn get_all_jre() -> Result<Vec<JavaVersion>, JREError> {
// Add JREs directly on PATH
jre_paths.extend(get_all_jre_path().await?);
jre_paths.extend(get_all_autoinstalled_jre_path().await?);
// Hard paths for locations for commonly installed .exes
let java_paths = [
@ -128,6 +132,7 @@ pub async fn get_all_jre() -> Result<Vec<JavaVersion>, JREError> {
jre_paths.insert(entry);
}
}
// Get JRE versions from potential paths concurrently
let j = check_java_at_filepaths(jre_paths)
.await?
@ -146,6 +151,7 @@ pub async fn get_all_jre() -> Result<Vec<JavaVersion>, JREError> {
// Add JREs directly on PATH
jre_paths.extend(get_all_jre_path().await?);
jre_paths.extend(get_all_autoinstalled_jre_path().await?);
// Hard paths for locations for commonly installed locations
let java_paths = [
@ -177,6 +183,30 @@ pub async fn get_all_jre() -> Result<Vec<JavaVersion>, JREError> {
Ok(j)
}
// Gets all JREs from the PATH env variable
#[tracing::instrument]
async fn get_all_autoinstalled_jre_path() -> Result<HashSet<PathBuf>, JREError>
{
let state = State::get().await.map_err(|_| JREError::StateError)?;
let mut jre_paths = HashSet::new();
let base_path = state.directories.java_versions_dir();
if base_path.is_dir() {
for entry in std::fs::read_dir(base_path)? {
let entry = entry?;
let file_path = entry.path().join("bin");
let contents = std::fs::read_to_string(file_path)?;
let entry = entry.path().join(contents);
println!("{:?}", entry);
jre_paths.insert(entry);
}
}
Ok(jre_paths)
}
// Gets all JREs from the PATH env variable
#[tracing::instrument]
async fn get_all_jre_path() -> Result<HashSet<PathBuf>, JREError> {
@ -231,26 +261,49 @@ pub async fn check_java_at_filepath(path: &Path) -> Option<JavaVersion> {
return None;
};
// Run 'java -version' using found java binary
let output = Command::new(&java).arg("-version").output().ok()?;
let stderr = String::from_utf8_lossy(&output.stderr);
let mut file = NamedTempFile::new().ok()?;
file.write_all(include_bytes!("../../library/JavaInfo.class"))
.ok()?;
// Match: version "1.8.0_361"
// Extracting version numbers
lazy_static! {
static ref JAVA_VERSION_CAPTURE: Regex =
Regex::new(r#"version "([\d\._]+)""#)
.expect("Error creating java version capture regex");
let original_path = file.path().to_path_buf();
let mut new_path = original_path.clone();
new_path.set_file_name("JavaInfo");
new_path.set_extension("class");
tokio::fs::rename(&original_path, &new_path).await.ok()?;
// Run java checker on java binary
let output = Command::new(&java)
.arg("-cp")
.arg(file.path().parent().unwrap())
.arg("JavaInfo")
.output()
.ok()?;
let stdout = String::from_utf8_lossy(&output.stdout);
let mut java_version = None;
let mut java_arch = None;
for line in stdout.lines() {
let mut parts = line.split('=');
let key = parts.next().unwrap_or_default();
let value = parts.next().unwrap_or_default();
if key == "os.arch" {
java_arch = Some(value);
} else if key == "java.version" {
java_version = Some(value);
}
}
// Extract version info from it
if let Some(captures) = JAVA_VERSION_CAPTURE.captures(&stderr) {
if let Some(version) = captures.get(1) {
let Some(path) = java.to_str() else { return None };
let path = path.to_string();
if let Some(arch) = java_arch {
if let Some(version) = java_version {
let path = java.to_string_lossy().to_string();
return Some(JavaVersion {
path,
version: version.as_str().to_string(),
version: version.to_string(),
architecture: arch.to_string(),
});
}
}
@ -311,6 +364,9 @@ pub enum JREError {
#[error("No stored tag for Minecraft Version {0}")]
NoMinecraftVersionFound(String),
#[error("Error getting launcher sttae")]
StateError,
}
#[cfg(test)]

View File

@ -8,27 +8,27 @@ pub trait OsExt {
fn native() -> Self;
/// Gets the OS + Arch of the current system
fn native_arch() -> Self;
fn native_arch(java_arch: &str) -> Self;
}
impl OsExt for Os {
fn native_arch() -> Self {
fn native_arch(java_arch: &str) -> Self {
if std::env::consts::OS == "windows" {
if std::env::consts::ARCH == "aarch64" {
if java_arch == "aarch64" {
Os::WindowsArm64
} else {
Os::Windows
}
} else if std::env::consts::OS == "linux" {
if std::env::consts::ARCH == "aarch64" {
if java_arch == "aarch64" {
Os::LinuxArm64
} else if std::env::consts::ARCH == "arm" {
} else if java_arch == "arm" {
Os::LinuxArm32
} else {
Os::Linux
}
} else if std::env::consts::OS == "macos" {
if std::env::consts::ARCH == "aarch64" {
if java_arch == "aarch64" {
Os::OsxArm64
} else {
Os::Osx
@ -39,30 +39,6 @@ impl OsExt for Os {
}
fn native() -> Self {
if std::env::consts::OS == "windows" {
if std::env::consts::ARCH == "aarch64" {
Os::WindowsArm64
} else {
Os::Windows
}
} else if std::env::consts::OS == "linux" {
if std::env::consts::ARCH == "aarch64" {
Os::LinuxArm64
} else if std::env::consts::ARCH == "arm" {
Os::LinuxArm32
} else {
Os::Linux
}
} else if std::env::consts::OS == "macos" {
if std::env::consts::ARCH == "aarch64" {
Os::OsxArm64
} else {
Os::Osx
}
} else {
Os::Unknown
};
match std::env::consts::OS {
"windows" => Self::Windows,
"macos" => Self::Osx,
@ -80,7 +56,7 @@ pub const ARCH_WIDTH: &str = "64";
pub const ARCH_WIDTH: &str = "32";
// Platform rule handling
pub fn os_rule(rule: &OsRule) -> bool {
pub fn os_rule(rule: &OsRule, java_arch: &str) -> bool {
let mut rule_match = true;
if let Some(ref arch) = rule.arch {
@ -88,7 +64,8 @@ pub fn os_rule(rule: &OsRule) -> bool {
}
if let Some(name) = &rule.name {
rule_match &= &Os::native() == name || &Os::native_arch() == name;
rule_match &=
&Os::native() == name || &Os::native_arch(java_arch) == name;
}
if let Some(version) = &rule.version {
@ -101,8 +78,8 @@ pub fn os_rule(rule: &OsRule) -> bool {
rule_match
}
pub fn classpath_separator() -> &'static str {
match Os::native_arch() {
pub fn classpath_separator(java_arch: &str) -> &'static str {
match Os::native_arch(java_arch) {
Os::Osx
| Os::OsxArm64
| Os::Linux

View File

@ -1,11 +1,9 @@
use std::path::{Path, PathBuf};
use std::path::PathBuf;
use crate::api::Result;
use theseus::prelude::JavaVersion;
use theseus::prelude::*;
use super::TheseusSerializableError;
/// Get all JREs that exist on the system
#[tauri::command]
pub async fn jre_get_all_jre() -> Result<Vec<JavaVersion>> {
@ -37,23 +35,6 @@ pub async fn jre_autodetect_java_globals() -> Result<JavaGlobals> {
Ok(jre::autodetect_java_globals().await?)
}
// Gets key for the optimal JRE to use, for a given profile Profile
// The key can be used in the hashmap contained by JavaGlobals in Settings (if it exists)
#[tauri::command]
pub async fn jre_get_optimal_jre_key(profile: Profile) -> Result<String> {
Ok(jre::get_optimal_jre_key(&profile).await?)
}
// Gets key for the optimal JRE to use, for a given profile path
// The key can be used in the hashmap contained by JavaGlobals in Settings (if it exists)
#[tauri::command]
pub async fn jre_get_optimal_jre_key_by_path(path: &Path) -> Result<String> {
let profile = profile::get(path, Some(true)).await?.ok_or_else(|| {
TheseusSerializableError::NoProfileFound(path.display().to_string())
})?;
Ok(jre::get_optimal_jre_key(&profile).await?)
}
// Validates java globals, by checking if the paths exist
// If false, recommend to direct them to reassign, or to re-guess
#[tauri::command]
@ -67,3 +48,15 @@ pub async fn jre_validate_globals() -> Result<bool> {
pub async fn jre_get_jre(path: PathBuf) -> Result<Option<JavaVersion>> {
jre::check_jre(path).await.map_err(|e| e.into())
}
// Auto installs java for the given java version
#[tauri::command]
pub async fn jre_auto_install_java(java_version: u32) -> Result<PathBuf> {
Ok(jre::auto_install_java(java_version).await?)
}
// Gets the maximum memory a system has available.
#[tauri::command]
pub async fn jre_get_max_memory() -> Result<u64> {
Ok(jre::get_max_memory().await?)
}

View File

@ -31,9 +31,6 @@ pub enum TheseusSerializableError {
#[error("IO error: {0}")]
IO(#[from] std::io::Error),
#[error("No profile found at {0}")]
NoProfileFound(String),
}
// Generic implementation of From<T> for ErrorTypeA
@ -92,6 +89,5 @@ macro_rules! impl_serialize {
// Use the macro to implement Serialize for TheseusSerializableError
impl_serialize! {
IO,
NoProfileFound,
IO
}

View File

@ -54,14 +54,6 @@ pub async fn profile_check_installed(
}
}
/// Syncs a profile's in memory state with the state on the disk
/// // invoke('profile_sync')
#[tauri::command]
pub async fn profile_sync(path: &Path) -> Result<()> {
profile::sync(path).await?;
Ok(())
}
/// Installs/Repairs a profile
/// invoke('profile_install')
#[tauri::command]
@ -89,18 +81,6 @@ pub async fn profile_update_project(
Ok(())
}
/// Replaces a project with the given version ID
/// invoke('profile_replace_project')
#[tauri::command]
pub async fn profile_replace_project(
path: &Path,
project: &Path,
version_id: String,
) -> Result<PathBuf> {
let res = profile::replace_project(path, project, version_id).await?;
Ok(res)
}
// Adds a project to a profile from a version ID
// invoke('profile_add_project_from_version')
#[tauri::command]

View File

@ -79,11 +79,9 @@ fn main() {
api::profile::profile_remove,
api::profile::profile_get,
api::profile::profile_list,
api::profile::profile_sync,
api::profile::profile_install,
api::profile::profile_update_all,
api::profile::profile_update_project,
api::profile::profile_replace_project,
api::profile::profile_add_project_from_version,
api::profile::profile_add_project_from_path,
api::profile::profile_toggle_disable_project,
@ -117,9 +115,9 @@ fn main() {
api::jre::jre_find_jre_17_jres,
api::jre::jre_find_jre_8_jres,
api::jre::jre_validate_globals,
api::jre::jre_get_optimal_jre_key,
api::jre::jre_get_optimal_jre_key_by_path,
api::jre::jre_get_jre,
api::jre::jre_auto_install_java,
api::jre::jre_get_max_memory,
api::process::process_get_all_uuids,
api::process::process_get_all_running_uuids,
api::process::process_get_uuids_by_profile_path,

View File

@ -11,7 +11,7 @@ JavaVersion {
path: Path
version: String
}
*/
/// Get all JREs that exist on the system
@ -50,20 +50,18 @@ export async function get_jre(path) {
return await invoke('jre_get_jre', { path })
}
// Gets key for the optimal JRE to use, for a given profile path
// The key can be used in the hashmap contained by JavaGlobals in Settings (if it exists)
export async function get_optimal_jre_key_by_path(path) {
return await invoke('jre_get_optimal_jre_key_by_path', { path })
}
// Gets key for the optimal JRE to use, for a given profile
// The key can be used in the hashmap contained by JavaGlobals in Settings (if it exists)
export async function get_optimal_jre_key(path) {
return await invoke('jre_get_optimal_jre_key', { path })
}
// Autodetect Java globals, by searching the users computer.
// Returns a *NEW* JavaGlobals that can be put into Settings
export async function autodetect_java_globals(path) {
return await invoke('jre_autodetect_java_globals', { path })
}
// Automatically installs specified java version
export async function jre_auto_install_java(javaVersion) {
return await invoke('jre_auto_install_java', { javaVersion })
}
// Get max memory in KiB
export async function get_max_memory() {
return await invoke('jre_get_max_memory')
}

View File

@ -46,11 +46,6 @@ export async function check_installed(path, projectId) {
return await invoke('profile_check_installed', { path, projectId })
}
// Syncs a profile with the disk
export async function sync(path) {
return await invoke('profile_sync', { path })
}
// Installs/Repairs a profile
export async function install(path) {
return await invoke('profile_install', { path })
@ -66,12 +61,6 @@ export async function update_project(path, projectPath) {
return await invoke('profile_update_project', { path, projectPath })
}
// Replaces a given project with the specified version ID
// Returns a path to the new project file
export async function replace_project(path, projectPath, versionId) {
return await invoke('profile_replace_project', { path, projectPath, versionId })
}
// Add a project to a profile from a version
// Returns a path to the new project file
export async function add_project_from_version(path, versionId) {

View File

@ -17,7 +17,7 @@ import {
import { BrowseIcon } from '@/assets/icons'
import { useTheming } from '@/store/state'
import { get, set } from '@/helpers/settings'
import { find_jre_8_jres, find_jre_17_jres, get_jre } from '@/helpers/jre'
import { find_jre_8_jres, find_jre_17_jres, get_jre, get_max_memory } from '@/helpers/jre'
import { open } from '@tauri-apps/api/dialog'
const themeStore = useTheming()
@ -29,6 +29,7 @@ if (!fetchSettings.java_globals?.JAVA_8)
if (!fetchSettings.java_globals?.JAVA_17)
fetchSettings.java_globals.JAVA_17 = { path: '', version: '' }
const settings = ref(fetchSettings)
const maxMemory = ref((await get_max_memory()) / 1024)
const chosenInstallOptions = ref([])
const browsingInstall = ref(0)
@ -285,11 +286,11 @@ const setJavaInstall = (javaInstall) => {
<div class="sliders">
<span class="slider">
Minimum Memory
<Slider v-model="settings.memory.minimum" :min="1000" :max="8200" :step="10" />
<Slider v-model="settings.memory.minimum" :min="256" :max="maxMemory" :step="10" />
</span>
<span class="slider">
Maximum Memory
<Slider v-model="settings.memory.maximum" :min="1000" :max="8200" :step="10" />
<Slider v-model="settings.memory.maximum" :min="256" :max="maxMemory" :step="10" />
</span>
</div>
</div>

View File

@ -7,8 +7,7 @@ use dunce::canonicalize;
use theseus::jre::autodetect_java_globals;
use theseus::prelude::*;
use theseus::profile_create::profile_create;
use tokio::time::{sleep, Duration};
use tracing_error::ErrorLayer;
use tracing_subscriber::layer::SubscriberExt;
@ -51,6 +50,8 @@ async fn main() -> theseus::Result<()> {
let st = State::get().await?;
//State::update();
// let path = jre::auto_install_java(8).await.unwrap();
st.settings.write().await.java_globals = autodetect_java_globals().await?;
st.settings.write().await.max_concurrent_downloads = 50;
st.settings.write().await.hooks.post_exit =
@ -58,6 +59,12 @@ async fn main() -> theseus::Result<()> {
// Changed the settings, so need to reset the semaphore
st.reset_fetch_semaphore().await;
//
// st.settings
// .write()
// .await
// .java_globals
// .insert(JAVA_8_KEY.to_string(), check_jre(path).await?.unwrap());
// Clear profiles
println!("Clearing profiles.");
{
@ -69,52 +76,53 @@ async fn main() -> theseus::Result<()> {
println!("Creating/adding profile.");
// let name = "Example".to_string();
// let game_version = "1.19.2".to_string();
// let modloader = ModLoader::Vanilla;
// let loader_version = "stable".to_string();
//
// let profile_path = profile_create(
// name.clone(),
// game_version,
// modloader,
// Some(loader_version),
// None,
// None,
// None,
// None,
// )
// .await?;
let name = "Example".to_string();
let game_version = "1.19.2".to_string();
let modloader = ModLoader::Vanilla;
let loader_version = "stable".to_string();
let profile_path = profile_create(
name.clone(),
game_version,
modloader,
Some(loader_version),
None,
None,
None,
None,
)
.await?;
//
// install(&profile_path).await.unwrap();
// let mut value = list().await?;
// let profile_path = value.iter().next().map(|x| x.0).unwrap();
// println!("Adding sodium");
// let sodium_path = profile::add_project_from_version(
// &profile_path,
// "rAfhHfow".to_string(),
// )
// .await?;
//
// let mod_menu_path = profile::add_project_from_version(
// &profile_path,
// "gSoPJyVn".to_string(),
// )
// .await?;
//
// println!("Disabling sodium");
// profile::toggle_disable_project(&profile_path, &sodium_path).await?;
// profile::remove_project(&profile_path, &mod_menu_path).await?;
let profile_path = pack::install_pack_from_version_id(
"CeeCkHke".to_string(),
"Technical Electrical".to_string(),
None,
println!("Adding sodium");
let sodium_path = profile::add_project_from_version(
&profile_path,
"rAfhHfow".to_string(),
)
.await
.unwrap();
.await?;
let mod_menu_path = profile::add_project_from_version(
&profile_path,
"gSoPJyVn".to_string(),
)
.await?;
println!("Disabling sodium");
profile::toggle_disable_project(&profile_path, &sodium_path).await?;
profile::remove_project(&profile_path, &mod_menu_path).await?;
// let profile_path = pack::install_pack_from_version_id(
// "CeeCkHke".to_string(),
// "Technical Electrical".to_string(),
// None,
// )
// .await
// .unwrap();
// async closure for testing any desired edits
// (ie: changing the java runtime of an added profile)
@ -147,8 +155,8 @@ async fn main() -> theseus::Result<()> {
println!("Minecraft PID: {:?}", pid);
// Wait 5 seconds
println!("Waiting 20 seconds to gather logs...");
sleep(Duration::from_secs(20)).await;
println!("Waiting 5 seconds to gather logs...");
sleep(Duration::from_secs(5)).await;
let stdout = process::get_stdout_by_uuid(&uuid).await?;
let stderr = process::get_stderr_by_uuid(&uuid).await?;
println!("Logs after 5sec <<< {stdout} >>> end stdout");