Correctly grab parent directories when installing artifacts

This commit is contained in:
James 2018-08-04 00:21:51 +10:00
parent cb29b4acdf
commit 05de23a918
5 changed files with 82 additions and 18 deletions

View File

@ -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,

View File

@ -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);

View File

@ -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(),
_ => {}
}

View File

@ -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)),

View File

@ -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;