mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 04:01:58 +00:00
address bugs
This commit is contained in:
committed by
Aiden McClelland
parent
c278e7fbc2
commit
cdca5e1b67
@@ -8,9 +8,9 @@ if [ "$0" != "./build-prod.sh" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
alias 'rust-arm-builder'='docker run --rm -it -v "$HOME/.cargo/registry":/root/.cargo/registry -v "$(pwd)":/home/rust/src start9/rust-arm-cross:latest'
|
alias 'rust-arm64-builder'='docker run --rm -it -v "$HOME/.cargo/registry":/root/.cargo/registry -v "$(pwd)":/home/rust/src start9/rust-arm-cross:aarch64'
|
||||||
|
|
||||||
cd ..
|
cd ../..
|
||||||
rust-arm-builder sh -c "(cd appmgr && cargo build --release --features=production)"
|
rust-arm64-builder sh -c "(cd embassy-os/appmgr && cargo +beta build --release --features=production)"
|
||||||
cd appmgr
|
cd embassy-os/appmgr
|
||||||
rust-arm-builder arm-linux-gnueabi-strip target/armv7-unknown-linux-gnueabihf/release/appmgr
|
#rust-arm64-builder aarch64-linux-gnu-strip target/aarch64-unknown-linux-gnu/release/embassyd
|
||||||
|
|||||||
@@ -1,8 +1,18 @@
|
|||||||
use embassy::Error;
|
use embassy::Error;
|
||||||
|
|
||||||
async fn inner_main() -> Result<(), Error> {
|
async fn inner_main() -> Result<(), Error> {
|
||||||
// os sync
|
// host setup flow if needed
|
||||||
embassy::volume::disk::mount("/dev/sda", "/mnt/embassy-os-crypt").await?;
|
|
||||||
|
// mount disk
|
||||||
|
embassy::volume::disk::mount("/dev/sda", "/mnt/embassy-os-crypt").await?; // TODO: by uuid
|
||||||
|
|
||||||
|
// unlock disk
|
||||||
|
|
||||||
|
// mount /var/log/journal
|
||||||
|
|
||||||
|
// sync ssh
|
||||||
|
|
||||||
|
// sync wifi
|
||||||
|
|
||||||
// hostname-set
|
// hostname-set
|
||||||
embassy::hostname::sync_hostname().await?;
|
embassy::hostname::sync_hostname().await?;
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ impl RpcContext {
|
|||||||
revision_cache: RwLock::new(VecDeque::new()),
|
revision_cache: RwLock::new(VecDeque::new()),
|
||||||
metrics_cache: RwLock::new(None),
|
metrics_cache: RwLock::new(None),
|
||||||
});
|
});
|
||||||
|
// TODO: handle apps in bad / transient state
|
||||||
Ok(Self(seed))
|
Ok(Self(seed))
|
||||||
}
|
}
|
||||||
pub async fn package_registry_url(&self) -> Result<Url, Error> {
|
pub async fn package_registry_url(&self) -> Result<Url, Error> {
|
||||||
|
|||||||
@@ -1,23 +1,29 @@
|
|||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
use patch_db::DbHandle;
|
||||||
use rpc_toolkit::command;
|
use rpc_toolkit::command;
|
||||||
|
|
||||||
use crate::context::EitherContext;
|
use crate::context::EitherContext;
|
||||||
|
use crate::db::util::WithRevision;
|
||||||
use crate::s9pk::manifest::PackageId;
|
use crate::s9pk::manifest::PackageId;
|
||||||
use crate::status::MainStatus;
|
use crate::status::MainStatus;
|
||||||
use crate::util::display_none;
|
use crate::util::display_none;
|
||||||
use crate::{Error, ResultExt};
|
use crate::{Error, ResultExt};
|
||||||
|
|
||||||
#[command(display(display_none))]
|
#[command(display(display_none))]
|
||||||
pub async fn start(#[context] ctx: EitherContext, #[arg] id: PackageId) -> Result<(), Error> {
|
pub async fn start(
|
||||||
|
#[context] ctx: EitherContext,
|
||||||
|
#[arg] id: PackageId,
|
||||||
|
) -> Result<WithRevision<()>, Error> {
|
||||||
let rpc_ctx = ctx.as_rpc().unwrap();
|
let rpc_ctx = ctx.as_rpc().unwrap();
|
||||||
let mut db = rpc_ctx.db.handle();
|
let mut db = rpc_ctx.db.handle();
|
||||||
|
let mut tx = db.begin().await?;
|
||||||
let installed = crate::db::DatabaseModel::new()
|
let installed = crate::db::DatabaseModel::new()
|
||||||
.package_data()
|
.package_data()
|
||||||
.idx_model(&id)
|
.idx_model(&id)
|
||||||
.and_then(|pkg| pkg.installed())
|
.and_then(|pkg| pkg.installed())
|
||||||
.expect(&mut db)
|
.expect(&mut tx)
|
||||||
.await
|
.await
|
||||||
.with_ctx(|_| {
|
.with_ctx(|_| {
|
||||||
(
|
(
|
||||||
@@ -29,10 +35,10 @@ pub async fn start(#[context] ctx: EitherContext, #[arg] id: PackageId) -> Resul
|
|||||||
.clone()
|
.clone()
|
||||||
.manifest()
|
.manifest()
|
||||||
.version()
|
.version()
|
||||||
.get(&mut db, true)
|
.get(&mut tx, true)
|
||||||
.await?
|
.await?
|
||||||
.to_owned();
|
.to_owned();
|
||||||
let mut status = installed.status().main().get_mut(&mut db).await?;
|
let mut status = installed.status().main().get_mut(&mut tx).await?;
|
||||||
|
|
||||||
*status = MainStatus::Running {
|
*status = MainStatus::Running {
|
||||||
started: Utc::now(),
|
started: Utc::now(),
|
||||||
@@ -45,20 +51,28 @@ pub async fn start(#[context] ctx: EitherContext, #[arg] id: PackageId) -> Resul
|
|||||||
})?,
|
})?,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
status.save(&mut db).await?;
|
status.save(&mut tx).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(WithRevision {
|
||||||
|
revision: tx.commit(None).await?,
|
||||||
|
response: (),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[command(display(display_none))]
|
#[command(display(display_none))]
|
||||||
pub async fn stop(#[context] ctx: EitherContext, #[arg] id: PackageId) -> Result<(), Error> {
|
pub async fn stop(
|
||||||
|
#[context] ctx: EitherContext,
|
||||||
|
#[arg] id: PackageId,
|
||||||
|
) -> Result<WithRevision<()>, Error> {
|
||||||
let rpc_ctx = ctx.as_rpc().unwrap();
|
let rpc_ctx = ctx.as_rpc().unwrap();
|
||||||
let mut db = rpc_ctx.db.handle();
|
let mut db = rpc_ctx.db.handle();
|
||||||
|
let mut tx = db.begin().await?;
|
||||||
|
|
||||||
let mut status = crate::db::DatabaseModel::new()
|
let mut status = crate::db::DatabaseModel::new()
|
||||||
.package_data()
|
.package_data()
|
||||||
.idx_model(&id)
|
.idx_model(&id)
|
||||||
.and_then(|pkg| pkg.installed())
|
.and_then(|pkg| pkg.installed())
|
||||||
.expect(&mut db)
|
.expect(&mut tx)
|
||||||
.await
|
.await
|
||||||
.with_ctx(|_| {
|
.with_ctx(|_| {
|
||||||
(
|
(
|
||||||
@@ -68,11 +82,14 @@ pub async fn stop(#[context] ctx: EitherContext, #[arg] id: PackageId) -> Result
|
|||||||
})?
|
})?
|
||||||
.status()
|
.status()
|
||||||
.main()
|
.main()
|
||||||
.get_mut(&mut db)
|
.get_mut(&mut tx)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
*status = MainStatus::Stopping;
|
*status = MainStatus::Stopping;
|
||||||
status.save(&mut db).await?;
|
status.save(&mut tx).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(WithRevision {
|
||||||
|
revision: tx.commit(None).await?,
|
||||||
|
response: (),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,19 @@
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
|
use bollard::image::ListImagesOptions;
|
||||||
use bollard::Docker;
|
use bollard::Docker;
|
||||||
use patch_db::DbHandle;
|
use patch_db::{DbHandle, PatchDbHandle};
|
||||||
|
use tokio::process::Command;
|
||||||
|
|
||||||
use super::PKG_PUBLIC_DIR;
|
use super::PKG_PUBLIC_DIR;
|
||||||
use crate::context::RpcContext;
|
use crate::context::RpcContext;
|
||||||
use crate::db::model::{InstalledPackageDataEntry, PackageDataEntry};
|
use crate::db::model::{InstalledPackageDataEntry, PackageDataEntry};
|
||||||
use crate::dependencies::DependencyError;
|
use crate::dependencies::DependencyError;
|
||||||
use crate::s9pk::manifest::{Manifest, PackageId};
|
use crate::s9pk::manifest::{Manifest, PackageId};
|
||||||
use crate::util::Version;
|
use crate::util::{Invoke, Version};
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
pub async fn update_dependents<'a, Db: DbHandle, I: IntoIterator<Item = &'a PackageId>>(
|
pub async fn update_dependents<'a, Db: DbHandle, I: IntoIterator<Item = &'a PackageId>>(
|
||||||
@@ -62,7 +65,35 @@ pub async fn update_dependents<'a, Db: DbHandle, I: IntoIterator<Item = &'a Pack
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn cleanup<Db: DbHandle>(
|
pub async fn cleanup(ctx: &RpcContext, id: &PackageId, version: &Version) -> Result<(), Error> {
|
||||||
|
ctx.managers.remove(&(id.clone(), version.clone())).await;
|
||||||
|
// docker images start9/$APP_ID/*:$VERSION -q | xargs docker rmi
|
||||||
|
let images = ctx
|
||||||
|
.docker
|
||||||
|
.list_images(Some(ListImagesOptions {
|
||||||
|
all: false,
|
||||||
|
filters: {
|
||||||
|
let mut f = HashMap::new();
|
||||||
|
f.insert(
|
||||||
|
"reference".to_owned(),
|
||||||
|
vec![format!("start9/{}/*:{}", id, version)],
|
||||||
|
);
|
||||||
|
f
|
||||||
|
},
|
||||||
|
digests: false,
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
futures::future::try_join_all(images.into_iter().map(|image| async {
|
||||||
|
let image = image; // move into future
|
||||||
|
ctx.docker.remove_image(&image.id, None, None).await
|
||||||
|
}))
|
||||||
|
.await?;
|
||||||
|
// TODO: delete public dir if not a dependency
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn cleanup_failed<Db: DbHandle>(
|
||||||
ctx: &RpcContext,
|
ctx: &RpcContext,
|
||||||
db: &mut Db,
|
db: &mut Db,
|
||||||
id: &PackageId,
|
id: &PackageId,
|
||||||
@@ -76,25 +107,21 @@ pub async fn cleanup<Db: DbHandle>(
|
|||||||
.get(db, true)
|
.get(db, true)
|
||||||
.await?
|
.await?
|
||||||
.to_owned();
|
.to_owned();
|
||||||
if let Some(manifest) = match &pde {
|
if match &pde {
|
||||||
PackageDataEntry::Installing { manifest, .. } => Some(manifest),
|
PackageDataEntry::Installing { .. } => true,
|
||||||
PackageDataEntry::Updating { manifest, .. } => {
|
PackageDataEntry::Updating { manifest, .. } => {
|
||||||
if &manifest.version != version {
|
if &manifest.version != version {
|
||||||
Some(manifest)
|
true
|
||||||
} else {
|
} else {
|
||||||
None
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
log::warn!("{}: Nothing to clean up!", id);
|
log::warn!("{}: Nothing to clean up!", id);
|
||||||
None
|
false
|
||||||
}
|
}
|
||||||
} {
|
} {
|
||||||
ctx.managers
|
cleanup(ctx, id, version).await?;
|
||||||
.remove(&(manifest.id.clone(), manifest.version.clone()))
|
|
||||||
.await;
|
|
||||||
// docker images start9/$APP_ID/*:$VERSION -q | xargs docker rmi
|
|
||||||
let public_dir_path = Path::new(PKG_PUBLIC_DIR).join(id).join(version.as_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match pde {
|
match pde {
|
||||||
@@ -126,14 +153,39 @@ pub async fn cleanup<Db: DbHandle>(
|
|||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(()) // TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn uninstall<Db: DbHandle>(
|
|
||||||
ctx: &RpcContext,
|
|
||||||
db: &mut Db,
|
|
||||||
entry: InstalledPackageDataEntry,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
//TODO
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn uninstall(
|
||||||
|
ctx: &RpcContext,
|
||||||
|
db: &mut PatchDbHandle,
|
||||||
|
entry: &InstalledPackageDataEntry,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
cleanup(ctx, &entry.manifest.id, &entry.manifest.version).await?;
|
||||||
|
let mut tx = db.begin().await?;
|
||||||
|
crate::db::DatabaseModel::new()
|
||||||
|
.package_data()
|
||||||
|
.remove(&mut tx, &entry.manifest.id)
|
||||||
|
.await?;
|
||||||
|
update_dependents(&mut tx, &entry.manifest.id, entry.current_dependents.keys()).await?;
|
||||||
|
tx.commit(None).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test() {
|
||||||
|
dbg!(
|
||||||
|
Docker::connect_with_socket_defaults()
|
||||||
|
.unwrap()
|
||||||
|
.list_images(Some(ListImagesOptions {
|
||||||
|
all: false,
|
||||||
|
filters: {
|
||||||
|
let mut f = HashMap::new();
|
||||||
|
f.insert("reference", vec!["start9/*:latest"]);
|
||||||
|
f
|
||||||
|
},
|
||||||
|
digests: false
|
||||||
|
}))
|
||||||
|
.await
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,15 +26,16 @@ use sha2::{Digest, Sha256};
|
|||||||
use tokio::fs::{File, OpenOptions};
|
use tokio::fs::{File, OpenOptions};
|
||||||
use tokio::io::{AsyncRead, AsyncSeek, AsyncSeekExt, AsyncWrite, AsyncWriteExt};
|
use tokio::io::{AsyncRead, AsyncSeek, AsyncSeekExt, AsyncWrite, AsyncWriteExt};
|
||||||
|
|
||||||
use self::cleanup::cleanup;
|
use self::cleanup::cleanup_failed;
|
||||||
use self::progress::{InstallProgress, InstallProgressTracker};
|
|
||||||
use crate::context::{EitherContext, ExtendedContext, RpcContext};
|
use crate::context::{EitherContext, ExtendedContext, RpcContext};
|
||||||
use crate::db::model::{
|
use crate::db::model::{
|
||||||
CurrentDependencyInfo, InstalledPackageDataEntry, PackageDataEntry, StaticDependencyInfo,
|
CurrentDependencyInfo, InstalledPackageDataEntry, PackageDataEntry, StaticDependencyInfo,
|
||||||
StaticFiles,
|
StaticFiles,
|
||||||
};
|
};
|
||||||
|
use crate::db::util::WithRevision;
|
||||||
use crate::dependencies::update_current_dependents;
|
use crate::dependencies::update_current_dependents;
|
||||||
use crate::install::cleanup::{uninstall, update_dependents};
|
use crate::install::cleanup::{cleanup, update_dependents};
|
||||||
|
use crate::install::progress::{InstallProgress, InstallProgressTracker};
|
||||||
use crate::s9pk::manifest::{Manifest, PackageId};
|
use crate::s9pk::manifest::{Manifest, PackageId};
|
||||||
use crate::s9pk::reader::S9pkReader;
|
use crate::s9pk::reader::S9pkReader;
|
||||||
use crate::status::{DependencyErrors, MainStatus, Status};
|
use crate::status::{DependencyErrors, MainStatus, Status};
|
||||||
@@ -48,7 +49,10 @@ pub const PKG_CACHE: &'static str = "/mnt/embassy-os/cache/packages";
|
|||||||
pub const PKG_PUBLIC_DIR: &'static str = "/mnt/embassy-os/public/package-data";
|
pub const PKG_PUBLIC_DIR: &'static str = "/mnt/embassy-os/public/package-data";
|
||||||
|
|
||||||
#[command(display(display_none))]
|
#[command(display(display_none))]
|
||||||
pub async fn install(#[context] ctx: EitherContext, #[arg] id: String) -> Result<(), Error> {
|
pub async fn install(
|
||||||
|
#[context] ctx: EitherContext,
|
||||||
|
#[arg] id: String,
|
||||||
|
) -> Result<WithRevision<()>, Error> {
|
||||||
let rpc_ctx = ctx.to_rpc().unwrap();
|
let rpc_ctx = ctx.to_rpc().unwrap();
|
||||||
let (pkg_id, version_str) = if let Some(split) = id.split_once("@") {
|
let (pkg_id, version_str) = if let Some(split) = id.split_once("@") {
|
||||||
split
|
split
|
||||||
@@ -68,14 +72,105 @@ pub async fn install(#[context] ctx: EitherContext, #[arg] id: String) -> Result
|
|||||||
))
|
))
|
||||||
)
|
)
|
||||||
.with_kind(crate::ErrorKind::Registry)?;
|
.with_kind(crate::ErrorKind::Registry)?;
|
||||||
let man = man_res.json().await.with_kind(crate::ErrorKind::Registry)?;
|
let man: Manifest = man_res.json().await.with_kind(crate::ErrorKind::Registry)?;
|
||||||
|
|
||||||
|
let progress = InstallProgress::new(s9pk.content_length());
|
||||||
|
let static_files = StaticFiles::remote(&man.id, &man.version, man.assets.icon_type());
|
||||||
|
let mut db_handle = rpc_ctx.db.handle();
|
||||||
|
let mut tx = db_handle.begin().await?;
|
||||||
|
let mut pde = crate::db::DatabaseModel::new()
|
||||||
|
.package_data()
|
||||||
|
.idx_model(&man.id)
|
||||||
|
.get_mut(&mut tx)
|
||||||
|
.await?;
|
||||||
|
match pde.take() {
|
||||||
|
Some(PackageDataEntry::Installed {
|
||||||
|
installed,
|
||||||
|
manifest,
|
||||||
|
static_files,
|
||||||
|
}) => {
|
||||||
|
*pde = Some(PackageDataEntry::Updating {
|
||||||
|
install_progress: progress.clone(),
|
||||||
|
static_files,
|
||||||
|
installed,
|
||||||
|
manifest,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
*pde = Some(PackageDataEntry::Installing {
|
||||||
|
install_progress: progress.clone(),
|
||||||
|
static_files,
|
||||||
|
manifest: man.clone(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
return Err(Error::new(
|
||||||
|
anyhow!("Cannot install over an app in a transient state"),
|
||||||
|
crate::ErrorKind::InvalidRequest,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pde.save(&mut tx).await?;
|
||||||
|
let res = tx.commit(None).await?;
|
||||||
|
drop(db_handle);
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
if let Err(e) = download_install_s9pk(&rpc_ctx, &man, s9pk).await {
|
if let Err(e) = download_install_s9pk(&rpc_ctx, &man, s9pk).await {
|
||||||
log::error!("Install of {}@{} Failed: {}", man.id, man.version, e);
|
log::error!("Install of {}@{} Failed: {}", man.id, man.version, e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(WithRevision {
|
||||||
|
revision: res,
|
||||||
|
response: (),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[command(display(display_none))]
|
||||||
|
pub async fn uninstall(
|
||||||
|
#[context] ctx: EitherContext,
|
||||||
|
#[arg] id: PackageId,
|
||||||
|
) -> Result<WithRevision<()>, Error> {
|
||||||
|
let mut handle = ctx.as_rpc().unwrap().db.handle();
|
||||||
|
let mut tx = handle.begin().await?;
|
||||||
|
|
||||||
|
let mut pde = crate::db::DatabaseModel::new()
|
||||||
|
.package_data()
|
||||||
|
.idx_model(&id)
|
||||||
|
.get_mut(&mut tx)
|
||||||
|
.await?;
|
||||||
|
let (manifest, static_files, installed) = match pde.take() {
|
||||||
|
Some(PackageDataEntry::Installed {
|
||||||
|
manifest,
|
||||||
|
static_files,
|
||||||
|
installed,
|
||||||
|
}) => (manifest, static_files, installed),
|
||||||
|
_ => {
|
||||||
|
return Err(Error::new(
|
||||||
|
anyhow!("Package is not installed."),
|
||||||
|
crate::ErrorKind::NotFound,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
*pde = Some(PackageDataEntry::Removing {
|
||||||
|
manifest,
|
||||||
|
static_files,
|
||||||
|
});
|
||||||
|
pde.save(&mut tx).await?;
|
||||||
|
let res = tx.commit(None).await?;
|
||||||
|
drop(handle);
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let rpc_ctx = ctx.as_rpc().unwrap();
|
||||||
|
if let Err(e) = cleanup::uninstall(rpc_ctx, &mut rpc_ctx.db.handle(), &installed).await {
|
||||||
|
log::error!("Uninstall of {} Failed: {}", id, e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(WithRevision {
|
||||||
|
revision: res,
|
||||||
|
response: (),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn download_install_s9pk(
|
pub async fn download_install_s9pk(
|
||||||
@@ -96,38 +191,6 @@ pub async fn download_install_s9pk(
|
|||||||
|
|
||||||
let res = (|| async {
|
let res = (|| async {
|
||||||
let progress = InstallProgress::new(s9pk.content_length());
|
let progress = InstallProgress::new(s9pk.content_length());
|
||||||
let static_files = StaticFiles::remote(pkg_id, version, temp_manifest.assets.icon_type());
|
|
||||||
let mut db_handle = ctx.db.handle();
|
|
||||||
let mut pde = pkg_data_entry.get_mut(&mut db_handle).await?;
|
|
||||||
match pde.take() {
|
|
||||||
Some(PackageDataEntry::Installed {
|
|
||||||
installed,
|
|
||||||
manifest,
|
|
||||||
static_files,
|
|
||||||
}) => {
|
|
||||||
*pde = Some(PackageDataEntry::Updating {
|
|
||||||
install_progress: progress.clone(),
|
|
||||||
static_files,
|
|
||||||
installed,
|
|
||||||
manifest,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
*pde = Some(PackageDataEntry::Installing {
|
|
||||||
install_progress: progress.clone(),
|
|
||||||
static_files,
|
|
||||||
manifest: temp_manifest.clone(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
return Err(Error::new(
|
|
||||||
anyhow!("Cannot install over an app in a transient state"),
|
|
||||||
crate::ErrorKind::InvalidRequest,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pde.save(&mut db_handle).await?;
|
|
||||||
drop(db_handle);
|
|
||||||
let progress_model = pkg_data_entry.and_then(|pde| pde.install_progress());
|
let progress_model = pkg_data_entry.and_then(|pde| pde.install_progress());
|
||||||
|
|
||||||
async fn check_cache(
|
async fn check_cache(
|
||||||
@@ -242,7 +305,7 @@ pub async fn download_install_s9pk(
|
|||||||
let mut handle = ctx.db.handle();
|
let mut handle = ctx.db.handle();
|
||||||
let mut tx = handle.begin().await?;
|
let mut tx = handle.begin().await?;
|
||||||
|
|
||||||
if let Err(e) = cleanup(&ctx, &mut tx, pkg_id, version).await {
|
if let Err(e) = cleanup_failed(&ctx, &mut tx, pkg_id, version).await {
|
||||||
log::error!(
|
log::error!(
|
||||||
"Failed to clean up {}@{}: {}: Adding to broken packages",
|
"Failed to clean up {}@{}: {}: Adding to broken packages",
|
||||||
pkg_id,
|
pkg_id,
|
||||||
@@ -566,7 +629,7 @@ pub async fn install_s9pk<R: AsyncRead + AsyncSeek + Unpin>(
|
|||||||
configured &= res.configured;
|
configured &= res.configured;
|
||||||
}
|
}
|
||||||
if &prev.manifest.version != version {
|
if &prev.manifest.version != version {
|
||||||
uninstall(ctx, &mut tx, prev).await?;
|
cleanup(ctx, &prev.manifest.id, &prev.manifest.version).await?;
|
||||||
}
|
}
|
||||||
if let Some(res) = manifest
|
if let Some(res) = manifest
|
||||||
.migrations
|
.migrations
|
||||||
|
|||||||
@@ -72,7 +72,13 @@ pub fn main_api(#[context] ctx: EitherContext) -> Result<EitherContext, RpcError
|
|||||||
Ok(ctx)
|
Ok(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[command(subcommands(install::install, config::config, control::start, control::stop))]
|
#[command(subcommands(
|
||||||
|
install::install,
|
||||||
|
install::uninstall,
|
||||||
|
config::config,
|
||||||
|
control::start,
|
||||||
|
control::stop
|
||||||
|
))]
|
||||||
pub fn package(#[context] ctx: EitherContext) -> Result<EitherContext, RpcError> {
|
pub fn package(#[context] ctx: EitherContext) -> Result<EitherContext, RpcError> {
|
||||||
Ok(ctx)
|
Ok(ctx)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -291,10 +291,10 @@ impl Manager {
|
|||||||
.unwrap(); // recv is still in scope, cannot fail
|
.unwrap(); // recv is still in scope, cannot fail
|
||||||
}
|
}
|
||||||
Ok(Err(e)) => {
|
Ok(Err(e)) => {
|
||||||
todo!("application crashed")
|
log::error!("application crashed: {}: {}", e.0, e.1)
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
todo!("failed to start application: {}", e)
|
log::error!("failed to start application: {}", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user