Various final backend fixes (#117)
* Various final backend fixes * Add FS watching * run lint * Autodetect installed jars
This commit is contained in:
parent
5cb54b44be
commit
3fa0e99de2
378
Cargo.lock
generated
378
Cargo.lock
generated
@ -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",
|
||||
]
|
||||
|
||||
@ -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"]
|
||||
|
||||
BIN
theseus/library/JavaInfo.class
Normal file
BIN
theseus/library/JavaInfo.class
Normal file
Binary file not shown.
22
theseus/library/JavaInfo.java
Normal file
22
theseus/library/JavaInfo.java
Normal 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);
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -84,6 +84,9 @@ pub enum ErrorKind {
|
||||
|
||||
#[error("Error: {0}")]
|
||||
OtherError(String),
|
||||
|
||||
#[error("File watching error: {0}")]
|
||||
NotifyError(#[from] notify::Error),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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()?
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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)]
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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?)
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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]
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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')
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user