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 futures;
extern crate hyper;
extern crate hyper_tls;
extern crate tokio_core;
extern crate includedir;
extern crate phf;
@ -27,12 +32,16 @@ use installer::InstallerFramework;
use rest::WebServer;
use sources::types::ReleaseSource;
// TODO: Fetch this over a HTTP request?
static RAW_CONFIG: &'static str = include_str!("../config.toml");
fn main() {
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 framework = InstallerFramework::new(config);

View File

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

View File

@ -1,9 +1,24 @@
/// 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::*;
pub struct GithubReleases {
}
/// The configuration for this release.
@ -14,6 +29,93 @@ struct GithubConfig {
impl ReleaseSource for GithubReleases {
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.
mod types;
pub mod types;
mod github;
pub mod github;

View File

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