mirror of
https://github.com/snowfallorg/nix-software-center.git
synced 2024-07-15 00:40:27 +03:00
Add unavailable package dialog
This commit is contained in:
parent
ceb00abc4c
commit
b25fd4e7b9
10
Cargo.lock
generated
10
Cargo.lock
generated
@ -1592,9 +1592,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "native-tls"
|
||||
version = "0.2.10"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9"
|
||||
checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"libc",
|
||||
@ -1617,7 +1617,7 @@ checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
|
||||
[[package]]
|
||||
name = "nix-data"
|
||||
version = "0.0.2"
|
||||
source = "git+https://github.com/snowflakelinux/nix-data#33479e595f14142f15fb6ec29cc585352c2c7703"
|
||||
source = "git+https://github.com/snowflakelinux/nix-data#315d3efee6860cdc48e514ac1fa288196312a4f4"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"csv",
|
||||
@ -1742,9 +1742,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.13.1"
|
||||
version = "1.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
|
||||
checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
|
@ -20,7 +20,7 @@ pkgs.stdenv.mkDerivation rec {
|
||||
cargoDeps = pkgs.rustPlatform.fetchCargoTarball {
|
||||
inherit src;
|
||||
name = "${pname}-${version}";
|
||||
hash = "sha256-CRw/T0TAgW+81C3966PAEpDHJotSbOHkAqhotY1sozM=";
|
||||
hash = "sha256-yChtK86/onSI2JQaQkBwwVzijGTEyc6vQbCUmgWb3u8=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = with pkgs; [
|
||||
|
@ -1,7 +1,7 @@
|
||||
use clap::{self, FromArgMatches, Subcommand};
|
||||
use std::{
|
||||
error::Error,
|
||||
fs::{File, self},
|
||||
fs::{self, File},
|
||||
io::{self, Read, Write},
|
||||
process::Command,
|
||||
};
|
||||
@ -23,6 +23,12 @@ enum SubCommands {
|
||||
/// Whether to rebuild the system after updating channels
|
||||
#[arg(short, long)]
|
||||
rebuild: bool,
|
||||
/// Update file
|
||||
#[arg(short, long)]
|
||||
update: bool,
|
||||
/// Write stdin to file in path output
|
||||
#[arg(short, long)]
|
||||
output: String,
|
||||
/// Run `nixos-rebuild` with the given arguments
|
||||
arguments: Vec<String>,
|
||||
},
|
||||
@ -33,6 +39,12 @@ enum SubCommands {
|
||||
/// Path to the flake file
|
||||
#[arg(short, long)]
|
||||
flakepath: String,
|
||||
/// Update file
|
||||
#[arg(short, long)]
|
||||
update: bool,
|
||||
/// Write stdin to file in path output
|
||||
#[arg(short, long)]
|
||||
output: String,
|
||||
/// Run `nixos-rebuild` with the given arguments
|
||||
arguments: Vec<String>,
|
||||
},
|
||||
@ -81,7 +93,18 @@ fn main() {
|
||||
std::process::exit(1);
|
||||
}
|
||||
},
|
||||
SubCommands::Channel { rebuild: dorebuild, arguments } => {
|
||||
SubCommands::Channel {
|
||||
rebuild: dorebuild,
|
||||
update,
|
||||
output,
|
||||
arguments,
|
||||
} => {
|
||||
if update {
|
||||
if let Err(e) = write_file(&output) {
|
||||
eprintln!("{}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
match channel() {
|
||||
Ok(_) => {
|
||||
if dorebuild {
|
||||
@ -93,14 +116,26 @@ fn main() {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
},
|
||||
SubCommands::Flake { rebuild: dorebuild, flakepath, arguments } => {
|
||||
}
|
||||
SubCommands::Flake {
|
||||
rebuild: dorebuild,
|
||||
flakepath,
|
||||
update,
|
||||
output,
|
||||
arguments,
|
||||
} => {
|
||||
if update {
|
||||
if let Err(e) = write_file(&output) {
|
||||
eprintln!("{}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
match flake(&flakepath) {
|
||||
Ok(_) => {
|
||||
if dorebuild {
|
||||
@ -112,7 +147,7 @@ fn main() {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
std::process::exit(1);
|
||||
@ -132,9 +167,7 @@ fn write_file(path: &str) -> Result<(), Box<dyn Error>> {
|
||||
}
|
||||
|
||||
fn rebuild(args: Vec<String>) -> Result<(), Box<dyn Error>> {
|
||||
let mut cmd = Command::new("nixos-rebuild")
|
||||
.args(args)
|
||||
.spawn()?;
|
||||
let mut cmd = Command::new("nixos-rebuild").args(args).spawn()?;
|
||||
let x = cmd.wait()?;
|
||||
if x.success() {
|
||||
Ok(())
|
||||
@ -148,9 +181,7 @@ fn rebuild(args: Vec<String>) -> Result<(), Box<dyn Error>> {
|
||||
}
|
||||
|
||||
fn channel() -> Result<(), Box<dyn Error>> {
|
||||
let mut cmd = Command::new("nix-channel")
|
||||
.arg("--update")
|
||||
.spawn()?;
|
||||
let mut cmd = Command::new("nix-channel").arg("--update").spawn()?;
|
||||
let x = cmd.wait()?;
|
||||
if x.success() {
|
||||
Ok(())
|
||||
@ -179,4 +210,4 @@ fn flake(path: &str) -> Result<(), Box<dyn Error>> {
|
||||
"nix flake failed",
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -135,6 +135,7 @@ impl Worker for InstallAsyncHandler {
|
||||
.arg("profile")
|
||||
.arg("install")
|
||||
.arg(format!("nixpkgs#{}", work.pkg))
|
||||
.arg("--impure")
|
||||
.kill_on_drop(true)
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
|
@ -10,6 +10,7 @@ pub mod preferencespage;
|
||||
pub mod rebuild;
|
||||
pub mod screenshotfactory;
|
||||
pub mod searchpage;
|
||||
pub mod unavailabledialog;
|
||||
pub mod updatepage;
|
||||
pub mod updateworker;
|
||||
pub mod welcome;
|
||||
|
264
src/ui/unavailabledialog.rs
Normal file
264
src/ui/unavailabledialog.rs
Normal file
@ -0,0 +1,264 @@
|
||||
use std::path::Path;
|
||||
|
||||
use gtk::pango;
|
||||
use log::*;
|
||||
use relm4::{*, prelude::*, factory::*};
|
||||
use adw::prelude::*;
|
||||
use crate::{APPINFO, ui::{window::REBUILD_BROKER, rebuild::RebuildMsg}};
|
||||
|
||||
use super::updatepage::{UpdatePageMsg, UpdateType};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct UnavailableDialogModel {
|
||||
hidden: bool,
|
||||
unavailableuseritems: FactoryVecDeque<UnavailableItemModel>,
|
||||
unavailablesysitems: FactoryVecDeque<UnavailableItemModel>,
|
||||
updatetype: UpdateType,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum UnavailableDialogMsg {
|
||||
Show(Vec<UnavailableItemModel>, Vec<UnavailableItemModel>, UpdateType),
|
||||
Close,
|
||||
Continue,
|
||||
}
|
||||
|
||||
#[relm4::component(pub)]
|
||||
impl SimpleComponent for UnavailableDialogModel {
|
||||
type Init = gtk::Window;
|
||||
type Input = UnavailableDialogMsg;
|
||||
type Output = UpdatePageMsg;
|
||||
type Widgets = UnavailableDialogWidgets;
|
||||
|
||||
view! {
|
||||
dialog = adw::MessageDialog {
|
||||
#[watch]
|
||||
set_visible: !model.hidden,
|
||||
set_transient_for: Some(&parent_window),
|
||||
set_modal: true,
|
||||
set_heading: Some("Some packages are unavailable!"),
|
||||
set_body: "If you continue this update, some packages will be removed",
|
||||
#[wrap(Some)]
|
||||
set_extra_child = >k::Box {
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
set_spacing: 20,
|
||||
adw::PreferencesGroup {
|
||||
#[watch]
|
||||
set_visible: !model.unavailableuseritems.is_empty(),
|
||||
set_title: "User Packages",
|
||||
#[local_ref]
|
||||
unavailableuserlist -> gtk::ListBox {
|
||||
add_css_class: "boxed-list",
|
||||
set_selection_mode: gtk::SelectionMode::None,
|
||||
},
|
||||
},
|
||||
adw::PreferencesGroup {
|
||||
#[watch]
|
||||
set_visible: !model.unavailablesysitems.is_empty(),
|
||||
set_title: "System Packages",
|
||||
#[local_ref]
|
||||
unavailablesyslist -> gtk::ListBox {
|
||||
add_css_class: "boxed-list",
|
||||
set_selection_mode: gtk::SelectionMode::None
|
||||
},
|
||||
}
|
||||
},
|
||||
add_response: ("cancel", "Cancel"),
|
||||
add_response: ("continue", "Continue"),
|
||||
set_response_appearance: ("continue", adw::ResponseAppearance::Destructive),
|
||||
connect_close_request => |_| {
|
||||
gtk::Inhibit(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn init(
|
||||
parent_window: Self::Init,
|
||||
root: &Self::Root,
|
||||
sender: ComponentSender<Self>,
|
||||
) -> ComponentParts<Self> {
|
||||
|
||||
let model = UnavailableDialogModel {
|
||||
unavailableuseritems: FactoryVecDeque::new(gtk::ListBox::new(), sender.input_sender()),
|
||||
unavailablesysitems: FactoryVecDeque::new(gtk::ListBox::new(), sender.input_sender()),
|
||||
updatetype: UpdateType::All,
|
||||
hidden: true,
|
||||
};
|
||||
|
||||
let unavailableuserlist = model.unavailableuseritems.widget();
|
||||
let unavailablesyslist = model.unavailablesysitems.widget();
|
||||
|
||||
let widgets = view_output!();
|
||||
|
||||
widgets.dialog.connect_response(None, move |_, resp| {
|
||||
match resp {
|
||||
"cancel" => {
|
||||
REBUILD_BROKER.send(RebuildMsg::Close);
|
||||
debug!("Response: cancel")
|
||||
},
|
||||
"continue" => {
|
||||
sender.input(UnavailableDialogMsg::Continue);
|
||||
debug!("Response: continue")
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
});
|
||||
ComponentParts { model, widgets }
|
||||
|
||||
}
|
||||
|
||||
fn update(&mut self, msg: Self::Input, sender: ComponentSender<Self>) {
|
||||
match msg {
|
||||
UnavailableDialogMsg::Show(useritems, sysitems, updatetype) => {
|
||||
self.updatetype = updatetype;
|
||||
let mut unavailableuseritems_guard = self.unavailableuseritems.guard();
|
||||
unavailableuseritems_guard.clear();
|
||||
for item in useritems {
|
||||
unavailableuseritems_guard.push_back(item);
|
||||
}
|
||||
let mut unavailablesysitems_guard = self.unavailablesysitems.guard();
|
||||
for item in sysitems {
|
||||
unavailablesysitems_guard.push_back(item);
|
||||
}
|
||||
self.hidden = false;
|
||||
}
|
||||
UnavailableDialogMsg::Close => {
|
||||
info!("UpdateDialogMsg::Close");
|
||||
let mut unavailableuseritems_guard = self.unavailableuseritems.guard();
|
||||
let mut unavailablesysitems_guard = self.unavailablesysitems.guard();
|
||||
unavailableuseritems_guard.clear();
|
||||
unavailablesysitems_guard.clear();
|
||||
self.hidden = true;
|
||||
}
|
||||
UnavailableDialogMsg::Continue => {
|
||||
match self.updatetype {
|
||||
UpdateType::User => {
|
||||
sender.output(UpdatePageMsg::UpdateAllUserRm(self.unavailableuseritems.iter().map(|x| x.pkg.to_string()).collect()));
|
||||
}
|
||||
UpdateType::System => {
|
||||
sender.output(UpdatePageMsg::UpdateSystemRm(self.unavailablesysitems.iter().map(|x| x.pkg.to_string()).collect()));
|
||||
}
|
||||
UpdateType::All => {
|
||||
sender.output(UpdatePageMsg::UpdateAllRm(self.unavailableuseritems.iter().map(|x| x.pkg.to_string()).collect(), self.unavailablesysitems.iter().map(|x| x.pkg.to_string()).collect()));
|
||||
}
|
||||
}
|
||||
sender.input(UnavailableDialogMsg::Close)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, PartialEq, Eq)]
|
||||
pub struct UnavailableItemModel {
|
||||
pub name: String,
|
||||
pub pkg: String,
|
||||
pub pname: String,
|
||||
pub icon: Option<String>,
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum UnavailableItemMsg {}
|
||||
|
||||
#[relm4::factory(pub)]
|
||||
impl FactoryComponent for UnavailableItemModel {
|
||||
type CommandOutput = ();
|
||||
type Init = UnavailableItemModel;
|
||||
type Input = ();
|
||||
type Output = UnavailableItemMsg;
|
||||
type Widgets = UnavailableItemWidgets;
|
||||
type ParentWidget = adw::gtk::ListBox;
|
||||
type ParentInput = UnavailableDialogMsg;
|
||||
|
||||
view! {
|
||||
adw::PreferencesRow {
|
||||
set_activatable: false,
|
||||
#[wrap(Some)]
|
||||
set_child = >k::Box {
|
||||
set_orientation: gtk::Orientation::Horizontal,
|
||||
set_hexpand: true,
|
||||
set_spacing: 10,
|
||||
set_margin_all: 10,
|
||||
adw::Bin {
|
||||
set_valign: gtk::Align::Center,
|
||||
#[wrap(Some)]
|
||||
set_child = if self.icon.is_some() {
|
||||
gtk::Image {
|
||||
add_css_class: "icon-dropshadow",
|
||||
set_halign: gtk::Align::Start,
|
||||
set_from_file: {
|
||||
if let Some(i) = &self.icon {
|
||||
let iconpath = format!("{}/icons/nixos/128x128/{}", APPINFO, i);
|
||||
let iconpath64 = format!("{}/icons/nixos/64x64/{}", APPINFO, i);
|
||||
if Path::new(&iconpath).is_file() {
|
||||
Some(iconpath)
|
||||
} else if Path::new(&iconpath64).is_file() {
|
||||
Some(iconpath64)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
set_pixel_size: 64,
|
||||
}
|
||||
} else {
|
||||
gtk::Image {
|
||||
add_css_class: "icon-dropshadow",
|
||||
set_halign: gtk::Align::Start,
|
||||
set_icon_name: Some("package-x-generic"),
|
||||
set_pixel_size: 64,
|
||||
}
|
||||
}
|
||||
},
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Horizontal,
|
||||
set_halign: gtk::Align::Fill,
|
||||
set_valign: gtk::Align::Center,
|
||||
set_hexpand: true,
|
||||
set_spacing: 20,
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
set_halign: gtk::Align::Fill,
|
||||
set_valign: gtk::Align::Center,
|
||||
set_spacing: 2,
|
||||
gtk::Label {
|
||||
set_halign: gtk::Align::Start,
|
||||
set_label: self.name.as_str(),
|
||||
set_ellipsize: pango::EllipsizeMode::End,
|
||||
set_lines: 1,
|
||||
set_wrap: true,
|
||||
set_max_width_chars: 0,
|
||||
},
|
||||
gtk::Label {
|
||||
set_halign: gtk::Align::Start,
|
||||
add_css_class: "dim-label",
|
||||
add_css_class: "caption",
|
||||
set_label: self.pkg.as_str(),
|
||||
set_ellipsize: pango::EllipsizeMode::End,
|
||||
set_lines: 1,
|
||||
set_wrap: true,
|
||||
set_max_width_chars: 0,
|
||||
},
|
||||
},
|
||||
gtk::Label {
|
||||
set_halign: gtk::Align::Center,
|
||||
set_hexpand: true,
|
||||
set_label: self.message.as_str(),
|
||||
set_wrap: true,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn init_model(
|
||||
init: Self::Init,
|
||||
_index: &DynamicIndex,
|
||||
_sender: FactoryComponentSender<Self>,
|
||||
) -> Self {
|
||||
init
|
||||
}
|
||||
}
|
@ -1,12 +1,14 @@
|
||||
use crate::APPINFO;
|
||||
use crate::{APPINFO, ui::unavailabledialog::UnavailableDialogModel};
|
||||
|
||||
use super::{pkgpage::InstallType, window::*, updateworker::{UpdateAsyncHandler, UpdateAsyncHandlerMsg, UpdateAsyncHandlerInit}, rebuild::RebuildMsg};
|
||||
use adw::prelude::*;
|
||||
use nix_data::config::configfile::NixDataConfig;
|
||||
use relm4::{factory::*, gtk::pango, *};
|
||||
use std::{path::Path, convert::identity};
|
||||
use std::{path::Path, convert::identity, collections::HashMap};
|
||||
use log::*;
|
||||
|
||||
pub static UNAVAILABLE_BROKER: MessageBroker<UnavailableDialogModel> = MessageBroker::new();
|
||||
|
||||
#[tracker::track]
|
||||
#[derive(Debug)]
|
||||
pub struct UpdatePageModel {
|
||||
@ -21,6 +23,8 @@ pub struct UpdatePageModel {
|
||||
systype: SystemPkgs,
|
||||
usertype: UserPkgs,
|
||||
updatetracker: u8,
|
||||
#[tracker::no_eq]
|
||||
unavailabledialog: Controller<UnavailableDialogModel>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -30,15 +34,25 @@ pub enum UpdatePageMsg {
|
||||
Update(Vec<UpdateItem>, Vec<UpdateItem>),
|
||||
OpenRow(usize, InstallType),
|
||||
UpdateSystem,
|
||||
UpdateSystemRm(Vec<String>),
|
||||
UpdateAllUser,
|
||||
UpdateAllUserRm(Vec<String>),
|
||||
UpdateUser(String),
|
||||
// UpdateChannels,
|
||||
// UpdateSystemAndChannels,
|
||||
UpdateAll,
|
||||
UpdateAllRm(Vec<String>, Vec<String>),
|
||||
DoneWorking,
|
||||
FailedWorking,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum UpdateType {
|
||||
System,
|
||||
User,
|
||||
All,
|
||||
}
|
||||
|
||||
pub struct UpdatePageInit {
|
||||
pub window: gtk::Window,
|
||||
pub systype: SystemPkgs,
|
||||
@ -84,101 +98,6 @@ impl SimpleComponent for UpdatePageModel {
|
||||
}
|
||||
}
|
||||
},
|
||||
// gtk::Box {
|
||||
// set_orientation: gtk::Orientation::Horizontal,
|
||||
// set_hexpand: true,
|
||||
// #[watch]
|
||||
// set_visible: model.channelupdate.is_some(),
|
||||
// gtk::Label {
|
||||
// set_halign: gtk::Align::Start,
|
||||
// add_css_class: "title-4",
|
||||
// set_label: "Channels",
|
||||
// },
|
||||
// },
|
||||
// gtk::ListBox {
|
||||
// set_valign: gtk::Align::Start,
|
||||
// add_css_class: "boxed-list",
|
||||
// set_selection_mode: gtk::SelectionMode::None,
|
||||
// #[watch]
|
||||
// set_visible: model.channelupdate.is_some(),
|
||||
// adw::PreferencesRow {
|
||||
// set_activatable: false,
|
||||
// set_can_focus: false,
|
||||
// #[wrap(Some)]
|
||||
// set_child = >k::Box {
|
||||
// set_orientation: gtk::Orientation::Horizontal,
|
||||
// set_hexpand: true,
|
||||
// set_spacing: 10,
|
||||
// set_margin_all: 10,
|
||||
// adw::Bin {
|
||||
// set_valign: gtk::Align::Center,
|
||||
// gtk::Image {
|
||||
// add_css_class: "icon-dropshadow",
|
||||
// set_halign: gtk::Align::Start,
|
||||
// set_icon_name: Some("application-x-addon"),
|
||||
// set_pixel_size: 64,
|
||||
// }
|
||||
// },
|
||||
// gtk::Box {
|
||||
// set_orientation: gtk::Orientation::Vertical,
|
||||
// set_halign: gtk::Align::Fill,
|
||||
// set_valign: gtk::Align::Center,
|
||||
// set_hexpand: true,
|
||||
// set_spacing: 2,
|
||||
// gtk::Label {
|
||||
// set_halign: gtk::Align::Start,
|
||||
// set_label: "nixos",
|
||||
// set_ellipsize: pango::EllipsizeMode::End,
|
||||
// set_lines: 1,
|
||||
// set_wrap: true,
|
||||
// set_max_width_chars: 0,
|
||||
// },
|
||||
// gtk::Label {
|
||||
// set_halign: gtk::Align::Start,
|
||||
// add_css_class: "dim-label",
|
||||
// add_css_class: "caption",
|
||||
// set_label: {
|
||||
// &(if let Some((old, new)) = &model.channelupdate {
|
||||
// format!("{} → {}", old, new)
|
||||
// } else {
|
||||
// String::default()
|
||||
// })
|
||||
// },
|
||||
// set_visible: model.channelupdate.is_some(),
|
||||
// set_ellipsize: pango::EllipsizeMode::End,
|
||||
// set_lines: 1,
|
||||
// set_wrap: true,
|
||||
// set_max_width_chars: 0,
|
||||
// },
|
||||
// },
|
||||
// gtk::Box {
|
||||
// set_orientation: gtk::Orientation::Vertical,
|
||||
// set_spacing: 5,
|
||||
// set_halign: gtk::Align::End,
|
||||
// set_valign: gtk::Align::Center,
|
||||
// gtk::Button {
|
||||
// add_css_class: "suggested-action",
|
||||
// set_valign: gtk::Align::Center,
|
||||
// set_halign: gtk::Align::End,
|
||||
// set_label: "Update channel and system",
|
||||
// set_can_focus: false,
|
||||
// connect_clicked[sender] => move |_| {
|
||||
// sender.input(UpdatePageMsg::UpdateSystemAndChannels);
|
||||
// }
|
||||
// },
|
||||
// gtk::Button {
|
||||
// set_valign: gtk::Align::Center,
|
||||
// set_halign: gtk::Align::End,
|
||||
// set_label: "Update channel only",
|
||||
// set_can_focus: false,
|
||||
// connect_clicked[sender] => move |_| {
|
||||
// sender.input(UpdatePageMsg::UpdateChannels);
|
||||
// }
|
||||
// },
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Horizontal,
|
||||
set_hexpand: true,
|
||||
@ -283,6 +202,10 @@ impl SimpleComponent for UpdatePageModel {
|
||||
.detach_worker(UpdateAsyncHandlerInit { syspkgs: initparams.systype.clone(), userpkgs: initparams.usertype.clone() })
|
||||
.forward(sender.input_sender(), identity);
|
||||
|
||||
let unavailabledialog = UnavailableDialogModel::builder()
|
||||
.launch_with_broker(initparams.window.clone(), &UNAVAILABLE_BROKER)
|
||||
.forward(sender.input_sender(), identity);
|
||||
|
||||
let config = initparams.config;
|
||||
updateworker.emit(UpdateAsyncHandlerMsg::UpdateConfig(config.clone()));
|
||||
|
||||
@ -295,6 +218,7 @@ impl SimpleComponent for UpdatePageModel {
|
||||
config,
|
||||
systype: initparams.systype,
|
||||
usertype: initparams.usertype,
|
||||
unavailabledialog,
|
||||
tracker: 0,
|
||||
};
|
||||
|
||||
@ -322,13 +246,6 @@ impl SimpleComponent for UpdatePageModel {
|
||||
info!("UpdatePageMsg::Update");
|
||||
debug!("UPDATEUSERLIST: {:?}", updateuserlist);
|
||||
debug!("UPDATESYSTEMLIST: {:?}", updatesystemlist);
|
||||
// self.channelupdate = match nix_data::cache::channel::uptodate() {
|
||||
// Ok(x) => {
|
||||
// x
|
||||
// },
|
||||
// Err(_) => None,
|
||||
// };
|
||||
// debug!("CHANNELUPDATE: {:?}", self.channelupdate);
|
||||
self.update_updatetracker(|_| ());
|
||||
let mut updateuserlist_guard = self.updateuserlist.guard();
|
||||
updateuserlist_guard.clear();
|
||||
@ -340,16 +257,6 @@ impl SimpleComponent for UpdatePageModel {
|
||||
for updatesystem in updatesystemlist {
|
||||
updatesystemlist_guard.push_back(updatesystem);
|
||||
}
|
||||
updatesystemlist_guard.push_back(UpdateItem {
|
||||
pkg: None,
|
||||
name: "NixOS".to_string(),
|
||||
pname: "nixos".to_string(),
|
||||
summary: None,
|
||||
icon: None,
|
||||
pkgtype: InstallType::System,
|
||||
verfrom: None,
|
||||
verto: None,
|
||||
});
|
||||
}
|
||||
UpdatePageMsg::OpenRow(row, pkgtype) => match pkgtype {
|
||||
InstallType::User => {
|
||||
@ -369,17 +276,33 @@ impl SimpleComponent for UpdatePageModel {
|
||||
}
|
||||
}
|
||||
},
|
||||
// UpdatePageMsg::UpdateChannels => {
|
||||
// self.updatedialog.emit(UpdateDialogMsg::Show(String::from("Updating channels...")));
|
||||
// self.updateworker.emit(UpdateAsyncHandlerMsg::UpdateChannels);
|
||||
// }
|
||||
// UpdatePageMsg::UpdateSystemAndChannels => {
|
||||
// self.updatedialog.emit(UpdateDialogMsg::Show(String::from("Updating system and channels...")));
|
||||
// self.updateworker.emit(UpdateAsyncHandlerMsg::UpdateChannelsAndSystem);
|
||||
// }
|
||||
UpdatePageMsg::UpdateSystem => {
|
||||
let systype = self.systype.clone();
|
||||
let systemconfig = self.config.systemconfig.clone();
|
||||
let workersender = self.updateworker.sender().clone();
|
||||
let output = sender.output_sender().clone();
|
||||
REBUILD_BROKER.send(RebuildMsg::Show);
|
||||
self.updateworker.emit(UpdateAsyncHandlerMsg::UpdateSystem);
|
||||
relm4::spawn(async move {
|
||||
let uninstallsys = match systype {
|
||||
SystemPkgs::Legacy => {
|
||||
nix_data::cache::channel::unavailablepkgs(&[&systemconfig.unwrap()]).await.unwrap_or_default()
|
||||
}
|
||||
SystemPkgs::Flake => {
|
||||
nix_data::cache::flakes::unavailablepkgs(&[&systemconfig.unwrap()]).await.unwrap_or_default()
|
||||
}
|
||||
_ => HashMap::new(),
|
||||
};
|
||||
if uninstallsys.is_empty() {
|
||||
workersender.send(UpdateAsyncHandlerMsg::UpdateSystem);
|
||||
} else {
|
||||
warn!("Uninstalling unavailable packages: {:?}", uninstallsys);
|
||||
output.send(AppMsg::GetUnavailableItems(HashMap::new(), uninstallsys, UpdateType::System));
|
||||
}
|
||||
});
|
||||
}
|
||||
UpdatePageMsg::UpdateSystemRm(pkgs) => {
|
||||
info!("UpdatePageMsg::UpdateSystemRm({:?})", pkgs);
|
||||
self.updateworker.emit(UpdateAsyncHandlerMsg::UpdateSystemRemove(pkgs));
|
||||
}
|
||||
UpdatePageMsg::UpdateUser(pkg) => {
|
||||
info!("UPDATE USER PKG: {}", pkg);
|
||||
@ -387,11 +310,62 @@ impl SimpleComponent for UpdatePageModel {
|
||||
}
|
||||
UpdatePageMsg::UpdateAllUser => {
|
||||
REBUILD_BROKER.send(RebuildMsg::Show);
|
||||
self.updateworker.emit(UpdateAsyncHandlerMsg::UpdateUserPkgs);
|
||||
if self.usertype == UserPkgs::Profile {
|
||||
let workersender = self.updateworker.sender().clone();
|
||||
let output = sender.output_sender().clone();
|
||||
relm4::spawn(async move {
|
||||
let uninstalluser = nix_data::cache::profile::unavailablepkgs().await.unwrap_or_default();
|
||||
if uninstalluser.is_empty() {
|
||||
workersender.send(UpdateAsyncHandlerMsg::UpdateUserPkgs);
|
||||
} else {
|
||||
warn!("Uninstalling unavailable packages: {:?}", uninstalluser);
|
||||
output.send(AppMsg::GetUnavailableItems(uninstalluser, HashMap::new(), UpdateType::User));
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
self.updateworker.emit(UpdateAsyncHandlerMsg::UpdateUserPkgs);
|
||||
}
|
||||
}
|
||||
UpdatePageMsg::UpdateAllUserRm(pkgs) => {
|
||||
info!("UpdatePageMsg::UpdateAllUserRm({:?})", pkgs);
|
||||
self.updateworker.emit(UpdateAsyncHandlerMsg::UpdateUserPkgsRemove(pkgs));
|
||||
}
|
||||
UpdatePageMsg::UpdateAll => {
|
||||
info!("UpdatePageMsg::UpdateAll");
|
||||
let systype = self.systype.clone();
|
||||
let usertype = self.usertype.clone();
|
||||
let systemconfig = self.config.systemconfig.clone();
|
||||
let workersender = self.updateworker.sender().clone();
|
||||
let output = sender.output_sender().clone();
|
||||
REBUILD_BROKER.send(RebuildMsg::Show);
|
||||
self.updateworker.emit(UpdateAsyncHandlerMsg::UpdateAll);
|
||||
relm4::spawn(async move {
|
||||
let uninstallsys = match systype {
|
||||
SystemPkgs::Legacy => {
|
||||
nix_data::cache::channel::unavailablepkgs(&[&systemconfig.unwrap()]).await.unwrap_or_default()
|
||||
}
|
||||
SystemPkgs::Flake => {
|
||||
nix_data::cache::flakes::unavailablepkgs(&[&systemconfig.unwrap()]).await.unwrap_or_default()
|
||||
}
|
||||
_ => HashMap::new(),
|
||||
};
|
||||
let uninstalluser = if usertype == UserPkgs::Profile {
|
||||
nix_data::cache::profile::unavailablepkgs().await.unwrap_or_default()
|
||||
} else {
|
||||
HashMap::new()
|
||||
};
|
||||
if uninstallsys.is_empty() && uninstalluser.is_empty() {
|
||||
workersender.send(UpdateAsyncHandlerMsg::UpdateAll);
|
||||
} else {
|
||||
warn!("Uninstalling unavailable user packages: {:?}", uninstalluser);
|
||||
warn!("Uninstalling unavailable system packages: {:?}", uninstallsys);
|
||||
output.send(AppMsg::GetUnavailableItems(uninstalluser, uninstallsys, UpdateType::All));
|
||||
}
|
||||
});
|
||||
}
|
||||
UpdatePageMsg::UpdateAllRm(userpkgs, syspkgs) => {
|
||||
info!("UpdatePageMsg::UpdateAllRm({:?}, {:?})", userpkgs, syspkgs);
|
||||
self.updateworker.emit(UpdateAsyncHandlerMsg::UpdateAllRemove(userpkgs, syspkgs));
|
||||
}
|
||||
UpdatePageMsg::DoneWorking => {
|
||||
REBUILD_BROKER.send(RebuildMsg::FinishSuccess);
|
||||
|
@ -1,9 +1,9 @@
|
||||
use anyhow::{anyhow, Result};
|
||||
use log::*;
|
||||
use nix_data::config::configfile::NixDataConfig;
|
||||
use relm4::*;
|
||||
use std::{path::Path, process::Stdio};
|
||||
use tokio::io::AsyncBufReadExt;
|
||||
use anyhow::Result;
|
||||
use log::*;
|
||||
use std::{fs, path::Path, process::Stdio};
|
||||
use tokio::io::{AsyncBufReadExt, AsyncWriteExt};
|
||||
|
||||
use crate::ui::{rebuild::RebuildMsg, window::REBUILD_BROKER};
|
||||
|
||||
@ -17,7 +17,7 @@ use super::{
|
||||
pub struct UpdateAsyncHandler {
|
||||
#[tracker::no_eq]
|
||||
process: Option<JoinHandle<()>>,
|
||||
systemconfig: Option<String>,
|
||||
systemconfig: String,
|
||||
flakeargs: Option<String>,
|
||||
syspkgs: SystemPkgs,
|
||||
userpkgs: UserPkgs,
|
||||
@ -30,13 +30,15 @@ pub enum UpdateAsyncHandlerMsg {
|
||||
|
||||
// UpdateChannels,
|
||||
// UpdateChannelsAndSystem,
|
||||
|
||||
UpdateSystem,
|
||||
UpdateSystemRemove(Vec<String>),
|
||||
|
||||
RebuildSystem,
|
||||
UpdateUserPkgs,
|
||||
UpdateUserPkgsRemove(Vec<String>),
|
||||
|
||||
UpdateAll,
|
||||
UpdateAllRemove(Vec<String>, Vec<String>),
|
||||
}
|
||||
|
||||
enum NscCmd {
|
||||
@ -58,7 +60,7 @@ impl Worker for UpdateAsyncHandler {
|
||||
fn init(params: Self::Init, _sender: relm4::ComponentSender<Self>) -> Self {
|
||||
Self {
|
||||
process: None,
|
||||
systemconfig: None,
|
||||
systemconfig: String::new(),
|
||||
flakeargs: None,
|
||||
syspkgs: params.syspkgs,
|
||||
userpkgs: params.userpkgs,
|
||||
@ -69,7 +71,7 @@ impl Worker for UpdateAsyncHandler {
|
||||
fn update(&mut self, msg: Self::Input, sender: ComponentSender<Self>) {
|
||||
match msg {
|
||||
UpdateAsyncHandlerMsg::UpdateConfig(config) => {
|
||||
self.systemconfig = config.systemconfig;
|
||||
self.systemconfig = config.systemconfig.unwrap_or_default();
|
||||
self.flakeargs = if let Some(flake) = config.flake {
|
||||
if let Some(flakearg) = config.flakearg {
|
||||
Some(format!("{}#{}", flake, flakearg))
|
||||
@ -84,46 +86,30 @@ impl Worker for UpdateAsyncHandler {
|
||||
self.syspkgs = syspkgs;
|
||||
self.userpkgs = userpkgs;
|
||||
}
|
||||
// UpdateAsyncHandlerMsg::UpdateChannels => {
|
||||
// let systemconfig = self.systemconfig.clone();
|
||||
// let flakeargs = self.flakeargs.clone();
|
||||
// let syspkgs = self.syspkgs.clone();
|
||||
// relm4::spawn(async move {
|
||||
// let result = runcmd(NscCmd::Channel, systemconfig, flakeargs, syspkgs).await;
|
||||
// match result {
|
||||
// Ok(true) => {
|
||||
// sender.output(UpdatePageMsg::DoneWorking);
|
||||
// }
|
||||
// _ => {
|
||||
// warn!("UPDATE CHANNEL FAILED");
|
||||
// sender.output(UpdatePageMsg::FailedWorking);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// UpdateAsyncHandlerMsg::UpdateChannelsAndSystem => {
|
||||
// let systenconfig = self.systemconfig.clone();
|
||||
// let flakeargs = self.flakeargs.clone();
|
||||
// let syspkgs = self.syspkgs.clone();
|
||||
// relm4::spawn(async move {
|
||||
// let result = runcmd(NscCmd::All, systenconfig, flakeargs, syspkgs).await;
|
||||
// match result {
|
||||
// Ok(true) => {
|
||||
// sender.output(UpdatePageMsg::DoneWorking);
|
||||
// }
|
||||
// _ => {
|
||||
// warn!("UPDATE CHANNEL AND SYSTEM FAILED");
|
||||
// sender.output(UpdatePageMsg::FailedWorking);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
UpdateAsyncHandlerMsg::UpdateSystem => {
|
||||
let systemconfig = self.systemconfig.clone();
|
||||
let flakeargs = self.flakeargs.clone();
|
||||
let syspkgs = self.syspkgs.clone();
|
||||
relm4::spawn(async move {
|
||||
let result = runcmd(NscCmd::All, systemconfig, flakeargs, syspkgs).await;
|
||||
let result = runcmd(NscCmd::All, systemconfig, flakeargs, syspkgs, None).await;
|
||||
match result {
|
||||
Ok(true) => {
|
||||
sender.output(UpdatePageMsg::DoneWorking);
|
||||
}
|
||||
_ => {
|
||||
warn!("UPDATE SYSTEM FAILED");
|
||||
sender.output(UpdatePageMsg::FailedWorking);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
UpdateAsyncHandlerMsg::UpdateSystemRemove(pkgs) => {
|
||||
let systemconfig = self.systemconfig.clone();
|
||||
let flakeargs = self.flakeargs.clone();
|
||||
let syspkgs = self.syspkgs.clone();
|
||||
relm4::spawn(async move {
|
||||
let result =
|
||||
runcmd(NscCmd::All, systemconfig, flakeargs, syspkgs, Some(pkgs)).await;
|
||||
match result {
|
||||
Ok(true) => {
|
||||
sender.output(UpdatePageMsg::DoneWorking);
|
||||
@ -141,8 +127,12 @@ impl Worker for UpdateAsyncHandler {
|
||||
let syspkgs = self.syspkgs.clone();
|
||||
relm4::spawn(async move {
|
||||
let result = match syspkgs {
|
||||
SystemPkgs::Legacy => runcmd(NscCmd::Rebuild, systemconfig, flakeargs, syspkgs).await,
|
||||
SystemPkgs::Flake => runcmd(NscCmd::All, systemconfig, flakeargs, syspkgs).await,
|
||||
SystemPkgs::Legacy => {
|
||||
runcmd(NscCmd::Rebuild, systemconfig, flakeargs, syspkgs, None).await
|
||||
}
|
||||
SystemPkgs::Flake => {
|
||||
runcmd(NscCmd::All, systemconfig, flakeargs, syspkgs, None).await
|
||||
}
|
||||
SystemPkgs::None => Ok(true),
|
||||
};
|
||||
match result {
|
||||
@ -161,7 +151,25 @@ impl Worker for UpdateAsyncHandler {
|
||||
relm4::spawn(async move {
|
||||
let result = match userpkgs {
|
||||
UserPkgs::Env => updateenv().await,
|
||||
UserPkgs::Profile => updateprofile().await,
|
||||
UserPkgs::Profile => updateprofile(None).await,
|
||||
};
|
||||
match result {
|
||||
Ok(true) => {
|
||||
sender.output(UpdatePageMsg::DoneWorking);
|
||||
}
|
||||
_ => {
|
||||
warn!("UPDATE USER FAILED");
|
||||
sender.output(UpdatePageMsg::FailedWorking);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
UpdateAsyncHandlerMsg::UpdateUserPkgsRemove(pkgs) => {
|
||||
let userpkgs = self.userpkgs.clone();
|
||||
relm4::spawn(async move {
|
||||
let result = match userpkgs {
|
||||
UserPkgs::Env => updateenv().await,
|
||||
UserPkgs::Profile => updateprofile(Some(pkgs)).await,
|
||||
};
|
||||
match result {
|
||||
Ok(true) => {
|
||||
@ -180,12 +188,41 @@ impl Worker for UpdateAsyncHandler {
|
||||
let syspkgs = self.syspkgs.clone();
|
||||
let userpkgs = self.userpkgs.clone();
|
||||
relm4::spawn(async move {
|
||||
let result = runcmd(NscCmd::All, systemconfig, flakeargs, syspkgs).await;
|
||||
let result = runcmd(NscCmd::All, systemconfig, flakeargs, syspkgs, None).await;
|
||||
match result {
|
||||
Ok(true) => {
|
||||
match match userpkgs {
|
||||
UserPkgs::Env => updateenv().await,
|
||||
UserPkgs::Profile => updateprofile().await,
|
||||
UserPkgs::Profile => updateprofile(None).await,
|
||||
} {
|
||||
Ok(true) => {
|
||||
sender.output(UpdatePageMsg::DoneWorking);
|
||||
}
|
||||
_ => {
|
||||
warn!("UPDATE ALL FAILED");
|
||||
sender.output(UpdatePageMsg::FailedWorking);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
warn!("UPDATE ALL FAILED");
|
||||
sender.output(UpdatePageMsg::FailedWorking);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
UpdateAsyncHandlerMsg::UpdateAllRemove(userrmpkgs, sysrmpkgs) => {
|
||||
let systemconfig = self.systemconfig.clone();
|
||||
let flakeargs = self.flakeargs.clone();
|
||||
let syspkgs = self.syspkgs.clone();
|
||||
let userpkgs = self.userpkgs.clone();
|
||||
relm4::spawn(async move {
|
||||
let result = runcmd(NscCmd::All, systemconfig, flakeargs, syspkgs, Some(sysrmpkgs)).await;
|
||||
match result {
|
||||
Ok(true) => {
|
||||
match match userpkgs {
|
||||
UserPkgs::Env => updateenv().await,
|
||||
UserPkgs::Profile => updateprofile(Some(userrmpkgs)).await,
|
||||
} {
|
||||
Ok(true) => {
|
||||
sender.output(UpdatePageMsg::DoneWorking);
|
||||
@ -209,10 +246,12 @@ impl Worker for UpdateAsyncHandler {
|
||||
|
||||
async fn runcmd(
|
||||
cmd: NscCmd,
|
||||
_systemconfig: Option<String>,
|
||||
systemconfig: String,
|
||||
flakeargs: Option<String>,
|
||||
syspkgs: SystemPkgs,
|
||||
rmpkgs: Option<Vec<String>>,
|
||||
) -> Result<bool> {
|
||||
let f = fs::read_to_string(&systemconfig)?;
|
||||
let exe = match std::env::current_exe() {
|
||||
Ok(mut e) => {
|
||||
e.pop(); // root/bin
|
||||
@ -231,7 +270,12 @@ async fn runcmd(
|
||||
};
|
||||
|
||||
let flakepathsplit = flakeargs.clone().unwrap_or_default().to_string();
|
||||
let flakepath = flakepathsplit.split('#').collect::<Vec<&str>>().first().cloned().unwrap_or_default();
|
||||
let flakepath = flakepathsplit
|
||||
.split('#')
|
||||
.collect::<Vec<&str>>()
|
||||
.first()
|
||||
.cloned()
|
||||
.unwrap_or_default();
|
||||
|
||||
let rebuildargs = if let Some(x) = flakeargs {
|
||||
let mut v = vec![String::from("--flake")];
|
||||
@ -260,27 +304,92 @@ async fn runcmd(
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()?,
|
||||
NscCmd::All => match syspkgs {
|
||||
SystemPkgs::Legacy => tokio::process::Command::new("pkexec")
|
||||
.arg(&exe)
|
||||
.arg("channel")
|
||||
.arg("--rebuild")
|
||||
.arg("--")
|
||||
.arg("switch")
|
||||
.args(&rebuildargs)
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()?,
|
||||
SystemPkgs::Flake => tokio::process::Command::new("pkexec")
|
||||
.arg(&exe)
|
||||
.arg("flake")
|
||||
.arg("--rebuild")
|
||||
.arg("--flakepath")
|
||||
.arg(flakepath)
|
||||
.arg("--")
|
||||
.arg("switch")
|
||||
.arg("--impure")
|
||||
.args(&rebuildargs)
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()?,
|
||||
SystemPkgs::Legacy => {
|
||||
if let Some(rmpkgs) = rmpkgs {
|
||||
let newconfig =
|
||||
match nix_editor::write::rmarr(&f, "environment.systemPackages", rmpkgs) {
|
||||
Ok(x) => x,
|
||||
Err(_) => {
|
||||
return Err(anyhow!("Failed to write configuration.nix"));
|
||||
}
|
||||
};
|
||||
let mut cmd = tokio::process::Command::new("pkexec")
|
||||
.arg(&exe)
|
||||
.arg("channel")
|
||||
.arg("--rebuild")
|
||||
.arg("--update")
|
||||
.arg("--output")
|
||||
.arg(&systemconfig)
|
||||
.arg("--")
|
||||
.arg("switch")
|
||||
.args(&rebuildargs)
|
||||
.stderr(Stdio::piped())
|
||||
.stdin(Stdio::piped())
|
||||
.spawn()?;
|
||||
cmd.stdin
|
||||
.take()
|
||||
.unwrap()
|
||||
.write_all(newconfig.as_bytes())
|
||||
.await?;
|
||||
cmd
|
||||
} else {
|
||||
tokio::process::Command::new("pkexec")
|
||||
.arg(&exe)
|
||||
.arg("channel")
|
||||
.arg("--rebuild")
|
||||
.arg("--")
|
||||
.arg("switch")
|
||||
.args(&rebuildargs)
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()?
|
||||
}
|
||||
}
|
||||
SystemPkgs::Flake => {
|
||||
if let Some(rmpkgs) = rmpkgs {
|
||||
let newconfig =
|
||||
match nix_editor::write::rmarr(&f, "environment.systemPackages", rmpkgs) {
|
||||
Ok(x) => x,
|
||||
Err(_) => {
|
||||
return Err(anyhow!("Failed to write configuration.nix"));
|
||||
}
|
||||
};
|
||||
let mut cmd = tokio::process::Command::new("pkexec")
|
||||
.arg(&exe)
|
||||
.arg("flake")
|
||||
.arg("--rebuild")
|
||||
.arg("--flakepath")
|
||||
.arg(&flakepath)
|
||||
.arg("--update")
|
||||
.arg("--output")
|
||||
.arg(&systemconfig)
|
||||
.arg("--")
|
||||
.arg("switch")
|
||||
.arg("--impure")
|
||||
.args(&rebuildargs)
|
||||
.stderr(Stdio::piped())
|
||||
.stdin(Stdio::piped())
|
||||
.spawn()?;
|
||||
cmd.stdin
|
||||
.take()
|
||||
.unwrap()
|
||||
.write_all(newconfig.as_bytes())
|
||||
.await?;
|
||||
cmd
|
||||
} else {
|
||||
tokio::process::Command::new("pkexec")
|
||||
.arg(&exe)
|
||||
.arg("flake")
|
||||
.arg("--rebuild")
|
||||
.arg("--flakepath")
|
||||
.arg(&flakepath)
|
||||
.arg("--")
|
||||
.arg("switch")
|
||||
.arg("--impure")
|
||||
.args(&rebuildargs)
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()?
|
||||
}
|
||||
}
|
||||
SystemPkgs::None => return Ok(true),
|
||||
},
|
||||
};
|
||||
@ -321,7 +430,38 @@ async fn updateenv() -> Result<bool> {
|
||||
}
|
||||
}
|
||||
|
||||
async fn updateprofile() -> Result<bool> {
|
||||
async fn updateprofile(rmpkgs: Option<Vec<String>>) -> Result<bool> {
|
||||
if let Some(rmpkgs) = rmpkgs {
|
||||
if !rmpkgs.is_empty() {
|
||||
let mut cmd = tokio::process::Command::new("nix")
|
||||
.arg("profile")
|
||||
.arg("remove")
|
||||
.args(
|
||||
&rmpkgs
|
||||
.iter()
|
||||
.map(|x| format!(
|
||||
"legacyPackages.x86_64-linux.{}",
|
||||
x
|
||||
))
|
||||
.collect::<Vec<String>>()
|
||||
)
|
||||
// Allow updating potential unfree packages
|
||||
.arg("--impure")
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()?;
|
||||
|
||||
let stderr = cmd.stderr.take().unwrap();
|
||||
let reader = tokio::io::BufReader::new(stderr);
|
||||
|
||||
let mut lines = reader.lines();
|
||||
while let Ok(Some(line)) = lines.next_line().await {
|
||||
REBUILD_BROKER.send(RebuildMsg::UpdateText(line.to_string()));
|
||||
trace!("CAUGHT NIX PROFILE LINE: {}", line);
|
||||
}
|
||||
cmd.wait().await?;
|
||||
}
|
||||
}
|
||||
|
||||
let mut cmd = tokio::process::Command::new("nix")
|
||||
.arg("profile")
|
||||
.arg("upgrade")
|
||||
@ -344,4 +484,4 @@ async fn updateprofile() -> Result<bool> {
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
134
src/ui/window.rs
134
src/ui/window.rs
@ -4,7 +4,7 @@ use crate::{
|
||||
config::{editconfig, getconfig},
|
||||
packages::{AppData, LicenseEnum, PkgMaintainer, Platform},
|
||||
},
|
||||
ui::{installedpage::InstalledItem, pkgpage::PkgPageInit, welcome::WelcomeMsg, rebuild::RebuildMsg},
|
||||
ui::{installedpage::InstalledItem, pkgpage::PkgPageInit, welcome::WelcomeMsg, rebuild::RebuildMsg, updatepage::UNAVAILABLE_BROKER, unavailabledialog::UnavailableDialogMsg},
|
||||
APPINFO,
|
||||
};
|
||||
use adw::prelude::*;
|
||||
@ -30,9 +30,9 @@ use super::{
|
||||
pkgtile::PkgTile,
|
||||
preferencespage::{PreferencesPageModel, PreferencesPageMsg},
|
||||
searchpage::{SearchItem, SearchPageModel, SearchPageMsg},
|
||||
updatepage::{UpdateItem, UpdatePageInit, UpdatePageModel, UpdatePageMsg},
|
||||
updatepage::{UpdateItem, UpdatePageInit, UpdatePageModel, UpdatePageMsg, UpdateType},
|
||||
welcome::WelcomeModel,
|
||||
windowloading::{LoadErrorModel, LoadErrorMsg, WindowAsyncHandler, WindowAsyncHandlerMsg}, rebuild::RebuildModel,
|
||||
windowloading::{LoadErrorModel, LoadErrorMsg, WindowAsyncHandler, WindowAsyncHandlerMsg}, rebuild::RebuildModel, unavailabledialog::UnavailableItemModel,
|
||||
};
|
||||
|
||||
pub static REBUILD_BROKER: MessageBroker<RebuildModel> = MessageBroker::new();
|
||||
@ -152,6 +152,7 @@ pub enum AppMsg {
|
||||
LoadCategory(PkgCategory),
|
||||
UpdateRecPkgs(Vec<String>),
|
||||
SetDarkMode(bool),
|
||||
GetUnavailableItems(HashMap<String, String>, HashMap<String, String>, UpdateType),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
@ -1825,6 +1826,133 @@ FROM pkgs JOIN meta ON (pkgs.attribute = meta.attribute) WHERE pkgs.attribute =
|
||||
let scheme = if dark { "Adwaita-dark" } else { "Adwaita" };
|
||||
self.rebuild.emit(RebuildMsg::SetScheme(scheme.to_string()));
|
||||
}
|
||||
AppMsg::GetUnavailableItems(userpkgs, syspkgs, updatetype) => {
|
||||
info!("AppMsg::GetUnavailableItems");
|
||||
let appdata: HashMap<String, AppData> = self
|
||||
.appdata
|
||||
.iter()
|
||||
.filter_map(|(k, v)| {
|
||||
if syspkgs.contains_key(k) || userpkgs.contains_key(k) {
|
||||
Some((k.to_string(), v.clone()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let poolref = self.pkgdb.clone();
|
||||
relm4::spawn(async move {
|
||||
let mut unavailableuser = vec![];
|
||||
let mut unavailablesys = vec![];
|
||||
if let Ok(pool) = &SqlitePool::connect(&format!("sqlite://{}", poolref)).await {
|
||||
let mut sortuserpkgs = userpkgs.into_iter().collect::<Vec<_>>();
|
||||
sortuserpkgs.sort();
|
||||
for (pkg, msg) in sortuserpkgs {
|
||||
if let Some(data) = appdata.get(&pkg) {
|
||||
let pname: Result<(String,), sqlx::Error> =
|
||||
sqlx::query_as("SELECT pname FROM pkgs WHERE attribute = $1")
|
||||
.bind(&pkg)
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
if let Ok(pname) = pname {
|
||||
unavailableuser.push(UnavailableItemModel {
|
||||
pkg: pkg.to_string(),
|
||||
name: if let Some(name) = &data.name {
|
||||
name.get("C").unwrap_or(&pname.0).to_string()
|
||||
} else {
|
||||
pname.0.to_string()
|
||||
},
|
||||
pname: pname.0.to_string(),
|
||||
icon: data
|
||||
.icon
|
||||
.as_ref()
|
||||
.and_then(|x| x.cached.as_ref())
|
||||
.map(|x| x[0].name.clone()),
|
||||
message: msg
|
||||
})
|
||||
} else {
|
||||
unavailableuser.push(UnavailableItemModel {
|
||||
pkg: pkg.to_string(),
|
||||
name: if let Some(name) = &data.name {
|
||||
name.get("C").unwrap_or(&pkg).to_string()
|
||||
} else {
|
||||
pkg.to_string()
|
||||
},
|
||||
pname: String::new(),
|
||||
icon: data
|
||||
.icon
|
||||
.as_ref()
|
||||
.and_then(|x| x.cached.as_ref())
|
||||
.map(|x| x[0].name.clone()),
|
||||
message: msg
|
||||
})
|
||||
}
|
||||
} else {
|
||||
unavailableuser.push(UnavailableItemModel {
|
||||
pkg: pkg.to_string(),
|
||||
name: pkg.to_string(),
|
||||
pname: String::new(),
|
||||
icon: None,
|
||||
message: msg
|
||||
})
|
||||
}
|
||||
}
|
||||
let mut sortsyspkgs = syspkgs.into_iter().collect::<Vec<_>>();
|
||||
sortsyspkgs.sort();
|
||||
for (pkg, msg) in sortsyspkgs {
|
||||
if let Some(data) = appdata.get(&pkg) {
|
||||
let pname: Result<(String,), sqlx::Error> =
|
||||
sqlx::query_as("SELECT pname FROM pkgs WHERE attribute = $1")
|
||||
.bind(&pkg)
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
if let Ok(pname) = pname {
|
||||
unavailablesys.push(UnavailableItemModel {
|
||||
pkg: pkg.to_string(),
|
||||
name: if let Some(name) = &data.name {
|
||||
name.get("C").unwrap_or(&pname.0).to_string()
|
||||
} else {
|
||||
pname.0.to_string()
|
||||
},
|
||||
pname: pname.0.to_string(),
|
||||
icon: data
|
||||
.icon
|
||||
.as_ref()
|
||||
.and_then(|x| x.cached.as_ref())
|
||||
.map(|x| x[0].name.clone()),
|
||||
message: msg
|
||||
})
|
||||
} else {
|
||||
unavailablesys.push(UnavailableItemModel {
|
||||
pkg: pkg.to_string(),
|
||||
name: if let Some(name) = &data.name {
|
||||
name.get("C").unwrap_or(&pkg).to_string()
|
||||
} else {
|
||||
pkg.to_string()
|
||||
},
|
||||
pname: String::new(),
|
||||
icon: data
|
||||
.icon
|
||||
.as_ref()
|
||||
.and_then(|x| x.cached.as_ref())
|
||||
.map(|x| x[0].name.clone()),
|
||||
message: msg
|
||||
})
|
||||
}
|
||||
} else {
|
||||
unavailablesys.push(UnavailableItemModel {
|
||||
pkg: pkg.to_string(),
|
||||
name: pkg.to_string(),
|
||||
pname: String::new(),
|
||||
icon: None,
|
||||
message: msg
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
UNAVAILABLE_BROKER.send(UnavailableDialogMsg::Show(unavailableuser, unavailablesys, updatetype));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user