<commit_before>use std::rc::Rc;

use serde_json;
use serde_json::map::Map;
use serde_json::value::Value;

use resman::ResMan;
use super::routegraph::RouteGraph;
use super::adjlist::AdjList;

/// Serializable info needed to look up an effect.
#[derive(Clone)]
#[derive(Serialize, Deserialize)]
pub struct EffectMeta {
    /// Canonical name of the effect
    name: String,
    /// Hash of the effect's definition file, or None if the effect is primitive
    sha256: Option<[u8; 32]>,
    /// List of URLs where the Effect can be obtained
    urls: Vec<String>,
    /// Arguments specific to the given effect (relevant for e.g. Constant).
    effect_args: Map<String, Value>,
}

/// All information that will be loaded from disk/network to describe how to
/// synthesize the Effect.
#[derive(Serialize, Deserialize)]
struct EffectDesc {
    // TODO: when de/serializing, the hashes should be removed from EffectMeta
    meta: EffectMeta,
    adjlist: AdjList,
}

/// Validated version of EffectDesc. Guaranteed to be synthesizable.
pub struct Effect {
    meta: EffectMeta,
    // option, because effect MAY be primitive.
    graph: Option<RouteGraph>,
}

impl Effect {
    pub fn are_slots_connected(&self, from_slot: u32, from_ch: u8, to_slot: u32, to_ch: u8) -> bool {
        match self.graph {
            Some(ref g) => g.are_slots_connected(from_slot, from_ch, to_slot, to_ch),
            // For primitive effects, we assume ALL slots are connected.
            None => true,
        }
    }
    pub fn meta(&self) -> EffectMeta {
        self.meta.clone()
    }
    /// Given the effect's information, and an interface by which to load
    /// resources, return an actual Effect.
    pub fn from_meta(meta: EffectMeta, resman: &ResMan) -> Result<Rc<Self>, ()> {
        // For primitive effects, don't attempt to locate their descriptions (they don't exist)
        if meta.is_primitive() {
            let me = Self {
                meta: meta,
                graph: None,
            };
            return Ok(Rc::new(me));
        }
        // Locate descriptions for non-primitive effects
        for reader in resman.find_effect(&meta) {
            // Try to deserialize to an effect description
            let desc: Result<EffectDesc, serde_json::Error> = serde_json::from_reader(reader);
            if let Ok(desc) = desc {
                // Validate the data
                if let Ok(graph) = RouteGraph::from_adjlist(desc.adjlist, resman) {
                    let me = Self {
                        meta: desc.meta,
                        graph: Some(graph),
                    };
                    // TODO: implement some form of caching
                    return Ok(Rc::new(me));
                }
            }
        }
        // No matching effects
        Err(())
    }
}

impl EffectMeta {
    pub fn sha256(&self) -> &Option<[u8; 32]> {
        &self.sha256
    }
    /// Returns true if the effect cannot be decomposed.
    /// This is determined by the fact that its url(s) will all begin with primitive://
    pub fn is_primitive(&self) -> bool {
        return !self.urls.is_empty() && self.urls.iter().all(|url| {
            url.starts_with("primitive://")
        });
    }
}

impl PartialEq for EffectMeta {
    // Equality implemented in a way where we can easily check things like
    //   "Is this the same primitive Delay effect this renderer knows how to implement?"
    fn eq(&self, other: &EffectMeta) -> bool {
        self.name == other.name &&
            self.sha256 == other.sha256 &&
            self.effect_args == other.effect_args
    }
}
impl Eq for EffectMeta {}

impl PartialEq for Effect {
    fn eq(&self, other: &Effect) -> bool {
        self.meta == other.meta
    }
}
impl Eq for Effect {}
<commit_msg>TODO: use a URI crate<commit_after>use std::rc::Rc;

use serde_json;
use serde_json::map::Map;
use serde_json::value::Value;

use resman::ResMan;
use super::routegraph::RouteGraph;
use super::adjlist::AdjList;

/// Serializable info needed to look up an effect.
#[derive(Clone)]
#[derive(Serialize, Deserialize)]
pub struct EffectMeta {
    /// Canonical name of the effect
    name: String,
    /// Hash of the effect's definition file, or None if the effect is primitive
    sha256: Option<[u8; 32]>,
    /// List of URLs where the Effect can be obtained
    urls: Vec<String>,
    /// Arguments specific to the given effect (relevant for e.g. Constant).
    effect_args: Map<String, Value>,
}

/// All information that will be loaded from disk/network to describe how to
/// synthesize the Effect.
#[derive(Serialize, Deserialize)]
struct EffectDesc {
    // TODO: when de/serializing, the hashes should be removed from EffectMeta
    meta: EffectMeta,
    adjlist: AdjList,
}

/// Validated version of EffectDesc. Guaranteed to be synthesizable.
pub struct Effect {
    meta: EffectMeta,
    // option, because effect MAY be primitive.
    graph: Option<RouteGraph>,
}

impl Effect {
    pub fn are_slots_connected(&self, from_slot: u32, from_ch: u8, to_slot: u32, to_ch: u8) -> bool {
        match self.graph {
            Some(ref g) => g.are_slots_connected(from_slot, from_ch, to_slot, to_ch),
            // For primitive effects, we assume ALL slots are connected.
            None => true,
        }
    }
    pub fn meta(&self) -> EffectMeta {
        self.meta.clone()
    }
    /// Given the effect's information, and an interface by which to load
    /// resources, return an actual Effect.
    pub fn from_meta(meta: EffectMeta, resman: &ResMan) -> Result<Rc<Self>, ()> {
        // For primitive effects, don't attempt to locate their descriptions (they don't exist)
        if meta.is_primitive() {
            let me = Self {
                meta: meta,
                graph: None,
            };
            return Ok(Rc::new(me));
        }
        // Locate descriptions for non-primitive effects
        for reader in resman.find_effect(&meta) {
            // Try to deserialize to an effect description
            let desc: Result<EffectDesc, serde_json::Error> = serde_json::from_reader(reader);
            if let Ok(desc) = desc {
                // Validate the data
                if let Ok(graph) = RouteGraph::from_adjlist(desc.adjlist, resman) {
                    let me = Self {
                        meta: desc.meta,
                        graph: Some(graph),
                    };
                    // TODO: implement some form of caching
                    return Ok(Rc::new(me));
                }
            }
        }
        // No matching effects
        Err(())
    }
}

impl EffectMeta {
    pub fn sha256(&self) -> &Option<[u8; 32]> {
        &self.sha256
    }
    /// Returns true if the effect cannot be decomposed.
    /// This is determined by the fact that its url(s) will all begin with primitive://
    pub fn is_primitive(&self) -> bool {
        return !self.urls.is_empty() && self.urls.iter().all(|url| {
            // TODO: use a URI crate
            url.starts_with("primitive://")
        });
    }
}

impl PartialEq for EffectMeta {
    // Equality implemented in a way where we can easily check things like
    //   "Is this the same primitive Delay effect this renderer knows how to implement?"
    fn eq(&self, other: &EffectMeta) -> bool {
        self.name == other.name &&
            self.sha256 == other.sha256 &&
            self.effect_args == other.effect_args
    }
}
impl Eq for EffectMeta {}

impl PartialEq for Effect {
    fn eq(&self, other: &Effect) -> bool {
        self.meta == other.meta
    }
}
impl Eq for Effect {}
<|endoftext|>


<commit_before>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

static FOO: i32 = 42;
static BAR: i32 = 42;

static BAZ: bool = { (&FOO as *const i32) == (&BAR as *const i32) }; //~ ERROR issue #53020
fn main() {
}
<commit_msg>Add feature gate test<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// gate-test-const_compare_raw_pointers

static FOO: i32 = 42;
static BAR: i32 = 42;

static BAZ: bool = { (&FOO as *const i32) == (&BAR as *const i32) }; //~ ERROR issue #53020
fn main() {
}
<|endoftext|>


<commit_before>//! Create graphene and other substrates for use in molecular dynamics simulations.

extern crate colored;
extern crate dialoguer;
extern crate serde;
extern crate serde_json;
extern crate structopt;
#[macro_use] extern crate structopt_derive;

extern crate grafen;
extern crate mdio;

mod error;
mod output;
mod ui;

use error::{GrafenCliError, Result};
use ui::read_configuration;

use grafen::database::{read_database, ComponentEntry, DataBase};
use grafen::read_conf::ReadConf;

use colored::*;
use std::env::{current_dir, home_dir, var, var_os};
use std::fs::DirBuilder;
use std::process;
use std::path::PathBuf;
use structopt::StructOpt;

const DEFAULT_DBNAME: &str = "database.json";

/// The program run configuration.
pub struct Config {
    /// Title of output system.
    pub title: String,
    /// Path to output file.
    pub output_path: PathBuf,
    /// Input components that were read from the command line.
    pub components: Vec<ComponentEntry>,
    /// Database of residue and substrate definitions.
    pub database: DataBase,
}

