Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 88 additions & 54 deletions src/db.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use actix_web::{error, web, Error};
use actix_web::{Error, error, web};
use rusqlite::Statement;

use crate::models::{Artefact, ArtefactType, Component, ComponentTarget, RustVersion};
Expand All @@ -15,19 +15,21 @@ pub enum Queries {
GetVersionInfo,
}

pub async fn execute(pool: &Pool, query: Queries, param: Option<String>) -> Result<Vec<RustVersion>, Error> {
pub async fn execute(
pool: &Pool,
query: Queries,
param: Option<String>,
) -> Result<Vec<RustVersion>, Error> {
let pool = pool.clone();

let conn = web::block(move || pool.get())
.await?
.map_err(error::ErrorInternalServerError)?;

web::block(move || {
match query {
Queries::GetNamedChannels => get_named_channels(&conn),
Queries::GetAllVersions => get_all_versions(&conn),
Queries::GetVersionInfo => get_version_info(&conn, param),
}
web::block(move || match query {
Queries::GetNamedChannels => get_named_channels(&conn),
Queries::GetAllVersions => get_all_versions(&conn),
Queries::GetVersionInfo => get_version_info(&conn, param),
})
.await?
.map_err(error::ErrorInternalServerError)
Expand Down Expand Up @@ -87,49 +89,52 @@ fn get_rust_components(conn: &Connection, version: &str) -> ComponentAggResult {
}

fn get_component_rows(mut statement: Statement, version: &str) -> ComponentAggResult {
let mut components_map: std::collections::HashMap<String, Component> = std::collections::HashMap::new();
let mut components_map: std::collections::HashMap<String, Component> =
std::collections::HashMap::new();

let _rows: Vec<_> = statement.query_map([version], |row| {
let name: String = row.get("component_name")?;
let target = if let (Ok(name), Ok(url), Ok(hash)) = (
row.get::<_, Option<String>>("target_name"),
row.get::<_, Option<String>>("url"),
row.get::<_, Option<String>>("hash"),
) {
Some(ComponentTarget {
name: name.unwrap_or_default(),
url: url.unwrap_or_default(),
hash: hash.unwrap_or_default(),
})
} else {
None
};
let _rows: Vec<_> = statement
.query_map([version], |row| {
let name: String = row.get("component_name")?;
let target = if let (Ok(name), Ok(url), Ok(hash)) = (
row.get::<_, Option<String>>("target_name"),
row.get::<_, Option<String>>("url"),
row.get::<_, Option<String>>("hash"),
) {
Some(ComponentTarget {
name: name.unwrap_or_default(),
url: url.unwrap_or_default(),
hash: hash.unwrap_or_default(),
})
} else {
None
};

if let Some(component) = components_map.get_mut(&name) {
if let Some(target) = target {
if let Some(targets) = &mut component.target {
targets.push(target);
if let Some(component) = components_map.get_mut(&name) {
if let Some(target) = target {
if let Some(targets) = &mut component.target {
targets.push(target);
} else {
component.target = Some(vec![target]);
}
}
} else {
component.target = Some(vec![target]);
}
components_map.insert(
name.clone(),
Component {
name: row.get("component_name")?,
version: row.get("version")?,
git_commit: row.get("git_commit")?,
profile_complete: row.get("profile_complete")?,
profile_default: row.get("profile_default")?,
profile_minimal: row.get("profile_minimal")?,
target: target.map(|t| vec![t]),
},
);
}
} else {
components_map.insert(
name.clone(),
Component {
name: row.get("component_name")?,
version: row.get("version")?,
git_commit: row.get("git_commit")?,
profile_complete: row.get("profile_complete")?,
profile_default: row.get("profile_default")?,
profile_minimal: row.get("profile_minimal")?,
target: target.map(|t| vec![t]),
},
);
}

Ok(())
})?.collect::<Result<_, rusqlite::Error>>()?;
Ok(())
})?
.collect::<Result<_, rusqlite::Error>>()?;

Ok(components_map.into_values().collect())
}
Expand Down Expand Up @@ -175,24 +180,46 @@ fn get_version_info(conn: &Connection, version: Option<String>) -> RustVersionsA
.iter()
.find(|v| v.latest_stable)
.map(|v| v.version.clone())
.ok_or_else(|| rusqlite::Error::ToSqlConversionFailure(Box::new(std::io::Error::new(std::io::ErrorKind::Other, "No stable version found")))),
.ok_or_else(|| {
rusqlite::Error::ToSqlConversionFailure(Box::new(std::io::Error::new(
std::io::ErrorKind::Other,
"No stable version found",
)))
}),
"beta" => versions
.iter()
.find(|v| v.latest_beta)
.map(|v| v.version.clone())
.ok_or_else(|| rusqlite::Error::ToSqlConversionFailure(Box::new(std::io::Error::new(std::io::ErrorKind::Other, "No beta version found")))),
.ok_or_else(|| {
rusqlite::Error::ToSqlConversionFailure(Box::new(std::io::Error::new(
std::io::ErrorKind::Other,
"No beta version found",
)))
}),
"nightly" => versions
.iter()
.find(|v| v.latest_nightly)
.map(|v| v.version.clone())
.ok_or_else(|| rusqlite::Error::ToSqlConversionFailure(Box::new(std::io::Error::new(std::io::ErrorKind::Other, "No nightly version found")))),
.ok_or_else(|| {
rusqlite::Error::ToSqlConversionFailure(Box::new(std::io::Error::new(
std::io::ErrorKind::Other,
"No nightly version found",
)))
}),
_ => versions
.iter()
.find(|v| v.version == version_str)
.map(|v| v.version.clone())
.ok_or_else(|| rusqlite::Error::ToSqlConversionFailure(Box::new(std::io::Error::new(std::io::ErrorKind::Other, "Version not found")))),
.ok_or_else(|| {
rusqlite::Error::ToSqlConversionFailure(Box::new(std::io::Error::new(
std::io::ErrorKind::Other,
"Version not found",
)))
}),
},
Err(e) => Err(rusqlite::Error::ToSqlConversionFailure(Box::new(std::io::Error::new(std::io::ErrorKind::Other, e)))),
Err(e) => Err(rusqlite::Error::ToSqlConversionFailure(Box::new(
std::io::Error::new(std::io::ErrorKind::Other, e),
))),
}?;

let stmt = conn.prepare(
Expand Down Expand Up @@ -242,7 +269,10 @@ fn get_version_info_rows(mut statement: Statement, version: &String) -> RustVers
.and_then(Iterator::collect)
}

fn get_rust_version_artefacts(conn: &Connection, version: &str) -> Result<Vec<Artefact>, rusqlite::Error> {
fn get_rust_version_artefacts(
conn: &Connection,
version: &str,
) -> Result<Vec<Artefact>, rusqlite::Error> {
let stmt = conn.prepare(
"SELECT
artefacts.type, artefacts.url, artefacts.hash
Expand All @@ -255,11 +285,15 @@ fn get_rust_version_artefacts(conn: &Connection, version: &str) -> Result<Vec<Ar
get_rust_version_artefact_rows(stmt, version)
}

fn get_rust_version_artefact_rows(mut statement: Statement, version: &str) -> Result<Vec<Artefact>, rusqlite::Error> {
fn get_rust_version_artefact_rows(
mut statement: Statement,
version: &str,
) -> Result<Vec<Artefact>, rusqlite::Error> {
statement
.query_map([version], |row| {
Ok(Artefact {
artefact_type: ArtefactType::try_from(row.get::<_, i32>("type")?).map_err(|_| rusqlite::Error::InvalidQuery)?,
artefact_type: ArtefactType::try_from(row.get::<_, i32>("type")?)
.map_err(|_| rusqlite::Error::InvalidQuery)?,
hash: row.get("hash")?,
url: row.get("url")?,
})
Expand Down
27 changes: 18 additions & 9 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,35 @@
use actix_files::{Files};
use actix_web::{middleware, web, get, App, HttpResponse, HttpServer, Responder, web::Data};
use tera::{Context, Tera};
use actix_files::Files;
use actix_web::{App, HttpResponse, HttpServer, Responder, get, middleware, web, web::Data};
use env_logger::Env;
use tera::{Context, Tera};

mod db;
use db::{Pool, Queries};

pub mod models;

#[get("/")]
pub async fn hello(tera: Data<Tera>, db: web::Data::<Pool>) -> impl Responder {
pub async fn hello(tera: Data<Tera>, db: web::Data<Pool>) -> impl Responder {
let mut ctx = Context::new();

let versions = db::execute(&db, Queries::GetAllVersions, None).await.unwrap();
let versions = db::execute(&db, Queries::GetAllVersions, None)
.await
.unwrap();
ctx.insert("versions", &versions);
let named_channels = db::execute(&db, Queries::GetNamedChannels, None).await.unwrap();
let named_channels = db::execute(&db, Queries::GetNamedChannels, None)
.await
.unwrap();
ctx.insert("named_channels", &named_channels);

HttpResponse::Ok().body(tera.render("index.tera", &ctx).unwrap())
}

#[get("/info/{version}")]
pub async fn versioninfo(tera: Data<Tera>, path: web::Path<String>, db: web::Data<Pool>) -> impl Responder {
pub async fn versioninfo(
tera: Data<Tera>,
path: web::Path<String>,
db: web::Data<Pool>,
) -> impl Responder {
let mut ctx = Context::new();

let rustversion = db::execute(&db, Queries::GetVersionInfo, Some(path.to_string()))
Expand All @@ -39,7 +47,9 @@ pub async fn versioninfo(tera: Data<Tera>, path: web::Path<String>, db: web::Da
pub async fn allversions(tera: Data<Tera>, db: web::Data<Pool>) -> impl Responder {
let mut ctx = Context::new();

let versions = db::execute(&db, Queries::GetAllVersions, None).await.unwrap();
let versions = db::execute(&db, Queries::GetAllVersions, None)
.await
.unwrap();
ctx.insert("versions", &versions);
HttpResponse::Ok().body(tera.render("allversions.tera", &ctx).unwrap())
}
Expand All @@ -57,7 +67,6 @@ pub async fn versioninfoapi(path: web::Path<String>, db: web::Data<Pool>) -> imp

#[actix_web::main]
async fn main() -> std::io::Result<()> {

env_logger::Builder::from_env(Env::default().default_filter_or("debug")).init();
let tera = Data::new(Tera::new("./templates/*").unwrap());

Expand Down
4 changes: 2 additions & 2 deletions src/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
pub enum ArtefactType {
InstallerMSI = 1,
InstallerPkg = 2,
SourceCode = 3
SourceCode = 3,
}

impl TryFrom<i32> for ArtefactType {
Expand Down Expand Up @@ -33,7 +33,7 @@ pub struct Artefact {
pub hash: String,
}

#[derive(Debug, Serialize, Deserialize, Clone,)]
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ComponentTarget {
pub name: String,
pub url: String,
Expand Down