Implement Github source backend

This commit is contained in:
James 2018-01-29 21:27:54 +11:00
parent c0eac985ad
commit 9baf44e330
5 changed files with 122 additions and 18 deletions

View File

@ -2,6 +2,11 @@
extern crate web_view; extern crate web_view;
extern crate futures;
extern crate hyper;
extern crate hyper_tls;
extern crate tokio_core;
extern crate includedir; extern crate includedir;
extern crate phf; extern crate phf;
@ -27,12 +32,16 @@ use installer::InstallerFramework;
use rest::WebServer; use rest::WebServer;
use sources::types::ReleaseSource;
// TODO: Fetch this over a HTTP request? // TODO: Fetch this over a HTTP request?
static RAW_CONFIG: &'static str = include_str!("../config.toml"); static RAW_CONFIG: &'static str = include_str!("../config.toml");
fn main() { fn main() {
let config = Config::from_toml_str(RAW_CONFIG).unwrap(); let config = Config::from_toml_str(RAW_CONFIG).unwrap();
let github_releases = sources::github::GithubReleases{};
println!("{:?}", github_releases.get_current_releases(&config.packages[0].source.config));
let app_name = config.general.name.clone(); let app_name = config.general.name.clone();
let framework = InstallerFramework::new(config); let framework = InstallerFramework::new(config);

View File

@ -3,23 +3,18 @@
/// Provides a HTTP/REST server for both frontend<->backend communication, as well /// Provides a HTTP/REST server for both frontend<->backend communication, as well
/// as talking to external applications. /// as talking to external applications.
extern crate futures;
extern crate hyper;
extern crate hyper_tls;
extern crate tokio_core;
extern crate nfd; extern crate nfd;
use rest::nfd::Response as NfdResponse; use rest::nfd::Response as NfdResponse;
use serde_json; use serde_json;
use rest::futures::future; use futures::future;
use rest::futures::future::FutureResult; use futures::future::FutureResult;
use rest::hyper::{Error as HyperError, Get, StatusCode}; use hyper::{self, Error as HyperError, Get, StatusCode};
use rest::hyper::header::{ContentLength, ContentType}; use hyper::header::{ContentLength, ContentType};
use rest::hyper::server::{Http, Request, Response, Service}; use hyper::server::{Http, Request, Response, Service};
use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::thread::{self, JoinHandle}; use std::thread::{self, JoinHandle};

View File

@ -1,9 +1,24 @@
/// github/mod.rs /// github/mod.rs
use futures::{Future, Stream};
use tokio_core::reactor::Core;
use hyper::Client;
use hyper::Uri;
use hyper::Method;
use hyper::Request;
use hyper::header::UserAgent;
use hyper_tls::HttpsConnector;
use toml;
use serde_json;
use sources::types::*; use sources::types::*;
pub struct GithubReleases { pub struct GithubReleases {
} }
/// The configuration for this release. /// The configuration for this release.
@ -14,6 +29,93 @@ struct GithubConfig {
impl ReleaseSource for GithubReleases { impl ReleaseSource for GithubReleases {
fn get_current_releases(&self, config: &TomlValue) -> Result<Vec<Release>, String> { fn get_current_releases(&self, config: &TomlValue) -> Result<Vec<Release>, String> {
unimplemented!() // Reparse our Config as strongly typed
let config_string = match toml::to_string(config) {
Ok(v) => v,
Err(v) => return Err(format!("Failed to convert config: {:?}", v))
};
let config : GithubConfig = match toml::from_str(&config_string) {
Ok(v) => v,
Err(v) => return Err(format!("Failed to convert config: {:?}", v))
};
let mut core = match Core::new() {
Ok(v) => v,
Err(v) => return Err(format!("Failed to init Tokio: {:?}", v))
};
// Build the HTTP client up
let client = Client::configure()
.connector(match HttpsConnector::new(4, &core.handle()) {
Ok(v) => v,
Err(v) => return Err(format!("Failed to init https: {:?}", v))
})
.build(&core.handle());
let mut results: Vec<Release> = Vec::new();
let target_url : Uri = match format!("https://api.github.com/repos/{}/releases",
config.repo).parse() {
Ok(v) => v,
Err(v) => return Err(format!("Failed to generate target url: {:?}", v))
};
let mut req = Request::new(Method::Get, target_url);
req.headers_mut().set(UserAgent::new("installer-rs (j-selby)"));
// Build our future
let future = client.request(req).and_then(|res| {
res.body().concat2().and_then(move |body| {
let raw_json : Result<serde_json::Value, String>
= match serde_json::from_slice(&body) {
Ok(v) => Ok(v),
Err(v) => Err(format!("Failed to parse response: {:?}", v))
};
Ok(raw_json)
})
});
// Unwrap the future's results
let result : serde_json::Value = match core.run(future) {
Ok(v) => v,
Err(v) => return Err(format!("Failed to fetch info: {:?}", v))
}?;
let result : &Vec<serde_json::Value> = match result.as_array() {
Some(v) => v,
None => return Err(format!("JSON payload not an array"))
};
// Parse JSON from server
for entry in result.into_iter() {
let mut files = Vec::new();
let id : u64 = match entry["id"].as_u64() {
Some(v) => v,
None => return Err(format!("JSON payload missing information about ID"))
};
let assets = match entry["assets"].as_array() {
Some(v) => v,
None => return Err(format!("JSON payload not an array"))
};
for asset in assets.into_iter() {
let string = match asset["name"].as_str() {
Some(v) => v,
None => return Err(format!("JSON payload missing information about ID"))
};
files.push(string.to_owned());
}
results.push(Release {
version: Version::new_number(id),
files
});
}
Ok(results)
} }
} }

View File

@ -2,6 +2,6 @@
/// ///
/// Contains backends to various release distribution services. /// Contains backends to various release distribution services.
mod types; pub mod types;
mod github; pub mod github;

View File

@ -4,8 +4,6 @@
use std::cmp::Ordering; use std::cmp::Ordering;
use installer::InstallerFramework;
pub use semver::Version as SemverVersion; pub use semver::Version as SemverVersion;
pub use toml::value::Value as TomlValue; pub use toml::value::Value as TomlValue;
@ -29,12 +27,12 @@ impl Version {
} }
/// Returns a new Version, backed by semver. /// Returns a new Version, backed by semver.
fn new_semver(version : SemverVersion) -> Version { pub fn new_semver(version : SemverVersion) -> Version {
Version::Semver(version) Version::Semver(version)
} }
/// Returns a new Version, backed by a integer. /// Returns a new Version, backed by a integer.
fn new_number(version : u64) -> Version { pub fn new_number(version : u64) -> Version {
Version::Integer(version) Version::Integer(version)
} }
} }