impl Config {
    /// Parse the input command line arguments and read the `DataBase`.
    ///
    /// # Errors
    /// Returns an error if the `DataBase` (if given as an input) could not be read.
    fn new() -> Result<Config> {
        eprintln!("{} {}\n", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"));

        let options = CliOptions::from_args();

        let output_path = options.output;
        let title = options.title.unwrap_or("System created by grafen".into());

        let mut database = match options.database {
            Some(path) => read_database(&path).map_err(|err| GrafenCliError::from(err)),
            None => read_or_create_default_database(),
        }?;

        let (components, mut entries) = read_input_configurations(options.input_confs);
        database.component_defs.append(&mut entries);

        Ok(Config { title, output_path, components, database })
    }
}

#[derive(StructOpt, Debug)]
#[structopt(raw(setting = "structopt::clap::AppSettings::ColoredHelp"))]
/// Command line options
struct CliOptions {
    #[structopt(short = "t", long = "title")]
    /// Title of output system
    title: Option<String>,
    #[structopt(short = "o", long = "output", default_value = "conf.gro", parse(from_os_str))]
    /// Output configuration file
    output: PathBuf,
    #[structopt(short = "d", long = "database", parse(from_os_str))]
    /// Path to residue and component database
    database: Option<PathBuf>,
    #[structopt(short = "c", long = "conf", parse(from_os_str))]
    /// Path to input configuration files to add as components
    input_confs: Vec<PathBuf>,
}

fn main() {
    if let Err(err) = Config::new().and_then(|conf| ui::user_menu(conf)) {
        eprintln!("{}", err);
        process::exit(1);
    }
}

fn read_input_configurations(confs: Vec<PathBuf>) -> (Vec<ComponentEntry>, Vec<ComponentEntry>) {
    let mut configurations = Vec::new();

    for path in confs {
        match read_configuration(&path) {
            Ok(conf) => configurations.push(conf),
            Err(err) => eprintln!("{}", err),
        }
    }

    eprint!("\n");

    let current_dir = current_dir().unwrap_or(PathBuf::new());
    let entries = configurations
        .iter()
        .map(|conf| ReadConf {
            conf: None,
            path: current_dir.join(&conf.path),
            backup_conf: None,
            description: conf.description.clone(),
            volume_type: conf.volume_type.clone(),
        })
        .map(|conf| ComponentEntry::ConfigurationFile(conf))
        .collect::<Vec<_>>();

    let components = configurations
        .into_iter()
        .map(|conf| ComponentEntry::ConfigurationFile(conf))
        .collect::<Vec<_>>();

    (components, entries)
}

fn read_or_create_default_database() -> Result<DataBase> {
    let default_database_paths = get_default_database_paths();

    if default_database_paths.is_empty() {
        eprintln!("{}", format!(
            "Could not find a location for the default database. \
            Opening a database which cannot be saved.",
        ).color("yellow"));

        return Ok(DataBase::new());
    }

    // See if a default database can be found at any path before creating a new one.
    for path in &default_database_paths {
        if path.is_file() {
            return read_database(&path).map_err(|err| GrafenCliError::from(err))
        }
    }

    let mut default_database = DataBase::new();
    let default_path = &default_database_paths[0];

    if let Some(parent_dir) = default_path.parent() {
        match DirBuilder::new().recursive(true).create(&parent_dir) {
            Ok(_) => default_database.set_path(&default_path).unwrap(),
            Err(err) => {
                eprintln!("{}", format!(
                    "Warning: Could not create a folder for a default database at '{}' ({}). \
                    Opening a database which cannot be saved.",
                    default_path.display(), err
                ).color("yellow"));
            },
        }
    }

    Ok(default_database)
}

fn get_default_database_paths() -> Vec<PathBuf> {
    get_platform_dependent_data_dirs()
        .into_iter()
        .map(|dir| dir.join("grafen").join(DEFAULT_DBNAME))
        .collect()
}

fn get_platform_dependent_data_dirs() -> Vec<PathBuf> {
    let xdg_data_dirs_variable = var("XDG_DATA_DIRS")
        .unwrap_or(String::from("/usr/local/share:/usr/local"));
    let xdg_dirs_iter = xdg_data_dirs_variable.split(':').map(|s| Some(PathBuf::from(s)));

    let dirs = if cfg!(target_os = "macos") {
        vec![
            var_os("XDG_DATA_HOME").map(|dir| PathBuf::from(dir)),
            home_dir().map(|dir| dir.join("Library").join("Application Support"))
        ].into_iter()
         .chain(xdg_dirs_iter)
         .chain(vec![Some(PathBuf::from("/").join("Library").join("Application Support"))])
         .collect()
    } else if cfg!(target_os = "linux") {
        vec![
            var_os("XDG_DATA_HOME").map(|dir| PathBuf::from(dir)),
            home_dir().map(|dir| dir.join(".local").join("share"))
        ].into_iter()
         .chain(xdg_dirs_iter)
         .collect()
    } else if cfg!(target_os = "windows") {
        vec![var_os("APPDATA").map(|dir| PathBuf::from(dir))]
    } else {
        Vec::new()
    };

    dirs.into_iter().filter_map(|dir| dir).collect()
}

#[cfg(test)]
pub mod tests {
    use super::*;
    use std::env::set_var;
    use std::path::Component;

    #[test]
    #[cfg(target_os = "macos")]
    fn default_database_dirs_on_macos_lead_with_xdg_dirs_then_application_support() {
        let xdg_data_home = "data_home";
        set_var("XDG_DATA_HOME", xdg_data_home);

        let xdg_data_directories = vec!["data_dir1", "data_dir2"];
        let xdg_data_dirs = format!("{}:{}", xdg_data_directories[0], xdg_data_directories[1]);
        set_var("XDG_DATA_DIRS", xdg_data_dirs);

        let user_appsupport = home_dir().unwrap().join("Library").join("Application Support");
        let root_appsupport = PathBuf::from("/").join("Library").join("Application Support");

        let result = get_platform_dependent_data_dirs();
        let priority_list = vec![
            PathBuf::from(xdg_data_home),
            user_appsupport,
            PathBuf::from(xdg_data_directories[0]),
            PathBuf::from(xdg_data_directories[1]),
            root_appsupport
        ];

        assert_eq!(result, priority_list);
    }

    #[test]
    #[cfg(target_os = "linux")]
    fn default_database_dirs_on_linux_lead_with_xdg_dirs_then_local_share() {
        let xdg_data_home = "data_home";
        set_var("XDG_DATA_HOME", xdg_data_home);

        let xdg_data_directories = vec!["data_dir1", "data_dir2"];
        let xdg_data_dirs = format!("{}:{}", xdg_data_directories[0], xdg_data_directories[1]);
        set_var("XDG_DATA_DIRS", xdg_data_dirs);

        let user_local_share = home_dir().unwrap().join(".local").join("share");
        let root_local_share = PathBuf::from("/").join("usr").join("local").join("share");
        let root_share = PathBuf::from("/").join("usr").join("share");

        let result = get_platform_dependent_data_dirs();
        let priority_list = vec![
            PathBuf::from(xdg_data_home),
            user_local_share,
            PathBuf::from(xdg_data_directories[0]),
            PathBuf::from(xdg_data_directories[1]),
            root_local_share,
            root_share
        ];

        assert_eq!(result, priority_list);
    }

    #[test]
    #[cfg(any(unix, windows))]
    fn default_database_path_adds_grafen_directory_and_database_path() {
        let dirs = get_default_database_paths();
        assert!(!dirs.is_empty());

        for path in dirs {
            let mut iter = path.components().rev();
            assert_eq!(iter.next().unwrap(), Component::Normal(DEFAULT_DBNAME.as_ref()));
            assert_eq!(iter.next().unwrap(), Component::Normal("grafen".as_ref()));
        }
    }
}
<commit_msg>Fix default database xdg spec on linux<commit_after>//! Create graphene and other substrates for use in molecular dynamics simulations.

extern crate colored;
extern crate dialoguer;
extern crate serde;
extern crate serde_json;
extern crate structopt;
#[macro_use] extern crate structopt_derive;

extern crate grafen;
extern crate mdio;

mod error;
mod output;
mod ui;

use error::{GrafenCliError, Result};
use ui::read_configuration;

use grafen::database::{read_database, ComponentEntry, DataBase};
use grafen::read_conf::ReadConf;

use colored::*;
use std::env::{current_dir, home_dir, var, var_os};
use std::fs::DirBuilder;
use std::process;
use std::path::PathBuf;
use structopt::StructOpt;

const DEFAULT_DBNAME: &str = "database.json";

/// The program run configuration.
pub struct Config {
    /// Title of output system.
    pub title: String,
    /// Path to output file.
    pub output_path: PathBuf,
    /// Input components that were read from the command line.
    pub components: Vec<ComponentEntry>,
    /// Database of residue and substrate definitions.
    pub database: DataBase,
}

impl Config {
    /// Parse the input command line arguments and read the `DataBase`.
    ///
    /// # Errors
    /// Returns an error if the `DataBase` (if given as an input) could not be read.
    fn new() -> Result<Config> {
        eprintln!("{} {}\n", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"));

        let options = CliOptions::from_args();

        let output_path = options.output;
        let title = options.title.unwrap_or("System created by grafen".into());

        let mut database = match options.database {
            Some(path) => read_database(&path).map_err(|err| GrafenCliError::from(err)),
            None => read_or_create_default_database(),
        }?;

        let (components, mut entries) = read_input_configurations(options.input_confs);
        database.component_defs.append(&mut entries);

        Ok(Config { title, output_path, components, database })
    }
}

#[derive(StructOpt, Debug)]
#[structopt(raw(setting = "structopt::clap::AppSettings::ColoredHelp"))]
/// Command line options
struct CliOptions {
    #[structopt(short = "t", long = "title")]
    /// Title of output system
    title: Option<String>,
    #[structopt(short = "o", long = "output", default_value = "conf.gro", parse(from_os_str))]
    /// Output configuration file
    output: PathBuf,
    #[structopt(short = "d", long = "database", parse(from_os_str))]
    /// Path to residue and component database
    database: Option<PathBuf>,
    #[structopt(short = "c", long = "conf", parse(from_os_str))]
    /// Path to input configuration files to add as components
    input_confs: Vec<PathBuf>,
}

fn main() {
    if let Err(err) = Config::new().and_then(|conf| ui::user_menu(conf)) {
        eprintln!("{}", err);
        process::exit(1);
    }
}

fn read_input_configurations(confs: Vec<PathBuf>) -> (Vec<ComponentEntry>, Vec<ComponentEntry>) {
    let mut configurations = Vec::new();

    for path in confs {
        match read_configuration(&path) {
            Ok(conf) => configurations.push(conf),
            Err(err) => eprintln!("{}", err),
        }
    }

    eprint!("\n");

    let current_dir = current_dir().unwrap_or(PathBuf::new());
    let entries = configurations
        .iter()
        .map(|conf| ReadConf {
            conf: None,
            path: current_dir.join(&conf.path),
            backup_conf: None,
            description: conf.description.clone(),
            volume_type: conf.volume_type.clone(),
        })
        .map(|conf| ComponentEntry::ConfigurationFile(conf))
        .collect::<Vec<_>>();

    let components = configurations
        .into_iter()
        .map(|conf| ComponentEntry::ConfigurationFile(conf))
        .collect::<Vec<_>>();

    (components, entries)
}

fn read_or_create_default_database() -> Result<DataBase> {
    let default_database_paths = get_default_database_paths();

    if default_database_paths.is_empty() {
        eprintln!("{}", format!(
            "Could not find a location for the default database. \
            Opening a database which cannot be saved.",
        ).color("yellow"));

        return Ok(DataBase::new());
    }

    // See if a default database can be found at any path before creating a new one.
    for path in &default_database_paths {
        if path.is_file() {
            return read_database(&path).map_err(|err| GrafenCliError::from(err))
        }
    }

    let mut default_database = DataBase::new();
    let default_path = &default_database_paths[0];

    if let Some(parent_dir) = default_path.parent() {
        match DirBuilder::new().recursive(true).create(&parent_dir) {
            Ok(_) => default_database.set_path(&default_path).unwrap(),
            Err(err) => {
                eprintln!("{}", format!(
                    "Warning: Could not create a folder for a default database at '{}' ({}). \
                    Opening a database which cannot be saved.",
                    default_path.display(), err
                ).color("yellow"));
            },
        }
    }

    Ok(default_database)
}

fn get_default_database_paths() -> Vec<PathBuf> {
    get_platform_dependent_data_dirs()
        .into_iter()
        .map(|dir| dir.join("grafen").join(DEFAULT_DBNAME))
        .collect()
}

fn get_platform_dependent_data_dirs() -> Vec<PathBuf> {
    let xdg_data_dirs_variable = var("XDG_DATA_DIRS")
        .unwrap_or(String::from("/usr/local/share:/usr/local"));
    let xdg_dirs_iter = xdg_data_dirs_variable.split(':').map(|s| Some(PathBuf::from(s)));

    let dirs = if cfg!(target_os = "macos") {
        vec![
            var_os("XDG_DATA_HOME").map(|dir| PathBuf::from(dir)),
            home_dir().map(|dir| dir.join("Library").join("Application Support"))
        ].into_iter()
         .chain(xdg_dirs_iter)
         .chain(vec![Some(PathBuf::from("/").join("Library").join("Application Support"))])
         .collect()
    } else if cfg!(target_os = "linux") {
        vec![
            var_os("XDG_DATA_HOME").map(|dir| PathBuf::from(dir)),
            home_dir().map(|dir| dir.join(".local").join("share"))
        ].into_iter()
         .chain(xdg_dirs_iter)
         .collect()
    } else if cfg!(target_os = "windows") {
        vec![var_os("APPDATA").map(|dir| PathBuf::from(dir))]
    } else {
        Vec::new()
    };

    dirs.into_iter().filter_map(|dir| dir).collect()
}

#[cfg(test)]
pub mod tests {
    use super::*;
    use std::env::set_var;
    use std::path::Component;

