From 74c5b5e736305b84acc5e8cecc1e2e5d30d94ba7 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Tue, 27 Nov 2018 12:24:55 +0100 Subject: hook up list sync --- src/main.rs | 6 ++---- src/schema.rs | 11 +++++++++-- src/sync/lists.rs | 51 ++++++++++++++++++--------------------------------- 3 files changed, 29 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/main.rs b/src/main.rs index 7ae7817..de20415 100644 --- a/src/main.rs +++ b/src/main.rs @@ -37,16 +37,15 @@ fn main() { fn run() -> Result<(), Error> { let cli = Cli::from_args(); + let data = Data::load()?; match cli { Cli::Check => { - let data = Data::load()?; crate::validate::validate(&data)?; } Cli::Sync => { - sync::lists::run()?; + sync::lists::run(&data)?; } Cli::DumpTeam { ref name } => { - let data = Data::load()?; let team = data.team(name).ok_or_else(|| err_msg("unknown team"))?; let leads = team.leads(); @@ -59,7 +58,6 @@ fn run() -> Result<(), Error> { } } Cli::DumpList { ref name } => { - let data = Data::load()?; let list = data.list(name)?.ok_or_else(|| err_msg("unknown list"))?; for email in list.emails() { println!("{}", email); diff --git a/src/schema.rs b/src/schema.rs index ac5b243..641e282 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -172,8 +172,7 @@ pub(crate) struct TeamList { pub(crate) enum ListAccessLevel { Everyone, Members, - #[serde(rename = "read-only")] - Readonly, + ReadOnly, } #[derive(Debug)] @@ -188,6 +187,14 @@ impl List { &self.address } + pub(crate) fn access_level_str(&self) -> &str { + match self.access_level { + ListAccessLevel::Everyone => "everyone", + ListAccessLevel::Members => "members", + ListAccessLevel::ReadOnly => "readonly", + } + } + pub(crate) fn emails(&self) -> &[String] { &self.emails } diff --git a/src/sync/lists.rs b/src/sync/lists.rs index d5c6710..1d457f3 100644 --- a/src/sync/lists.rs +++ b/src/sync/lists.rs @@ -1,23 +1,12 @@ +use crate::data::Data; +use crate::schema::List; use curl::easy::{Easy, Form}; use failure::{bail, format_err, Error, ResultExt}; use std::cell::RefCell; use std::collections::{HashMap, HashSet}; use std::env; -use std::fs; use std::str; -#[derive(serde_derive::Deserialize)] -struct Mailmap { - lists: Vec, -} - -#[derive(serde_derive::Deserialize)] -struct List { - address: String, - access_level: String, - members: Vec, -} - mod api { #[derive(serde_derive::Deserialize)] pub struct ListResponse { @@ -55,12 +44,8 @@ mod api { #[derive(serde_derive::Deserialize)] struct Empty {} -pub(crate) fn run() -> Result<(), Error> { - let mailmap = - fs::read_to_string("mailmap.toml").with_context(|_| "failed to read `mailmap.toml`")?; - - let mailmap: Mailmap = - toml::from_str(&mailmap).with_context(|_| "failed to deserialize toml mailmap")?; +pub(crate) fn run(data: &Data) -> Result<(), Error> { + let mailmap = data.lists()?; let mut lists = Vec::new(); let mut response = get::("/lists/pages")?; @@ -70,15 +55,15 @@ pub(crate) fn run() -> Result<(), Error> { } let mut addr2list = HashMap::new(); - for list in mailmap.lists.iter() { - if addr2list.insert(&list.address, list).is_some() { - bail!("duplicate address: {}", list.address); + for list in mailmap.values() { + if addr2list.insert(list.address(), list).is_some() { + bail!("duplicate address: {}", list.address()); } } for prev_list in lists { let address = &prev_list.address; - match addr2list.remove(address) { + match addr2list.remove(address.as_str()) { Some(new_list) => sync(&prev_list, &new_list) .with_context(|_| format!("failed to sync {}", address))?, None => del(&prev_list).with_context(|_| format!("failed to delete {}", address))?, @@ -86,7 +71,7 @@ pub(crate) fn run() -> Result<(), Error> { } for (_, list) in addr2list.iter() { - create(list).with_context(|_| format!("failed to create {}", list.address))?; + create(list).with_context(|_| format!("failed to create {}", list.address()))?; } Ok(()) @@ -95,24 +80,24 @@ pub(crate) fn run() -> Result<(), Error> { fn create(new: &List) -> Result<(), Error> { let mut form = Form::new(); form.part("address") - .contents(new.address.as_bytes()) + .contents(new.address().as_bytes()) .add()?; form.part("access_level") - .contents(new.access_level.as_bytes()) + .contents(new.access_level_str().as_bytes()) .add()?; post::("/lists", form)?; - add_members(&new.address, &new.members)?; + add_members(new.address(), new.emails())?; Ok(()) } fn sync(prev: &api::List, new: &List) -> Result<(), Error> { - assert_eq!(prev.address, new.address); + assert_eq!(prev.address, new.address()); let url = format!("/lists/{}", prev.address); - if prev.access_level != new.access_level { + if prev.access_level != new.access_level_str() { let mut form = Form::new(); form.part("access_level") - .contents(new.access_level.as_bytes()) + .contents(new.access_level_str().as_bytes()) .add()?; put::(&url, form)?; } @@ -126,17 +111,17 @@ fn sync(prev: &api::List, new: &List) -> Result<(), Error> { } let mut to_add = Vec::new(); - for member in new.members.iter() { + for member in new.emails() { if !prev_members.remove(member) { to_add.push(member.clone()); } } if to_add.len() > 0 { - add_members(&new.address, &to_add)?; + add_members(new.address(), &to_add)?; } for member in prev_members { - delete::(&format!("/lists/{}/members/{}", new.address, member))?; + delete::(&format!("/lists/{}/members/{}", new.address(), member))?; } Ok(()) -- cgit v1.2.3