diff --git a/src/installer.rs b/src/installer.rs index 634e752..24e2060 100644 --- a/src/installer.rs +++ b/src/installer.rs @@ -94,8 +94,24 @@ impl InstallerFramework { .expect("Install directory not initialised") ); + // Calculate packages to *uninstall* + let mut uninstall_items = Vec::new(); + if !fresh_install { + for package in &self.database { + if !items.contains(&package.name) { + uninstall_items.push(package.name.clone()); + } + } + + println!( + "Framework: Uninstalling {:?} additionally.", + uninstall_items + ); + } + let task = Box::new(InstallTask { items, + uninstall_items, fresh_install, }); diff --git a/src/tasks/download_pkg.rs b/src/tasks/download_pkg.rs index 9dcb4d7..5c4f740 100644 --- a/src/tasks/download_pkg.rs +++ b/src/tasks/download_pkg.rs @@ -19,11 +19,10 @@ impl Task for DownloadPackageTask { fn execute( &mut self, mut input: Vec, - _: &mut InstallerFramework, + context: &mut InstallerFramework, messenger: &Fn(&str, f32), ) -> Result { assert_eq!(input.len(), 1); - messenger(&format!("Downloading package {:?}...", self.name), 0.0); let file = input.pop().expect("Should have input from resolver!"); let (version, file) = match file { @@ -31,6 +30,19 @@ impl Task for DownloadPackageTask { _ => return Err(format!("Unexpected param type to download package")), }; + // Check to see if this is the newest file available already + for element in &context.database { + if element.name == self.name { + if element.version == version { + println!("{:?} is already up to date.", self.name); + return Ok(TaskParamType::Break); + } + break; + } + } + + messenger(&format!("Downloading package {:?}...", self.name), 0.0); + let mut downloaded = 0; let mut data_storage: Vec = Vec::new(); diff --git a/src/tasks/install.rs b/src/tasks/install.rs index 98ce2ee..886351e 100644 --- a/src/tasks/install.rs +++ b/src/tasks/install.rs @@ -6,12 +6,14 @@ use tasks::install_dir::VerifyInstallDirTask; use tasks::install_pkg::InstallPackageTask; use tasks::save_database::SaveDatabaseTask; use tasks::save_executable::SaveExecutableTask; +use tasks::uninstall_pkg::UninstallPackageTask; use tasks::Task; use tasks::TaskParamType; pub struct InstallTask { pub items: Vec, + pub uninstall_items: Vec, pub fresh_install: bool, } @@ -37,6 +39,13 @@ impl Task for InstallTask { elements.push(Box::new(InstallPackageTask { name: item.clone() })); } + for item in &self.uninstall_items { + elements.push(Box::new(UninstallPackageTask { + name: item.clone(), + optional: false, + })); + } + elements.push(Box::new(SaveDatabaseTask {})); if self.fresh_install { diff --git a/src/tasks/install_pkg.rs b/src/tasks/install_pkg.rs index cc0fdb6..16aa987 100644 --- a/src/tasks/install_pkg.rs +++ b/src/tasks/install_pkg.rs @@ -51,7 +51,12 @@ impl Task for InstallPackageTask { None => return Err(format!("Package {:?} could not be found.", self.name)), }; - let _ = input.pop().expect("Should have input from uninstaller!"); + // Check to see if no archive was available. + match input.pop().expect("Should have input from uninstaller!") { + // No file to install, but all is good. + TaskParamType::Break => return Ok(TaskParamType::None), + _ => {} + } let data = input.pop().expect("Should have input from resolver!"); let (file, data) = match data { @@ -97,20 +102,17 @@ impl Task for InstallPackageTask { // Create target file let target_path = path.join(&filename); - println!("target_path: {:?}", target_path); - - installed_files.push(filename.to_string()); // Check to make sure this isn't a directory if filename.ends_with("/") || filename.ends_with("\\") { - // Create this directory and move on - match create_dir_all(target_path) { - Ok(v) => v, - Err(v) => return Err(format!("Unable to create dir: {:?}", v)), - } + // Directory was already created continue; } + println!("Creating file: {:?}", target_path); + + installed_files.push(filename.to_string()); + let mut target_file = match File::create(target_path) { Ok(v) => v, Err(v) => return Err(format!("Unable to open file handle: {:?}", v)), diff --git a/src/tasks/mod.rs b/src/tasks/mod.rs index 021f285..1342dab 100644 --- a/src/tasks/mod.rs +++ b/src/tasks/mod.rs @@ -22,8 +22,12 @@ pub mod uninstall_pkg; /// An abstraction over the various paramaters that can be passed around. pub enum TaskParamType { None, + /// Metadata about a file File(Version, File), + /// Downloaded contents of a file FileContents(Version, Vec), + /// Tells the runtime to break parsing other dependencies + Break } /// A Task is a small, async task conforming to a fixed set of inputs/outputs. @@ -89,13 +93,25 @@ impl DependencyTree { let mut count = 0; for i in &mut self.dependencies { - inputs.push(i.execute(context, &|msg: &str, progress: f32| { + let result = i.execute(context, &|msg: &str, progress: f32| { messenger( msg, progress / total_tasks + (1.0 / total_tasks) * count as f32, ) - })?); + })?; + + // Check to see if we skip matching other dependencies + let do_break = match &result { + &TaskParamType::Break => true, + _ => false + }; + + inputs.push(result); count += 1; + + if do_break { + break; + } } self.task