    #[test]
    #[cfg(target_os = "macos")]
    fn default_database_dirs_on_macos_lead_with_xdg_dirs_then_application_support() {
        let xdg_data_home = "data_home";
        set_var("XDG_DATA_HOME", xdg_data_home);

        let xdg_data_directories = vec!["data_dir1", "data_dir2"];
        let xdg_data_dirs = format!("{}:{}", xdg_data_directories[0], xdg_data_directories[1]);
        set_var("XDG_DATA_DIRS", xdg_data_dirs);

        let user_appsupport = home_dir().unwrap().join("Library").join("Application Support");
        let root_appsupport = PathBuf::from("/").join("Library").join("Application Support");

        let result = get_platform_dependent_data_dirs();
        let priority_list = vec![
            PathBuf::from(xdg_data_home),
            user_appsupport,
            PathBuf::from(xdg_data_directories[0]),
            PathBuf::from(xdg_data_directories[1]),
            root_appsupport
        ];

        assert_eq!(result, priority_list);
    }

    #[test]
    #[cfg(target_os = "linux")]
    fn default_database_dirs_on_linux_lead_with_xdg_dirs_then_local_share() {
        let xdg_data_home = "data_home";
        set_var("XDG_DATA_HOME", xdg_data_home);

        let xdg_data_directories = vec!["data_dir1", "data_dir2"];
        let xdg_data_dirs = format!("{}:{}", xdg_data_directories[0], xdg_data_directories[1]);
        set_var("XDG_DATA_DIRS", xdg_data_dirs);

        let user_local_share = home_dir().unwrap().join(".local").join("share");

        let result = get_platform_dependent_data_dirs();
        let priority_list = vec![
            PathBuf::from(xdg_data_home),
            user_local_share,
            PathBuf::from(xdg_data_directories[0]),
            PathBuf::from(xdg_data_directories[1])
        ];

        assert_eq!(result, priority_list);
    }

    #[test]
    #[cfg(any(unix, windows))]
    fn default_database_path_adds_grafen_directory_and_database_path() {
        let dirs = get_default_database_paths();
        assert!(!dirs.is_empty());

        for path in dirs {
            let mut iter = path.components().rev();
            assert_eq!(iter.next().unwrap(), Component::Normal(DEFAULT_DBNAME.as_ref()));
            assert_eq!(iter.next().unwrap(), Component::Normal("grafen".as_ref()));
        }
    }
}
<|endoftext|>


<commit_before>pub enum File {
    FileId(&str),
    Url(&str),
    File(&str),
}
<commit_msg>Changing &str to String<commit_after>pub enum File {
    FileId(String),
    Url(String),
    File(String),
}
<|endoftext|>


<commit_before>//
// FlightVars
// Copyright (c) 2015, 2016 Alvaro Polo
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::io;
use std::net;

use comm::*;

#[derive(Debug)]
pub struct TcpInput(net::TcpStream);

#[cfg(unix)]
impl io::Read for TcpInput {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }
}

#[cfg(windows)]
impl io::Read for TcpInput {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }
}

impl ShutdownInterruption for TcpInput {
    type Int = TcpInterruptor;

    fn shutdown_interruption(&mut self) -> TcpInterruptor {
        TcpInterruptor::from_stream(&self.0)
    }
}

#[derive(Debug)]
pub struct TcpOutput(net::TcpStream);

impl io::Write for TcpOutput {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) }
    fn flush(&mut self) -> io::Result<()> { self.0.flush() }
}

pub struct TcpListener(net::TcpListener);

impl TcpListener {
    pub fn bind<A: net::ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
        net::TcpListener::bind(addr).map(|l| TcpListener(l))
    }

    #[cfg(unix)]
    fn accept(&mut self) -> io::Result<net::TcpStream> {
        self.0.accept().map(|(s, _)| s)
    }

    #[cfg(windows)]
    fn accept(&mut self) -> io::Result<net::TcpStream> {
        self.0.accept()
            .map(|(s, _)| s)
            .map_err(Self::map_interrupt_error)
    }

    #[cfg(windows)]
    fn map_interrupt_error(error: io::Error) -> io::Error {
        if error.kind() == io::ErrorKind::Other && error.raw_os_error() == Some(10004) {
            io::Error::new(io::ErrorKind::ConnectionAborted, "listener was interrupted")
        } else {
            error
        }
    }
}

impl Listen<TcpInput, TcpOutput> for TcpListener {
    fn listen(&mut self) -> io::Result<(TcpInput, TcpOutput)> {
        let conn = try!(self.accept());
        let input = TcpInput(try!(conn.try_clone()));
        let output = TcpOutput(conn);
        Ok((input, output))
    }
}

impl ShutdownInterruption for TcpListener {
    type Int = TcpInterruptor;

    fn shutdown_interruption(&mut self) -> TcpInterruptor {
        TcpInterruptor::from_listener(&self.0)
    }
}

pub struct TcpTransport {
    listener: TcpListener
}

impl TcpTransport {
    pub fn bind<A: net::ToSocketAddrs>(addr: A) -> io::Result<TcpTransport> {
        Ok(TcpTransport { listener: try!(TcpListener::bind(addr)) })
    }
}

impl Transport for TcpTransport {
    type Input = TcpInput;
    type Output = TcpOutput;
    type Listener = TcpListener;

    fn listener(&mut self) -> &mut TcpListener {
        &mut self.listener
    }
}

#[cfg(unix)]
pub mod unix {
    use std::net;
    use std::os::unix::io::{AsRawFd, RawFd};

    use libc;

    use comm::*;

    pub struct TcpInterruptor {
        fd: RawFd
    }

    impl TcpInterruptor {
        pub fn from_listener(listener: &net::TcpListener) -> TcpInterruptor {
            TcpInterruptor { fd: listener.as_raw_fd() }
        }

        pub fn from_stream(stream: &net::TcpStream) -> TcpInterruptor {
            TcpInterruptor { fd: stream.as_raw_fd() }
        }
    }

    impl Interrupt for TcpInterruptor {
        fn interrupt(self) {
            unsafe { libc::close(self.fd); }
        }
    }
}

#[cfg(unix)]
pub use self::unix::*;

#[cfg(windows)]
pub mod win {
    use std::net;
    use std::os::windows::io::{AsRawSocket, RawSocket};

    use ws2_32;

    use comm::*;

    pub struct TcpInterruptor {
        socket: RawSocket
    }

    impl TcpInterruptor {
        pub fn from_listener(listener: &net::TcpListener) -> TcpInterruptor {
            TcpInterruptor { socket: listener.as_raw_socket() }
        }

        pub fn from_stream(stream: &net::TcpStream) -> TcpInterruptor {
            TcpInterruptor { socket: stream.as_raw_socket() }
        }
    }

    impl Interrupt for TcpInterruptor {
        fn interrupt(self) {
            unsafe { ws2_32::closesocket(self.socket); }
        }
    }
}

#[cfg(windows)]
pub use self::win::*;

#[cfg(test)]
mod tests {
    use std::io;
    use std::io::{BufRead, Read, Write};
    use std::net;
    use std::thread;
    use std::time;

    use comm::*;

    use super::*;

    #[test]
    fn should_wait_conn() {
        let child = thread::spawn(|| {
            let mut listener = TcpListener::bind("127.0.0.1:1234").unwrap();
            let (r, mut w) = listener.listen().unwrap();
            let mut input = io::BufReader::new(r);
            let mut line = String::new();
            input.read_line(&mut line).unwrap();
            assert_eq!(line, "Hello server\n");
            w.write_all(b"Hello client\n").unwrap();
        });
        thread::sleep(time::Duration::from_millis(25));
        let mut conn = net::TcpStream::connect("127.0.0.1:1234").unwrap();
        conn.write_all(b"Hello server\n").unwrap();
        let mut input = io::BufReader::new(conn);
        let mut line = String::new();
        input.read_line(&mut line).unwrap();
        assert_eq!(line, "Hello client\n");
        child.join().unwrap();
    }

    #[test]
    fn should_close_listener_from_shutdown_handle() {
        let mut listener = TcpListener::bind("127.0.0.1:1235").unwrap();
        let interruption = listener.shutdown_interruption();
        let child = thread::spawn(move || {
            assert_eq!(listener.listen().unwrap_err().kind(), io::ErrorKind::ConnectionAborted);
        });
        thread::sleep(time::Duration::from_millis(25));
        interruption.interrupt();
        child.join().unwrap();
    }

