SHA256
Compare commits
5
Commits
| Author | SHA256 | Date | |
|---|---|---|---|
|
|
25a706d6ea | ||
|
|
2fedcd0805 | ||
|
|
4a4e6927bd | ||
|
|
39fb7c55b9 | ||
|
|
6811002ca6 |
Generated
+25
-201
@@ -52,32 +52,17 @@ dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atomic-polyfill"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
|
||||
dependencies = [
|
||||
"critical-section",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.13.1"
|
||||
version = "2.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
@@ -87,9 +72,9 @@ checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.6.6"
|
||||
version = "4.6.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "473c7e07f409a8d772161724aa8db6a765a2532a70f9667eeb7b49d3d02fbdca"
|
||||
checksum = "aa8876b300ab35ba921adea3dfd70157a46249b33f95c9084ae5709785478946"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@@ -97,9 +82,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.6.6"
|
||||
version = "4.6.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b48fea5a88e9ae728a2dcbedbfc0e730f7d60da42e1cb049a83c9fb8b789889"
|
||||
checksum = "ec0797fb7aeb1406c84efac526901f7ec3ead2124f946b494e72879d4b54704d"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@@ -109,9 +94,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.6.4"
|
||||
version = "4.6.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d012d2b9d65aca7f18f4d9878a045bc17899bba951561ba5ec3c2ba1eed9a061"
|
||||
checksum = "f9c751b79415d4e559e3d1fcf128e09e720eb673a06d26cf6f392d37d75b66e0"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
@@ -121,18 +106,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "1.1.0"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9"
|
||||
|
||||
[[package]]
|
||||
name = "cobs"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
checksum = "1c133bc6a41be0d194c306b5506d15e6feeea7b1d6604bd3f8310dfb2ca96486"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
@@ -140,24 +116,6 @@ version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
|
||||
|
||||
[[package]]
|
||||
name = "critical-section"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
|
||||
|
||||
[[package]]
|
||||
name = "embedded-io"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced"
|
||||
|
||||
[[package]]
|
||||
name = "embedded-io"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d"
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.2"
|
||||
@@ -174,35 +132,12 @@ dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hash32"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.17.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
|
||||
|
||||
[[package]]
|
||||
name = "heapless"
|
||||
version = "0.7.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f"
|
||||
dependencies = [
|
||||
"atomic-polyfill",
|
||||
"hash32",
|
||||
"rustc_version",
|
||||
"serde",
|
||||
"spin",
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
@@ -211,14 +146,12 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "hive-up"
|
||||
version = "0.1.2"
|
||||
version = "0.2.2"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"nix",
|
||||
"postcard",
|
||||
"regex-lite",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"signal-hook",
|
||||
"time-format",
|
||||
"toml",
|
||||
@@ -240,32 +173,11 @@ version = "1.70.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.189"
|
||||
version = "0.2.190"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
|
||||
dependencies = [
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
|
||||
checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78"
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
@@ -285,19 +197,6 @@ version = "1.70.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
|
||||
|
||||
[[package]]
|
||||
name = "postcard"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24"
|
||||
dependencies = [
|
||||
"cobs",
|
||||
"embedded-io 0.4.0",
|
||||
"embedded-io 0.6.1",
|
||||
"heapless",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.107"
|
||||
@@ -322,27 +221,6 @@ version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cab834c73d247e67f4fae452806d17d3c7501756d98c8808d7c9c7aa7d18f973"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
|
||||
dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.229"
|
||||
@@ -373,19 +251,6 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.151"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
"serde",
|
||||
"serde_core",
|
||||
"zmij",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "1.1.1"
|
||||
@@ -397,9 +262,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook"
|
||||
version = "0.4.4"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2a0c28ca5908dbdbcd52e6fdaa00358ab88637f8ab33e1f188dd510eb44b53d"
|
||||
checksum = "b29ffa27d3d59a049bb328258de100f8012848d1b08d444e08bbc02ac468435e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"signal-hook-registry",
|
||||
@@ -415,21 +280,6 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.9.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
@@ -438,46 +288,26 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "3.0.5"
|
||||
version = "3.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12df2e0110f65b775f769bb17ef989067a1d931b2eb822bd4346631eeada89f9"
|
||||
checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "2.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "2.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time-format"
|
||||
version = "1.2.3"
|
||||
version = "1.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb54c799611991d3d4a66fee3ff17b9f600c2a0f8c0d34e8209dbd153ff0a87b"
|
||||
checksum = "c21b401b09485cb2403a336b3c6f9d53bd8a7273463f71b71d4f6325f7f74f6c"
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "1.1.5+spec-1.1.0"
|
||||
version = "1.1.6+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12c0ba9680044b4ce98d391a62094047eada0d64860b80166c39f4a6b5640785"
|
||||
checksum = "920602543f0911ab71da12c50d59701da54c196d1a2bf5cb4b75667f137a406a"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde_core",
|
||||
@@ -514,9 +344,9 @@ checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.24"
|
||||
version = "1.0.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||
checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
@@ -544,9 +374,3 @@ name = "winnow"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81"
|
||||
|
||||
[[package]]
|
||||
name = "zmij"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
|
||||
|
||||
+1
-3
@@ -1,15 +1,13 @@
|
||||
[package]
|
||||
name = "hive-up"
|
||||
version = "0.1.2"
|
||||
version = "0.2.2"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.6", features = ["derive"] }
|
||||
nix = { version = "0", features = ["user"] }
|
||||
postcard = { version = "1.1", features = ["use-std"] }
|
||||
regex-lite = "0.1"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
signal-hook = "0.4"
|
||||
time-format = "1.2"
|
||||
toml = "1.1"
|
||||
|
||||
@@ -4,57 +4,54 @@ Program to manage update process of Kira Linux. Creating snapshots. Dealing with
|
||||
|
||||
There should be some documantation here.
|
||||
|
||||
hive-up uses `/var/lib/hive-up/hyve-db.json` file as database for stuff
|
||||
And `/etc/hive-up.toml` as config file.
|
||||
|
||||
As an daemon hive-up righ now doing only periodical checks for updates.
|
||||
hive-up uses `/etc/hive-up.toml` as config file.
|
||||
|
||||
```text
|
||||
Update program fot Kira Linux :3
|
||||
|
||||
Usage: hive-up <COMMAND>
|
||||
|
||||
Commands:
|
||||
cli Perform local operations
|
||||
remote Ask hive-up daemon something
|
||||
daemon Run hive-up in daemon mode
|
||||
boot Manage system boot
|
||||
pac Intended to be used by pacman hooks
|
||||
help Print this message or the help of the given subcommand(s)
|
||||
|
||||
Options:
|
||||
-h, --help Print help
|
||||
-V, --version Print version
|
||||
|
||||
```
|
||||
|
||||
For cli mode:
|
||||
Pac mode:
|
||||
|
||||
```text
|
||||
Usage: hive-up cli <--upgrade|--update-boot|--init-boot-menu|--init-boot>
|
||||
Usage: hive-up pac <COMMAND>
|
||||
|
||||
Commands:
|
||||
snapshot-system Creates snapshoots of /usr and /var subvolumea
|
||||
start This supposed to be called by pacman hook before transaction hive-up will check for /var/lib/hive-up/pac-lock and will not create snapshots in case it present Its safe lock mesure to prevent multiple snapshots on system fixing or some corner cases Lock file can be deleted by `pac finish` that should be called by pacman after transaction
|
||||
finis This supposed to be called by pacman hook before transaction. Right now only thing it does is removes /var/lib/hive-up/pac-lock file
|
||||
help Print this message or the help of the given subcommand(s)
|
||||
|
||||
Options:
|
||||
--upgrade Perform system upgrade
|
||||
--update-boot Install new kernel into boot partition
|
||||
--init-boot-menu Cleans up and recreates UFI boot menu
|
||||
--init-boot Cleans up and recreates UFI boot menu and /EFI dir content
|
||||
-h, --help Print help
|
||||
Print help
|
||||
```
|
||||
|
||||
For remote mode:
|
||||
Boot mode:
|
||||
|
||||
```text
|
||||
Usage: hive-up remote <--check-updates|--updates-avail|--schedule-update>
|
||||
Usage: hive-up boot <COMMAND>
|
||||
|
||||
Commands:
|
||||
update Install new kernel into boot partition
|
||||
efi-menu-init Cleans up and recreates UFI boot menu
|
||||
init Cleans up and recreates UFI boot menu and /EFI dir content
|
||||
help Print this message or the help of the given subcommand(s)
|
||||
|
||||
Options:
|
||||
--check-updates Ask daemon to check for updates
|
||||
--updates-avail Ask daemon if there is any updates available
|
||||
--schedule-update Ask daemon to perform system update on next reboot
|
||||
-h, --help Print help
|
||||
|
||||
```
|
||||
|
||||
`hive-up daemon` - do not have any flags for now.
|
||||
|
||||
`hive-up cli --upgrade` - generally not supposed to be called by user. It get called by system service manager (dinit) after hive-up service stop (on reboot or system shutdown)
|
||||
When `hive-up cli --upgrade` is called, it checks if `update_on_reboot` flag is set in **DB** or `auto_update` flag checked in **config**, and if `updates_available` in **DB** is non zero. Update routine continue only if this conditios are met.
|
||||
|
||||
1. It creates snapshots of `/usr` and `/var` subvolumes
|
||||
2. It sets `update_status` to **false** in **DB**
|
||||
3. Performs update, and if everything was fine sets `update_status` to **true** in **DB**
|
||||
|
||||
After this, system reboots, and on system boot Nyanit figures up what to do with failed updates if any
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
[Trigger]
|
||||
Operation = Install
|
||||
Operation = Upgrade
|
||||
Operation = Remove
|
||||
Type = Package
|
||||
Target = *
|
||||
|
||||
[Action]
|
||||
Description = Release lock and do stuff
|
||||
When = PostTransaction
|
||||
Exec = /usr/bin/hive-up pac finish
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
[Trigger]
|
||||
Operation = Install
|
||||
Operation = Upgrade
|
||||
Operation = Remove
|
||||
Type = Package
|
||||
Target = *
|
||||
|
||||
[Action]
|
||||
Description = Snapshot system before any changes
|
||||
When = PreTransaction
|
||||
Exec = /usr/bin/hive-up pac start
|
||||
|
||||
@@ -9,4 +9,5 @@ Target = linux-kira-server-lts
|
||||
[Action]
|
||||
Description = Running custom command after kernel update
|
||||
When = PostTransaction
|
||||
Exec = /usr/bin/hive-up cli --update-boot
|
||||
Exec = /usr/bin/hive-up boot update
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
type = process
|
||||
command = /usr/bin/hive-up daemon
|
||||
stop-command = /usr/bin/hive-up cli --upgrade
|
||||
depends-on = network.target
|
||||
logfile = /var/log/dinit/hive-up.log
|
||||
log-type = file
|
||||
@@ -1,11 +1,4 @@
|
||||
# Section (Table) headers
|
||||
[update]
|
||||
# Interval between updates check in hours. 0 - no auto check for updates.
|
||||
check_interval = 58
|
||||
# Tells hive-up to automatically download updates when awailable.
|
||||
download_updates = true
|
||||
# Tells hive-up to automatically perform updates during system reboot
|
||||
auto_update = false
|
||||
|
||||
# In [kernel] section user may specify kernel cmd
|
||||
# [kernel]
|
||||
|
||||
-264
@@ -1,264 +0,0 @@
|
||||
// <hive-up - update program fot Kira Linux.>
|
||||
// Copyright (C) <2026> <Kira Foundation>
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
/*
|
||||
hive-up daemon logic
|
||||
*/
|
||||
|
||||
use std::os::unix::net::UnixDatagram;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::thread;
|
||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||
|
||||
use crate::hive_config;
|
||||
use crate::hive_config::HiveConfig;
|
||||
use crate::hive_db::{self, HiveDb};
|
||||
use crate::hive_intercom::{self, BzzReq, BzzResp, IntercomError};
|
||||
use crate::hive_system;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum DaemonError {
|
||||
IoError(std::io::Error),
|
||||
DBError(hive_db::DBError),
|
||||
ConfigError(hive_config::ConfigError),
|
||||
ExecCommandError(hive_system::ExecCommandError),
|
||||
TimestampError,
|
||||
}
|
||||
|
||||
// 2. Implement From for each wrapped error type
|
||||
impl From<std::io::Error> for DaemonError {
|
||||
fn from(err: std::io::Error) -> Self {
|
||||
DaemonError::IoError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<hive_db::DBError> for DaemonError {
|
||||
fn from(err: hive_db::DBError) -> Self {
|
||||
DaemonError::DBError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<hive_config::ConfigError> for DaemonError {
|
||||
fn from(err: hive_config::ConfigError) -> Self {
|
||||
DaemonError::ConfigError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<hive_system::ExecCommandError> for DaemonError {
|
||||
fn from(err: hive_system::ExecCommandError) -> Self {
|
||||
DaemonError::ExecCommandError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for DaemonError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
DaemonError::IoError(e) => write!(f, "IO Error: {}", e),
|
||||
DaemonError::DBError(e) => write!(f, "Database error: {}", e),
|
||||
DaemonError::ConfigError(e) => write!(f, "Config Error: {}", e),
|
||||
DaemonError::ExecCommandError(e) => write!(f, "Exec Command Error: {}", e),
|
||||
DaemonError::TimestampError => write!(f, "Timestamp Error"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Implement std::error::Error
|
||||
impl std::error::Error for DaemonError {}
|
||||
|
||||
fn get_timestamp_sec() -> u64 {
|
||||
SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.expect("Time went backwards")
|
||||
.as_secs()
|
||||
}
|
||||
|
||||
/// bloking function. Bloaks for configured socker recv timeout
|
||||
fn process_remoute(
|
||||
bzz_db: &mut HiveDb,
|
||||
listening_socket: &UnixDatagram,
|
||||
recv_buf: &mut [u8],
|
||||
) -> Result<(), DaemonError> {
|
||||
// waiting on socket recv_from untill timeout (also using this as a timer)
|
||||
match hive_intercom::socket_recv(&listening_socket, recv_buf) {
|
||||
// we get some request to process
|
||||
Ok((bzz_req, client_addr)) => {
|
||||
match bzz_req {
|
||||
// return awailable updates number
|
||||
BzzReq::UpdatesAvailable => {
|
||||
let resp = BzzResp::UpdatesAvailable(bzz_db.updates_available);
|
||||
if let Err(ex) =
|
||||
hive_intercom::socket_send(&listening_socket, &client_addr, resp)
|
||||
{
|
||||
println!("Error while ansvering cli request: {}", ex);
|
||||
}
|
||||
}
|
||||
// we should apply updates if any on reboot
|
||||
BzzReq::ScheduleUpdate => {
|
||||
// but only if we have actually any updates
|
||||
if bzz_db.updates_available > 0 {
|
||||
bzz_db.update_on_reboot = true;
|
||||
// keep it simple Kira
|
||||
// lets just return err from the loop if something wrong with db
|
||||
hive_db::write_db(&bzz_db)?;
|
||||
// signal remoute that evertyhing go OK
|
||||
if let Err(ex) = hive_intercom::socket_send(
|
||||
&listening_socket,
|
||||
&client_addr,
|
||||
BzzResp::Finish,
|
||||
) {
|
||||
println!("Error while ansvering cli request: {}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
BzzReq::CheckForUpdates => {
|
||||
let resp = BzzResp::Working(1);
|
||||
if let Err(ex) =
|
||||
hive_intercom::socket_send(&listening_socket, &client_addr, resp)
|
||||
{
|
||||
println!("Error while ansvering cli request: {}", ex);
|
||||
} else {
|
||||
// perform update check
|
||||
println!("Cheking for updates...");
|
||||
// now that may fail because of bad internet and idealy we
|
||||
// want to just log error and retry in other time
|
||||
bzz_db.updates_available = match hive_system::check_updates() {
|
||||
Ok(updates_num) => updates_num,
|
||||
Err(ex) => {
|
||||
println!("Error while shecking for updates: {}", ex);
|
||||
0u32
|
||||
}
|
||||
};
|
||||
hive_db::write_db(&bzz_db)?;
|
||||
println!(
|
||||
"Found {} packages that needs to be updated.",
|
||||
bzz_db.updates_available
|
||||
);
|
||||
// send evailable updates numbet to client
|
||||
let resp = BzzResp::UpdatesAvailable(bzz_db.updates_available);
|
||||
if let Err(ex) =
|
||||
hive_intercom::socket_send(&listening_socket, &client_addr, resp)
|
||||
{
|
||||
println!("Error while ansvering cli request: {}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
// if time out - do nothing
|
||||
Err(IntercomError::Timeout) => Ok(()),
|
||||
// if some actual IO error then return it
|
||||
Err(IntercomError::IoError(ex)) => Err(ex.into()),
|
||||
// if other kinds of errors - log and continue
|
||||
Err(ex) => {
|
||||
println!("Got error while listenin to unix socket: {}", ex);
|
||||
print!("Sleeping for 1 secong and continue...");
|
||||
thread::sleep(Duration::from_secs(1));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// doing what daemons usually beezz
|
||||
fn do_local_work(config: &HiveConfig, bzz_db: &mut HiveDb) -> Result<(), DaemonError> {
|
||||
// if updates check is turned on
|
||||
if config.update.check_interval != 0 {
|
||||
let timestamp = get_timestamp_sec();
|
||||
|
||||
// calculate how many hours passed sinse last update
|
||||
let hours_since_update_check = timestamp
|
||||
.checked_sub(bzz_db.update_check_timestamp)
|
||||
.ok_or(DaemonError::TimestampError)?
|
||||
/ 3600;
|
||||
|
||||
// if more than updates_check_interval specifiyed in config - check for updates
|
||||
if hours_since_update_check > config.update.check_interval {
|
||||
// perform update check
|
||||
println!("Cheking for updates...");
|
||||
// now that may fail because of bad internet and idealy we
|
||||
// want to just log error and retry in other time
|
||||
bzz_db.updates_available = match hive_system::check_updates() {
|
||||
Ok(updates_num) => updates_num,
|
||||
Err(ex) => {
|
||||
println!("Error while shecking for updates: {}", ex);
|
||||
0u32
|
||||
}
|
||||
};
|
||||
hive_db::write_db(&bzz_db)?;
|
||||
println!(
|
||||
"Found {} packages that needs to be updated.",
|
||||
bzz_db.updates_available
|
||||
);
|
||||
|
||||
// if auto download for updates is enabled and there is some updates - download them
|
||||
if config.update.download_updates && bzz_db.updates_available != 0 {
|
||||
println!("Downloadin updates...");
|
||||
match hive_system::download_updates() {
|
||||
Ok(()) => {
|
||||
println!("Updates downloaded...");
|
||||
}
|
||||
Err(ex) => {
|
||||
println!("Error downloading updates: {}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// updating las tcheck for updates timestamp in db
|
||||
bzz_db.update_check_timestamp = get_timestamp_sec();
|
||||
hive_db::write_db(&bzz_db)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run(
|
||||
mut bzz_config: HiveConfig,
|
||||
term_flag: Arc<AtomicBool>,
|
||||
reload_flag: Arc<AtomicBool>,
|
||||
) -> Result<(), DaemonError> {
|
||||
// reading db from disk
|
||||
let mut bzz_db = hive_db::read_db()?;
|
||||
|
||||
// stop flag
|
||||
let mut keep_going = true;
|
||||
|
||||
// init udp unix socket for communication with cli and such
|
||||
let listening_socket = hive_intercom::socket_bind(1)?;
|
||||
let mut recv_buf: Vec<u8> = Vec::with_capacity(1024);
|
||||
|
||||
// main loop (I love loops) (No please just do recursion properly)
|
||||
while keep_going {
|
||||
process_remoute(&mut bzz_db, &listening_socket, recv_buf.as_mut_slice())?;
|
||||
do_local_work(&bzz_config, &mut bzz_db)?;
|
||||
// check termination flags
|
||||
if term_flag.load(Ordering::Relaxed) {
|
||||
println!("SIGTERM recieved - wrapping things up.");
|
||||
keep_going = false;
|
||||
}
|
||||
|
||||
// checking reload signal flag
|
||||
if reload_flag.load(Ordering::Relaxed) {
|
||||
println!("SIGHUP recieved - reloading config and DB.");
|
||||
bzz_config = hive_config::read_config()?;
|
||||
bzz_db = hive_db::read_db()?;
|
||||
println!("Reloaded!");
|
||||
}
|
||||
}
|
||||
|
||||
println!("Exiting...");
|
||||
Ok(())
|
||||
}
|
||||
@@ -28,8 +28,6 @@ const CONFIG_PATH: &str = "/etc/hive-up.toml";
|
||||
pub struct HiveConfig {
|
||||
// Matches [kernel] in TOML
|
||||
pub kernel: Option<KernelConfig>,
|
||||
// Updates [update] in TOML
|
||||
pub update: UpdateConfig,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
@@ -38,15 +36,6 @@ pub struct KernelConfig {
|
||||
pub cmd: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct UpdateConfig {
|
||||
/// Interval between updates check in hours. 0 - no auto check for updates.
|
||||
pub check_interval: u64,
|
||||
/// Tells hive-up to automatically download updates when awailable.
|
||||
pub download_updates: bool,
|
||||
/// Tells hive-up to automatically perform updates during system reboot.
|
||||
pub auto_update: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ConfigError {
|
||||
|
||||
-105
@@ -1,105 +0,0 @@
|
||||
// <hive-up - update program fot Kira Linux.>
|
||||
// Copyright (C) <2026> <Kira Foundation>
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
/*
|
||||
Functions for reading and writyng daemon and updates state
|
||||
*/
|
||||
|
||||
const DB_PATH: &str = "/var/lib/hive-up/hyve-db.json";
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fs;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum DBError {
|
||||
IoError(std::io::Error),
|
||||
JsonError(serde_json::Error),
|
||||
}
|
||||
|
||||
// 2. Implement From for each wrapped error type
|
||||
impl From<std::io::Error> for DBError {
|
||||
fn from(err: std::io::Error) -> Self {
|
||||
DBError::IoError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<serde_json::Error> for DBError {
|
||||
fn from(err: serde_json::Error) -> Self {
|
||||
DBError::JsonError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for DBError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
DBError::IoError(e) => write!(f, "IO Error: {}", e),
|
||||
DBError::JsonError(e) => {
|
||||
write!(f, "Json parse error: {}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Implement std::error::Error
|
||||
impl std::error::Error for DBError {}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct HiveDb {
|
||||
/// Timestamp of last check for updates in seconds from UNIX_EPOCH
|
||||
pub update_check_timestamp: u64,
|
||||
/// non zero if there is updates that can bee applied, showing numbers of packages that can be updated
|
||||
pub updates_available: u32,
|
||||
/// true if last update was successful
|
||||
/// if it is false - nyanit need to roll back snapshots
|
||||
pub update_status: bool,
|
||||
/// datetime of last snapshot in format "%Y-%m-%dT%H:%M:%S"
|
||||
pub last_snapshot_time: String,
|
||||
/// set to true if we want to apply available updates on reboot
|
||||
pub update_on_reboot: bool,
|
||||
}
|
||||
|
||||
fn init_db() -> Result<HiveDb, DBError> {
|
||||
let bzz_db = HiveDb{
|
||||
update_check_timestamp: 0,
|
||||
updates_available: 0,
|
||||
update_status: false,
|
||||
last_snapshot_time: "".into(),
|
||||
update_on_reboot: false,
|
||||
};
|
||||
write_db(&bzz_db)?;
|
||||
Ok(bzz_db)
|
||||
}
|
||||
|
||||
pub fn read_db() -> Result<HiveDb, DBError> {
|
||||
if fs::exists(DB_PATH)? {
|
||||
let file_content = fs::read_to_string(DB_PATH)?;
|
||||
let db: HiveDb = serde_json::from_str(&file_content)?;
|
||||
Ok(db)
|
||||
}
|
||||
else {
|
||||
println!("WARNING database file do not exist {}", DB_PATH);
|
||||
print!("Creating default db file...");
|
||||
init_db()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_db(db: &HiveDb) -> Result<(), DBError> {
|
||||
let serialized_db = serde_json::to_string(db)?;
|
||||
fs::write(DB_PATH, serialized_db)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -1,205 +0,0 @@
|
||||
// <hive-up - update program fot Kira Linux.>
|
||||
// Copyright (C) <2026> <Kira Foundation>
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
/*
|
||||
hive-up unix socket communication
|
||||
*/
|
||||
|
||||
use postcard;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fs;
|
||||
use std::os::unix::net::{SocketAddr, UnixDatagram};
|
||||
use std::time::Duration;
|
||||
|
||||
pub const SOCKET_DIR: &str = "/run/hive-up";
|
||||
pub const SOCKET_PATH: &str = "/run/hive-up/hive-intercom.soc";
|
||||
pub const CLINET_READ_TIMEOUT_SECONDS: u64 = 88;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum IntercomError {
|
||||
IoError(std::io::Error),
|
||||
PostcardError(postcard::Error),
|
||||
ConnectionClosed,
|
||||
Timeout,
|
||||
UnexpectedResponse,
|
||||
ServerError(String),
|
||||
}
|
||||
|
||||
// Wrapping IO errors but separating time out error
|
||||
impl From<std::io::Error> for IntercomError {
|
||||
fn from(err: std::io::Error) -> Self {
|
||||
if err.kind() == std::io::ErrorKind::TimedOut
|
||||
|| err.kind() == std::io::ErrorKind::WouldBlock
|
||||
{
|
||||
IntercomError::Timeout
|
||||
} else {
|
||||
IntercomError::IoError(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<postcard::Error> for IntercomError {
|
||||
fn from(err: postcard::Error) -> Self {
|
||||
IntercomError::PostcardError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for IntercomError {
|
||||
fn from(err: String) -> Self {
|
||||
IntercomError::ServerError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for IntercomError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
IntercomError::IoError(e) => write!(f, "IO Error: {}", e),
|
||||
IntercomError::PostcardError(e) => {
|
||||
write!(f, "Data parsing (postcard) error: {}", e)
|
||||
}
|
||||
IntercomError::Timeout => write!(f, "Operation Timeout"),
|
||||
IntercomError::ConnectionClosed => write!(f, "Connection closed"),
|
||||
IntercomError::UnexpectedResponse => write!(f, "Unexpected response"),
|
||||
IntercomError::ServerError(err) => write!(f, "Server side error: {}", err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Implement std::error::Error
|
||||
impl std::error::Error for IntercomError {}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum BzzResp {
|
||||
/// signalls progress of a task as u16 integer.
|
||||
/// interpretation is up to you.
|
||||
Working(u16),
|
||||
Finish,
|
||||
UpdatesAvailable(u32),
|
||||
Error(String),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[repr(u8)]
|
||||
pub enum BzzReq {
|
||||
UpdatesAvailable,
|
||||
CheckForUpdates,
|
||||
ScheduleUpdate,
|
||||
}
|
||||
|
||||
pub fn socket_bind(read_timeout_sec: u64) -> Result<UnixDatagram, std::io::Error> {
|
||||
// create socket directory if it is does not exist
|
||||
if let Ok(path_exist) = fs::exists(SOCKET_DIR)
|
||||
&& path_exist == false
|
||||
{
|
||||
fs::create_dir(SOCKET_DIR)?;
|
||||
}
|
||||
// remove socket file if any present
|
||||
let _ = fs::remove_file(SOCKET_PATH);
|
||||
|
||||
// bind datagram unix socket
|
||||
let socket = UnixDatagram::bind(SOCKET_PATH)?;
|
||||
socket.set_read_timeout(Some(Duration::from_secs(read_timeout_sec)))?;
|
||||
Ok(socket)
|
||||
}
|
||||
|
||||
// for daemon side
|
||||
pub fn socket_send(
|
||||
socket: &UnixDatagram,
|
||||
client_addr: &SocketAddr,
|
||||
resp: BzzResp,
|
||||
) -> Result<(), IntercomError> {
|
||||
let resp_buff = postcard::to_stdvec(&resp)?;
|
||||
socket.send_to_addr(resp_buff.as_slice(), client_addr)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// for daemon side
|
||||
pub fn socket_recv(
|
||||
socket: &UnixDatagram,
|
||||
recv_buf: &mut [u8],
|
||||
) -> Result<(BzzReq, SocketAddr), IntercomError> {
|
||||
match socket.recv_from(recv_buf) {
|
||||
Ok((rec_count, client_addr)) => {
|
||||
if rec_count != 0 {
|
||||
println!("DEBUG: Total bytes recieved {}", rec_count);
|
||||
let decoded_req: BzzReq = postcard::from_bytes(&recv_buf)?;
|
||||
Ok((decoded_req, client_addr))
|
||||
} else {
|
||||
Err(IntercomError::ConnectionClosed)
|
||||
}
|
||||
}
|
||||
Err(ex) => Err(ex.into()),
|
||||
}
|
||||
}
|
||||
|
||||
fn send_and_recv(request: BzzReq) -> Result<BzzResp, IntercomError> {
|
||||
let socket = UnixDatagram::unbound()?;
|
||||
socket.connect(SOCKET_PATH)?;
|
||||
socket.set_read_timeout(Some(Duration::from_secs(CLINET_READ_TIMEOUT_SECONDS)))?;
|
||||
|
||||
let encoded_buf = postcard::to_stdvec(&request)?;
|
||||
|
||||
socket.send(encoded_buf.as_slice())?;
|
||||
|
||||
let mut recv_buf: Vec<u8> = Vec::with_capacity(1024);
|
||||
|
||||
loop {
|
||||
match socket.recv(recv_buf.as_mut_slice()) {
|
||||
Ok(rec_count) => {
|
||||
if rec_count != 0 {
|
||||
println!("DEBUG: Total bytes recieved {}", rec_count);
|
||||
let decoded_resp: BzzResp = postcard::from_bytes(&recv_buf)?;
|
||||
if let BzzResp::Working(progress) = decoded_resp {
|
||||
println!("Working... {}", progress);
|
||||
continue;
|
||||
} else {
|
||||
return Ok(decoded_resp);
|
||||
}
|
||||
} else {
|
||||
return Err(IntercomError::ConnectionClosed);
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(e.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn client_updates_available() -> Result<u32, IntercomError> {
|
||||
let resp = send_and_recv(BzzReq::UpdatesAvailable)?;
|
||||
match resp {
|
||||
BzzResp::UpdatesAvailable(updates_count) => Ok(updates_count),
|
||||
BzzResp::Error(ex) => Err(IntercomError::ServerError(ex)),
|
||||
_ => Err(IntercomError::UnexpectedResponse),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn client_check_for_updates() -> Result<u32, IntercomError> {
|
||||
let resp = send_and_recv(BzzReq::CheckForUpdates)?;
|
||||
match resp {
|
||||
BzzResp::UpdatesAvailable(updates_count) => Ok(updates_count),
|
||||
BzzResp::Error(ex) => Err(IntercomError::ServerError(ex)),
|
||||
_ => Err(IntercomError::UnexpectedResponse),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn client_schedule_update() -> Result<(), IntercomError> {
|
||||
let resp = send_and_recv(BzzReq::ScheduleUpdate)?;
|
||||
match resp {
|
||||
BzzResp::Finish => Ok(()),
|
||||
BzzResp::Error(ex) => Err(IntercomError::ServerError(ex)),
|
||||
_ => Err(IntercomError::UnexpectedResponse),
|
||||
}
|
||||
}
|
||||
+94
-62
@@ -25,14 +25,17 @@ use time_format;
|
||||
|
||||
const SNAPS_DIR: &str = "/bzz-snaps";
|
||||
const EFI_BOOT_MOUNT_POINT: &str = "/beefi";
|
||||
const UKI_IMAGE_NAME: &str = "/beefi/EFI/linux-kira-lts.efi";
|
||||
const UKI_IMAGE_BACK_NAME: &str = "/beefi/EFI/linux-kira-lts-back.efi";
|
||||
const EFI_BOOT_DIR: &str = "/beefi/EFI/boot";
|
||||
const UKI_IMAGE_NAME: &str = "/beefi/EFI/boot/linux-kira-lts.efi";
|
||||
const UKI_IMAGE_BACK_NAME: &str = "/beefi/EFI/boot/linux-kira-lts-back.efi";
|
||||
const EFI_PARTLABEL: &str = "bee-efi";
|
||||
|
||||
const BOOT_MENU_LABEL: &str = "Kira OS";
|
||||
const BOOT_MENU_LABEL_BACK: &str = "Kira OS Fallback";
|
||||
const BOOT_UKI_IMAGE_NAME: &str = "\\EFI\\linux-kira-lts.efi";
|
||||
const BOOT_UKI_IMAGE_NAME_BACK: &str = "\\EFI\\linux-kira-lts-back.efi";
|
||||
const BOOT_UKI_IMAGE_NAME: &str = "\\EFI\\boot\\linux-kira-lts.efi";
|
||||
const BOOT_UKI_IMAGE_NAME_BACK: &str = "\\EFI\\boot\\linux-kira-lts-back.efi";
|
||||
|
||||
const PAC_LOCK_FILE: &str = "/var/lib/hive-up/pac-lock";
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CommandFailed {
|
||||
@@ -143,47 +146,46 @@ pub fn exec_command_out(cmd: &str, args: &Vec<&str>) -> Result<String, ExecComma
|
||||
/// pacman -Sy
|
||||
/// pacman -Qu
|
||||
/// returns number of updatable packages, returns 0 if there is no updates awailable
|
||||
pub fn check_updates() -> Result<u32, ExecCommandError> {
|
||||
// Synchronize pacman DB
|
||||
exec_command("pacman", &vec!["-Sy"])?;
|
||||
// Check for updates
|
||||
let out = Command::new("pacman").arg("-Qu").output()?;
|
||||
if out.status.success() {
|
||||
Ok(String::from_utf8(out.stdout)?
|
||||
.lines()
|
||||
.count()
|
||||
.try_into()
|
||||
.unwrap())
|
||||
} else {
|
||||
if let Some(code) = out.status.code()
|
||||
&& code == 1
|
||||
{
|
||||
Ok(0)
|
||||
} else {
|
||||
Err(ExecCommandError::Other(format!(
|
||||
"pacman -Qu failed: {}",
|
||||
String::from_utf8(out.stderr)?
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
// pub fn check_updates() -> Result<u32, ExecCommandError> {
|
||||
// // Synchronize pacman DB
|
||||
// exec_command("pacman", &vec!["-Sy"])?;
|
||||
// // Check for updates
|
||||
// let out = Command::new("pacman").arg("-Qu").output()?;
|
||||
// if out.status.success() {
|
||||
// Ok(String::from_utf8(out.stdout)?
|
||||
// .lines()
|
||||
// .count()
|
||||
// .try_into()
|
||||
// .unwrap())
|
||||
// } else {
|
||||
// if let Some(code) = out.status.code()
|
||||
// && code == 1
|
||||
// {
|
||||
// Ok(0)
|
||||
// } else {
|
||||
// Err(ExecCommandError::Other(format!(
|
||||
// "pacman -Qu failed: {}",
|
||||
// String::from_utf8(out.stderr)?
|
||||
// )))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
///
|
||||
/// sudo pacman -Suw --noconfirm --noprogressbar
|
||||
/// Download updates (need to check for updates first)
|
||||
///
|
||||
pub fn download_updates() -> Result<(), ExecCommandError> {
|
||||
exec_command("pacman", &vec!["-Suw", "--noconfirm", "--noprogressbar"])
|
||||
}
|
||||
// pub fn download_updates() -> Result<(), ExecCommandError> {
|
||||
// exec_command("pacman", &vec!["-Suw", "--noconfirm", "--noprogressbar"])
|
||||
// }
|
||||
|
||||
///
|
||||
/// sudo pacman -Su --noconfirm --noprogressbar
|
||||
/// Perform updates
|
||||
///
|
||||
pub fn pkg_upgrade() -> Result<(), ExecCommandError> {
|
||||
exec_command("pacman", &vec!["-Su", "--noconfirm", "--noprogressbar"])
|
||||
}
|
||||
|
||||
// pub fn pkg_upgrade() -> Result<(), ExecCommandError> {
|
||||
// exec_command("pacman", &vec!["-Su", "--noconfirm", "--noprogressbar"])
|
||||
// }
|
||||
|
||||
///
|
||||
/// creates read only snapshoy of "subvolume" and places it into "target"]
|
||||
@@ -192,7 +194,6 @@ pub fn pkg_upgrade() -> Result<(), ExecCommandError> {
|
||||
/// returns snapshot time on sucess
|
||||
///
|
||||
pub fn snapshot(subvolume: &str, target: &str) -> Result<(), ExecCommandError> {
|
||||
|
||||
exec_command(
|
||||
"bcachefs",
|
||||
&vec!["subvolume", "snapshot", "-r", subvolume, target],
|
||||
@@ -227,6 +228,36 @@ pub fn snapshot_system() -> Result<String, ExecCommandError> {
|
||||
Ok(local_time)
|
||||
}
|
||||
|
||||
/// Function for pacman preTransaction hook
|
||||
///
|
||||
pub fn pac_start() -> Result<(), ExecCommandError> {
|
||||
use std::path::Path;
|
||||
// Check if lock file exist
|
||||
let pack_lock_path = Path::new(PAC_LOCK_FILE);
|
||||
if pack_lock_path.exists() {
|
||||
println!("Warning! Pac Lock file exist, skipping system snapshot...");
|
||||
return Ok(());
|
||||
}
|
||||
println!("Creating system snapshot...");
|
||||
let snap_time = snapshot_system()?;
|
||||
println!("Ok.");
|
||||
fs::write(PAC_LOCK_FILE, snap_time)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn pac_finish() -> Result<(), ExecCommandError> {
|
||||
use std::path::Path;
|
||||
// Check if lock file exist
|
||||
let pack_lock_path = Path::new(PAC_LOCK_FILE);
|
||||
if pack_lock_path.exists() {
|
||||
println!("Remowing pac-lock...");
|
||||
fs::remove_file(pack_lock_path)?;
|
||||
} else {
|
||||
println!("Warning! Pac Lock file does not exist - something is wrong...");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
//const TMP_ROOT: &str = "/mnt/bee-root";
|
||||
// pub fn list_bzzpss_snaps() -> Result<Vec<String>, ExecCommandError> {
|
||||
// use regex::Regex;
|
||||
@@ -264,38 +295,38 @@ pub fn check_if_run_as_root() -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SysUpgradeError {
|
||||
SnapshotError(ExecCommandError),
|
||||
PkgUpgradeErr((String, ExecCommandError)),
|
||||
}
|
||||
// #[derive(Debug)]
|
||||
// pub enum SysUpgradeError {
|
||||
// SnapshotError(ExecCommandError),
|
||||
// PkgUpgradeErr((String, ExecCommandError)),
|
||||
// }
|
||||
|
||||
impl std::fmt::Display for SysUpgradeError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
SysUpgradeError::SnapshotError(e) => write!(f, "Snapshot creation error: {}", e),
|
||||
SysUpgradeError::PkgUpgradeErr((_, e)) => write!(f, "Packages upgrade error: {}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
// impl std::fmt::Display for SysUpgradeError {
|
||||
// fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
// match self {
|
||||
// SysUpgradeError::SnapshotError(e) => write!(f, "Snapshot creation error: {}", e),
|
||||
// SysUpgradeError::PkgUpgradeErr((_, e)) => write!(f, "Packages upgrade error: {}", e),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// Implement std::error::Error
|
||||
impl std::error::Error for SysUpgradeError {}
|
||||
// // Implement std::error::Error
|
||||
// impl std::error::Error for SysUpgradeError {}
|
||||
|
||||
///
|
||||
/// Perform system upgrade
|
||||
/// Reruns root snapshot name on success
|
||||
/// In case of upgrade error SysUpgradeError::PkgUpgradeErr contains snapshot time is str format
|
||||
///
|
||||
pub fn sys_upgrade() -> Result<String, SysUpgradeError> {
|
||||
// snapshooting root
|
||||
let snap_time = snapshot_system().map_err(SysUpgradeError::SnapshotError)?;
|
||||
// try to perform packages upgrade
|
||||
match pkg_upgrade() {
|
||||
Ok(_) => Ok(snap_time),
|
||||
Err(ex) => Err(SysUpgradeError::PkgUpgradeErr((snap_time, ex))),
|
||||
}
|
||||
}
|
||||
// pub fn sys_upgrade() -> Result<String, SysUpgradeError> {
|
||||
// // snapshooting root
|
||||
// let snap_time = snapshot_system().map_err(SysUpgradeError::SnapshotError)?;
|
||||
// // try to perform packages upgrade
|
||||
// match pkg_upgrade() {
|
||||
// Ok(_) => Ok(snap_time),
|
||||
// Err(ex) => Err(SysUpgradeError::PkgUpgradeErr((snap_time, ex))),
|
||||
// }
|
||||
// }
|
||||
|
||||
/// Gets device node aka /dev/sda1 from gpr partition label
|
||||
/// blkid -s PARTLABEL --match-token PARTLABEL="bzz-primary"
|
||||
@@ -492,8 +523,9 @@ pub fn init_efi_boot_partition_content() -> Result<(), ExecCommandError> {
|
||||
let efi_dir = format!("{}/EFI", EFI_BOOT_MOUNT_POINT);
|
||||
println!("Romoving efi dir {}", efi_dir);
|
||||
fs::remove_dir_all(&efi_dir)?;
|
||||
println!("Creating efi dir {}", efi_dir);
|
||||
fs::create_dir(efi_dir)?;
|
||||
|
||||
println!("Creating efi dir {}", EFI_BOOT_DIR);
|
||||
fs::create_dir_all(EFI_BOOT_DIR)?;
|
||||
println!("Copy {} to {}", kernel_img_path, UKI_IMAGE_NAME);
|
||||
fs::copy(&kernel_img_path, UKI_IMAGE_NAME)?;
|
||||
println!("Copy {} to {}", kernel_img_path, UKI_IMAGE_BACK_NAME);
|
||||
|
||||
+48
-118
@@ -14,31 +14,20 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use clap::{Args, Parser, Subcommand};
|
||||
use clap::{Parser, Subcommand};
|
||||
use signal_hook;
|
||||
use std;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
|
||||
mod hive_system;
|
||||
|
||||
mod hive_config;
|
||||
|
||||
use crate::hive_config::HiveConfig;
|
||||
use crate::hive_system::SysUpgradeError;
|
||||
|
||||
mod daemon;
|
||||
mod hive_db;
|
||||
mod hive_intercom;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum HiveUpError {
|
||||
IoError(std::io::Error),
|
||||
HiveSystemCommandError(hive_system::ExecCommandError),
|
||||
HiveDbError(hive_db::DBError),
|
||||
HiveConfigError(hive_config::ConfigError),
|
||||
HiveIntercomError(hive_intercom::IntercomError),
|
||||
HiveDaemonErr(daemon::DaemonError),
|
||||
Other(String),
|
||||
}
|
||||
|
||||
@@ -54,30 +43,12 @@ impl From<hive_system::ExecCommandError> for HiveUpError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<hive_db::DBError> for HiveUpError {
|
||||
fn from(err: hive_db::DBError) -> Self {
|
||||
HiveUpError::HiveDbError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<hive_config::ConfigError> for HiveUpError {
|
||||
fn from(err: hive_config::ConfigError) -> Self {
|
||||
HiveUpError::HiveConfigError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<hive_intercom::IntercomError> for HiveUpError {
|
||||
fn from(err: hive_intercom::IntercomError) -> Self {
|
||||
HiveUpError::HiveIntercomError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<daemon::DaemonError> for HiveUpError {
|
||||
fn from(err: daemon::DaemonError) -> Self {
|
||||
HiveUpError::HiveDaemonErr(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for HiveUpError {
|
||||
fn from(err: String) -> Self {
|
||||
HiveUpError::Other(err)
|
||||
@@ -95,10 +66,7 @@ impl std::fmt::Display for HiveUpError {
|
||||
match self {
|
||||
HiveUpError::IoError(e) => write!(f, "IO Error: {}", e),
|
||||
HiveUpError::HiveSystemCommandError(e) => write!(f, "ExecCommandError: {}", e),
|
||||
HiveUpError::HiveDbError(ex) => write!(f, "DBError: {}", ex),
|
||||
HiveUpError::HiveConfigError(ex) => write!(f, "Config error: {}", ex),
|
||||
HiveUpError::HiveIntercomError(e) => write!(f, "IntercomError: {}", e),
|
||||
HiveUpError::HiveDaemonErr(e) => write!(f, "HiveDaemonErr: {}", e),
|
||||
HiveUpError::Other(msg) => write!(f, "Error: {}", msg),
|
||||
}
|
||||
}
|
||||
@@ -107,49 +75,42 @@ impl std::fmt::Display for HiveUpError {
|
||||
// Implement std::error::Error
|
||||
impl std::error::Error for HiveUpError {}
|
||||
|
||||
// Define the mutually exclusive group
|
||||
#[derive(Args, Debug)]
|
||||
#[group(required = true, multiple = false)]
|
||||
struct RemoteArgs {
|
||||
/// Ask daemon to check for updates
|
||||
#[arg(long)]
|
||||
check_updates: bool,
|
||||
|
||||
/// Ask daemon if there is any updates available
|
||||
#[arg(long)]
|
||||
updates_avail: bool,
|
||||
|
||||
/// Ask daemon to perform system update on next reboot
|
||||
#[arg(long)]
|
||||
schedule_update: bool,
|
||||
#[derive(Subcommand, Debug)]
|
||||
#[group(required = true)]
|
||||
enum BootCommand {
|
||||
/// Install new kernel into boot partition
|
||||
Update,
|
||||
/// Cleans up and recreates UFI boot menu
|
||||
EfiMenuInit,
|
||||
/// Cleans up and recreates UFI boot menu and /EFI dir content
|
||||
Init,
|
||||
}
|
||||
|
||||
#[derive(Args, Debug)]
|
||||
#[group(required = true, multiple = false)]
|
||||
struct CliArgs {
|
||||
/// Perform system upgrade
|
||||
#[arg(long)]
|
||||
upgrade: bool,
|
||||
/// Install new kernel into boot partition
|
||||
#[arg(long)]
|
||||
update_boot: bool,
|
||||
/// Cleans up and recreates UFI boot menu
|
||||
#[arg(long)]
|
||||
init_boot_menu: bool,
|
||||
/// Cleans up and recreates UFI boot menu and /EFI dir content
|
||||
#[arg(long)]
|
||||
init_boot: bool,
|
||||
#[derive(Subcommand, Debug)]
|
||||
#[group(required = true)]
|
||||
enum Pac {
|
||||
/// Creates snapshoots of /usr and /var subvolumea
|
||||
SnapshotSystem,
|
||||
/// This supposed to be called by pacman hook before transaction
|
||||
/// hive-up will check for /var/lib/hive-up/pac-lock and will not create snapshots in case it present
|
||||
/// Its safe lock mesure to prevent multiple snapshots on system fixing or some corner cases
|
||||
/// Lock file can be deleted by `pac finish` that should be called by pacman after transaction
|
||||
Start,
|
||||
/// This supposed to be called by pacman hook before transaction.
|
||||
/// Right now only thing it does is removes /var/lib/hive-up/pac-lock file
|
||||
Finis,
|
||||
}
|
||||
|
||||
#[derive(Subcommand, Debug)]
|
||||
#[group(required = true)] // 'multiple = false' enforces exclusivity
|
||||
enum HiveUpMode {
|
||||
/// Perform local operations
|
||||
Cli(CliArgs),
|
||||
/// Ask hive-up daemon something
|
||||
Remote(RemoteArgs),
|
||||
/// Run hive-up in daemon mode
|
||||
Daemon,
|
||||
/// Manage system boot
|
||||
#[command(subcommand)]
|
||||
Boot(BootCommand),
|
||||
|
||||
/// Intended to be used by pacman hooks
|
||||
#[command(subcommand)]
|
||||
Pac(Pac),
|
||||
}
|
||||
|
||||
/// Update program fot Kira Linux :3
|
||||
@@ -161,40 +122,14 @@ struct Cli {
|
||||
mode: HiveUpMode,
|
||||
}
|
||||
|
||||
fn cli_upgrade(bzz_config: HiveConfig) -> Result<(), HiveUpError> {
|
||||
let mut bzz_db = hive_db::read_db()?;
|
||||
|
||||
if (bzz_db.updates_available !=0) && (bzz_db.update_on_reboot || bzz_config.update.auto_update) {
|
||||
println!("Starting full system upgrade");
|
||||
bzz_db.update_status = false;
|
||||
hive_db::write_db(&bzz_db)?;
|
||||
match hive_system::sys_upgrade() {
|
||||
Ok(snap_time) => {
|
||||
bzz_db.update_status = true;
|
||||
bzz_db.update_on_reboot = false;
|
||||
bzz_db.last_snapshot_time = snap_time;
|
||||
hive_db::write_db(&bzz_db)?;
|
||||
}
|
||||
Err(SysUpgradeError::PkgUpgradeErr((snap_time, ex))) => {
|
||||
bzz_db.update_status = false;
|
||||
bzz_db.update_on_reboot = false;
|
||||
bzz_db.last_snapshot_time = snap_time;
|
||||
hive_db::write_db(&bzz_db)?;
|
||||
return Err(ex.into());
|
||||
}
|
||||
Err(ex) => return Err(ex.to_string().into()),
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() -> Result<(), HiveUpError> {
|
||||
// registering signals handling
|
||||
// we really do not want for this program to get terminated in a middle of something,
|
||||
// so doing nothing with signals.
|
||||
// second sigtrm should kill it tho
|
||||
let term_flag: Arc<AtomicBool> = Arc::new(AtomicBool::new(false));
|
||||
let reload_flag = Arc::new(AtomicBool::new(false));
|
||||
signal_hook::flag::register(signal_hook::consts::SIGTERM, Arc::clone(&term_flag)).unwrap();
|
||||
signal_hook::flag::register(signal_hook::consts::SIGINT, Arc::clone(&term_flag)).unwrap();
|
||||
signal_hook::flag::register(signal_hook::consts::SIGHUP, Arc::clone(&reload_flag)).unwrap();
|
||||
|
||||
let args = Cli::parse();
|
||||
|
||||
@@ -206,18 +141,17 @@ fn main() -> Result<(), HiveUpError> {
|
||||
let bzz_config = hive_config::read_config()?;
|
||||
|
||||
match args.mode {
|
||||
HiveUpMode::Daemon => daemon::run(bzz_config, term_flag.clone(), reload_flag.clone())?,
|
||||
HiveUpMode::Cli(cli_args) => {
|
||||
if cli_args.upgrade {
|
||||
cli_upgrade(bzz_config)?;
|
||||
} else if cli_args.update_boot {
|
||||
HiveUpMode::Boot(boot_submode) => match boot_submode {
|
||||
BootCommand::Update => {
|
||||
println!("Updating boot...");
|
||||
hive_system::boot_update()?;
|
||||
} else if cli_args.init_boot_menu {
|
||||
}
|
||||
BootCommand::EfiMenuInit => {
|
||||
println!("Init EFI boot menu...");
|
||||
let kernel_cmd = bzz_config.kernel.and_then(|kk| kk.cmd.clone());
|
||||
hive_system::init_efi_boot_record(&kernel_cmd)?;
|
||||
} else if cli_args.init_boot {
|
||||
}
|
||||
BootCommand::Init => {
|
||||
println!("Init EFI boot menu and EFI partition content...");
|
||||
println!("Init EFI Partition content...");
|
||||
let kernel_cmd = bzz_config.kernel.and_then(|kk| kk.cmd.clone());
|
||||
@@ -225,19 +159,15 @@ fn main() -> Result<(), HiveUpError> {
|
||||
println!("Init EFI boot menu...");
|
||||
hive_system::init_efi_boot_partition_content()?;
|
||||
}
|
||||
}
|
||||
HiveUpMode::Remote(remote_args) => {
|
||||
if remote_args.check_updates {
|
||||
let up_num = hive_intercom::client_check_for_updates()?;
|
||||
println!("Updates awailable: {}", up_num);
|
||||
} else if remote_args.updates_avail {
|
||||
let up_num = hive_intercom::client_updates_available()?;
|
||||
println!("Updates awailable: {}", up_num);
|
||||
} else if remote_args.schedule_update {
|
||||
println!("Scheduling system update...");
|
||||
hive_intercom::client_schedule_update()?;
|
||||
print!("Done!")
|
||||
}
|
||||
},
|
||||
HiveUpMode::Pac(pac_mode) => match pac_mode {
|
||||
Pac::SnapshotSystem => {
|
||||
println!("Creating system snapshot...");
|
||||
let _ = hive_system::snapshot_system()?;
|
||||
println!("Ok.");
|
||||
},
|
||||
Pac::Start => hive_system::pac_start()?,
|
||||
Pac::Finis => hive_system::pac_finish()?
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user