diff --git a/src/authors.rs b/src/authors.rs new file mode 100644 index 0000000..8a7ce93 --- /dev/null +++ b/src/authors.rs @@ -0,0 +1,29 @@ +use models::{Author, NewAuthor}; + +use diesel; +use diesel::result::Error; +use diesel::pg::PgConnection; +use diesel::prelude::*; + +pub fn load_or_create(conn: &PgConnection, author_name: &str, author_email: &str) -> Author { + use schema::authors::dsl::*; + use diesel::associations::HasTable; + + match authors + .filter(name.eq(author_name)) + .filter(email.eq(author_email)) + .first(conn) { + Ok(author) => author, + Err(Error::NotFound) => { + let new_author = NewAuthor { + name: author_name, + email: author_email, + }; + diesel::insert(&new_author) + .into(authors::table()) + .get_result(conn) + .expect("Error saving new author") + }, + Err(_) => panic!("Error loading author from the datebase") + } +} diff --git a/src/bin/populate.rs b/src/bin/populate.rs index 45f19ae..5f0f235 100644 --- a/src/bin/populate.rs +++ b/src/bin/populate.rs @@ -189,7 +189,8 @@ fn main() { // We tag all commits initially to the first release. Each release will // set this properly below. - thanks::commits::create(&connection, &sha, &author_name, &author_email, &first_release); + let author = thanks::authors::load_or_create(&connection, &author_name, &author_email); + thanks::commits::create(&connection, &sha, &author, &first_release); } } diff --git a/src/bin/update-commit-db.rs b/src/bin/update-commit-db.rs index b251319..bb7acec 100644 --- a/src/bin/update-commit-db.rs +++ b/src/bin/update-commit-db.rs @@ -81,8 +81,9 @@ fn update_commit_db(log: &slog::Logger, project: &Project, connection: &PgConnec }, Err(_) => { info!(log, "Creating commit {} for release {}", object.sha, master_release.version); + let author = thanks::authors::load_or_create(&connection, &object.commit.author.name, &object.commit.author.email); // this commit will be part of master - thanks::commits::create(connection, &object.sha, &object.commit.author.name, &object.commit.author.email, &master_release); + thanks::commits::create(connection, &object.sha, &author, &master_release); }, }; } diff --git a/src/commits.rs b/src/commits.rs index 801d2a9..e775234 100644 --- a/src/commits.rs +++ b/src/commits.rs @@ -1,18 +1,18 @@ use models::{Commit, NewCommit}; +use models::Author; use models::Release; use diesel; use diesel::pg::PgConnection; use diesel::prelude::*; -pub fn create<'a>(conn: &PgConnection, sha: &'a str, author_name: &'a str, author_email: &'a str, release: &Release) -> Commit { +pub fn create<'a>(conn: &PgConnection, sha: &'a str, author: &Author, release: &Release) -> Commit { use schema::commits; let new_commit = NewCommit { sha: sha, release_id: release.id, - author_name: author_name, - author_email: author_email, + author_id: author.id, }; diesel::insert(&new_commit).into(commits::table) diff --git a/src/lib.rs b/src/lib.rs index 844c51e..1a5f3f8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,6 +28,7 @@ pub mod models; pub mod projects; pub mod releases; pub mod commits; +pub mod authors; use serde_json::value::Value; @@ -42,15 +43,18 @@ pub fn establish_connection() -> PgConnection { pub fn scores() -> Vec { use schema::commits::dsl::*; + use schema::authors::dsl::*; use diesel::expression::dsl::sql; use diesel::types::BigInt; + use diesel::associations::HasTable; let connection = establish_connection(); let scores: Vec<_> = - commits - .select((author_name, sql::("COUNT(author_name) AS author_count"))) - .group_by(author_name) + commits::table() + .inner_join(authors::table()) + .select((name, sql::("COUNT(author_id) AS author_count"))) + .group_by((author_id, name)) .order(sql::("author_count").desc()) .load(&connection) .unwrap(); diff --git a/src/models.rs b/src/models.rs index 75a1bec..1517eac 100644 --- a/src/models.rs +++ b/src/models.rs @@ -43,6 +43,7 @@ pub struct NewProject<'a> { pub url_path: &'a str, pub github_name: &'a str, } + use super::schema::commits; #[derive(Insertable)] diff --git a/src/releases.rs b/src/releases.rs index 3582637..4785523 100644 --- a/src/releases.rs +++ b/src/releases.rs @@ -92,7 +92,8 @@ pub fn assign_commits(log: &Logger, release_name: &str, previous_release: &str, info!(log, "Creating commit {} for release {}", the_sha, the_release.version); - ::commits::create(&connection, &the_sha, &the_author_name, &the_author_email, &the_release); + let author = ::authors::load_or_create(&connection, &the_author_name, &the_author_email); + ::commits::create(&connection, &the_sha, &author, &the_release); }, }; } @@ -114,8 +115,9 @@ pub fn create(conn: &PgConnection, version: &str, project_id: i32) -> Release { pub fn contributors(project: &str, release_name: &str) -> Option> { use schema::releases::dsl::*; use schema::commits::dsl::*; + use schema::authors::dsl::*; use models::Release; - use models::Commit; + use diesel::associations::HasTable; let connection = ::establish_connection(); @@ -144,8 +146,8 @@ pub fn contributors(project: &str, release_name: &str) -> Option> { // it'd be better to do this in the db // but Postgres doesn't do Unicode collation correctly on OSX // http://postgresql.nabble.com/Collate-order-on-Mac-OS-X-text-with-diacritics-in-UTF-8-td1912473.html - let mut names: Vec = Commit::belonging_to(&release) - .select(author_name).distinct().load(&connection).unwrap(); + let mut names: Vec = authors::table().inner_join(commits::table()).filter(release_id.eq(release.id)) + .select(name).distinct().load(&connection).unwrap(); inaccurate_sort(&mut names);