    #[test]
    fn should_close_input_from_shutdown_handle() {
        let mut listener = TcpListener::bind("127.0.0.1:1236").unwrap();
        let interruption = listener.shutdown_interruption();
        let client = thread::spawn(move || {
            let conn = net::TcpStream::connect("127.0.0.1:1236");
            thread::sleep(time::Duration::from_millis(50));
        });
        let child = thread::spawn(move || {
            let (mut conn, _) = listener.listen().unwrap();
            let interruption = conn.shutdown_interruption();
            thread::spawn(move || {
                thread::sleep(time::Duration::from_millis(20));
                interruption.interrupt();
            });
            let mut buf = [10; 0];
            assert_eq!(conn.read(&mut buf).unwrap_err().kind(), io::ErrorKind::ConnectionAborted);
        });
        thread::sleep(time::Duration::from_millis(50));
        interruption.interrupt();
        child.join().unwrap();
        client.join().unwrap();
    }
}
<commit_msg>Fix some issues in `comm::tcp` for Unix<commit_after>//
// FlightVars
// Copyright (c) 2015, 2016 Alvaro Polo
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::io;
use std::net;

use comm::*;

#[derive(Debug)]
pub struct TcpInput(net::TcpStream);

#[cfg(unix)]
impl io::Read for TcpInput {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf).map_err(|e|
            if e.kind() == io::ErrorKind::Other && e.raw_os_error() == Some(9) {
                io::Error::new(io::ErrorKind::ConnectionAborted, "tcp input was interrupted")
            } else { e }
        )
    }
}

#[cfg(windows)]
impl io::Read for TcpInput {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }
}

impl ShutdownInterruption for TcpInput {
    type Int = TcpInterruptor;

    fn shutdown_interruption(&mut self) -> TcpInterruptor {
        TcpInterruptor::from_stream(&self.0)
    }
}

#[derive(Debug)]
pub struct TcpOutput(net::TcpStream);

impl io::Write for TcpOutput {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) }
    fn flush(&mut self) -> io::Result<()> { self.0.flush() }
}

pub struct TcpListener(net::TcpListener);

impl TcpListener {
    pub fn bind<A: net::ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
        net::TcpListener::bind(addr).map(|l| TcpListener(l))
    }

    #[cfg(unix)]
    fn accept(&mut self) -> io::Result<net::TcpStream> {
        self.0.accept().map(|(s, _)| s)
    }

    #[cfg(windows)]
    fn accept(&mut self) -> io::Result<net::TcpStream> {
        self.0.accept()
            .map(|(s, _)| s)
            .map_err(Self::map_interrupt_error)
    }

    #[cfg(windows)]
    fn map_interrupt_error(error: io::Error) -> io::Error {
        if error.kind() == io::ErrorKind::Other && error.raw_os_error() == Some(10004) {
            io::Error::new(io::ErrorKind::ConnectionAborted, "listener was interrupted")
        } else {
            error
        }
    }
}

impl Listen<TcpInput, TcpOutput> for TcpListener {
    fn listen(&mut self) -> io::Result<(TcpInput, TcpOutput)> {
        let conn = try!(self.accept());
        let input = TcpInput(try!(conn.try_clone()));
        let output = TcpOutput(conn);
        Ok((input, output))
    }
}

impl ShutdownInterruption for TcpListener {
    type Int = TcpInterruptor;

    fn shutdown_interruption(&mut self) -> TcpInterruptor {
        TcpInterruptor::from_listener(&self.0)
    }
}

pub struct TcpTransport {
    listener: TcpListener
}

impl TcpTransport {
    pub fn bind<A: net::ToSocketAddrs>(addr: A) -> io::Result<TcpTransport> {
        Ok(TcpTransport { listener: try!(TcpListener::bind(addr)) })
    }
}

impl Transport for TcpTransport {
    type Input = TcpInput;
    type Output = TcpOutput;
    type Listener = TcpListener;

    fn listener(&mut self) -> &mut TcpListener {
        &mut self.listener
    }
}

#[cfg(unix)]
pub mod unix {
    use std::net;
    use std::os::unix::io::{AsRawFd, RawFd};

    use libc;

    use comm::*;

    pub struct TcpInterruptor {
        fd: RawFd
    }

    impl TcpInterruptor {
        pub fn from_listener(listener: &net::TcpListener) -> TcpInterruptor {
            TcpInterruptor { fd: listener.as_raw_fd() }
        }

        pub fn from_stream(stream: &net::TcpStream) -> TcpInterruptor {
            TcpInterruptor { fd: stream.as_raw_fd() }
        }
    }

    impl Interrupt for TcpInterruptor {
        fn interrupt(self) {
            unsafe { libc::close(self.fd); }
        }
    }
}

#[cfg(unix)]
pub use self::unix::*;

#[cfg(windows)]
pub mod win {
    use std::net;
    use std::os::windows::io::{AsRawSocket, RawSocket};

    use ws2_32;

    use comm::*;

    pub struct TcpInterruptor {
        socket: RawSocket
    }

    impl TcpInterruptor {
        pub fn from_listener(listener: &net::TcpListener) -> TcpInterruptor {
            TcpInterruptor { socket: listener.as_raw_socket() }
        }

        pub fn from_stream(stream: &net::TcpStream) -> TcpInterruptor {
            TcpInterruptor { socket: stream.as_raw_socket() }
        }
    }

    impl Interrupt for TcpInterruptor {
        fn interrupt(self) {
            unsafe { ws2_32::closesocket(self.socket); }
        }
    }
}

#[cfg(windows)]
pub use self::win::*;

#[cfg(test)]
mod tests {
    use std::io;
    use std::io::{BufRead, Read, Write};
    use std::net;
    use std::thread;
    use std::time;

    use comm::*;

    use super::*;

    #[test]
    fn should_wait_conn() {
        let child = thread::spawn(|| {
            let mut listener = TcpListener::bind("127.0.0.1:1234").unwrap();
            let (r, mut w) = listener.listen().unwrap();
            let mut input = io::BufReader::new(r);
            let mut line = String::new();
            input.read_line(&mut line).unwrap();
            assert_eq!(line, "Hello server\n");
            w.write_all(b"Hello client\n").unwrap();
        });
        thread::sleep(time::Duration::from_millis(25));
        let mut conn = net::TcpStream::connect("127.0.0.1:1234").unwrap();
        conn.write_all(b"Hello server\n").unwrap();
        let mut input = io::BufReader::new(conn);
        let mut line = String::new();
        input.read_line(&mut line).unwrap();
        assert_eq!(line, "Hello client\n");
        child.join().unwrap();
    }

    #[test]
    fn should_close_listener_from_shutdown_handle() {
        let mut listener = TcpListener::bind("127.0.0.1:1235").unwrap();
        let interruption = listener.shutdown_interruption();
        let child = thread::spawn(move || {
            assert_eq!(listener.listen().unwrap_err().kind(), io::ErrorKind::ConnectionAborted);
        });
        thread::sleep(time::Duration::from_millis(25));
        interruption.interrupt();
        child.join().unwrap();
    }

    #[test]
    fn should_close_input_from_shutdown_handle() {
        let mut listener = TcpListener::bind("127.0.0.1:1236").unwrap();
        let interruption = listener.shutdown_interruption();
        let client = thread::spawn(move || {
            let conn = net::TcpStream::connect("127.0.0.1:1236");
            thread::sleep(time::Duration::from_millis(50));
        });
        let child = thread::spawn(move || {
            let (mut conn, _) = listener.listen().unwrap();
            let interruption = conn.shutdown_interruption();
            thread::spawn(move || {
                thread::sleep(time::Duration::from_millis(20));
                interruption.interrupt();
            });
            let mut buf = [0; 10];
            assert_eq!(conn.read(&mut buf).unwrap_err().kind(), io::ErrorKind::ConnectionAborted);
        });
        thread::sleep(time::Duration::from_millis(50));
        interruption.interrupt();
        child.join().unwrap();
        client.join().unwrap();
    }
}
<|endoftext|>


<commit_before>pub struct Document {
    attributes: Vec<(String, String)>,
    content: String,
}

impl Document {
    pub fn new(attributes: Vec<(String, String)>, content: String) -> Document {
        Document {
            attributes: attributes,
            content: content,
        }
    }
}
<commit_msg>implemented std::fmt::Show trait for Document, better for debugging purpose, started implementation for document html view<commit_after>use std::fmt;

pub struct Document {
    attributes: Vec<(String, String)>,
    content: String,
}

impl Document {
    pub fn new(attributes: Vec<(String, String)>, content: String) -> Document {
        Document {
            attributes: attributes,
            content: content,
        }
    }

    pub fn as_html(&self) -> &str {
        "test"
    }
}

impl fmt::Show for Document {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Attributes: {}\nContent: {}", self.attributes, self.content)
    }
}
<|endoftext|>


<commit_before>use std::io::{self, Write};
use std::fmt::Display;
use std::fs::{File, create_dir_all, set_permissions, metadata};
use std::os::unix::ffi::OsStrExt;
use std::os::unix::fs::{symlink, MetadataExt, PermissionsExt};
use std::path::Path;
use std::collections::{BTreeMap, BTreeSet};

use cronparse::Limited;
use cronparse::crontab::{CrontabEntry, SystemCrontabEntry, UserCrontabEntry};
use cronparse::schedule::{Schedule, Period, Calendar};
use cronparse::interval::Interval;

use users::{get_user_by_name, get_user_by_uid};

use super::{REBOOT_FILE, PACKAGE, LIB_DIR};

