mirror of
https://github.com/snowfallorg/nix-software-center.git
synced 2024-09-11 21:27:09 +03:00
Add nix profile support
Also broke a bunch of legacy/channel stuff I'll fix later
This commit is contained in:
parent
175e7c23e9
commit
eb3822c07a
@ -30,7 +30,6 @@ reqwest = { version = "0.11", features = ["blocking"] }
|
||||
sha256 = "1.0"
|
||||
image = "0.24"
|
||||
spdx = "0.9"
|
||||
# { git = "https://github.com/EmbarkStudios/spdx", version = "0.8" }
|
||||
edit-distance = "2.1"
|
||||
ijson = "0.1"
|
||||
strum = "0.24"
|
||||
|
@ -51,11 +51,11 @@
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1661361016,
|
||||
"narHash": "sha256-Bjf6ZDnDc6glTwIIItvwfcaeJ5zWFM6GYfPajSArdUY=",
|
||||
"lastModified": 1661720780,
|
||||
"narHash": "sha256-AJNGyaB2eKZAYaPNjBZOzap87yL+F9ZLaFzzMkvega0=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "b784c5ae63dd288375af1b4d37b8a27dd8061887",
|
||||
"rev": "a63021a330d8d33d862a8e29924b42d73037dd37",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -48,6 +48,7 @@
|
||||
buildInputs = with pkgs; [
|
||||
cargo
|
||||
clippy
|
||||
desktop-file-utils
|
||||
rust-analyzer
|
||||
rustc
|
||||
rustfmt
|
||||
@ -58,10 +59,13 @@
|
||||
gtk4
|
||||
gtksourceview5
|
||||
libadwaita-git
|
||||
meson
|
||||
ninja
|
||||
openssl
|
||||
pandoc
|
||||
pango
|
||||
pkgconfig
|
||||
polkit
|
||||
wrapGAppsHook4
|
||||
nixos-appstream-data
|
||||
];
|
||||
|
@ -25,7 +25,16 @@ enum SubCommands {
|
||||
rebuild: bool,
|
||||
/// Run `nixos-rebuild` with the given arguments
|
||||
arguments: Vec<String>,
|
||||
}
|
||||
},
|
||||
Flake {
|
||||
/// Whether to rebuild the system after updating flake
|
||||
#[clap(short, long)]
|
||||
rebuild: bool,
|
||||
/// Path to the flake file
|
||||
flakepath: String,
|
||||
/// Run `nixos-rebuild` with the given arguments
|
||||
arguments: Vec<String>,
|
||||
},
|
||||
}
|
||||
|
||||
fn main() {
|
||||
@ -88,6 +97,24 @@ fn main() {
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
SubCommands::Flake { rebuild: dorebuild, flakepath, arguments } => {
|
||||
match dorebuild {
|
||||
true => match rebuild(arguments) {
|
||||
Ok(_) => (),
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
std::process::exit(1);
|
||||
}
|
||||
},
|
||||
false => match flake(&flakepath) {
|
||||
Ok(_) => (),
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
std::process::exit(1);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -125,10 +152,28 @@ fn channel() -> Result<(), Box<dyn Error>> {
|
||||
if x.success() {
|
||||
Ok(())
|
||||
} else {
|
||||
eprintln!("nixos-rebuild failed with exit code {}", x.code().unwrap());
|
||||
eprintln!("nix-channel failed with exit code {}", x.code().unwrap());
|
||||
Err(Box::new(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"nix-channel failed",
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
fn flake(path: &str) -> Result<(), Box<dyn Error>> {
|
||||
let mut cmd = Command::new("nix")
|
||||
.arg("flake")
|
||||
.arg("upgrade")
|
||||
.arg(path)
|
||||
.spawn()?;
|
||||
let x = cmd.wait()?;
|
||||
if x.success() {
|
||||
Ok(())
|
||||
} else {
|
||||
eprintln!("nix flake failed with exit code {}", x.code().unwrap());
|
||||
Err(Box::new(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"nix flake failed",
|
||||
)))
|
||||
}
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
use std::{path::Path, fs};
|
||||
|
||||
pub mod ui;
|
||||
pub mod parse;
|
||||
pub mod config;
|
||||
|
@ -1,5 +1,6 @@
|
||||
use ijson::IString;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
env,
|
||||
@ -21,13 +22,14 @@ struct NewPackage {
|
||||
}
|
||||
|
||||
pub fn checkcache() -> Result<(), Box<dyn Error>> {
|
||||
setuppkgscache()?;
|
||||
setupupdatecache()?;
|
||||
setupnewestver()?;
|
||||
// setuplegacypkgscache().unwrap();
|
||||
// setupupdatecache().unwrap();
|
||||
// setupnewestver().unwrap();
|
||||
setupflakepkgscache()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn uptodate() -> Result<Option<(String, String)>, Box<dyn Error>> {
|
||||
pub fn uptodatelegacy() -> Result<Option<(String, String)>, Box<dyn Error>> {
|
||||
let cachedir = format!("{}/.cache/nix-software-center", env::var("HOME")?);
|
||||
let oldversion = fs::read_to_string(format!("{}/sysver.txt", cachedir))?
|
||||
.trim()
|
||||
@ -39,11 +41,32 @@ pub fn uptodate() -> Result<Option<(String, String)>, Box<dyn Error>> {
|
||||
println!("System is up to date");
|
||||
Ok(None)
|
||||
} else {
|
||||
println!("OLD {:?} != NEW {:?}", oldversion, newversion);
|
||||
Ok(Some((oldversion, newversion)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn uptodateflake() -> Result<Option<(String, String)>, Box<dyn Error>> {
|
||||
let cachedir = format!("{}/.cache/nix-software-center", env::var("HOME")?);
|
||||
let oldversion = fs::read_to_string(format!("{}/flakever.txt", cachedir))?
|
||||
.trim()
|
||||
.to_string();
|
||||
let newversion = fs::read_to_string(format!("{}/newver.txt", cachedir))?
|
||||
.trim()
|
||||
.to_string();
|
||||
if oldversion == newversion {
|
||||
println!("System is up to date");
|
||||
Ok(None)
|
||||
} else {
|
||||
println!("OLD {:?} != NEW {:?}", oldversion, newversion);
|
||||
if let (Some(oldv), Some(newv)) = (oldversion.get(..8), newversion.get(..8)) {
|
||||
println!("OLD {:?} != NEW {:?}", oldv, newv);
|
||||
Ok(Some((oldv.to_string(), newv.to_string())))
|
||||
} else {
|
||||
Ok(Some((oldversion, newversion)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn channelver() -> Result<Option<(String, String)>, Box<dyn Error>> {
|
||||
let cachedir = format!("{}/.cache/nix-software-center", env::var("HOME")?);
|
||||
let oldversion = fs::read_to_string(format!("{}/chnver.txt", cachedir))?
|
||||
@ -61,7 +84,24 @@ pub fn channelver() -> Result<Option<(String, String)>, Box<dyn Error>> {
|
||||
}
|
||||
}
|
||||
|
||||
fn setuppkgscache() -> Result<(), Box<dyn Error>> {
|
||||
pub fn flakever() -> Result<Option<(String, String)>, Box<dyn Error>> {
|
||||
let cachedir = format!("{}/.cache/nix-software-center", env::var("HOME")?);
|
||||
let oldversion = fs::read_to_string(format!("{}/flakever.txt", cachedir))?
|
||||
.trim()
|
||||
.to_string();
|
||||
let newversion = fs::read_to_string(format!("{}/newver.txt", cachedir))?
|
||||
.trim()
|
||||
.to_string();
|
||||
if oldversion == newversion {
|
||||
println!("Flake hashes match");
|
||||
Ok(None)
|
||||
} else {
|
||||
println!("flakever {:?} != newver {:?}", oldversion, newversion);
|
||||
Ok(Some((oldversion, newversion)))
|
||||
}
|
||||
}
|
||||
|
||||
fn setuplegacypkgscache() -> Result<(), Box<dyn Error>> {
|
||||
let vout = Command::new("nix-instantiate")
|
||||
.arg("-I")
|
||||
.arg("nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos")
|
||||
@ -124,8 +164,187 @@ fn setuppkgscache() -> Result<(), Box<dyn Error>> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn setupflakepkgscache() -> Result<(), Box<dyn Error>> {
|
||||
println!("SETUP FLAKES CACHE");
|
||||
let cachedir = format!("{}/.cache/nix-software-center", env::var("HOME")?);
|
||||
|
||||
// First remove legacy files
|
||||
if Path::new(format!("{}/chnver.txt", &cachedir).as_str()).exists() {
|
||||
fs::remove_file(format!("{}/chnver.txt", &cachedir).as_str())?;
|
||||
}
|
||||
|
||||
let vout = Command::new("nixos-version")
|
||||
.arg("--json")
|
||||
.output()?;
|
||||
|
||||
let versiondata: Value = serde_json::from_str(&String::from_utf8_lossy(&vout.stdout))?;
|
||||
let rev = versiondata.get("nixpkgsRevision").unwrap().as_str().unwrap();
|
||||
let dlver = versiondata.get("nixosVersion").unwrap().as_str().unwrap();
|
||||
|
||||
let mut relver = dlver.split('.').collect::<Vec<&str>>()[0..2].join(".");
|
||||
println!("RELVER {}", relver);
|
||||
if relver == "22.11" {
|
||||
relver = "unstable".to_string();
|
||||
}
|
||||
|
||||
fs::create_dir_all(&cachedir).expect("Failed to create cache directory");
|
||||
let url = format!(
|
||||
"https://channels.nixos.org/nixos-{}/packages.json.br",
|
||||
relver
|
||||
);
|
||||
|
||||
println!("VERSION {}", relver);
|
||||
// let response = reqwest::blocking::get(url)?;
|
||||
// if let Some(latest) = response.url().to_string().split('/').last() {
|
||||
let cachedir = format!("{}/.cache/nix-software-center", env::var("HOME")?);
|
||||
if !Path::new(&cachedir).exists() {
|
||||
fs::create_dir_all(&cachedir).expect("Failed to create cache directory");
|
||||
}
|
||||
|
||||
fn writesyspkgs(outfile: &str) -> Result<(), Box<dyn Error>> {
|
||||
let output = Command::new("nix")
|
||||
.arg("search")
|
||||
.arg("--inputs-from")
|
||||
.arg("/home/victor/nix")
|
||||
.arg("nixpkgs")
|
||||
.arg("--json")
|
||||
.output()?;
|
||||
let mut file = fs::File::create(outfile)?;
|
||||
file.write_all(&output.stdout)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn writeprofilepkgs(outfile: &str) -> Result<(), Box<dyn Error>> {
|
||||
let output = Command::new("nix")
|
||||
.arg("search")
|
||||
.arg("nixpkgs")
|
||||
.arg("--json")
|
||||
.output()?;
|
||||
let mut file = fs::File::create(outfile)?;
|
||||
file.write_all(&output.stdout)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
if !Path::new(&format!("{}/flakever.txt", &cachedir)).exists() {
|
||||
let mut sysver = fs::File::create(format!("{}/flakever.txt", &cachedir))?;
|
||||
sysver.write_all(rev.as_bytes())?;
|
||||
writesyspkgs(&format!("{}/syspackages.json", &cachedir))?;
|
||||
} else {
|
||||
let oldver = fs::read_to_string(&Path::new(format!("{}/flakever.txt", &cachedir).as_str()))?;
|
||||
let sysver = rev;
|
||||
if oldver != sysver {
|
||||
println!("OLD FLAKEVER: {}, != NEW: {}", oldver, sysver);
|
||||
let mut sysver = fs::File::create(format!("{}/flakever.txt", &cachedir))?;
|
||||
sysver.write_all(rev.as_bytes())?;
|
||||
writesyspkgs(&format!("{}/syspackages.json", &cachedir))?;
|
||||
}
|
||||
}
|
||||
|
||||
if !Path::new(&format!("{}/syspackages.json", &cachedir)).exists() {
|
||||
writesyspkgs(&format!("{}/syspackages.json", &cachedir))?;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Check nix profile nixpkgs version
|
||||
let client = reqwest::blocking::Client::builder()
|
||||
.user_agent("request")
|
||||
.build()?;
|
||||
let response = client.get("https://api.github.com/repos/NixOS/nixpkgs/commits/nixpkgs-unstable").send()?;
|
||||
if response.status().is_success() {
|
||||
let profilerevjson = response.text()?;
|
||||
let profilerevdata: Value = serde_json::from_str(&profilerevjson)?;
|
||||
let profilerev = profilerevdata.get("sha").unwrap().as_str().unwrap();
|
||||
println!("PROFILE REV {}", profilerev);
|
||||
|
||||
if !Path::new(&format!("{}/profilever.txt", &cachedir)).exists() {
|
||||
let mut sysver = fs::File::create(format!("{}/profilever.txt", &cachedir))?;
|
||||
sysver.write_all(profilerev.as_bytes())?;
|
||||
writeprofilepkgs(&format!("{}/profilepackages.json", &cachedir))?;
|
||||
} else {
|
||||
let oldver = fs::read_to_string(&Path::new(format!("{}/profilever.txt", &cachedir).as_str()))?;
|
||||
let sysver = profilerev;
|
||||
if oldver != sysver {
|
||||
println!("OLD PROFILEVER: {}, != NEW: {}", oldver, sysver);
|
||||
let mut sysver = fs::File::create(format!("{}/profilever.txt", &cachedir))?;
|
||||
sysver.write_all(profilerev.as_bytes())?;
|
||||
writeprofilepkgs(&format!("{}/profilepackages.json", &cachedir))?;
|
||||
} else {
|
||||
println!("PROFILEVER UP TO DATE");
|
||||
}
|
||||
}
|
||||
}
|
||||
if !Path::new(&format!("{}/profilepackages.json", &cachedir)).exists() {
|
||||
writeprofilepkgs(&format!("{}/profilepackages.json", &cachedir))?;
|
||||
}
|
||||
|
||||
|
||||
// Check newest nixpkgs version
|
||||
let revurl = format!("https://channels.nixos.org/nixos-{}/git-revision", relver);
|
||||
let response = reqwest::blocking::get(revurl)?;
|
||||
let mut dl = false;
|
||||
if response.status().is_success() {
|
||||
let newrev = response.text()?;
|
||||
println!("NEW REV: {}", newrev);
|
||||
if Path::new(&format!("{}/newver.txt", &cachedir)).exists() {
|
||||
let oldrev = fs::read_to_string(&format!("{}/newver.txt", &cachedir))?;
|
||||
if oldrev != newrev {
|
||||
dl = true;
|
||||
}
|
||||
} else {
|
||||
dl = true;
|
||||
}
|
||||
let mut sysver = fs::File::create(format!("{}/newver.txt", &cachedir))?;
|
||||
sysver.write_all(newrev.as_bytes())?;
|
||||
// if !Path::new(&format!("{}/newver.txt", &cachedir)).exists() {
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
||||
// if Path::new(format!("{}/chnver.txt", &cachedir).as_str()).exists()
|
||||
// && fs::read_to_string(&Path::new(format!("{}/chnver.txt", &cachedir).as_str()))? == dlver
|
||||
// && Path::new(format!("{}/packages.json", &cachedir).as_str()).exists()
|
||||
// {
|
||||
// return Ok(());
|
||||
// } else {
|
||||
// let oldver = fs::read_to_string(&Path::new(format!("{}/chnver.txt", &cachedir).as_str()))?;
|
||||
// let sysver = &dlver;
|
||||
// // Change to debug msg
|
||||
// println!("OLD: {}, != NEW: {}", oldver, sysver);
|
||||
// }
|
||||
// if Path::new(format!("{}/chnver.txt", &cachedir).as_str()).exists() {
|
||||
// fs::remove_file(format!("{}/chnver.txt", &cachedir).as_str())?;
|
||||
// }
|
||||
// let mut sysver = fs::File::create(format!("{}/chnver.txt", &cachedir))?;
|
||||
// sysver.write_all(dlver.as_bytes())?;
|
||||
|
||||
|
||||
|
||||
let outfile = format!("{}/packages.json", &cachedir);
|
||||
if dl {
|
||||
dlfile(&url, &outfile)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// nix-instantiate --eval -E '(builtins.getFlake "/home/victor/nix").inputs.nixpkgs.outPath'
|
||||
// nix-env -f /nix/store/sjmq1gphj1arbzf4aqqnygd9pf4hkfkf-source -qa --json > packages.json
|
||||
fn setupupdatecache() -> Result<(), Box<dyn Error>> {
|
||||
let dlver = fs::read_to_string("/run/current-system/nixos-version")?;
|
||||
let vout = Command::new("nix-instantiate")
|
||||
.arg("-I")
|
||||
.arg("nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos")
|
||||
.arg("<nixpkgs/lib>")
|
||||
.arg("-A")
|
||||
.arg("version")
|
||||
.arg("--eval")
|
||||
.arg("--json")
|
||||
.output()?;
|
||||
|
||||
let dlver = String::from_utf8_lossy(&vout.stdout)
|
||||
.to_string()
|
||||
.replace('"', "");
|
||||
// let dlver = fs::read_to_string("/run/current-system/nixos-version")?;
|
||||
|
||||
let mut relver = dlver.split('.').collect::<Vec<&str>>().join(".")[0..5].to_string();
|
||||
|
||||
@ -171,7 +390,7 @@ fn setupupdatecache() -> Result<(), Box<dyn Error>> {
|
||||
dlfile(&url, &outfile)?;
|
||||
let file = File::open(&outfile)?;
|
||||
let reader = BufReader::new(file);
|
||||
let pkgbase: NewPackageBase = simd_json::serde::from_reader(reader).unwrap();
|
||||
let pkgbase: NewPackageBase = simd_json::serde::from_reader(reader)?;
|
||||
let mut outbase = HashMap::new();
|
||||
for (pkg, ver) in pkgbase.packages {
|
||||
outbase.insert(pkg.clone(), ver.version.clone());
|
||||
|
@ -156,23 +156,29 @@ pub struct AppScreenshotImage {
|
||||
pub url: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct FlakeJson {
|
||||
pname: IString,
|
||||
version: IString,
|
||||
}
|
||||
|
||||
pub async fn readpkgs() -> Result<HashMap<String, Package>, Box<dyn Error + Send + Sync>> {
|
||||
let cachedir = format!("{}/.cache/nix-software-center/", env::var("HOME")?);
|
||||
let cachefile = format!("{}/packages.json", cachedir);
|
||||
let file = File::open(cachefile).unwrap();
|
||||
let file = File::open(cachefile)?;
|
||||
let reader = BufReader::new(file);
|
||||
let pkgbase: PackageBase = simd_json::serde::from_reader(reader).unwrap();
|
||||
let pkgbase: PackageBase = simd_json::serde::from_reader(reader)?;
|
||||
let mut pkgs = pkgbase.packages;
|
||||
println!("APPDATADIR {}", APPINFO);
|
||||
let appdata = File::open(&format!("{}/xmls/nixos_x86_64_linux.yml.gz", APPINFO)).unwrap();
|
||||
let appdata = File::open(&format!("{}/xmls/nixos_x86_64_linux.yml.gz", APPINFO))?;
|
||||
let appreader = BufReader::new(appdata);
|
||||
let mut d = GzDecoder::new(appreader);
|
||||
let mut s = String::new();
|
||||
d.read_to_string(&mut s).unwrap();
|
||||
d.read_to_string(&mut s)?;
|
||||
let mut files = s.split("\n---\n").collect::<Vec<_>>();
|
||||
files.remove(0);
|
||||
for f in files {
|
||||
let appstream: AppData = serde_yaml::from_str(f).unwrap();
|
||||
let appstream: AppData = serde_yaml::from_str(f)?;
|
||||
if let Some(p) = pkgs.get_mut(&appstream.package.to_string()) {
|
||||
p.appdata = Some(appstream);
|
||||
}
|
||||
@ -180,11 +186,32 @@ pub async fn readpkgs() -> Result<HashMap<String, Package>, Box<dyn Error + Sen
|
||||
Ok(pkgs)
|
||||
}
|
||||
|
||||
pub fn readsyspkgs() -> Result<HashMap<String, String>, Box<dyn Error + Send + Sync>> {
|
||||
pub fn readlegacysyspkgs() -> Result<HashMap<String, String>, Box<dyn Error + Send + Sync>> {
|
||||
let cachedir = format!("{}/.cache/nix-software-center/", env::var("HOME")?);
|
||||
let cachefile = format!("{}/syspackages.json", cachedir);
|
||||
let file = File::open(cachefile)?;
|
||||
let reader = BufReader::new(file);
|
||||
let newpkgs: HashMap<String, String> = simd_json::serde::from_reader(reader).unwrap();
|
||||
let newpkgs: HashMap<String, String> = simd_json::serde::from_reader(reader)?;
|
||||
Ok(newpkgs)
|
||||
}
|
||||
|
||||
pub fn readflakesyspkgs() -> Result<HashMap<String, String>, Box<dyn Error + Send + Sync>> {
|
||||
println!("READFLAKESYSPKGS");
|
||||
let cachedir = format!("{}/.cache/nix-software-center/", env::var("HOME")?);
|
||||
let cachefile = format!("{}/syspackages.json", cachedir);
|
||||
let file = File::open(cachefile)?;
|
||||
let reader = BufReader::new(file);
|
||||
let newpkgs: HashMap<String, FlakeJson> = simd_json::serde::from_reader(reader)?;
|
||||
let newpkgs = newpkgs.into_iter().filter_map(|(k, v)| if let Some(pkg) = k.strip_prefix("legacyPackages.x86_64-linux.") { Some((pkg.to_string(), v.version.to_string())) } else { None }).collect::<HashMap<_, _>>();
|
||||
Ok(newpkgs)
|
||||
}
|
||||
|
||||
pub fn readprofilepkgs() -> Result<HashMap<String, String>, Box<dyn Error + Send + Sync>> {
|
||||
let cachedir = format!("{}/.cache/nix-software-center/", env::var("HOME")?);
|
||||
let cachefile = format!("{}/profilepackages.json", cachedir);
|
||||
let file = File::open(cachefile)?;
|
||||
let reader = BufReader::new(file);
|
||||
let profilepkgs: HashMap<String, FlakeJson> = simd_json::serde::from_reader(reader)?;
|
||||
let profilepkgs = profilepkgs.into_iter().filter_map(|(k, v)| if let Some(pkg) = k.strip_prefix("legacyPackages.x86_64-linux.") { Some((pkg.to_string(), v.version.to_string())) } else { None }).collect::<HashMap<_, _>>();
|
||||
Ok(profilepkgs)
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
use crate::parse::config::NscConfig;
|
||||
|
||||
use super::pkgpage::{InstallType, PkgAction, PkgMsg, WorkPkg};
|
||||
use super::window::{UserPkgs, SystemPkgs};
|
||||
use relm4::*;
|
||||
use std::error::Error;
|
||||
use std::path::Path;
|
||||
@ -17,6 +18,8 @@ pub struct InstallAsyncHandler {
|
||||
systemconfig: String,
|
||||
flakeargs: Option<String>,
|
||||
pid: Option<u32>,
|
||||
syspkgs: SystemPkgs,
|
||||
userpkgs: UserPkgs,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -27,18 +30,26 @@ pub enum InstallAsyncHandlerMsg {
|
||||
SetPid(Option<u32>),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InstallAsyncHandlerInit {
|
||||
pub syspkgs: SystemPkgs,
|
||||
pub userpkgs: UserPkgs,
|
||||
}
|
||||
|
||||
impl Worker for InstallAsyncHandler {
|
||||
type InitParams = ();
|
||||
type InitParams = InstallAsyncHandlerInit;
|
||||
type Input = InstallAsyncHandlerMsg;
|
||||
type Output = PkgMsg;
|
||||
|
||||
fn init(_params: Self::InitParams, _sender: relm4::ComponentSender<Self>) -> Self {
|
||||
fn init(params: Self::InitParams, _sender: relm4::ComponentSender<Self>) -> Self {
|
||||
Self {
|
||||
process: None,
|
||||
work: None,
|
||||
systemconfig: String::new(),
|
||||
flakeargs: None,
|
||||
pid: None,
|
||||
syspkgs: params.syspkgs,
|
||||
userpkgs: params.userpkgs,
|
||||
tracker: 0,
|
||||
}
|
||||
}
|
||||
@ -61,91 +72,188 @@ impl Worker for InstallAsyncHandler {
|
||||
match work.action {
|
||||
PkgAction::Install => {
|
||||
println!("Installing user package: {}", work.pkg);
|
||||
self.process = Some(relm4::spawn(async move {
|
||||
let mut p = tokio::process::Command::new("nix-env")
|
||||
.arg("-iA")
|
||||
.arg(format!("nixos.{}", work.pkg))
|
||||
.kill_on_drop(true)
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()
|
||||
.expect("Failed to run nix-env");
|
||||
|
||||
let stderr = p.stderr.take().unwrap();
|
||||
let reader = tokio::io::BufReader::new(stderr);
|
||||
|
||||
let mut lines = reader.lines();
|
||||
while let Ok(Some(line)) = lines.next_line().await {
|
||||
println!("CAUGHT LINE: {}", line);
|
||||
}
|
||||
|
||||
match p.wait().await {
|
||||
Ok(o) => {
|
||||
if o.success() {
|
||||
println!(
|
||||
"Removed user package: {} success",
|
||||
work.pkg
|
||||
);
|
||||
// println!("{}", String::from_utf8_lossy(&pstdout));
|
||||
sender.output(PkgMsg::FinishedProcess(work))
|
||||
} else {
|
||||
println!(
|
||||
"Removed user package: {} failed",
|
||||
work.pkg
|
||||
);
|
||||
// println!("{}", String::from_utf8_lossy(&p.stderr));
|
||||
sender.output(PkgMsg::FailedProcess(work));
|
||||
println!("{:?}", self.userpkgs);
|
||||
match self.userpkgs {
|
||||
UserPkgs::Env => {
|
||||
self.process = Some(relm4::spawn(async move {
|
||||
let mut p = tokio::process::Command::new("nix-env")
|
||||
.arg("-iA")
|
||||
.arg(format!("nixos.{}", work.pkg))
|
||||
.kill_on_drop(true)
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()
|
||||
.expect("Failed to run nix-env");
|
||||
|
||||
let stderr = p.stderr.take().unwrap();
|
||||
let reader = tokio::io::BufReader::new(stderr);
|
||||
|
||||
let mut lines = reader.lines();
|
||||
while let Ok(Some(line)) = lines.next_line().await {
|
||||
println!("CAUGHT LINE: {}", line);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("Error removing user package: {}", e);
|
||||
sender.output(PkgMsg::FailedProcess(work));
|
||||
}
|
||||
|
||||
match p.wait().await {
|
||||
Ok(o) => {
|
||||
if o.success() {
|
||||
println!(
|
||||
"Removed user package: {} success",
|
||||
work.pkg
|
||||
);
|
||||
// println!("{}", String::from_utf8_lossy(&pstdout));
|
||||
sender.output(PkgMsg::FinishedProcess(work))
|
||||
} else {
|
||||
println!(
|
||||
"Removed user package: {} failed",
|
||||
work.pkg
|
||||
);
|
||||
// println!("{}", String::from_utf8_lossy(&p.stderr));
|
||||
sender.output(PkgMsg::FailedProcess(work));
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("Error removing user package: {}", e);
|
||||
sender.output(PkgMsg::FailedProcess(work));
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
}));
|
||||
UserPkgs::Profile => {
|
||||
self.process = Some(relm4::spawn(async move {
|
||||
let mut p = tokio::process::Command::new("nix")
|
||||
.arg("profile")
|
||||
.arg("install")
|
||||
.arg(format!("nixpkgs#{}", work.pkg))
|
||||
.kill_on_drop(true)
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()
|
||||
.expect("Failed to run nix profile");
|
||||
|
||||
let stderr = p.stderr.take().unwrap();
|
||||
let reader = tokio::io::BufReader::new(stderr);
|
||||
|
||||
let mut lines = reader.lines();
|
||||
while let Ok(Some(line)) = lines.next_line().await {
|
||||
println!("CAUGHT LINE: {}", line);
|
||||
}
|
||||
|
||||
match p.wait().await {
|
||||
Ok(o) => {
|
||||
if o.success() {
|
||||
println!(
|
||||
"Removed user package: {} success",
|
||||
work.pkg
|
||||
);
|
||||
// println!("{}", String::from_utf8_lossy(&pstdout));
|
||||
sender.output(PkgMsg::FinishedProcess(work))
|
||||
} else {
|
||||
println!(
|
||||
"Removed user package: {} failed",
|
||||
work.pkg
|
||||
);
|
||||
// println!("{}", String::from_utf8_lossy(&p.stderr));
|
||||
sender.output(PkgMsg::FailedProcess(work));
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("Error removing user package: {}", e);
|
||||
sender.output(PkgMsg::FailedProcess(work));
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
PkgAction::Remove => {
|
||||
println!("Removing user package: {}", work.pkg);
|
||||
self.process = Some(relm4::spawn(async move {
|
||||
let mut p = tokio::process::Command::new("nix-env")
|
||||
.arg("-e")
|
||||
.arg(&work.pname)
|
||||
.kill_on_drop(true)
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()
|
||||
.expect("Failed to run nix-env");
|
||||
let stderr = p.stderr.take().unwrap();
|
||||
let reader = tokio::io::BufReader::new(stderr);
|
||||
|
||||
let mut lines = reader.lines();
|
||||
while let Ok(Some(line)) = lines.next_line().await {
|
||||
println!("CAUGHT LINE: {}", line);
|
||||
}
|
||||
match p.wait().await {
|
||||
Ok(o) => {
|
||||
if o.success() {
|
||||
println!(
|
||||
"Removed user package: {} success",
|
||||
work.pkg
|
||||
);
|
||||
// println!("{}", String::from_utf8_lossy(&pstdout));
|
||||
sender.output(PkgMsg::FinishedProcess(work))
|
||||
} else {
|
||||
println!(
|
||||
"Removed user package: {} failed",
|
||||
work.pkg
|
||||
);
|
||||
// println!("{}", String::from_utf8_lossy(&p.stderr));
|
||||
sender.output(PkgMsg::FailedProcess(work));
|
||||
match self.userpkgs {
|
||||
UserPkgs::Env => {
|
||||
self.process = Some(relm4::spawn(async move {
|
||||
let mut p = tokio::process::Command::new("nix-env")
|
||||
.arg("-e")
|
||||
.arg(&work.pname)
|
||||
.kill_on_drop(true)
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()
|
||||
.expect("Failed to run nix-env");
|
||||
let stderr = p.stderr.take().unwrap();
|
||||
let reader = tokio::io::BufReader::new(stderr);
|
||||
|
||||
let mut lines = reader.lines();
|
||||
while let Ok(Some(line)) = lines.next_line().await {
|
||||
println!("CAUGHT LINE: {}", line);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("Error removing user package: {}", e);
|
||||
sender.output(PkgMsg::FailedProcess(work));
|
||||
}
|
||||
match p.wait().await {
|
||||
Ok(o) => {
|
||||
if o.success() {
|
||||
println!(
|
||||
"Removed user package: {} success",
|
||||
work.pkg
|
||||
);
|
||||
// println!("{}", String::from_utf8_lossy(&pstdout));
|
||||
sender.output(PkgMsg::FinishedProcess(work))
|
||||
} else {
|
||||
println!(
|
||||
"Removed user package: {} failed",
|
||||
work.pkg
|
||||
);
|
||||
// println!("{}", String::from_utf8_lossy(&p.stderr));
|
||||
sender.output(PkgMsg::FailedProcess(work));
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("Error removing user package: {}", e);
|
||||
sender.output(PkgMsg::FailedProcess(work));
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
}));
|
||||
UserPkgs::Profile => {
|
||||
self.process = Some(relm4::spawn(async move {
|
||||
let mut p = tokio::process::Command::new("nix")
|
||||
.arg("profile")
|
||||
.arg("remove")
|
||||
.arg(&format!("legacyPackages.x86_64-linux.{}", work.pkg))
|
||||
.kill_on_drop(true)
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()
|
||||
.expect("Failed to run nix profile");
|
||||
let stderr = p.stderr.take().unwrap();
|
||||
let reader = tokio::io::BufReader::new(stderr);
|
||||
|
||||
let mut lines = reader.lines();
|
||||
while let Ok(Some(line)) = lines.next_line().await {
|
||||
println!("CAUGHT LINE: {}", line);
|
||||
}
|
||||
match p.wait().await {
|
||||
Ok(o) => {
|
||||
if o.success() {
|
||||
println!(
|
||||
"Removed user package: {} success",
|
||||
work.pkg
|
||||
);
|
||||
// println!("{}", String::from_utf8_lossy(&pstdout));
|
||||
sender.output(PkgMsg::FinishedProcess(work))
|
||||
} else {
|
||||
println!(
|
||||
"Removed user package: {} failed",
|
||||
work.pkg
|
||||
);
|
||||
// println!("{}", String::from_utf8_lossy(&p.stderr));
|
||||
sender.output(PkgMsg::FailedProcess(work));
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
println!("Error removing user package: {}", e);
|
||||
sender.output(PkgMsg::FailedProcess(work));
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -276,8 +384,8 @@ async fn installsys(
|
||||
let exe = match std::env::current_exe() {
|
||||
Ok(mut e) => {
|
||||
e.pop(); // root/bin
|
||||
// e.pop(); // root/
|
||||
// e.push("libexec"); // root/libexec
|
||||
e.pop(); // root/
|
||||
e.push("libexec"); // root/libexec
|
||||
e.push("nsc-helper");
|
||||
let x = e.to_string_lossy().to_string();
|
||||
println!("CURRENT PATH {}", x);
|
||||
|
@ -9,6 +9,7 @@ use relm4::{factory::FactoryVecDeque, *};
|
||||
use sha256::digest;
|
||||
use std::collections::HashSet;
|
||||
use std::convert::identity;
|
||||
use std::io::Cursor;
|
||||
use std::process::Command;
|
||||
use std::{
|
||||
env,
|
||||
@ -27,6 +28,9 @@ use crate::parse::packages::StrOrVec;
|
||||
use crate::ui::installworker::InstallAsyncHandlerMsg;
|
||||
|
||||
use super::installworker::InstallAsyncHandler;
|
||||
use super::installworker::InstallAsyncHandlerInit;
|
||||
use super::window::SystemPkgs;
|
||||
use super::window::UserPkgs;
|
||||
use super::{screenshotfactory::ScreenshotItem, window::AppMsg};
|
||||
|
||||
#[tracker::track]
|
||||
@ -46,6 +50,9 @@ pub struct PkgModel {
|
||||
maintainers: Vec<PkgMaintainer>,
|
||||
launchable: Option<Launch>,
|
||||
|
||||
syspkgtype: SystemPkgs,
|
||||
userpkgtype: UserPkgs,
|
||||
|
||||
#[tracker::no_eq]
|
||||
screenshots: FactoryVecDeque<ScreenshotItem>,
|
||||
#[tracker::no_eq]
|
||||
@ -158,9 +165,15 @@ pub enum PkgAsyncMsg {
|
||||
SetError(String, usize),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PkgPageTypes {
|
||||
pub syspkgs: SystemPkgs,
|
||||
pub userpkgs: UserPkgs
|
||||
}
|
||||
|
||||
#[relm4::component(pub)]
|
||||
impl Component for PkgModel {
|
||||
type Init = ();
|
||||
type Init = PkgPageTypes;
|
||||
type Input = PkgMsg;
|
||||
type Output = AppMsg;
|
||||
type Widgets = PkgWidgets;
|
||||
@ -188,12 +201,26 @@ impl Component for PkgModel {
|
||||
},
|
||||
pack_end = >k::MenuButton {
|
||||
#[watch]
|
||||
set_label: match model.installtype {
|
||||
InstallType::User => "User (nix-env)",
|
||||
InstallType::System => "System (configuration.nix)",
|
||||
set_label: match model.userpkgtype {
|
||||
UserPkgs::Env => {
|
||||
match model.installtype {
|
||||
InstallType::User => "User (nix-env)",
|
||||
InstallType::System => "System (configuration.nix)",
|
||||
}
|
||||
}
|
||||
UserPkgs::Profile => {
|
||||
match model.installtype {
|
||||
InstallType::User => "User (nix profile)",
|
||||
InstallType::System => "System (configuration.nix)",
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
#[wrap(Some)]
|
||||
set_popover = >k::PopoverMenu::from_model(Some(&installtype)) {}
|
||||
set_popover = >k::PopoverMenu::from_model(Some(&match model.userpkgtype {
|
||||
UserPkgs::Env => installtype,
|
||||
UserPkgs::Profile => installprofiletype,
|
||||
})) {}
|
||||
}
|
||||
},
|
||||
gtk::ScrolledWindow {
|
||||
@ -899,6 +926,10 @@ impl Component for PkgModel {
|
||||
"User (nix-env)" => NixEnvAction,
|
||||
"System (configuration.nix)" => NixSystemAction,
|
||||
},
|
||||
installprofiletype: {
|
||||
"User (nix-profile)" => NixProfileAction,
|
||||
"System (configuration.nix)" => NixSystemAction,
|
||||
},
|
||||
runaction: {
|
||||
"Run without installing" => LaunchAction,
|
||||
"Open interactive shell" => TermShellAction,
|
||||
@ -906,12 +937,12 @@ impl Component for PkgModel {
|
||||
}
|
||||
|
||||
fn init(
|
||||
(): Self::Init,
|
||||
pkgtypes: Self::Init,
|
||||
root: &Self::Root,
|
||||
sender: ComponentSender<Self>,
|
||||
) -> ComponentParts<Self> {
|
||||
let installworker = InstallAsyncHandler::builder()
|
||||
.detach_worker(())
|
||||
.detach_worker(InstallAsyncHandlerInit { syspkgs: pkgtypes.syspkgs.clone(), userpkgs: pkgtypes.userpkgs.clone() })
|
||||
.forward(sender.input_sender(), identity);
|
||||
let config = getconfig();
|
||||
installworker.emit(InstallAsyncHandlerMsg::SetConfig(config.clone()));
|
||||
@ -936,6 +967,8 @@ impl Component for PkgModel {
|
||||
// installinguserpkgs: HashSet::new(),
|
||||
// installingsystempkgs: HashSet::new(),
|
||||
// removinguserpkgs: HashSet::new(),
|
||||
syspkgtype: pkgtypes.syspkgs,
|
||||
userpkgtype: pkgtypes.userpkgs,
|
||||
workqueue: HashSet::new(),
|
||||
launchable: None,
|
||||
tracker: 0,
|
||||
@ -962,6 +995,15 @@ impl Component for PkgModel {
|
||||
})
|
||||
};
|
||||
|
||||
let nixprofile: RelmAction<NixProfileAction> = {
|
||||
let sender = sender.clone();
|
||||
RelmAction::new_stateless(move |_| {
|
||||
println!("NIX PROFILE!");
|
||||
sender.input(PkgMsg::SetInstallType(InstallType::User));
|
||||
// sender.input(AppMsg::Increment);
|
||||
})
|
||||
};
|
||||
|
||||
let nixsystem: RelmAction<NixSystemAction> = {
|
||||
let sender = sender.clone();
|
||||
RelmAction::new_stateless(move |_| {
|
||||
@ -972,6 +1014,7 @@ impl Component for PkgModel {
|
||||
};
|
||||
|
||||
group.add_action(nixenv);
|
||||
group.add_action(nixprofile);
|
||||
group.add_action(nixsystem);
|
||||
|
||||
let actions = group.into_action_group();
|
||||
@ -1124,6 +1167,7 @@ impl Component for PkgModel {
|
||||
let sha = digest(&url);
|
||||
let scrnpath = format!("{}/screenshots/{}", cachedir, sha);
|
||||
let pkg = self.pkg.clone();
|
||||
|
||||
sender.command(move |out, shutdown| {
|
||||
let url = url.clone();
|
||||
let home = home.clone();
|
||||
@ -1135,8 +1179,8 @@ impl Component for PkgModel {
|
||||
if Path::new(&format!("{}.png", scrnpath)).exists() {
|
||||
out.send(PkgAsyncMsg::LoadScreenshot(pkg, i, format!("{}.png", scrnpath)));
|
||||
} else {
|
||||
match reqwest::blocking::get(&url) {
|
||||
Ok(mut response) => {
|
||||
match reqwest::get(&url).await {
|
||||
Ok(response) => {
|
||||
if response.status().is_success() {
|
||||
if !Path::new(&format!(
|
||||
"{}/.cache/nix-software-center/screenshots",
|
||||
@ -1156,43 +1200,49 @@ impl Component for PkgModel {
|
||||
}
|
||||
}
|
||||
if let Ok(mut file) = File::create(&scrnpath) {
|
||||
if response.copy_to(&mut file).is_ok() {
|
||||
fn openimg(scrnpath: &str) -> Result<(), Box<dyn Error>> {
|
||||
// let mut reader = Reader::new(Cursor::new(imgdata.buffer())).with_guessed_format().expect("Cursor io never fails");
|
||||
let img = if let Ok(x) = image::load(BufReader::new(File::open(scrnpath)?), image::ImageFormat::Png) {
|
||||
x
|
||||
} else if let Ok(x) = image::load(BufReader::new(File::open(scrnpath)?), image::ImageFormat::Jpeg) {
|
||||
x
|
||||
} else if let Ok(x) = image::load(BufReader::new(File::open(scrnpath)?), image::ImageFormat::WebP) {
|
||||
x
|
||||
} else {
|
||||
let imgdata = BufReader::new(File::open(scrnpath)?);
|
||||
let format = image::guess_format(imgdata.buffer())?;
|
||||
image::load(imgdata, format)?
|
||||
};
|
||||
let scaled = img.resize(640, 360, FilterType::Lanczos3);
|
||||
let mut output = File::create(&format!("{}.png", scrnpath))?;
|
||||
scaled.write_to(&mut output, ImageFormat::Png)?;
|
||||
if let Err(e) = fs::remove_file(&scrnpath) {
|
||||
eprintln!("{}", e);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
match openimg(&scrnpath) {
|
||||
Ok(_) => {
|
||||
out.send(PkgAsyncMsg::LoadScreenshot(
|
||||
pkg, i, format!("{}.png", scrnpath),
|
||||
));
|
||||
}
|
||||
Err(_) => {
|
||||
if let Ok(b) = response.bytes().await {
|
||||
let mut content = Cursor::new(b);
|
||||
if std::io::copy(&mut content, &mut file).is_ok() {
|
||||
fn openimg(scrnpath: &str) -> Result<(), Box<dyn Error>> {
|
||||
// let mut reader = Reader::new(Cursor::new(imgdata.buffer())).with_guessed_format().expect("Cursor io never fails");
|
||||
let img = if let Ok(x) = image::load(BufReader::new(File::open(scrnpath)?), image::ImageFormat::Png) {
|
||||
x
|
||||
} else if let Ok(x) = image::load(BufReader::new(File::open(scrnpath)?), image::ImageFormat::Jpeg) {
|
||||
x
|
||||
} else if let Ok(x) = image::load(BufReader::new(File::open(scrnpath)?), image::ImageFormat::WebP) {
|
||||
x
|
||||
} else {
|
||||
let imgdata = BufReader::new(File::open(scrnpath)?);
|
||||
let format = image::guess_format(imgdata.buffer())?;
|
||||
image::load(imgdata, format)?
|
||||
};
|
||||
let scaled = img.resize(640, 360, FilterType::Lanczos3);
|
||||
let mut output = File::create(&format!("{}.png", scrnpath))?;
|
||||
scaled.write_to(&mut output, ImageFormat::Png)?;
|
||||
if let Err(e) = fs::remove_file(&scrnpath) {
|
||||
eprintln!("{}", e);
|
||||
}
|
||||
out.send(PkgAsyncMsg::SetError(pkg, i));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
match openimg(&scrnpath) {
|
||||
Ok(_) => {
|
||||
out.send(PkgAsyncMsg::LoadScreenshot(
|
||||
pkg, i, format!("{}.png", scrnpath),
|
||||
));
|
||||
}
|
||||
Err(_) => {
|
||||
if let Err(e) = fs::remove_file(&scrnpath) {
|
||||
eprintln!("{}", e);
|
||||
}
|
||||
out.send(PkgAsyncMsg::SetError(pkg, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.send(PkgAsyncMsg::SetError(pkg, i));
|
||||
eprintln!("Error: {}", response.status());
|
||||
}
|
||||
} else {
|
||||
out.send(PkgAsyncMsg::SetError(pkg, i));
|
||||
@ -1361,7 +1411,8 @@ impl Component for PkgModel {
|
||||
self.installedsystempkgs.remove(&work.pkg);
|
||||
// sender.output(AppMsg::RemoveSystemPkg(work.pkg));
|
||||
}
|
||||
}
|
||||
};
|
||||
sender.output(AppMsg::UpdateUpdatePkgs);
|
||||
}
|
||||
}
|
||||
sender.output(AppMsg::UpdatePkgs(None));
|
||||
@ -1465,6 +1516,7 @@ impl Component for PkgModel {
|
||||
|
||||
relm4::new_action_group!(ModeActionGroup, "mode");
|
||||
relm4::new_stateless_action!(NixEnvAction, ModeActionGroup, "env");
|
||||
relm4::new_stateless_action!(NixProfileAction, ModeActionGroup, "profile");
|
||||
relm4::new_stateless_action!(NixSystemAction, ModeActionGroup, "system");
|
||||
|
||||
relm4::new_action_group!(RunActionGroup, "run");
|
||||
|
@ -5,12 +5,15 @@ use adw::prelude::*;
|
||||
use relm4::*;
|
||||
use relm4_components::open_dialog::*;
|
||||
|
||||
#[tracker::track]
|
||||
#[derive(Debug)]
|
||||
pub struct PreferencesPageModel {
|
||||
hidden: bool,
|
||||
configpath: PathBuf,
|
||||
flake: Option<(PathBuf, String)>,
|
||||
#[tracker::no_eq]
|
||||
open_dialog: Controller<OpenDialog>,
|
||||
#[tracker::no_eq]
|
||||
flake_file_dialog: Controller<OpenDialog>,
|
||||
}
|
||||
|
||||
@ -74,13 +77,13 @@ impl SimpleComponent for PreferencesPageModel {
|
||||
sender.input(PreferencesPageMsg::Open);
|
||||
}
|
||||
},
|
||||
gtk::Button {
|
||||
add_css_class: "flat",
|
||||
set_icon_name: "view-refresh-symbolic",
|
||||
connect_clicked[sender] => move |_| {
|
||||
sender.input(PreferencesPageMsg::SetConfigPath(PathBuf::from("/etc/nixos/configuration.nix")));
|
||||
}
|
||||
}
|
||||
// gtk::Button {
|
||||
// add_css_class: "flat",
|
||||
// set_icon_name: "view-refresh-symbolic",
|
||||
// connect_clicked[sender] => move |_| {
|
||||
// sender.input(PreferencesPageMsg::SetConfigPath(PathBuf::from("/etc/nixos/configuration.nix")));
|
||||
// }
|
||||
// }
|
||||
}
|
||||
},
|
||||
add = &adw::ActionRow {
|
||||
@ -94,7 +97,10 @@ impl SimpleComponent for PreferencesPageModel {
|
||||
sender.input(PreferencesPageMsg::SetFlake(None));
|
||||
}
|
||||
gtk::Inhibit(false)
|
||||
}
|
||||
} @switched,
|
||||
#[track(model.changed(PreferencesPageModel::flake()))]
|
||||
#[block_signal(switched)]
|
||||
set_state: model.flake.is_some()
|
||||
}
|
||||
},
|
||||
add = &adw::ActionRow {
|
||||
@ -133,13 +139,13 @@ impl SimpleComponent for PreferencesPageModel {
|
||||
sender.input(PreferencesPageMsg::OpenFlake);
|
||||
}
|
||||
},
|
||||
gtk::Button {
|
||||
add_css_class: "flat",
|
||||
set_icon_name: "user-trash-symbolic",
|
||||
connect_clicked[sender] => move |_| {
|
||||
sender.input(PreferencesPageMsg::SetFlakePath(PathBuf::new()));
|
||||
}
|
||||
}
|
||||
// gtk::Button {
|
||||
// add_css_class: "flat",
|
||||
// set_icon_name: "user-trash-symbolic",
|
||||
// connect_clicked[sender] => move |_| {
|
||||
// sender.input(PreferencesPageMsg::SetFlakePath(PathBuf::new()));
|
||||
// }
|
||||
// }
|
||||
}
|
||||
},
|
||||
add = &adw::EntryRow {
|
||||
@ -148,7 +154,10 @@ impl SimpleComponent for PreferencesPageModel {
|
||||
set_title: "Flake arguments (--flake path/to/flake.nix#<THIS ENTRY>)",
|
||||
connect_changed[sender] => move |x| {
|
||||
sender.input(PreferencesPageMsg::SetFlakeArg(x.text().to_string()));
|
||||
}
|
||||
} @flakeentry,
|
||||
#[track(model.changed(PreferencesPageModel::flake()))]
|
||||
#[block_signal(flakeentry)]
|
||||
set_text: &model.flake.as_ref().map(|(_, a)| a.to_string()).unwrap_or_default()
|
||||
}
|
||||
|
||||
}
|
||||
@ -181,6 +190,7 @@ impl SimpleComponent for PreferencesPageModel {
|
||||
flake: None,
|
||||
open_dialog,
|
||||
flake_file_dialog,
|
||||
tracker: 0,
|
||||
};
|
||||
|
||||
let widgets = view_output!();
|
||||
@ -189,10 +199,11 @@ impl SimpleComponent for PreferencesPageModel {
|
||||
}
|
||||
|
||||
fn update(&mut self, msg: Self::Input, sender: ComponentSender<Self>) {
|
||||
self.reset();
|
||||
match msg {
|
||||
PreferencesPageMsg::Show(path, flake) => {
|
||||
self.configpath = path;
|
||||
self.flake = flake;
|
||||
self.set_flake(flake);
|
||||
self.hidden = false;
|
||||
println!("FLAKE {:?}", self.flake);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::{parse::{cache::channelver, config::{getconfig, NscConfig}}, APPINFO};
|
||||
|
||||
use super::{pkgpage::InstallType, window::*, updatedialog::{UpdateDialogModel, UpdateDialogMsg}, updateworker::{UpdateAsyncHandler, UpdateAsyncHandlerMsg}};
|
||||
use super::{pkgpage::InstallType, window::*, updatedialog::{UpdateDialogModel, UpdateDialogMsg}, updateworker::{UpdateAsyncHandler, UpdateAsyncHandlerMsg, UpdateAsyncHandlerInit}};
|
||||
use adw::prelude::*;
|
||||
use relm4::{factory::*, gtk::pango, *};
|
||||
use std::{path::Path, convert::identity};
|
||||
@ -18,6 +18,8 @@ pub struct UpdatePageModel {
|
||||
#[tracker::no_eq]
|
||||
updateworker: WorkerController<UpdateAsyncHandler>,
|
||||
config: NscConfig,
|
||||
systype: SystemPkgs,
|
||||
usertype: UserPkgs,
|
||||
updatetracker: u8,
|
||||
}
|
||||
|
||||
@ -37,9 +39,15 @@ pub enum UpdatePageMsg {
|
||||
FailedWorking,
|
||||
}
|
||||
|
||||
pub struct UpdatePageInit {
|
||||
pub window: gtk::Window,
|
||||
pub systype: SystemPkgs,
|
||||
pub usertype: UserPkgs,
|
||||
}
|
||||
|
||||
#[relm4::component(pub)]
|
||||
impl SimpleComponent for UpdatePageModel {
|
||||
type InitParams = gtk::Window;
|
||||
type InitParams = UpdatePageInit;
|
||||
type Input = UpdatePageMsg;
|
||||
type Output = AppMsg;
|
||||
type Widgets = UpdatePageWidgets;
|
||||
@ -178,7 +186,10 @@ impl SimpleComponent for UpdatePageModel {
|
||||
gtk::Label {
|
||||
set_halign: gtk::Align::Start,
|
||||
add_css_class: "title-4",
|
||||
set_label: "User (nix-env)",
|
||||
set_label: match model.usertype {
|
||||
UserPkgs::Env => "User (nix-env)",
|
||||
UserPkgs::Profile => "User (nix profile)",
|
||||
}
|
||||
},
|
||||
gtk::Button {
|
||||
add_css_class: "suggested-action",
|
||||
@ -263,15 +274,15 @@ impl SimpleComponent for UpdatePageModel {
|
||||
}
|
||||
|
||||
fn init(
|
||||
parent_window: Self::InitParams,
|
||||
initparams: Self::InitParams,
|
||||
root: &Self::Root,
|
||||
sender: ComponentSender<Self>,
|
||||
) -> ComponentParts<Self> {
|
||||
let updatedialog = UpdateDialogModel::builder()
|
||||
.launch(parent_window.upcast())
|
||||
.launch(initparams.window.upcast())
|
||||
.forward(sender.input_sender(), identity);
|
||||
let updateworker = UpdateAsyncHandler::builder()
|
||||
.detach_worker(())
|
||||
.detach_worker(UpdateAsyncHandlerInit { syspkgs: initparams.systype.clone(), userpkgs: initparams.usertype.clone() })
|
||||
.forward(sender.input_sender(), identity);
|
||||
|
||||
let config = getconfig();
|
||||
@ -285,6 +296,8 @@ impl SimpleComponent for UpdatePageModel {
|
||||
updatedialog,
|
||||
updateworker,
|
||||
config,
|
||||
systype: initparams.systype,
|
||||
usertype: initparams.usertype,
|
||||
tracker: 0,
|
||||
};
|
||||
|
||||
@ -304,6 +317,8 @@ impl SimpleComponent for UpdatePageModel {
|
||||
self.updateworker.emit(UpdateAsyncHandlerMsg::UpdateConfig(self.config.clone()));
|
||||
}
|
||||
UpdatePageMsg::Update(updateuserlist, updatesystemlist) => {
|
||||
println!("UPDATEUSERLIST: {:?}", updateuserlist);
|
||||
println!("UPDATESYSTEMLIST: {:?}", updatesystemlist);
|
||||
self.channelupdate = channelver().unwrap_or(None);
|
||||
self.update_updatetracker(|_| ());
|
||||
let mut updateuserlist_guard = self.updateuserlist.guard();
|
||||
|
@ -1,10 +1,13 @@
|
||||
use std::{error::Error, path::Path, process::Stdio};
|
||||
use relm4::*;
|
||||
use std::{error::Error, path::Path, process::Stdio};
|
||||
use tokio::io::AsyncBufReadExt;
|
||||
|
||||
use crate::parse::config::NscConfig;
|
||||
|
||||
use super::updatepage::UpdatePageMsg;
|
||||
use super::{
|
||||
updatepage::UpdatePageMsg,
|
||||
window::{SystemPkgs, UserPkgs},
|
||||
};
|
||||
|
||||
#[tracker::track]
|
||||
#[derive(Debug)]
|
||||
@ -13,6 +16,8 @@ pub struct UpdateAsyncHandler {
|
||||
process: Option<JoinHandle<()>>,
|
||||
systemconfig: String,
|
||||
flakeargs: Option<String>,
|
||||
syspkgs: SystemPkgs,
|
||||
userpkgs: UserPkgs,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -34,16 +39,23 @@ enum NscCmd {
|
||||
All,
|
||||
}
|
||||
|
||||
pub struct UpdateAsyncHandlerInit {
|
||||
pub syspkgs: SystemPkgs,
|
||||
pub userpkgs: UserPkgs,
|
||||
}
|
||||
|
||||
impl Worker for UpdateAsyncHandler {
|
||||
type InitParams = ();
|
||||
type InitParams = UpdateAsyncHandlerInit;
|
||||
type Input = UpdateAsyncHandlerMsg;
|
||||
type Output = UpdatePageMsg;
|
||||
|
||||
fn init(_params: Self::InitParams, _sender: relm4::ComponentSender<Self>) -> Self {
|
||||
fn init(params: Self::InitParams, _sender: relm4::ComponentSender<Self>) -> Self {
|
||||
Self {
|
||||
process: None,
|
||||
systemconfig: String::default(),
|
||||
flakeargs: None,
|
||||
syspkgs: params.syspkgs,
|
||||
userpkgs: params.userpkgs,
|
||||
tracker: 0,
|
||||
}
|
||||
}
|
||||
@ -57,9 +69,10 @@ impl Worker for UpdateAsyncHandler {
|
||||
UpdateAsyncHandlerMsg::UpdateChannels => {
|
||||
let systenconfig = self.systemconfig.clone();
|
||||
let flakeargs = self.flakeargs.clone();
|
||||
let syspkgs = self.syspkgs.clone();
|
||||
relm4::spawn(async move {
|
||||
println!("STARTED");
|
||||
let result = runcmd(NscCmd::Channel, systenconfig, flakeargs).await;
|
||||
let result = runcmd(NscCmd::Channel, systenconfig, flakeargs, syspkgs).await;
|
||||
match result {
|
||||
Ok(true) => {
|
||||
println!("CHANNEL DONE");
|
||||
@ -75,9 +88,10 @@ impl Worker for UpdateAsyncHandler {
|
||||
UpdateAsyncHandlerMsg::UpdateChannelsAndSystem => {
|
||||
let systenconfig = self.systemconfig.clone();
|
||||
let flakeargs = self.flakeargs.clone();
|
||||
let syspkgs = self.syspkgs.clone();
|
||||
relm4::spawn(async move {
|
||||
println!("STARTED");
|
||||
let result = runcmd(NscCmd::All, systenconfig, flakeargs).await;
|
||||
let result = runcmd(NscCmd::All, systenconfig, flakeargs, syspkgs).await;
|
||||
match result {
|
||||
Ok(true) => {
|
||||
println!("ALL DONE");
|
||||
@ -93,9 +107,10 @@ impl Worker for UpdateAsyncHandler {
|
||||
UpdateAsyncHandlerMsg::RebuildSystem => {
|
||||
let systenconfig = self.systemconfig.clone();
|
||||
let flakeargs = self.flakeargs.clone();
|
||||
let syspkgs = self.syspkgs.clone();
|
||||
relm4::spawn(async move {
|
||||
println!("STARTED");
|
||||
let result = runcmd(NscCmd::Rebuild, systenconfig, flakeargs).await;
|
||||
let result = runcmd(NscCmd::Rebuild, systenconfig, flakeargs, syspkgs).await;
|
||||
match result {
|
||||
Ok(true) => {
|
||||
println!("REBUILD DONE");
|
||||
@ -109,9 +124,13 @@ impl Worker for UpdateAsyncHandler {
|
||||
});
|
||||
}
|
||||
UpdateAsyncHandlerMsg::UpdateUserPkgs => {
|
||||
let userpkgs = self.userpkgs.clone();
|
||||
relm4::spawn(async move {
|
||||
println!("STARTED");
|
||||
let result = updateenv().await;
|
||||
let result = match userpkgs {
|
||||
UserPkgs::Env => updateenv().await,
|
||||
UserPkgs::Profile => updateprofile().await,
|
||||
};
|
||||
match result {
|
||||
Ok(true) => {
|
||||
println!("USER DONE");
|
||||
@ -125,11 +144,26 @@ impl Worker for UpdateAsyncHandler {
|
||||
});
|
||||
}
|
||||
UpdateAsyncHandlerMsg::UpdateAll => {
|
||||
let systenconfig = self.systemconfig.clone();
|
||||
let systemconfig = self.systemconfig.clone();
|
||||
let flakeargs = self.flakeargs.clone();
|
||||
let syspkgs = self.syspkgs.clone();
|
||||
let userpkgs = self.userpkgs.clone();
|
||||
relm4::spawn(async move {
|
||||
println!("STARTED");
|
||||
let result = runcmd(NscCmd::All, systenconfig, flakeargs).await;
|
||||
// if syspkgs == SystemPkgs::Flake {
|
||||
// if let Some(fa) = &flakeargs {
|
||||
// match updateflake(fa.split('#').collect::<Vec<_>>().first().unwrap().to_string()).await {
|
||||
// Ok(true) => {
|
||||
// println!("FLAKE DONE");
|
||||
// }
|
||||
// _ => {
|
||||
// println!("FLAKE FAILED");
|
||||
// sender.output(UpdatePageMsg::FailedWorking);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
let result = runcmd(NscCmd::All, systemconfig, flakeargs, syspkgs).await;
|
||||
match result {
|
||||
Ok(true) => {
|
||||
println!("ALL pkexec DONE");
|
||||
@ -159,12 +193,13 @@ async fn runcmd(
|
||||
cmd: NscCmd,
|
||||
_systemconfig: String,
|
||||
flakeargs: Option<String>,
|
||||
syspkgs: SystemPkgs,
|
||||
) -> Result<bool, Box<dyn Error + Send + Sync>> {
|
||||
let exe = match std::env::current_exe() {
|
||||
Ok(mut e) => {
|
||||
e.pop(); // root/bin
|
||||
// e.pop(); // root/
|
||||
// e.push("libexec"); // root/libexec
|
||||
e.pop(); // root/
|
||||
e.push("libexec"); // root/libexec
|
||||
e.push("nsc-helper");
|
||||
let x = e.to_string_lossy().to_string();
|
||||
println!("CURRENT PATH {}", x);
|
||||
@ -177,6 +212,9 @@ async fn runcmd(
|
||||
Err(_) => String::from("nsc-helper"),
|
||||
};
|
||||
|
||||
let flakepathsplit = flakeargs.clone().unwrap_or_default().to_string();
|
||||
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")];
|
||||
for arg in x.split(' ') {
|
||||
@ -203,15 +241,28 @@ async fn runcmd(
|
||||
.arg("channel")
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()?,
|
||||
NscCmd::All => tokio::process::Command::new("pkexec")
|
||||
.arg(&exe)
|
||||
.arg("channel")
|
||||
.arg("--rebuild")
|
||||
.arg("--")
|
||||
.arg("switch")
|
||||
.args(&rebuildargs)
|
||||
.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")
|
||||
.args(&rebuildargs)
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()?,
|
||||
},
|
||||
};
|
||||
|
||||
println!("SENT INPUT");
|
||||
@ -259,3 +310,33 @@ async fn updateenv() -> Result<bool, Box<dyn Error + Send + Sync>> {
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
|
||||
async fn updateprofile() -> Result<bool, Box<dyn Error + Send + Sync>> {
|
||||
let mut cmd = tokio::process::Command::new("nix")
|
||||
.arg("profile")
|
||||
.arg("upgrade")
|
||||
.arg("'.*'")
|
||||
// Allow updating potential unfree packages
|
||||
.arg("--impure")
|
||||
.stderr(Stdio::piped())
|
||||
.spawn()?;
|
||||
|
||||
println!("SENT INPUT");
|
||||
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 {
|
||||
println!("CAUGHT NIX PROFILE LINE: {}", line);
|
||||
}
|
||||
println!("READER DONE");
|
||||
if cmd.wait().await?.success() {
|
||||
println!("SUCCESS");
|
||||
// sender.input(InstallAsyncHandlerMsg::SetPid(None));
|
||||
Ok(true)
|
||||
} else {
|
||||
println!("FAILURE");
|
||||
// sender.input(InstallAsyncHandlerMsg::SetPid(None));
|
||||
Ok(false)
|
||||
}
|
||||
}
|
371
src/ui/window.rs
371
src/ui/window.rs
@ -1,16 +1,17 @@
|
||||
use std::{collections::{HashMap, HashSet}, convert::identity, error::Error, process::Command, fs, io, path::PathBuf};
|
||||
use std::{collections::{HashMap, HashSet}, convert::identity, error::Error, process::Command, fs, io, path::{PathBuf, Path}, sync::Arc};
|
||||
use ijson::IValue;
|
||||
use relm4::{actions::*, factory::*, *};
|
||||
use adw::prelude::*;
|
||||
use edit_distance;
|
||||
use serde_json::Value;
|
||||
use spdx::Expression;
|
||||
use crate::{parse::{packages::{Package, LicenseEnum, Platform}, cache::uptodate, config::{NscConfig, getconfig, editconfig}}, ui::installedpage::InstalledItem, APPINFO};
|
||||
use crate::{parse::{packages::{Package, LicenseEnum, Platform}, cache::{uptodatelegacy, uptodateflake}, config::{NscConfig, getconfig, editconfig}}, ui::{installedpage::InstalledItem, pkgpage::PkgPageTypes}, APPINFO};
|
||||
|
||||
use super::{
|
||||
categories::{PkgGroup, PkgCategory},
|
||||
pkgtile::PkgTile,
|
||||
pkgpage::{PkgModel, PkgMsg, PkgInitModel, self, InstallType, WorkPkg},
|
||||
windowloading::{LoadErrorModel, LoadErrorMsg, WindowAsyncHandler, WindowAsyncHandlerMsg, CacheReturn}, searchpage::{SearchPageModel, SearchPageMsg, SearchItem}, installedpage::{InstalledPageModel, InstalledPageMsg}, updatepage::{UpdatePageModel, UpdatePageMsg, UpdateItem}, about::{AboutPageModel, AboutPageMsg}, preferencespage::{PreferencesPageModel, PreferencesPageMsg}, categorypage::{CategoryPageModel, CategoryPageMsg}, categorytile::CategoryTile,
|
||||
windowloading::{LoadErrorModel, LoadErrorMsg, WindowAsyncHandler, WindowAsyncHandlerMsg, CacheReturn}, searchpage::{SearchPageModel, SearchPageMsg, SearchItem}, installedpage::{InstalledPageModel, InstalledPageMsg}, updatepage::{UpdatePageModel, UpdatePageMsg, UpdateItem, UpdatePageInit}, about::{AboutPageModel, AboutPageMsg}, preferencespage::{PreferencesPageModel, PreferencesPageMsg}, categorypage::{CategoryPageModel, CategoryPageMsg}, categorytile::CategoryTile,
|
||||
};
|
||||
|
||||
#[derive(PartialEq)]
|
||||
@ -25,6 +26,19 @@ enum MainPage {
|
||||
CategoryPage,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum SystemPkgs {
|
||||
Legacy,
|
||||
Flake,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum UserPkgs {
|
||||
Env,
|
||||
Profile,
|
||||
}
|
||||
|
||||
|
||||
#[tracker::track]
|
||||
pub struct AppModel {
|
||||
application: adw::Application,
|
||||
@ -40,10 +54,13 @@ pub struct AppModel {
|
||||
#[tracker::no_eq]
|
||||
pkgs: HashMap<String, Package>,
|
||||
syspkgs: HashMap<String, String>,
|
||||
profilepkgs: Option<HashMap<String, String>>,
|
||||
// pkgset: HashSet<String>,
|
||||
pkgitems: HashMap<String, PkgItem>,
|
||||
installeduserpkgs: HashMap<String, String>,
|
||||
installedsystempkgs: HashSet<String>,
|
||||
syspkgtype: SystemPkgs,
|
||||
userpkgtype: UserPkgs,
|
||||
categoryrec: HashMap<PkgCategory, Vec<String>>,
|
||||
categoryall: HashMap<PkgCategory, Vec<String>>,
|
||||
#[tracker::no_eq]
|
||||
@ -76,7 +93,7 @@ pub enum AppMsg {
|
||||
ReloadUpdate,
|
||||
Close,
|
||||
LoadError(String, String),
|
||||
Initialize(HashMap<String, Package>, Vec<String>, HashMap<String, String>, HashMap<PkgCategory, Vec<String>>, HashMap<PkgCategory, Vec<String>>),
|
||||
Initialize(HashMap<String, Package>, Vec<String>, HashMap<String, String>, HashMap<PkgCategory, Vec<String>>, HashMap<PkgCategory, Vec<String>>, Option<HashMap<String, String>> /* profile pkgs */),
|
||||
ReloadUpdateItems(HashMap<String, Package>, HashMap<String, String>),
|
||||
OpenPkg(String),
|
||||
FrontPage,
|
||||
@ -336,6 +353,35 @@ impl Component for AppModel {
|
||||
root: &Self::Root,
|
||||
sender: ComponentSender<Self>,
|
||||
) -> ComponentParts<Self> {
|
||||
|
||||
let userpkgtype = if let Ok(h) = std::env::var("HOME") {
|
||||
if Path::new(&format!("{}/.nix-profile/manifest.json", h)).exists() {
|
||||
UserPkgs::Profile
|
||||
} else {
|
||||
UserPkgs::Env
|
||||
}
|
||||
} else {
|
||||
UserPkgs::Env
|
||||
};
|
||||
|
||||
let syspkgtype = match fs::read_to_string("/run/current-system/nixos-version") {
|
||||
Ok(s) => {
|
||||
if let Some(last) = s.split('.').last() {
|
||||
if last.len() == 7 {
|
||||
SystemPkgs::Flake
|
||||
} else {
|
||||
SystemPkgs::Legacy
|
||||
}
|
||||
} else {
|
||||
SystemPkgs::Legacy
|
||||
}
|
||||
}
|
||||
Err(_) => SystemPkgs::Legacy,
|
||||
};
|
||||
println!("userpkgtype: {:?}", userpkgtype);
|
||||
println!("syspkgtype: {:?}", syspkgtype);
|
||||
|
||||
|
||||
let windowloading = WindowAsyncHandler::builder()
|
||||
.detach_worker(())
|
||||
.forward(sender.input_sender(), identity);
|
||||
@ -343,7 +389,10 @@ impl Component for AppModel {
|
||||
.launch(root.clone().upcast())
|
||||
.forward(sender.input_sender(), identity);
|
||||
let pkgpage = PkgModel::builder()
|
||||
.launch(())
|
||||
.launch(PkgPageTypes {
|
||||
userpkgs: userpkgtype.clone(),
|
||||
syspkgs: syspkgtype.clone(),
|
||||
})
|
||||
.forward(sender.input_sender(), identity);
|
||||
let searchpage = SearchPageModel::builder()
|
||||
.launch(())
|
||||
@ -355,7 +404,8 @@ impl Component for AppModel {
|
||||
.launch(())
|
||||
.forward(sender.input_sender(), identity);
|
||||
let updatepage = UpdatePageModel::builder()
|
||||
.launch(root.clone().upcast())
|
||||
// ADD FLAKE DETECTION
|
||||
.launch(UpdatePageInit { window: root.clone().upcast(), systype: syspkgtype.clone(), usertype: userpkgtype.clone() })
|
||||
.forward(sender.input_sender(), identity);
|
||||
let viewstack = adw::ViewStack::new();
|
||||
|
||||
@ -375,6 +425,9 @@ impl Component for AppModel {
|
||||
pkgitems: HashMap::new(),
|
||||
installeduserpkgs: HashMap::new(),
|
||||
installedsystempkgs: HashSet::new(),
|
||||
profilepkgs: None,
|
||||
syspkgtype,
|
||||
userpkgtype,
|
||||
categoryrec: HashMap::new(),
|
||||
categoryall: HashMap::new(),
|
||||
recommendedapps: FactoryVecDeque::new(gtk::FlowBox::new(), &sender.input),
|
||||
@ -393,7 +446,7 @@ impl Component for AppModel {
|
||||
tracker: 0,
|
||||
};
|
||||
|
||||
model.windowloading.emit(WindowAsyncHandlerMsg::CheckCache(CacheReturn::Init));
|
||||
model.windowloading.emit(WindowAsyncHandlerMsg::CheckCache(CacheReturn::Init, model.syspkgtype.clone(), model.userpkgtype.clone()));
|
||||
let recbox = model.recommendedapps.widget();
|
||||
let categorybox = model.categories.widget();
|
||||
let viewstack = &model.viewstack;
|
||||
@ -444,10 +497,10 @@ impl Component for AppModel {
|
||||
match msg {
|
||||
AppMsg::TryLoad => {
|
||||
self.busy = true;
|
||||
self.windowloading.emit(WindowAsyncHandlerMsg::CheckCache(CacheReturn::Init));
|
||||
self.windowloading.emit(WindowAsyncHandlerMsg::CheckCache(CacheReturn::Init, self.syspkgtype.clone(), self.userpkgtype.clone()));
|
||||
}
|
||||
AppMsg::ReloadUpdate => {
|
||||
self.windowloading.emit(WindowAsyncHandlerMsg::CheckCache(CacheReturn::Update));
|
||||
self.windowloading.emit(WindowAsyncHandlerMsg::CheckCache(CacheReturn::Update, self.syspkgtype.clone(), self.userpkgtype.clone()));
|
||||
}
|
||||
AppMsg::Close => {
|
||||
self.application.quit();
|
||||
@ -479,8 +532,9 @@ impl Component for AppModel {
|
||||
self.pkgpage.emit(PkgMsg::UpdateConfig(self.config.clone()));
|
||||
self.updatepage.emit(UpdatePageMsg::UpdateConfig(self.config.clone()));
|
||||
}
|
||||
AppMsg::Initialize(pkgs, recommendedapps, syspkgs, categoryrec, categoryall) => {
|
||||
AppMsg::Initialize(pkgs, recommendedapps, syspkgs, categoryrec, categoryall, profilepkgs) => {
|
||||
self.syspkgs = syspkgs;
|
||||
self.profilepkgs = profilepkgs;
|
||||
self.categoryrec = categoryrec;
|
||||
self.categoryall = categoryall;
|
||||
let mut pkgitems = HashMap::new();
|
||||
@ -791,7 +845,7 @@ impl Component for AppModel {
|
||||
}
|
||||
}
|
||||
|
||||
fn getuserpkgs() -> Result<HashMap<String, String>, Box<dyn Error>> {
|
||||
fn getuserenvpkgs() -> Result<HashMap<String, String>, Box<dyn Error>> {
|
||||
let out = Command::new("nix-env").arg("-q").arg("--json").output()?;
|
||||
let data: IValue = serde_json::from_str(&String::from_utf8_lossy(&out.stdout))?;
|
||||
let mut pcurrpkgs = HashMap::new();
|
||||
@ -810,6 +864,45 @@ impl Component for AppModel {
|
||||
Ok(pcurrpkgs)
|
||||
}
|
||||
|
||||
fn getuserprofilepkgs() -> Result<HashMap<String, String>, Box<dyn Error>> {
|
||||
let data: IValue = serde_json::from_str(&fs::read_to_string(Path::new(&format!("{}/.nix-profile/manifest.json", std::env::var("HOME")?)))?)?;
|
||||
let mut pcurrpkgs = HashMap::new();
|
||||
for pkg in data.as_object().unwrap()["elements"].as_array().unwrap().iter() {
|
||||
if let Some(p) = pkg.get("attrPath") {
|
||||
if let Some(pkgname) = p.as_string()
|
||||
.unwrap()
|
||||
// Change to current platform
|
||||
.strip_prefix("legacyPackages.x86_64-linux.") {
|
||||
if let Some(sp) = pkg.get("storePaths") {
|
||||
if let Some(sp) = sp.as_array().unwrap().get(0) {
|
||||
let storepath = sp.as_string().unwrap().to_string();
|
||||
let output = Command::new("nix")
|
||||
.arg("show-derivation")
|
||||
.arg(&storepath)
|
||||
.output()?;
|
||||
let data: Value = serde_json::from_str(&String::from_utf8_lossy(&output.stdout))?;
|
||||
if let Some(version) = data.as_object().unwrap().values().next().unwrap()["env"].get("version") {
|
||||
let version = version.as_str().unwrap().to_string();
|
||||
pcurrpkgs.insert(
|
||||
pkgname.to_string(),
|
||||
version,
|
||||
);
|
||||
} else {
|
||||
pcurrpkgs.insert(
|
||||
pkgname.to_string(),
|
||||
String::default(),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("CURRENT PROFILE PKGS: {:?}", pcurrpkgs);
|
||||
Ok(pcurrpkgs)
|
||||
}
|
||||
|
||||
let systempkgs = match getsystempkgs(&self.config.systemconfig) {
|
||||
Ok(x) => x,
|
||||
Err(_) => {
|
||||
@ -817,10 +910,22 @@ impl Component for AppModel {
|
||||
}
|
||||
};
|
||||
|
||||
let userpkgs = match getuserpkgs() {
|
||||
Ok(out) => out,
|
||||
Err(_) => {
|
||||
self.installeduserpkgs.clone()
|
||||
let userpkgs = match self.userpkgtype {
|
||||
UserPkgs::Env => {
|
||||
match getuserenvpkgs() {
|
||||
Ok(out) => out,
|
||||
Err(_) => {
|
||||
self.installeduserpkgs.clone()
|
||||
}
|
||||
}
|
||||
},
|
||||
UserPkgs::Profile => {
|
||||
match getuserprofilepkgs() {
|
||||
Ok(out) => out,
|
||||
Err(_) => {
|
||||
self.installeduserpkgs.clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -880,34 +985,53 @@ impl Component for AppModel {
|
||||
}
|
||||
AppMsg::UpdateInstalledPkgs => {
|
||||
let mut installeduseritems = vec![];
|
||||
for installedpname in self.installeduserpkgs.keys() {
|
||||
let possibleitems = self.pkgitems.iter().filter(|(_, x)| &x.pname == installedpname);
|
||||
let count = possibleitems.clone().count();
|
||||
match count {
|
||||
1 => {
|
||||
let (pkg, data) = possibleitems.collect::<Vec<_>>()[0];
|
||||
installeduseritems.push(InstalledItem {
|
||||
name: data.name.clone(),
|
||||
pname: data.pname.clone(),
|
||||
pkg: Some(pkg.clone()),
|
||||
summary: data.summary.clone(),
|
||||
icon: data.icon.clone(),
|
||||
pkgtype: InstallType::User,
|
||||
busy: self.installedpagebusy.contains(&(data.pname.clone(), InstallType::User)),
|
||||
})
|
||||
match self.userpkgtype {
|
||||
UserPkgs::Env => {
|
||||
for installedpname in self.installeduserpkgs.keys() {
|
||||
let possibleitems = self.pkgitems.iter().filter(|(_, x)| &x.pname == installedpname);
|
||||
let count = possibleitems.clone().count();
|
||||
match count {
|
||||
1 => {
|
||||
let (pkg, data) = possibleitems.collect::<Vec<_>>()[0];
|
||||
installeduseritems.push(InstalledItem {
|
||||
name: data.name.clone(),
|
||||
pname: data.pname.clone(),
|
||||
pkg: Some(pkg.clone()),
|
||||
summary: data.summary.clone(),
|
||||
icon: data.icon.clone(),
|
||||
pkgtype: InstallType::User,
|
||||
busy: self.installedpagebusy.contains(&(data.pname.clone(), InstallType::User)),
|
||||
})
|
||||
}
|
||||
2.. => {
|
||||
installeduseritems.push(InstalledItem {
|
||||
name: installedpname.clone(),
|
||||
pname: installedpname.clone(),
|
||||
pkg: None,
|
||||
summary: None, //data.summary.clone(),
|
||||
icon: None, //data.icon.clone(),
|
||||
pkgtype: InstallType::User,
|
||||
busy: self.installedpagebusy.contains(&(installedpname.clone(), InstallType::User)),
|
||||
})
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
2.. => {
|
||||
installeduseritems.push(InstalledItem {
|
||||
name: installedpname.clone(),
|
||||
pname: installedpname.clone(),
|
||||
pkg: None,
|
||||
summary: None, //data.summary.clone(),
|
||||
icon: None, //data.icon.clone(),
|
||||
pkgtype: InstallType::User,
|
||||
busy: self.installedpagebusy.contains(&(installedpname.clone(), InstallType::User)),
|
||||
})
|
||||
}
|
||||
UserPkgs::Profile => {
|
||||
for installedpkg in self.installeduserpkgs.keys() {
|
||||
if let Some(item) = self.pkgitems.get(installedpkg) {
|
||||
installeduseritems.push(InstalledItem {
|
||||
name: item.name.clone(),
|
||||
pname: item.pname.clone(),
|
||||
pkg: Some(item.pkg.clone()),
|
||||
summary: item.summary.clone(),
|
||||
icon: item.icon.clone(),
|
||||
pkgtype: InstallType::User,
|
||||
busy: self.installedpagebusy.contains(&(item.pkg.clone(), InstallType::User)),
|
||||
})
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -930,54 +1054,84 @@ impl Component for AppModel {
|
||||
self.installedpage.emit(InstalledPageMsg::Update(installeduseritems, installedsystemitems));
|
||||
}
|
||||
AppMsg::UpdateUpdatePkgs => {
|
||||
println!("InstalledUserPkgs: {:?}", self.installeduserpkgs);
|
||||
println!("InstalledSystemPkgs: {:?}", self.installedsystempkgs);
|
||||
let mut updateuseritems = vec![];
|
||||
for (installedpname, version) in self.installeduserpkgs.iter() {
|
||||
let possibleitems = self.pkgitems.iter().filter(|(_, x)| &x.pname == installedpname);
|
||||
let count = possibleitems.clone().count();
|
||||
match count {
|
||||
1 => {
|
||||
let (pkg, data) = possibleitems.collect::<Vec<_>>()[0];
|
||||
if &data.version != version {
|
||||
updateuseritems.push(UpdateItem {
|
||||
name: data.name.clone(),
|
||||
pname: data.pname.clone(),
|
||||
pkg: Some(pkg.clone()),
|
||||
summary: data.summary.clone(),
|
||||
icon: data.icon.clone(),
|
||||
pkgtype: InstallType::User,
|
||||
verfrom: Some(version.clone()),
|
||||
verto: Some(data.version.clone()),
|
||||
})
|
||||
} else {
|
||||
println!("Pkg {} is up to date", pkg);
|
||||
match self.userpkgtype {
|
||||
UserPkgs::Env => {
|
||||
for (installedpname, version) in self.installeduserpkgs.iter() {
|
||||
let possibleitems = self.pkgitems.iter().filter(|(_, x)| &x.pname == installedpname);
|
||||
let count = possibleitems.clone().count();
|
||||
match count {
|
||||
1 => {
|
||||
let (pkg, data) = possibleitems.collect::<Vec<_>>()[0];
|
||||
if &data.version != version {
|
||||
updateuseritems.push(UpdateItem {
|
||||
name: data.name.clone(),
|
||||
pname: data.pname.clone(),
|
||||
pkg: Some(pkg.clone()),
|
||||
summary: data.summary.clone(),
|
||||
icon: data.icon.clone(),
|
||||
pkgtype: InstallType::User,
|
||||
verfrom: Some(version.clone()),
|
||||
verto: Some(data.version.clone()),
|
||||
})
|
||||
} else {
|
||||
println!("Pkg {} is up to date", pkg);
|
||||
}
|
||||
}
|
||||
2.. => {
|
||||
let mut update = true;
|
||||
for (pkg, _) in possibleitems {
|
||||
if let Some(ver) = self.syspkgs.get(pkg) {
|
||||
if version == ver {
|
||||
update = false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if update {
|
||||
updateuseritems.push(UpdateItem {
|
||||
name: installedpname.clone(),
|
||||
pname: installedpname.clone(),
|
||||
pkg: None,
|
||||
summary: None, //data.summary.clone(),
|
||||
icon: None, //data.icon.clone(),
|
||||
pkgtype: InstallType::User,
|
||||
verfrom: Some(version.clone()),
|
||||
verto: None,
|
||||
})
|
||||
} else {
|
||||
println!("Pkg {} is up to date", installedpname);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
2.. => {
|
||||
let mut update = true;
|
||||
for (pkg, _) in possibleitems {
|
||||
if let Some(ver) = self.syspkgs.get(pkg) {
|
||||
if version == ver {
|
||||
update = false;
|
||||
}
|
||||
UserPkgs::Profile => {
|
||||
for (installedpkg, version) in &self.installeduserpkgs {
|
||||
if let Some(item) = self.pkgitems.get(installedpkg) {
|
||||
if let Some(profilepkgs) = &self.profilepkgs {
|
||||
if let Some(newver) = profilepkgs.get(installedpkg) {
|
||||
if version != newver {
|
||||
updateuseritems.push(UpdateItem {
|
||||
name: item.name.clone(),
|
||||
pname: item.pname.clone(),
|
||||
pkg: Some(item.pkg.clone()),
|
||||
summary: item.summary.clone(),
|
||||
icon: item.icon.clone(),
|
||||
pkgtype: InstallType::User,
|
||||
verfrom: Some(version.clone()),
|
||||
verto: Some(newver.clone()),
|
||||
})
|
||||
} else {
|
||||
println!("Pkg {} is up to date. Ver: {}", item.pname, version);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if update {
|
||||
updateuseritems.push(UpdateItem {
|
||||
name: installedpname.clone(),
|
||||
pname: installedpname.clone(),
|
||||
pkg: None,
|
||||
summary: None, //data.summary.clone(),
|
||||
icon: None, //data.icon.clone(),
|
||||
pkgtype: InstallType::User,
|
||||
verfrom: Some(version.clone()),
|
||||
verto: None,
|
||||
})
|
||||
} else {
|
||||
println!("Pkg {} is up to date", installedpname);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
updateuseritems.sort_by(|a, b| a.name.to_lowercase().cmp(&b.name.to_lowercase()));
|
||||
@ -1004,17 +1158,35 @@ impl Component for AppModel {
|
||||
}
|
||||
}
|
||||
updatesystemitems.sort_by(|a, b| a.name.to_lowercase().cmp(&b.name.to_lowercase()));
|
||||
if let Ok(Some((old, new))) = uptodate() {
|
||||
updatesystemitems.insert(0, UpdateItem {
|
||||
name: String::from("NixOS System"),
|
||||
pname: String::new(),
|
||||
pkg: None,
|
||||
summary: Some(String::from("NixOS internal packages and modules")),
|
||||
icon: None,
|
||||
pkgtype: InstallType::System,
|
||||
verfrom: Some(old),
|
||||
verto: Some(new),
|
||||
})
|
||||
match self.syspkgtype {
|
||||
SystemPkgs::Legacy => {
|
||||
if let Ok(Some((old, new))) = uptodatelegacy() {
|
||||
updatesystemitems.insert(0, UpdateItem {
|
||||
name: String::from("NixOS System"),
|
||||
pname: String::new(),
|
||||
pkg: None,
|
||||
summary: Some(String::from("NixOS internal packages and modules")),
|
||||
icon: None,
|
||||
pkgtype: InstallType::System,
|
||||
verfrom: Some(old),
|
||||
verto: Some(new),
|
||||
})
|
||||
}
|
||||
}
|
||||
SystemPkgs::Flake => {
|
||||
if let Ok(Some((old, new))) = uptodateflake() {
|
||||
updatesystemitems.insert(0, UpdateItem {
|
||||
name: String::from("NixOS System"),
|
||||
pname: String::new(),
|
||||
pkg: None,
|
||||
summary: Some(String::from("NixOS internal packages and modules")),
|
||||
icon: None,
|
||||
pkgtype: InstallType::System,
|
||||
verfrom: Some(old),
|
||||
verto: Some(new),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
self.updatepage.emit(UpdatePageMsg::Update(updateuseritems, updatesystemitems));
|
||||
}
|
||||
@ -1119,7 +1291,18 @@ impl Component for AppModel {
|
||||
let preferencespage = PreferencesPageModel::builder()
|
||||
.launch(self.mainwindow.clone().upcast())
|
||||
.forward(sender.input_sender(), identity);
|
||||
preferencespage.emit(PreferencesPageMsg::Show(PathBuf::from(&self.config.systemconfig), None));
|
||||
if let Some(flake) = &self.config.flake {
|
||||
let flakeparts = flake.split('#').collect::<Vec<&str>>();
|
||||
if let Some(p) = flakeparts.first() {
|
||||
let path = PathBuf::from(p);
|
||||
let args = flakeparts.get(1).unwrap_or(&"").to_string();
|
||||
preferencespage.emit(PreferencesPageMsg::Show(PathBuf::from(&self.config.systemconfig), Some((path, args))))
|
||||
} else {
|
||||
preferencespage.emit(PreferencesPageMsg::Show(PathBuf::from(&self.config.systemconfig), None))
|
||||
}
|
||||
} else {
|
||||
preferencespage.emit(PreferencesPageMsg::Show(PathBuf::from(&self.config.systemconfig), None))
|
||||
}
|
||||
}
|
||||
AppMsg::AddInstalledToWorkQueue(work) => {
|
||||
println!("ADDING INSTALLED TO WORK QUEUE {:?}", work);
|
||||
|
@ -1,9 +1,13 @@
|
||||
use super::window::AppMsg;
|
||||
use super::window::SystemPkgs;
|
||||
use crate::parse::cache::checkcache;
|
||||
use crate::parse::packages::readflakesyspkgs;
|
||||
use crate::parse::packages::readpkgs;
|
||||
use crate::parse::packages::readsyspkgs;
|
||||
use crate::parse::packages::readlegacysyspkgs;
|
||||
use crate::parse::packages::Package;
|
||||
use crate::parse::packages::readprofilepkgs;
|
||||
use crate::ui::categories::PkgCategory;
|
||||
use crate::ui::window::UserPkgs;
|
||||
use rand::prelude::SliceRandom;
|
||||
use rand::thread_rng;
|
||||
use relm4::adw::prelude::*;
|
||||
@ -15,7 +19,7 @@ pub struct WindowAsyncHandler;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum WindowAsyncHandlerMsg {
|
||||
CheckCache(CacheReturn),
|
||||
CheckCache(CacheReturn, SystemPkgs, UserPkgs),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
@ -35,7 +39,7 @@ impl Worker for WindowAsyncHandler {
|
||||
|
||||
fn update(&mut self, msg: Self::Input, sender: ComponentSender<Self>) {
|
||||
match msg {
|
||||
WindowAsyncHandlerMsg::CheckCache(cr) => {
|
||||
WindowAsyncHandlerMsg::CheckCache(cr, syspkgs, userpkgs) => {
|
||||
println!("CHECK CACHE");
|
||||
relm4::spawn(async move {
|
||||
match checkcache() {
|
||||
@ -65,19 +69,47 @@ impl Worker for WindowAsyncHandler {
|
||||
}
|
||||
};
|
||||
|
||||
let newpkgs = match readsyspkgs() {
|
||||
Ok(newpkgs) => newpkgs,
|
||||
Err(_) => {
|
||||
println!("FAILED TO LOAD NEW PKGS");
|
||||
sender.output(AppMsg::LoadError(
|
||||
String::from("Could not load new packages"),
|
||||
String::from(
|
||||
"Try connecting to the internet or launching the application again",
|
||||
),
|
||||
));
|
||||
return;
|
||||
println!("SYSTEM PKGS {:?}", syspkgs);
|
||||
let newpkgs = match syspkgs {
|
||||
SystemPkgs::Legacy => {
|
||||
match readlegacysyspkgs() {
|
||||
Ok(newpkgs) => newpkgs,
|
||||
Err(_) => {
|
||||
println!("FAILED TO LOAD NEW PKGS");
|
||||
sender.output(AppMsg::LoadError(
|
||||
String::from("Could not load new packages"),
|
||||
String::from(
|
||||
"Try connecting to the internet or launching the application again",
|
||||
),
|
||||
));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
SystemPkgs::Flake => {
|
||||
match readflakesyspkgs() {
|
||||
Ok(newpkgs) => newpkgs,
|
||||
Err(_) => {
|
||||
println!("FAILED TO LOAD NEW PKGS");
|
||||
sender.output(AppMsg::LoadError(
|
||||
String::from("Could not load new packages"),
|
||||
String::from(
|
||||
"Try connecting to the internet or launching the application again",
|
||||
),
|
||||
));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
// println!("SYSPKGS: {:#?}", syspkgs);
|
||||
|
||||
let profilepkgs = match userpkgs {
|
||||
UserPkgs::Env => None,
|
||||
UserPkgs::Profile => if let Ok(r) = readprofilepkgs() { Some(r) } else { None },
|
||||
};
|
||||
// println!("PROFILEPKGS: {:?}", profilepkgs);
|
||||
|
||||
|
||||
println!("GOT PKGS");
|
||||
|
||||
@ -380,7 +412,7 @@ impl Worker for WindowAsyncHandler {
|
||||
println!("SEND INIT");
|
||||
match cr {
|
||||
CacheReturn::Init => {
|
||||
sender.output(AppMsg::Initialize(pkgs, recpicks, newpkgs, catpicks, catpkgs));
|
||||
sender.output(AppMsg::Initialize(pkgs, recpicks, newpkgs, catpicks, catpkgs, profilepkgs));
|
||||
}
|
||||
CacheReturn::Update => {
|
||||
sender.output(AppMsg::ReloadUpdateItems(pkgs, newpkgs));
|
||||
|
Loading…
Reference in New Issue
Block a user