diff --git a/src/installer.rs b/src/installer.rs index 35e42db..634e752 100644 --- a/src/installer.rs +++ b/src/installer.rs @@ -85,6 +85,7 @@ impl InstallerFramework { messages: &Sender<InstallMessage>, fresh_install: bool, ) -> Result<(), String> { + // TODO: Uninstall packages that aren't selected println!( "Framework: Installing {:?} to {:?}", items, diff --git a/src/main.rs b/src/main.rs index 00ceeb9..61b474d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,7 @@ //! The main entrypoint for the application. Orchestrates the building of the installation //! framework, and opens necessary HTTP servers/frontends. -#![windows_subsystem = "windows"] +//#![windows_subsystem = "windows"] #[cfg(windows)] extern crate nfd; @@ -77,6 +77,7 @@ fn main() { // Startup HTTP server for handling the web view let http_address = format!("http://{}", server.get_addr()); + println!("Server: {:?}", http_address); // Init the web view let size = (1024, 500); diff --git a/src/rest.rs b/src/rest.rs index 7706805..a058fb9 100644 --- a/src/rest.rs +++ b/src/rest.rs @@ -111,6 +111,21 @@ impl Service for WebService { .with_header(ContentType::json()) .with_body(file) } + // This endpoint should be usable directly from a <script> tag during loading. + // TODO: Handle errors + (&Get, "/api/packages") => { + let framework = self.framework.read().unwrap(); + + let file = enscapsulate_json( + "packages", + &serde_json::to_string(&framework.database).unwrap(), + ); + + Response::<hyper::Body>::new() + .with_header(ContentLength(file.len() as u64)) + .with_header(ContentType::json()) + .with_body(file) + } // Returns the default path for a installation (&Get, "/api/default-path") => { let framework = self.framework.read().unwrap(); @@ -220,9 +235,12 @@ impl Service for WebService { thread::spawn(move || { let mut framework = framework.write().unwrap(); - framework.set_install_dir(&path); + let new_install = !framework.preexisting_install; + if new_install { + framework.set_install_dir(&path); + } - match framework.install(to_install, &sender, true) { + match framework.install(to_install, &sender, new_install) { Err(v) => sender.send(InstallMessage::Error(v)).unwrap(), _ => {} } diff --git a/src/tasks/install_pkg.rs b/src/tasks/install_pkg.rs index 73c93a6..cc0fdb6 100644 --- a/src/tasks/install_pkg.rs +++ b/src/tasks/install_pkg.rs @@ -7,12 +7,15 @@ use tasks::TaskParamType; use config::PackageDescription; use installer::LocalInstallation; + use std::fs::create_dir_all; use std::fs::File; use std::io::copy; use std::io::Cursor; + use tasks::download_pkg::DownloadPackageTask; use tasks::uninstall_pkg::UninstallPackageTask; + use zip::ZipArchive; pub struct InstallPackageTask { @@ -73,30 +76,41 @@ impl Task for InstallPackageTask { (i as f32) / (zip_size as f32), ); + let filename = file.name().replace("\\", "/"); + + // Ensure that parent directories exist + let mut parent_dir = &filename[..]; + while let Some(v) = parent_dir.rfind("/") { + parent_dir = &parent_dir[0..v + 1]; + + if !installed_files.contains(&parent_dir.to_string()) { + installed_files.push(parent_dir.to_string()); + } + + match create_dir_all(path.join(&parent_dir)) { + Ok(v) => v, + Err(v) => return Err(format!("Unable to create dir: {:?}", v)), + } + + parent_dir = &parent_dir[0..v]; + } + // Create target file - let target_path = path.join(file.name()); + let target_path = path.join(&filename); println!("target_path: {:?}", target_path); - installed_files.push(file.name().to_string()); + installed_files.push(filename.to_string()); // Check to make sure this isn't a directory - if file.name().ends_with("/") || file.name().ends_with("\\") { + 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 open file: {:?}", v)), + Err(v) => return Err(format!("Unable to create dir: {:?}", v)), } continue; } - match target_path.parent() { - Some(v) => match create_dir_all(v) { - Ok(v) => v, - Err(v) => return Err(format!("Unable to open file: {:?}", v)), - }, - None => {} - } - 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/static/index.html b/static/index.html index d4be602..e88eec3 100644 --- a/static/index.html +++ b/static/index.html @@ -47,7 +47,7 @@ </a> </p> <p class="control"> - <a class="button" v-on:click="exit"> + <a class="button" v-on:click="modify_packages"> Modify </a> </p> @@ -70,6 +70,7 @@ <label class="checkbox"> <input type="checkbox" v-model="package.default" /> {{ package.name }} + <span v-if="package.installed"><i>(installed)</i></span> </label> <p> {{ package.description }} @@ -79,8 +80,8 @@ </div> </div> - <div class="subtitle is-6">Install Location</div> - <div class="field has-addons"> + <div class="subtitle is-6" v-if="show_install_location">Install Location</div> + <div class="field has-addons" v-if="show_install_location"> <div class="control is-expanded"> <input class="input" type="text" v-model="install_location" placeholder="Enter a install path here"> @@ -135,6 +136,7 @@ </div> <script src="/api/config"></script> + <script src="/api/packages"></script> <script src="/js/helpers.js"></script> <script src="/js/vue.min.js"></script> <script> @@ -146,6 +148,7 @@ el: '#app', data: { config : config, + packages : packages, install_location : "", modify_install : false, select_packages : true, @@ -155,6 +158,7 @@ progress : 0, progress_message : "", has_error : false, + show_install_location : true, error : "", metadata : { database : [], @@ -216,6 +220,10 @@ "cancel_uninstall": function() { app.confirm_uninstall = false; }, + "modify_packages": function() { + app.select_packages = true; + app.modify_install = false; + }, "uninstall": function() { app.confirm_uninstall = false; this.select_packages = false; @@ -248,8 +256,30 @@ if (e.preexisting_install) { app.modify_install = true; app.select_packages = false; + app.show_install_location = false; app.install_location = e.install_path; + + // Copy over installed packages + for (var x = 0; x < config.length; x++) { + config[x].default = false; + config[x].installed = false; + } + + for (var i = 0; i < packages.length; i++) { + // Find this config package + for (var x = 0; x < config.length; x++) { + if (config[x].name === packages[i].name) { + config[x].default = true; + config[x].installed = true; + } + } + } + } else { + for (var x = 0; x < config.length; x++) { + config[x].installed = false; + } + ajax("/api/default-path", function(e) { if (e.path != null) { app.install_location = e.path;