pub fn generate_systemd_units(entry: CrontabEntry, env: &BTreeMap<String, String>, path: &Path, dstdir: &Path) -> io::Result<()> {
    use cronparse::crontab::CrontabEntry::*;

    info!("generating units for {}: \"{}\", {:?}", path.display(), entry, env);

    let owner = try!(metadata(path)).uid();

    let mut persistent = env.get("PERSISTENT").and_then(|v| match &**v {
        "yes" | "true" | "1" => Some(true),
        "auto" | "" => None,
        _ => Some(false)
    }).unwrap_or_else(|| match entry {
        Anacron(_) | User(UserCrontabEntry { sched: Schedule::Period(_), .. }) | System(SystemCrontabEntry { sched: Schedule::Period(_), .. }) => true,
        _ => false
    });

    let batch = env.get("BATCH").map(|v| match &**v {
        "yes" | "true" | "1" => true,
        _ => false
    }).unwrap_or(false);

    let random_delay = env.get("RANDOM_DELAY").and_then(|v| v.parse::<u64>().ok()).unwrap_or(1);
    let mut delay = env.get("DELAY").and_then(|v| v.parse::<u64>().ok()).unwrap_or(0);
    let hour = env.get("START_HOURS_RANGE").and_then(|v| v.splitn(1, '-').next().and_then(|v| v.parse::<u64>().ok())).unwrap_or(0);
    let shell = env.get("SHELL").map(|v| &**v).unwrap_or("/bin/sh");
    let daemon_reload = metadata(REBOOT_FILE).map(|m| m.is_file()).unwrap_or(false);

    let schedule = entry.period().and_then(|period| match *period {
        Period::Reboot => {
            persistent = false;
            if delay == 0 {
                delay = 1;
            }
            None
        },
        Period::Minutely => {
            persistent = false;
            Some("@minutely".to_owned())
        },
        Period::Hourly => {
            if delay == 0 {
                Some("@hourly".to_owned())
            } else {
                Some(format!("*-*-* *:{}:0", delay))
            }
        },
        Period::Midnight => {
            if delay == 0 {
                Some("@daily".to_owned())
            } else {
                Some(format!("*-*-* 0:{}:0", delay))
            }
        },
        Period::Daily => {
            if delay == 0 && hour == 0 {
                Some("@daily".to_owned())
            } else {
                Some(format!("*-*-* {}:{}:0", hour, delay))
            }
        },
        Period::Weekly => {
            if delay == 0 && hour == 0 {
                Some("@weekly".to_owned())
            } else {
                Some(format!("Mon *-*-* {}:{}:0", hour, delay))
            }
        },
        Period::Monthly => {
            if delay == 0 && hour == 0 {
                Some("@monthly".to_owned())
            } else {
                Some(format!("*-*-1 {}:{}:0", hour, delay))
            }
        },
        Period::Quaterly => {
            if delay == 0 && hour == 0 {
                Some("@quaterly".to_owned())
            } else {
                Some(format!("*-1,4,7,10-1 {}:{}:0", hour, delay))
            }
        },
        Period::Biannually => {
            if delay == 0 && hour == 0 {
                Some("@semi-annually".to_owned())
            } else {
                Some(format!("*-1,7-1 {}:{}:0", hour, delay))
            }
        },
        Period::Yearly => {
            if delay == 0 && hour == 0 {
                Some("@yearly".to_owned())
            } else {
                Some(format!("*-1-1 {}:{}:0", hour, delay))
            }
        },
        Period::Days(days) => {
            // workaround for anacrontab
            if days > 31 {
                Some(format!("*-1/{}-1 {}:{}:0", days / 30, hour, delay))
            } else {
                Some(format!("*-*-1/{} {}:{}:0", days, hour, delay))
            }
        },
    }).or_else(|| entry.calendar().and_then(|cal| {
        let Calendar {
            ref dows,
            ref days,
            ref mons,
            ref hrs,
            ref mins
        } = *cal;

        Some(format!("{} *-{}-{} {}:{}:00",
                     linearize(&**dows, ""),
                     linearize(&**mons, "*"),
                     linearize(&**days, "*"),
                     linearize(&**hrs, "*"),
                     linearize(&**mins, "*")))
    }));

    if daemon_reload && schedule.is_none() {
        warn!("skipping job from {}: \"{}\"", path.display(), entry);
        return Ok(());
    }

    if let Some(cmd) = entry.command() {

        // make sure we know the user
        let user = try!(entry.user().and_then(get_user_by_name).or_else(|| get_user_by_uid(owner))
            .ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "unknown user")));

        // generate unique cron job id
        let mut md5ctx = ::md5::Context::new();
        md5ctx.consume(path.as_os_str().as_bytes());
        if let Some(ref schedule) = schedule {
            md5ctx.consume(schedule.as_bytes());
        }
        md5ctx.consume(cmd.as_bytes());
        let md5hex = tohex(&md5ctx.compute());

        // create service and timer unit names
        let service_unit_name = format!("cron-{}.service", md5hex);
        let timer_unit_name = format!("cron-{}.timer", md5hex);

        // unit paths
        let service_unit_path = dstdir.join(&service_unit_name);
        let timer_unit_path = dstdir.join(&timer_unit_name);

        // make sure cron.target.wants dir exists
        let cron_target_wants_path = dstdir.join("cron.target.wants");
        try!(create_dir_all(&cron_target_wants_path));

        // process command in case it should be put into script
        let command = if metadata(cmd).map(|m| m.is_file()).unwrap_or(false) {
            cmd.to_owned()
        } else {
            let script_command_path = dstdir.join(format!("cron-{}.sh", md5hex));

            debug!("generating script {:?} from {:?}", script_command_path, path);
            {
                let mut script_command_file = try!(File::create(&script_command_path));
                try!(writeln!(script_command_file, "#!{}", shell));
                try!(writeln!(script_command_file, "{}", cmd));
            }

            let mut perms = try!(metadata(&script_command_path)).permissions();
            perms.set_mode(0o755);
            try!(set_permissions(&script_command_path, perms));
            script_command_path.to_str().unwrap().to_owned()
        };

        debug!("generating service {:?} from {:?}", service_unit_path, path);
        {
            let mut service_unit_file = try!(File::create(service_unit_path));

            try!(writeln!(service_unit_file, r###"[Unit]
Description=[Cron] "{entry}"
Documentation=man:systemd-crontab-generator(8)
RefuseManualStart=true
RefuseManualStop=true
SourcePath={source_crontab_path}"###,
                entry = entry,
                source_crontab_path = path.display(),
                ));

            if env.contains_key("MAILTO") {
                try!(writeln!(service_unit_file, "OnFailure=cron-failure@%i.service"));
            }

            if user.uid != 0 {
                try!(writeln!(service_unit_file, "Requires=systemd-user-sessions.service"));
                if !user.home_dir.is_empty() {
                    try!(writeln!(service_unit_file, "RequiresMountsFor={}", user.home_dir));
                }
            }

            try!(writeln!(service_unit_file, r###"
[Service]
Type=oneshot
IgnoreSIGPIPE=false
ExecStart={command}"###,
                command = command,
                ));

            if schedule.is_some() && delay > 0 {
                try!(writeln!(service_unit_file, "ExecStartPre=-{}/{}/boot-delay {}", LIB_DIR, PACKAGE, delay));
            }

            if user.uid != 0 {
                try!(writeln!(service_unit_file, "User={}", user.name));
            }

            if let Some(group) = entry.group() {
                try!(writeln!(service_unit_file, "Group={}", group));
            }
            if batch {
                try!(writeln!(service_unit_file, "CPUSchedulingPolicy=idle"));
                try!(writeln!(service_unit_file, "IOSchedulingClass=idle"));
            }

            if !env.is_empty() {
                for (name, value) in env.iter() {
                    try!(writeln!(service_unit_file, r#"Environment="{}={}""#, name, value));
                }
            }
        }

        debug!("generating timer {:?} from {:?}", timer_unit_path, path);
        {
            let mut timer_unit_file = try!(File::create(&timer_unit_path));

            try!(writeln!(timer_unit_file, r###"[Unit]
Description=[Timer] "{entry}"
Documentation=man:systemd-crontab-generator(8)
PartOf=cron.target
RefuseManualStart=true
RefuseManualStop=true
SourcePath={source_crontab_path}

[Timer]
Unit={service_unit_name}"###,
                entry = entry,
                source_crontab_path = path.display(),
                service_unit_name = service_unit_name,
                ));

            if cfg![feature="persistent"] {
                try!(writeln!(timer_unit_file, "Persistent={}", persistent));
            }

            if let Some(schedule) = schedule {
                try!(writeln!(timer_unit_file, "OnCalendar={}", schedule));
            } else {
                try!(writeln!(timer_unit_file, "OnBootSec={}m", delay));
            }

            if random_delay != 1 {
                try!(writeln!(timer_unit_file, "AccuracySec={}m", random_delay));
            }
        }
        try!(symlink(timer_unit_path, cron_target_wants_path.join(timer_unit_name)));
    }

    Ok(())
}

fn linearize<T: Limited + Display>(input: &[Interval<T>], star: &str) -> String {
    if input.len() == 1 && input[0] == Interval::Full(1) {
        star.to_owned()
    } else {
        let mut output = String::new();
        for part in input.iter().flat_map(|v| v.iter()).collect::<BTreeSet<_>>().iter() {
            output.push_str(&*part.to_string());
            output.push(',');
        }
        output.pop();
        output
    }
}

fn tohex(input: &[u8]) -> String {
    #[inline]
    fn hex(d: u8) -> char {
        match d {
            0...9 => (d + 0x30) as char,
            10...15 => (d + 0x57) as char,
            _ => unreachable!("unexpected value: {}", d)
        }
    }

    let mut buf = String::with_capacity(32);
    for b in input.into_iter() {
        buf.push(hex(b >> 4));
        buf.push(hex(b & 0xf));
    }
    buf
}

<commit_msg>fix bug: invalid month name generator<commit_after>use std::io::{self, Write};
use std::fs::{File, create_dir_all, set_permissions, metadata};
use std::os::unix::ffi::OsStrExt;
use std::os::unix::fs::{symlink, MetadataExt, PermissionsExt};
use std::path::Path;
use std::collections::{BTreeMap, BTreeSet};

use cronparse::Limited;
use cronparse::crontab::{CrontabEntry, SystemCrontabEntry, UserCrontabEntry};
use cronparse::schedule::{Schedule, Period, Calendar};
use cronparse::interval::Interval;

use users::{get_user_by_name, get_user_by_uid};

use super::{REBOOT_FILE, PACKAGE, LIB_DIR};

pub fn generate_systemd_units(entry: CrontabEntry, env: &BTreeMap<String, String>, path: &Path, dstdir: &Path) -> io::Result<()> {
    use cronparse::crontab::CrontabEntry::*;

    info!("generating units for {}: \"{}\", {:?}", path.display(), entry, env);

    let owner = try!(metadata(path)).uid();

    let mut persistent = env.get("PERSISTENT").and_then(|v| match &**v {
        "yes" | "true" | "1" => Some(true),
        "auto" | "" => None,
        _ => Some(false)
    }).unwrap_or_else(|| match entry {
        Anacron(_) | User(UserCrontabEntry { sched: Schedule::Period(_), .. }) | System(SystemCrontabEntry { sched: Schedule::Period(_), .. }) => true,
        _ => false
    });

    let batch = env.get("BATCH").map(|v| match &**v {
        "yes" | "true" | "1" => true,
        _ => false
    }).unwrap_or(false);

    let random_delay = env.get("RANDOM_DELAY").and_then(|v| v.parse::<u64>().ok()).unwrap_or(1);
    let mut delay = env.get("DELAY").and_then(|v| v.parse::<u64>().ok()).unwrap_or(0);
    let hour = env.get("START_HOURS_RANGE").and_then(|v| v.splitn(1, '-').next().and_then(|v| v.parse::<u64>().ok())).unwrap_or(0);
    let shell = env.get("SHELL").map(|v| &**v).unwrap_or("/bin/sh");
    let daemon_reload = metadata(REBOOT_FILE).map(|m| m.is_file()).unwrap_or(false);

    let schedule = entry.period().and_then(|period| match *period {
        Period::Reboot => {
            persistent = false;
            if delay == 0 {
                delay = 1;
            }
            None
        },
        Period::Minutely => {
            persistent = false;
            Some("@minutely".to_owned())
        },
        Period::Hourly => {
            if delay == 0 {
                Some("@hourly".to_owned())
            } else {
                Some(format!("*-*-* *:{}:0", delay))
            }
        },
        Period::Midnight => {
            if delay == 0 {
                Some("@daily".to_owned())
            } else {
                Some(format!("*-*-* 0:{}:0", delay))
            }
        },
        Period::Daily => {
            if delay == 0 && hour == 0 {
                Some("@daily".to_owned())
            } else {
                Some(format!("*-*-* {}:{}:0", hour, delay))
            }
        },
        Period::Weekly => {
            if delay == 0 && hour == 0 {
                Some("@weekly".to_owned())
            } else {
                Some(format!("Mon *-*-* {}:{}:0", hour, delay))
            }
        },
        Period::Monthly => {
            if delay == 0 && hour == 0 {
                Some("@monthly".to_owned())
            } else {
                Some(format!("*-*-1 {}:{}:0", hour, delay))
            }
        },
        Period::Quaterly => {
            if delay == 0 && hour == 0 {
                Some("@quaterly".to_owned())
            } else {
                Some(format!("*-1,4,7,10-1 {}:{}:0", hour, delay))
            }
        },
        Period::Biannually => {
            if delay == 0 && hour == 0 {
                Some("@semi-annually".to_owned())
            } else {
                Some(format!("*-1,7-1 {}:{}:0", hour, delay))
            }
        },
        Period::Yearly => {
            if delay == 0 && hour == 0 {
                Some("@yearly".to_owned())
            } else {
                Some(format!("*-1-1 {}:{}:0", hour, delay))
            }
        },
        Period::Days(days) => {
            // workaround for anacrontab
            if days > 31 {
                Some(format!("*-1/{}-1 {}:{}:0", days / 30, hour, delay))
            } else {
                Some(format!("*-*-1/{} {}:{}:0", days, hour, delay))
            }
        },
    }).or_else(|| entry.calendar().and_then(|cal| {
        let Calendar {
            ref dows,
            ref days,
            ref mons,
            ref hrs,
            ref mins
        } = *cal;

        Some(format!("{} *-{}-{} {}:{}:00",
                     linearize(&**dows, "", ToString::to_string),
                     linearize(&**mons, "*", |&mon| (mon as u8).to_string()),
                     linearize(&**days, "*", ToString::to_string),
                     linearize(&**hrs, "*", ToString::to_string),
                     linearize(&**mins, "*", ToString::to_string)))
    }));

    if daemon_reload && schedule.is_none() {
        warn!("skipping job from {}: \"{}\"", path.display(), entry);
        return Ok(());
    }

    if let Some(cmd) = entry.command() {

        // make sure we know the user
        let user = try!(entry.user().and_then(get_user_by_name).or_else(|| get_user_by_uid(owner))
            .ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "unknown user")));

        // generate unique cron job id
        let mut md5ctx = ::md5::Context::new();
        md5ctx.consume(path.as_os_str().as_bytes());
        if let Some(ref schedule) = schedule {
            md5ctx.consume(schedule.as_bytes());
        }
        md5ctx.consume(cmd.as_bytes());
        let md5hex = tohex(&md5ctx.compute());

        // create service and timer unit names
        let service_unit_name = format!("cron-{}.service", md5hex);
        let timer_unit_name = format!("cron-{}.timer", md5hex);

        // unit paths
        let service_unit_path = dstdir.join(&service_unit_name);
        let timer_unit_path = dstdir.join(&timer_unit_name);

        // make sure cron.target.wants dir exists
        let cron_target_wants_path = dstdir.join("cron.target.wants");
        try!(create_dir_all(&cron_target_wants_path));

        // process command in case it should be put into script
        let command = if metadata(cmd).map(|m| m.is_file()).unwrap_or(false) {
            cmd.to_owned()
        } else {
            let script_command_path = dstdir.join(format!("cron-{}.sh", md5hex));

            debug!("generating script {:?} from {:?}", script_command_path, path);
            {
                let mut script_command_file = try!(File::create(&script_command_path));
                try!(writeln!(script_command_file, "#!{}", shell));
                try!(writeln!(script_command_file, "{}", cmd));
            }

            let mut perms = try!(metadata(&script_command_path)).permissions();
            perms.set_mode(0o755);
            try!(set_permissions(&script_command_path, perms));
            script_command_path.to_str().unwrap().to_owned()
        };

        debug!("generating service {:?} from {:?}", service_unit_path, path);
        {
            let mut service_unit_file = try!(File::create(service_unit_path));

            try!(writeln!(service_unit_file, r###"[Unit]
Description=[Cron] "{entry}"
Documentation=man:systemd-crontab-generator(8)
RefuseManualStart=true
RefuseManualStop=true
SourcePath={source_crontab_path}"###,
                entry = entry,
                source_crontab_path = path.display(),
                ));

            if env.contains_key("MAILTO") {
                try!(writeln!(service_unit_file, "OnFailure=cron-failure@%i.service"));
            }

            if user.uid != 0 {
                try!(writeln!(service_unit_file, "Requires=systemd-user-sessions.service"));
                if !user.home_dir.is_empty() {
                    try!(writeln!(service_unit_file, "RequiresMountsFor={}", user.home_dir));
                }
            }

            try!(writeln!(service_unit_file, r###"
[Service]
Type=oneshot
IgnoreSIGPIPE=false
ExecStart={command}"###,
                command = command,
                ));

            if schedule.is_some() && delay > 0 {
                try!(writeln!(service_unit_file, "ExecStartPre=-{}/{}/boot-delay {}", LIB_DIR, PACKAGE, delay));
            }

            if user.uid != 0 {
                try!(writeln!(service_unit_file, "User={}", user.name));
            }

            if let Some(group) = entry.group() {
                try!(writeln!(service_unit_file, "Group={}", group));
            }
            if batch {
                try!(writeln!(service_unit_file, "CPUSchedulingPolicy=idle"));
                try!(writeln!(service_unit_file, "IOSchedulingClass=idle"));
            }

            if !env.is_empty() {
                for (name, value) in env.iter() {
                    try!(writeln!(service_unit_file, r#"Environment="{}={}""#, name, value));
                }
            }
        }

        debug!("generating timer {:?} from {:?}", timer_unit_path, path);
        {
            let mut timer_unit_file = try!(File::create(&timer_unit_path));

            try!(writeln!(timer_unit_file, r###"[Unit]
Description=[Timer] "{entry}"
Documentation=man:systemd-crontab-generator(8)
PartOf=cron.target
RefuseManualStart=true
RefuseManualStop=true
SourcePath={source_crontab_path}

[Timer]
Unit={service_unit_name}"###,
                entry = entry,
                source_crontab_path = path.display(),
                service_unit_name = service_unit_name,
                ));

            if cfg![feature="persistent"] {
                try!(writeln!(timer_unit_file, "Persistent={}", persistent));
            }

            if let Some(schedule) = schedule {
                try!(writeln!(timer_unit_file, "OnCalendar={}", schedule));
            } else {
                try!(writeln!(timer_unit_file, "OnBootSec={}m", delay));
            }

            if random_delay != 1 {
                try!(writeln!(timer_unit_file, "AccuracySec={}m", random_delay));
            }
        }
        try!(symlink(timer_unit_path, cron_target_wants_path.join(timer_unit_name)));
    }

    Ok(())
}

fn linearize<T, C>(input: &[Interval<T>], star: &str, conv: C) -> String where T: Limited, C: Fn(&T) -> String {
    if input.len() == 1 && input[0] == Interval::Full(1) {
        star.to_owned()
    } else {
        let mut output = String::new();
        for part in input.iter().flat_map(|v| v.iter()).collect::<BTreeSet<_>>().iter() {
            output.push_str(&*conv(&part));
            output.push(',');
        }
        output.pop();
        output
    }
}

fn tohex(input: &[u8]) -> String {
    #[inline]
    fn hex(d: u8) -> char {
        match d {
            0...9 => (d + 0x30) as char,
            10...15 => (d + 0x57) as char,
            _ => unreachable!("unexpected value: {}", d)
        }
    }

    let mut buf = String::with_capacity(32);
    for b in input.into_iter() {
        buf.push(hex(b >> 4));
        buf.push(hex(b & 0xf));
    }
    buf
}

<|endoftext|>


<commit_before>extern crate num;
extern crate byteorder;

use std::fs::File;
use std::io::Read;
use std::io::Cursor;
use std::mem;
use byteorder::{ByteOrder, LittleEndian, BigEndian, NativeEndian};
use std::iter::FromIterator;

type c32 = num::Complex<f32>;
type c64 = num::Complex<f64>;

// [Working around the lack of associated method on parametric traits?](http://stackoverflow.com/questions/27888069/working-around-the-lack-of-associated-method-on-parametric-traits)

struct Grid<T> {
    points: Vec<Vec<T>>,
}

impl Grid<f32> {
    fn new() -> Self { Grid {points: Vec::new() } }
    fn read(&mut self,
            little_endian: bool,
            xsize: usize,
            ysize: usize,
            grid_buf: &Vec<u8>) {
        self.points = Vec::from_iter((0..xsize).map(|i| {
            Vec::from_iter((0..ysize).map(|j| {
                let start = (i * ysize + j) * mem::size_of::<f32>();
                let real = if little_endian {
                    LittleEndian::read_f32(&grid_buf[start + 0..start + 4])
                } else {
                    BigEndian::read_f32(&grid_buf[start + 0..start + 4])
                };
                real
            }))
        }))
    }
}

impl Grid<c32> {
    fn new() -> Self { Grid {points: Vec::new() } }
    fn read(&mut self,
            little_endian: bool,
            xsize: usize,
            ysize: usize,
            grid_buf: &Vec<u8>) {
         self.points = Vec::from_iter((0..xsize).map(|i| {
            Vec::from_iter((0..ysize).map(|j| {
                let start = (i * ysize + j) * 2 * mem::size_of::<f32>();
                let (real, imag) = if little_endian {
                    (LittleEndian::read_f32(&grid_buf[start + 0..start + 4]),
                     LittleEndian::read_f32(&grid_buf[start + 4..start + 8]))
                } else {
                    (BigEndian::read_f32(&grid_buf[start + 0..start + 4]),
                     BigEndian::read_f32(&grid_buf[start + 4..start + 8]))
                };
                c32::new(real, imag)
            }))
        }));
    }
}

impl Grid<f64> {
    fn new() -> Self { Grid {points: Vec::new() } }
    fn read(&mut self,
            little_endian: bool,
            xsize: usize,
            ysize: usize,
            grid_buf: &Vec<u8>) {
         self.points = Vec::from_iter((0..xsize).map(|i| {
            Vec::from_iter((0..ysize).map(|j| {
                let start = (i * ysize + j) * mem::size_of::<f64>();
                let real = if little_endian {
                    LittleEndian::read_f64(&grid_buf[start + 0..start + 8])
                } else {
                    BigEndian::read_f64(&grid_buf[start + 0..start + 8])
                };
                real
            }))
        }));
    }
}

impl Grid<c64> {
    fn new() -> Self { Grid {points: Vec::new() } }
    fn read(&mut self,
            little_endian: bool,
            xsize: usize,
            ysize: usize,
            grid_buf: &Vec<u8>) {
        self.points =  Vec::from_iter((0..xsize).map(|i| {
            Vec::from_iter((0..ysize).map(|j| {
                let start = (i * ysize + j) * 2 * mem::size_of::<f64>();
                let (real, imag) = if little_endian {
                    (LittleEndian::read_f64(&grid_buf[start + 0..start + 8]),
                     LittleEndian::read_f64(&grid_buf[start + 8..start + 16]))
                } else {
                    (BigEndian::read_f64(&grid_buf[start + 0..start + 8]),
                     BigEndian::read_f64(&grid_buf[start + 8..start + 16]))
                };
                c64::new(real, imag)
            }))
        }));
    }
}

fn main() {
    let mut grid = Grid::<f32>::new();
    grid.read(true, 8, 8, &vec![0u8; 64 * 4]);
}
<commit_msg>generics: cleanup.<commit_after>extern crate num;
extern crate byteorder;

use std::fs::File;
use std::io::Read;
use std::io::Cursor;
use std::mem;
use byteorder::{ByteOrder, LittleEndian, BigEndian, NativeEndian};
use std::iter::FromIterator;

type c32 = num::Complex<f32>;
type c64 = num::Complex<f64>;

struct Grid<T> {
    points: Vec<Vec<T>>,
}

impl Grid<f32> {
    fn new() -> Self { Grid {points: Vec::new() } }
    fn read(&mut self,
            little_endian: bool,
            xsize: usize,
            ysize: usize,
            grid_buf: &Vec<u8>) {
        self.points = Vec::from_iter((0..xsize).map(|i| {
            Vec::from_iter((0..ysize).map(|j| {
                let start = (i * ysize + j) * mem::size_of::<f32>();
                let real = if little_endian {
                    LittleEndian::read_f32(&grid_buf[start + 0..start + 4])
                } else {
                    BigEndian::read_f32(&grid_buf[start + 0..start + 4])
                };
                real
            }))
        }))
    }
}

impl Grid<c32> {
    fn new() -> Self { Grid {points: Vec::new() } }
    fn read(&mut self,
            little_endian: bool,
            xsize: usize,
            ysize: usize,
            grid_buf: &Vec<u8>) {
         self.points = Vec::from_iter((0..xsize).map(|i| {
            Vec::from_iter((0..ysize).map(|j| {
                let start = (i * ysize + j) * 2 * mem::size_of::<f32>();
                let (real, imag) = if little_endian {
                    (LittleEndian::read_f32(&grid_buf[start + 0..start + 4]),
                     LittleEndian::read_f32(&grid_buf[start + 4..start + 8]))
                } else {
                    (BigEndian::read_f32(&grid_buf[start + 0..start + 4]),
                     BigEndian::read_f32(&grid_buf[start + 4..start + 8]))
                };
                c32::new(real, imag)
            }))
        }));
    }
}

impl Grid<f64> {
    fn new() -> Self { Grid {points: Vec::new() } }
    fn read(&mut self,
            little_endian: bool,
            xsize: usize,
            ysize: usize,
            grid_buf: &Vec<u8>) {
         self.points = Vec::from_iter((0..xsize).map(|i| {
            Vec::from_iter((0..ysize).map(|j| {
                let start = (i * ysize + j) * mem::size_of::<f64>();
                let real = if little_endian {
                    LittleEndian::read_f64(&grid_buf[start + 0..start + 8])
                } else {
                    BigEndian::read_f64(&grid_buf[start + 0..start + 8])
                };
                real
            }))
        }));
    }
}

impl Grid<c64> {
    fn new() -> Self { Grid {points: Vec::new() } }
    fn read(&mut self,
            little_endian: bool,
            xsize: usize,
            ysize: usize,
            grid_buf: &Vec<u8>) {
        self.points =  Vec::from_iter((0..xsize).map(|i| {
            Vec::from_iter((0..ysize).map(|j| {
                let start = (i * ysize + j) * 2 * mem::size_of::<f64>();
                let (real, imag) = if little_endian {
                    (LittleEndian::read_f64(&grid_buf[start + 0..start + 8]),
                     LittleEndian::read_f64(&grid_buf[start + 8..start + 16]))
                } else {
                    (BigEndian::read_f64(&grid_buf[start + 0..start + 8]),
                     BigEndian::read_f64(&grid_buf[start + 8..start + 16]))
                };
                c64::new(real, imag)
            }))
        }));
    }
}

fn main() {
    let mut grid = Grid::<f32>::new();
    grid.read(true, 8, 8, &vec![0u8; 64 * 4]);
}
<|endoftext|>


<commit_before>// Copyright 2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![crate_type="bin"]

#![allow(dead_code)]

#![warn(non_upper_case_globals)]
#![warn(non_camel_case_types)]
#![warn(unused_qualifications)]

// Unstable APIs:
#![feature(convert)]
#![feature(fs_time)]
#![feature(std_misc)]
#![feature(test)]

#![feature(custom_attribute)]
#![feature(plugin)]
#![plugin(quickcheck_macros)]

// Standard Rust imports
extern crate rand;
extern crate test;
extern crate time;

// Rust bindings
extern crate sodiumoxide;
extern crate sqlite3;

extern crate rustc_serialize;
extern crate threadpool;

// Argument parsing
#[macro_use]
extern crate clap;

// Testing
#[cfg(test)]
extern crate quickcheck;

// use std::env;
use std::path::PathBuf;
use std::borrow::ToOwned;

use clap::{App, SubCommand};

mod callback_container;
mod cumulative_counter;
mod ordered_collection;
mod periodic_timer;
mod unique_priority_queue;

mod hat;
mod listdir;
mod process;

mod hash_index;
mod hash_tree;

mod blob_index;
mod blob_store;

mod key_index;
mod key_store;

mod snapshot_index;

static MAX_BLOB_SIZE: usize = 4 * 1024 * 1024;

fn blob_dir() -> PathBuf { PathBuf::from("blobs") }

// #[cfg(not(test))]
// fn usage() {
//   println!("Usage: {} [snapshot|commit|checkout] name path", env::args().next().unwrap());
// }

#[cfg(not(test))]
fn license() {
  println!(include_str!("../../LICENSE"));
  println!("clap (Command Line Argument Parser) License:");
  println!(include_str!("../../LICENSE-CLAP"));
}

#[cfg(not(test))]
fn main() {
    // Because "snapshot" and "checkout" use the exact same type of arguments, we can make a template
    // This template defines two positional arguments, both are required
    let arg_template = "<NAME> 'Name of the snapshot'
                        <PATH> 'The path of the snapshot'";

    // Create valid arguments
    let matches = App::new("hat-backup")
                        // get version from Cargo.toml
                        .version(&crate_version!()[..])
                        .about("Create backup snapshots")
                        // If custom usage statement desired (instead of the auto-generated one), uncomment:
                        //.usage("hat-backup [snapshot|commit|checkout] <name> <path>")
                        .arg_from_usage("--license 'Display the license'")
                        .subcommand(SubCommand::new("snapshot")
                            .about("Create a snapshot")
                            .args_from_usage(arg_template))
                        .subcommand(SubCommand::new("checkout")
                            .about("Checkout a snapshot")
                            .args_from_usage(arg_template))
                        .subcommand(SubCommand::new("commit")
                            .about("Commit a snapshot")
                            .arg_from_usage("<NAME> 'Name of the snapshot'"))
                        .get_matches();

    // Check for license flag
    if matches.is_present("license") { license(); std::process::exit(0); }

    // Initialize sodium (must only be called once)
    sodiumoxide::init();

    match matches.subcommand() {
        ("snapshot", Some(matches)) => {
            let name = matches.value_of("NAME").unwrap().to_owned();
            let path = matches.value_of("PATH").unwrap();

            let backend = blob_store::FileBackend::new(blob_dir());
            let hat = hat::Hat::open_repository(&PathBuf::from("repo"), backend, MAX_BLOB_SIZE);

            let family_opt = hat.open_family(name.clone());
            let family = family_opt.expect(&format!("Could not open family '{}'", name));

            family.snapshot_dir(PathBuf::from(path));
            family.flush();

            println!("Waiting for final flush...");
        },
        ("checkout", Some(matches)) => {
            let name = matches.value_of("NAME").unwrap().to_owned();
            let path = matches.value_of("PATH").unwrap();

            let backend = blob_store::FileBackend::new(blob_dir());
            let hat = hat::Hat::open_repository(&PathBuf::from("repo"), backend, MAX_BLOB_SIZE);

            hat.checkout_in_dir(name.clone(), PathBuf::from(path));
        },
        ("commit", Some(matches)) => {
            let name = matches.value_of("NAME").unwrap().to_owned();

            let backend = blob_store::FileBackend::new(blob_dir());
            let hat = hat::Hat::open_repository(&PathBuf::from("repo"), backend, MAX_BLOB_SIZE);

            hat.commit(name);
        },
        _       => {
            println!("No subcommand specified\n{}\nFor more information re-run with --help", matches.usage());
            std::process::exit(1);
        }
    }
}
<commit_msg>added 'v' to version, used shorter name for app<commit_after>// Copyright 2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![crate_type="bin"]

#![allow(dead_code)]

#![warn(non_upper_case_globals)]
#![warn(non_camel_case_types)]
#![warn(unused_qualifications)]

// Unstable APIs:
#![feature(convert)]
#![feature(fs_time)]
#![feature(std_misc)]
#![feature(test)]

#![feature(custom_attribute)]
#![feature(plugin)]
#![plugin(quickcheck_macros)]

// Standard Rust imports
extern crate rand;
extern crate test;
extern crate time;

// Rust bindings
extern crate sodiumoxide;
extern crate sqlite3;

extern crate rustc_serialize;
extern crate threadpool;

// Argument parsing
#[macro_use]
extern crate clap;

// Testing
#[cfg(test)]
extern crate quickcheck;

// use std::env;
use std::path::PathBuf;
use std::borrow::ToOwned;

use clap::{App, SubCommand};

mod callback_container;
mod cumulative_counter;
mod ordered_collection;
mod periodic_timer;
mod unique_priority_queue;

mod hat;
mod listdir;
mod process;

mod hash_index;
mod hash_tree;

mod blob_index;
mod blob_store;

mod key_index;
mod key_store;

mod snapshot_index;

static MAX_BLOB_SIZE: usize = 4 * 1024 * 1024;

fn blob_dir() -> PathBuf { PathBuf::from("blobs") }

// #[cfg(not(test))]
// fn usage() {
//   println!("Usage: {} [snapshot|commit|checkout] name path", env::args().next().unwrap());
// }

#[cfg(not(test))]
fn license() {
  println!(include_str!("../../LICENSE"));
  println!("clap (Command Line Argument Parser) License:");
  println!(include_str!("../../LICENSE-CLAP"));
}

#[cfg(not(test))]
fn main() {
    // Because "snapshot" and "checkout" use the exact same type of arguments, we can make a template
    // This template defines two positional arguments, both are required
    let arg_template = "<NAME> 'Name of the snapshot'
                        <PATH> 'The path of the snapshot'";

    // Create valid arguments
    let matches = App::new("hat")
                        // get version from Cargo.toml
                        .version(&format!("v{}",crate_version!())[..])
                        .about("Create backup snapshots")
                        // If custom usage statement desired (instead of the auto-generated one), uncomment:
                        //.usage("hat-backup [snapshot|commit|checkout] <name> <path>")
                        .arg_from_usage("--license 'Display the license'")
                        .subcommand(SubCommand::new("snapshot")
                            .about("Create a snapshot")
                            .args_from_usage(arg_template))
                        .subcommand(SubCommand::new("checkout")
                            .about("Checkout a snapshot")
                            .args_from_usage(arg_template))
                        .subcommand(SubCommand::new("commit")
                            .about("Commit a snapshot")
                            .arg_from_usage("<NAME> 'Name of the snapshot'"))
                        .get_matches();

    // Check for license flag
    if matches.is_present("license") { license(); std::process::exit(0); }

    // Initialize sodium (must only be called once)
    sodiumoxide::init();

    match matches.subcommand() {
        ("snapshot", Some(matches)) => {
            let name = matches.value_of("NAME").unwrap().to_owned();
            let path = matches.value_of("PATH").unwrap();

            let backend = blob_store::FileBackend::new(blob_dir());
            let hat = hat::Hat::open_repository(&PathBuf::from("repo"), backend, MAX_BLOB_SIZE);

            let family_opt = hat.open_family(name.clone());
            let family = family_opt.expect(&format!("Could not open family '{}'", name));

            family.snapshot_dir(PathBuf::from(path));
            family.flush();

            println!("Waiting for final flush...");
        },
        ("checkout", Some(matches)) => {
            let name = matches.value_of("NAME").unwrap().to_owned();
            let path = matches.value_of("PATH").unwrap();

            let backend = blob_store::FileBackend::new(blob_dir());
            let hat = hat::Hat::open_repository(&PathBuf::from("repo"), backend, MAX_BLOB_SIZE);

            hat.checkout_in_dir(name.clone(), PathBuf::from(path));
        },
        ("commit", Some(matches)) => {
            let name = matches.value_of("NAME").unwrap().to_owned();

            let backend = blob_store::FileBackend::new(blob_dir());
            let hat = hat::Hat::open_repository(&PathBuf::from("repo"), backend, MAX_BLOB_SIZE);

            hat.commit(name);
        },
        _       => {
            println!("No subcommand specified\n{}\nFor more information re-run with --help", matches.usage());
            std::process::exit(1);
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![deny(missing_docs)]

//! An efficient, low-level, bindless graphics API for Rust. See [the
//! blog](http://gfx-rs.github.io/) for explanations and annotated examples.

#[macro_use]
extern crate log;
extern crate draw_state;
extern crate gfx_core;

/// public re-exported traits
pub mod traits {
    pub use gfx_core::{Device, Factory, DeviceFence};
    pub use factory::FactoryExt;
}

// draw state re-exports
pub use draw_state::{preset, state};
pub use draw_state::target::*;

// public re-exports
pub use gfx_core as core;
pub use gfx_core::{Device, SubmitInfo, Resources};
pub use gfx_core::{format, handle, tex};
pub use gfx_core::factory::{Factory, BufferRole, BufferInfo, BufferUsage,
                            Bind, BufferUpdateError, CombinedError,
                            ResourceViewError, TargetViewError,
                            SHADER_RESOURCE, UNORDERED_ACCESS, RENDER_TARGET,
                            cast_slice};
pub use gfx_core::{VertexCount, InstanceCount};
pub use gfx_core::Primitive;
pub use gfx_core::{ShaderSet, VertexShader, HullShader, DomainShader,
                   GeometryShader, PixelShader};
pub use gfx_core::draw::{CommandBuffer, InstanceOption};
pub use gfx_core::shade::{ProgramInfo, UniformValue};

pub use encoder::{Encoder, UpdateError};
pub use factory::PipelineStateError;
pub use mesh::{Slice, ToIndexSlice, SliceKind};
pub use pso::{PipelineState};
pub use pso::buffer::{VertexBuffer, InstanceBuffer,
                      ConstantBuffer, Global};
pub use pso::resource::{ShaderResource, UnorderedAccess,
                        Sampler, TextureSampler};
pub use pso::target::{DepthStencilTarget, DepthTarget, StencilTarget,
                      RenderTarget, BlendTarget, BlendRef, Scissor};

/// Render commands encoder
mod encoder;
/// Factory extensions
mod factory;
/// Meshes
mod mesh;
/// Pipeline states
pub mod pso;
/// Shaders
pub mod shade;
/// Convenience macros
pub mod macros;
<commit_msg>An attempt to avoid merge conflicts with master<commit_after>// Copyright 2015 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![deny(missing_docs)]

//! An efficient, low-level, bindless graphics API for Rust. See [the
//! blog](http://gfx-rs.github.io/) for explanations and annotated examples.

#[macro_use]
extern crate log;
extern crate draw_state;
extern crate gfx_core;

/// public re-exported traits
pub mod traits {
    pub use gfx_core::{Device, Factory, DeviceFence};
    pub use factory::FactoryExt;
}

// draw state re-exports
pub use draw_state::{preset, state};
pub use draw_state::target::*;

// public re-exports
pub use gfx_core as core;
pub use gfx_core::{Device, SubmitInfo, Resources};
pub use gfx_core::{format, handle, tex};
pub use gfx_core::factory::{Factory, BufferRole, BufferInfo, BufferUsage,
                            Bind, BufferError, BufferUpdateError, CombinedError,
                            ResourceViewError, TargetViewError,
                            SHADER_RESOURCE, UNORDERED_ACCESS, RENDER_TARGET,
                            cast_slice};
pub use gfx_core::{VertexCount, InstanceCount};
pub use gfx_core::Primitive;
pub use gfx_core::{ShaderSet, VertexShader, HullShader, DomainShader,
                   GeometryShader, PixelShader};
pub use gfx_core::draw::{CommandBuffer, InstanceOption};
pub use gfx_core::shade::{ProgramInfo, UniformValue};

pub use encoder::{Encoder, UpdateError};
pub use factory::PipelineStateError;
pub use mesh::{Slice, ToIndexSlice, SliceKind};
pub use pso::{PipelineState};
pub use pso::buffer::{VertexBuffer, InstanceBuffer,
                      ConstantBuffer, Global};
pub use pso::resource::{ShaderResource, UnorderedAccess,
                        Sampler, TextureSampler};
pub use pso::target::{DepthStencilTarget, DepthTarget, StencilTarget,
                      RenderTarget, BlendTarget, BlendRef, Scissor};

/// Render commands encoder
mod encoder;
/// Factory extensions
mod factory;
/// Meshes
mod mesh;
/// Pipeline states
pub mod pso;
/// Shaders
pub mod shade;
/// Convenience macros
pub mod macros;
<|endoftext|>


<commit_before>use super::renderer;
use fastup::Document;

#[derive(Debug, Copy, Clone, Default)]
pub struct Renderer;

impl renderer::Renderer for Renderer {
    fn render(&self, doc: &Document) -> String {
        "".into()
    }
}

<commit_msg>+ html renderer<commit_after>use super::renderer;
use fastup::{Document, Node};
use fastup::Node::*;

#[derive(Debug, Copy, Clone, Default)]
pub struct Renderer;

impl renderer::Renderer for Renderer {
    fn render(&self, doc: &Document) -> String {
        html_from_document(doc)
    }
}

fn html_from_document(doc: &Document) -> String {
    doc.0.iter().map(html_from_node).collect()
}

fn html_from_node(node: &Node) -> String {
    match *node {
        Text(ref text) => escape_html(text),
        Foreground(color, ref doc) => {
            format!("{}",
                    color.clamp_to_888(),
                    html_from_document(doc))
        }
        Background(color, ref doc) => {
            format!("{}",
                    color.clamp_to_888(),
                    html_from_document(doc))
        }
        Bold(ref doc) => format!("{}", html_from_document(doc)),
        Widget(..) => unreachable!(),
    }
}

fn escape_html(text: &str) -> String {
    text.chars().map(escape_html_char).collect()
}

fn escape_html_char(ch: char) -> String {
    match ch {
        '\n' => "
".into(),
        ' ' => " ".into(),
        '>' => ">".into(),
        '<' => "<".into(),
        c => c.to_string(),
    }
}

<|endoftext|>