<commit_before>// 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/.

#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(not(feature = "clippy"), allow(unknown_lints))]

#![allow(doc_markdown)]

extern crate devicemapper;
extern crate libstratis;
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate clap;
#[cfg(feature="dbus_enabled")]
extern crate dbus;
extern crate libc;
extern crate libudev;
extern crate nix;

#[cfg(test)]
extern crate quickcheck;

use std::cell::RefCell;
use std::env;
use std::fs::{File, OpenOptions};
use std::io::{Read, Write};
use std::os::unix::io::AsRawFd;
use std::path::PathBuf;
use std::process::exit;
use std::rc::Rc;

use clap::{App, Arg};
use env_logger::LogBuilder;
use libc::pid_t;
use log::{LogLevelFilter, SetLoggerError};
use nix::fcntl::{flock, FlockArg};
use nix::unistd::getpid;

#[cfg(feature="dbus_enabled")]
use dbus::WatchEvent;

use devicemapper::Device;

use libstratis::engine::{Engine, SimEngine, StratEngine};
use libstratis::stratis::{StratisError, StratisResult, VERSION};

const STRATISD_PID_PATH: &str = "/var/run/stratisd.pid";

/// If writing a program error to stderr fails, panic.
fn print_err(err: StratisError) -> () {
    eprintln!("{}", err);
}

/// Configure and initialize the logger.
/// If debug is true, log at debug level. Otherwise read log configuration
/// parameters from the environment if RUST_LOG is set. Otherwise, just
/// accept the default configuration.
fn initialize_log(debug: bool) -> Result<(), SetLoggerError> {
    let mut builder = LogBuilder::new();
    if debug {
        builder.filter(Some("stratisd"), LogLevelFilter::Debug);
        builder.filter(Some("libstratis"), LogLevelFilter::Debug);
    } else if let Ok(s) = env::var("RUST_LOG") {
        builder.parse(&s);
    };

    builder.init()
}

/// Given a udev event check to see if it's an add and if it is return the device node and
/// devicemapper::Device.
fn handle_udev_add(event: &libudev::Event) -> Option<(Device, PathBuf)> {
    if event.event_type() == libudev::EventType::Add {
        let device = event.device();
        return device
                   .devnode()
                   .and_then(|devnode| {
                                 device
                                     .devnum()
                                     .and_then(|devnum| {
                                                   Some((Device::from(devnum),
                                                         PathBuf::from(devnode)))
                                               })
                             });
    }
    None
}

/// To ensure only one instance of stratisd runs at a time, acquire an
/// exclusive lock. Return an error if lock attempt fails.
fn create_pid_file() -> StratisResult<File> {
    let mut f = OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open(STRATISD_PID_PATH)?;
    match flock(f.as_raw_fd(), FlockArg::LockExclusiveNonblock) {
        Ok(_) => {
            f.write(format!("{}\n", getpid()).as_bytes())?;
            Ok(f)
        }
        Err(_) => {
            let mut buf = String::new();
            f.read_to_string(&mut buf)?;
            // pidfile is supposed to contain pid of holder. But you never
            // know so be paranoid.
            let pid_str = buf.split_whitespace()
                .next()
                .and_then(|s| s.parse::<pid_t>().ok())
                .map(|pid| format!("{}", pid))
                .unwrap_or_else(|| "<unknown>".into());
            Err(StratisError::Error(format!("Daemon already running with pid: {}", pid_str)))
        }
    }
}

fn run() -> StratisResult<()> {

    // Exit immediately if stratisd is already running
    let _ = create_pid_file()?;

    let matches = App::new("stratis")
        .version(VERSION)
        .about("Stratis storage management")
        .arg(Arg::with_name("debug")
                 .long("debug")
                 .help("Print additional output for debugging"))
        .arg(Arg::with_name("sim")
                 .long("sim")
                 .help("Use simulator engine"))
        .get_matches();

    initialize_log(matches.is_present("debug"))
        .expect("This is the first and only invocation of this method; it must succeed.");

    // We must setup a udev listener before we initialize the
    // engine. It is possible that a device may appear after the engine has read the
    // /dev directory but before it has completed initialization. Unless the udev
    // event has been recorded, the engine will be unaware of the existence of the
    // device.
    // This is especially important since stratisd is required to be able to run
    // during early boot.
    let context = libudev::Context::new()?;
    let mut monitor = libudev::Monitor::new(&context)?;
    monitor.match_subsystem_devtype("block", "disk")?;
    let mut udev = monitor.listen()?;

    let engine: Rc<RefCell<Engine>> = {
        if matches.is_present("sim") {
            info!("Using SimEngine");
            Rc::new(RefCell::new(SimEngine::default()))
        } else {
            info!("Using StratEngine");
            Rc::new(RefCell::new(StratEngine::initialize()?))
        }
    };

    /*
    The file descriptor array indexes are laid out in the following:

    0   == Always udev fd index
    1   == engine index if eventable
    1/2 == Start of dbus client file descriptor(s), 1 if engine is not eventable, else 2
    */
    const FD_INDEX_UDEV: usize = 0;
    const FD_INDEX_ENGINE: usize = 1;

    let mut fds = Vec::new();

    fds.push(libc::pollfd {
                 fd: udev.as_raw_fd(),
                 revents: 0,
                 events: libc::POLLIN,
             });

    let eventable = engine.borrow().get_eventable();

    // The variable _dbus_client_index_start is only used when dbus support is compiled in, thus
    // we denote the value as not needed to compile when dbus support is not included.
    let (engine_eventable, poll_timeout, _dbus_client_index_start) = match eventable {
        Some(ref evt) => {
            fds.push(libc::pollfd {
                         fd: evt.get_pollable_fd(),
                         revents: 0,
                         events: libc::POLLIN,
                     });

            // Don't timeout if eventable, we are event driven
            (true, -1, FD_INDEX_ENGINE + 1)
        }

        // We periodically need to timeout as we are not event driven
        None => (false, 10000, FD_INDEX_ENGINE),
    };

    #[cfg(feature="dbus_enabled")]
    let (dbus_conn, mut tree, base_object_path, dbus_context) =
        libstratis::dbus_api::connect(Rc::clone(&engine))?;

    loop {
        // Process any udev block events
        if fds[FD_INDEX_UDEV].revents != 0 {
            while let Some(event) = udev.receive_event() {
                if let Some((device, devnode)) = handle_udev_add(&event) {

                    // If block evaluate returns an error we are going to ignore it as
                    // there is nothing we can do for a device we are getting errors with.
                    let pool_uuid = engine
                        .borrow_mut()
                        .block_evaluate(device, devnode)
                        .unwrap_or(None);

                    // We need to pretend that we aren't using the variable _pool_uuid so
                    // that we can conditionally compile out the register_pool when dbus
                    // is not enabled.
                    if let Some(_pool_uuid) = pool_uuid {
                                #[cfg(feature="dbus_enabled")]
                        libstratis::dbus_api::register_pool(&dbus_conn,
                                                            &Rc::clone(&engine),
                                                            &dbus_context,
                                                            &mut tree,
                                                            _pool_uuid,
                                                            &base_object_path)?;
                    }
                }
            }
        }

        // Handle engine events, if the engine is eventable
        if engine_eventable {
            if fds[FD_INDEX_ENGINE].revents != 0 {
                fds[FD_INDEX_ENGINE].revents = 0;

                eventable
                    .as_ref()
                    .expect("eventable.is_some()")
                    .clear_event()?;

                engine.borrow_mut().evented()?;
            }
        } else {
            // Unconditionally call evented() if engine has no eventable.
            // This looks like a bad idea, but the only engine that has
            // no eventable is the sim engine, and for that engine, evented()
            // is essentially a no-op.
            engine.borrow_mut().evented()?;
        }

        // Iterate through D-Bus file descriptors (if enabled)
        #[cfg(feature="dbus_enabled")]
        {
            for pfd in fds[_dbus_client_index_start..]
                    .iter()
                    .filter(|pfd| pfd.revents != 0) {
                for item in dbus_conn.watch_handle(pfd.fd, WatchEvent::from_revents(pfd.revents)) {
                    if let Err(r) = libstratis::dbus_api::handle(&dbus_conn,
                                                                 &item,
                                                                 &mut tree,
                                                                 &dbus_context) {
                        print_err(From::from(r));
                    }
                }
            }

            // Refresh list of dbus fds to poll for every time. This can change as
            // D-Bus clients come and go.
            fds.truncate(_dbus_client_index_start);

            fds.extend(dbus_conn.watch_fds().iter().map(|w| w.to_pollfd()));
        }

        let r = unsafe { libc::poll(fds.as_mut_ptr(), fds.len() as libc::c_ulong, poll_timeout) };
        assert!(r >= 0);
    }
}

fn main() {
    let error_code = match run() {
        Ok(_) => 0,
        Err(err) => {
            print_err(err);
            1
        }
    };
    exit(error_code);
}
<commit_msg>Pass Error argument by reference<commit_after>// 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/.

#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(not(feature = "clippy"), allow(unknown_lints))]

#![allow(doc_markdown)]

extern crate devicemapper;
extern crate libstratis;
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate clap;
#[cfg(feature="dbus_enabled")]
extern crate dbus;
extern crate libc;
extern crate libudev;
extern crate nix;

#[cfg(test)]
extern crate quickcheck;

use std::cell::RefCell;
use std::env;
use std::fs::{File, OpenOptions};
use std::io::{Read, Write};
use std::os::unix::io::AsRawFd;
use std::path::PathBuf;
use std::process::exit;
use std::rc::Rc;

use clap::{App, Arg};
use env_logger::LogBuilder;
use libc::pid_t;
use log::{LogLevelFilter, SetLoggerError};
use nix::fcntl::{flock, FlockArg};
use nix::unistd::getpid;

#[cfg(feature="dbus_enabled")]
use dbus::WatchEvent;

use devicemapper::Device;

use libstratis::engine::{Engine, SimEngine, StratEngine};
use libstratis::stratis::{StratisError, StratisResult, VERSION};

const STRATISD_PID_PATH: &str = "/var/run/stratisd.pid";

/// If writing a program error to stderr fails, panic.
fn print_err(err: &StratisError) -> () {
    eprintln!("{}", err);
}

/// Configure and initialize the logger.
/// If debug is true, log at debug level. Otherwise read log configuration
/// parameters from the environment if RUST_LOG is set. Otherwise, just
/// accept the default configuration.
fn initialize_log(debug: bool) -> Result<(), SetLoggerError> {
    let mut builder = LogBuilder::new();
    if debug {
        builder.filter(Some("stratisd"), LogLevelFilter::Debug);
        builder.filter(Some("libstratis"), LogLevelFilter::Debug);
    } else if let Ok(s) = env::var("RUST_LOG") {
        builder.parse(&s);
    };

    builder.init()
}

/// Given a udev event check to see if it's an add and if it is return the device node and
/// devicemapper::Device.
fn handle_udev_add(event: &libudev::Event) -> Option<(Device, PathBuf)> {
    if event.event_type() == libudev::EventType::Add {
        let device = event.device();
        return device
                   .devnode()
                   .and_then(|devnode| {
                                 device
                                     .devnum()
                                     .and_then(|devnum| {
                                                   Some((Device::from(devnum),
                                                         PathBuf::from(devnode)))
                                               })
                             });
    }
    None
}

/// To ensure only one instance of stratisd runs at a time, acquire an
/// exclusive lock. Return an error if lock attempt fails.
fn create_pid_file() -> StratisResult<File> {
    let mut f = OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open(STRATISD_PID_PATH)?;
    match flock(f.as_raw_fd(), FlockArg::LockExclusiveNonblock) {
        Ok(_) => {
            f.write(format!("{}\n", getpid()).as_bytes())?;
            Ok(f)
        }
        Err(_) => {
            let mut buf = String::new();
            f.read_to_string(&mut buf)?;
            // pidfile is supposed to contain pid of holder. But you never
            // know so be paranoid.
            let pid_str = buf.split_whitespace()
                .next()
                .and_then(|s| s.parse::<pid_t>().ok())
                .map(|pid| format!("{}", pid))
                .unwrap_or_else(|| "<unknown>".into());
            Err(StratisError::Error(format!("Daemon already running with pid: {}", pid_str)))
        }
    }
}

fn run() -> StratisResult<()> {

    // Exit immediately if stratisd is already running
    let _ = create_pid_file()?;

    let matches = App::new("stratis")
        .version(VERSION)
        .about("Stratis storage management")
        .arg(Arg::with_name("debug")
                 .long("debug")
                 .help("Print additional output for debugging"))
        .arg(Arg::with_name("sim")
                 .long("sim")
                 .help("Use simulator engine"))
        .get_matches();

    initialize_log(matches.is_present("debug"))
        .expect("This is the first and only invocation of this method; it must succeed.");

    // We must setup a udev listener before we initialize the
    // engine. It is possible that a device may appear after the engine has read the
    // /dev directory but before it has completed initialization. Unless the udev
    // event has been recorded, the engine will be unaware of the existence of the
    // device.
    // This is especially important since stratisd is required to be able to run
    // during early boot.
    let context = libudev::Context::new()?;
    let mut monitor = libudev::Monitor::new(&context)?;
    monitor.match_subsystem_devtype("block", "disk")?;
    let mut udev = monitor.listen()?;

    let engine: Rc<RefCell<Engine>> = {
        if matches.is_present("sim") {
            info!("Using SimEngine");
            Rc::new(RefCell::new(SimEngine::default()))
        } else {
            info!("Using StratEngine");
            Rc::new(RefCell::new(StratEngine::initialize()?))
        }
    };

    /*
    The file descriptor array indexes are laid out in the following:

    0   == Always udev fd index
    1   == engine index if eventable
    1/2 == Start of dbus client file descriptor(s), 1 if engine is not eventable, else 2
    */
    const FD_INDEX_UDEV: usize = 0;
    const FD_INDEX_ENGINE: usize = 1;

    let mut fds = Vec::new();

    fds.push(libc::pollfd {
                 fd: udev.as_raw_fd(),
                 revents: 0,
                 events: libc::POLLIN,
             });

    let eventable = engine.borrow().get_eventable();

    // The variable _dbus_client_index_start is only used when dbus support is compiled in, thus
    // we denote the value as not needed to compile when dbus support is not included.
    let (engine_eventable, poll_timeout, _dbus_client_index_start) = match eventable {
        Some(ref evt) => {
            fds.push(libc::pollfd {
                         fd: evt.get_pollable_fd(),
                         revents: 0,
                         events: libc::POLLIN,
                     });

            // Don't timeout if eventable, we are event driven
            (true, -1, FD_INDEX_ENGINE + 1)
        }

        // We periodically need to timeout as we are not event driven
        None => (false, 10000, FD_INDEX_ENGINE),
    };

    #[cfg(feature="dbus_enabled")]
    let (dbus_conn, mut tree, base_object_path, dbus_context) =
        libstratis::dbus_api::connect(Rc::clone(&engine))?;

    loop {
        // Process any udev block events
        if fds[FD_INDEX_UDEV].revents != 0 {
            while let Some(event) = udev.receive_event() {
                if let Some((device, devnode)) = handle_udev_add(&event) {

                    // If block evaluate returns an error we are going to ignore it as
                    // there is nothing we can do for a device we are getting errors with.
                    let pool_uuid = engine
                        .borrow_mut()
                        .block_evaluate(device, devnode)
                        .unwrap_or(None);

                    // We need to pretend that we aren't using the variable _pool_uuid so
                    // that we can conditionally compile out the register_pool when dbus
                    // is not enabled.
                    if let Some(_pool_uuid) = pool_uuid {
                                #[cfg(feature="dbus_enabled")]
                        libstratis::dbus_api::register_pool(&dbus_conn,
                                                            &Rc::clone(&engine),
                                                            &dbus_context,
                                                            &mut tree,
                                                            _pool_uuid,
                                                            &base_object_path)?;
                    }
                }
            }
        }

        // Handle engine events, if the engine is eventable
        if engine_eventable {
            if fds[FD_INDEX_ENGINE].revents != 0 {
                fds[FD_INDEX_ENGINE].revents = 0;

                eventable
                    .as_ref()
                    .expect("eventable.is_some()")
                    .clear_event()?;

                engine.borrow_mut().evented()?;
            }
        } else {
            // Unconditionally call evented() if engine has no eventable.
            // This looks like a bad idea, but the only engine that has
            // no eventable is the sim engine, and for that engine, evented()
            // is essentially a no-op.
            engine.borrow_mut().evented()?;
        }

        // Iterate through D-Bus file descriptors (if enabled)
        #[cfg(feature="dbus_enabled")]
        {
            for pfd in fds[_dbus_client_index_start..]
                    .iter()
                    .filter(|pfd| pfd.revents != 0) {
                for item in dbus_conn.watch_handle(pfd.fd, WatchEvent::from_revents(pfd.revents)) {
                    if let Err(r) = libstratis::dbus_api::handle(&dbus_conn,
                                                                 &item,
                                                                 &mut tree,
                                                                 &dbus_context) {
                        print_err(&From::from(r));
                    }
                }
            }

            // Refresh list of dbus fds to poll for every time. This can change as
            // D-Bus clients come and go.
            fds.truncate(_dbus_client_index_start);

            fds.extend(dbus_conn.watch_fds().iter().map(|w| w.to_pollfd()));
        }

        let r = unsafe { libc::poll(fds.as_mut_ptr(), fds.len() as libc::c_ulong, poll_timeout) };
        assert!(r >= 0);
    }
}

fn main() {
    let error_code = match run() {
        Ok(_) => 0,
        Err(err) => {
            print_err(&err);
            1
        }
    };
    exit(error_code);
}
<|endoftext|>


<commit_before>use diesel::*;
use diesel::pg::PgConnection;
use std::error::Error;

use super::data_structures::*;

// https://www.postgresql.org/docs/9.5/static/catalog-pg-attribute.html
table! {
    pg_attribute (attrelid) {
        attrelid -> Oid,
        attname -> VarChar,
        atttypid -> Oid,
        attnotnull -> Bool,
        attnum -> SmallInt,
        attisdropped -> Bool,
    }
}

// https://www.postgresql.org/docs/9.5/static/catalog-pg-type.html
table! {
    pg_type (oid) {
        oid -> Oid,
        typname -> VarChar,
    }
}

joinable!(pg_attribute -> pg_type (atttypid));
select_column_workaround!(pg_attribute -> pg_type (attrelid, attname, atttypid, attnotnull, attnum, attisdropped));
select_column_workaround!(pg_type -> pg_attribute (oid, typname));

// https://www.postgresql.org/docs/9.5/static/catalog-pg-index.html
table! {
    pg_index (indrelid) {
        indrelid -> Oid,
        indexrelid -> Oid,
        indkey -> Array<SmallInt>,
        indisprimary -> Bool,
    }
}

// https://www.postgresql.org/docs/9.5/static/catalog-pg-class.html
table! {
    pg_class (oid) {
        oid -> Oid,
        relname -> VarChar,
    }
}

pub fn determine_column_type(attr: &ColumnInformation) -> Result<ColumnType, Box<Error>> {
    let is_array = attr.type_name.starts_with("_");
    let tpe = if is_array {
        &attr.type_name[1..]
    } else {
        &attr.type_name
    };

    Ok(ColumnType {
        path: vec!["diesel".into(), "types".into(), capitalize(tpe)],
        is_array: is_array,
        is_nullable: attr.nullable,
    })
}

fn capitalize(name: &str) -> String {
    name[..1].to_uppercase() + &name[1..]
}

pub fn get_table_data(conn: &PgConnection, table_name: &str) -> QueryResult<Vec<ColumnInformation>> {
    use self::pg_attribute::dsl::*;
    use self::pg_type::dsl::{pg_type, typname};
    use self::pg_class::dsl::*;

    let table_oid = pg_class.select(oid).filter(relname.eq(table_name)).limit(1);

    pg_attribute.inner_join(pg_type)
        .select((attname, typname, attnotnull))
        .filter(attrelid.eq_any(table_oid))
        .filter(attnum.gt(0).and(attisdropped.ne(true)))
        .order(attnum)
        .load(conn)
}

pub fn get_primary_keys(conn: &PgConnection, table_name: &str) -> QueryResult<Vec<String>> {
    use self::pg_attribute::dsl::*;
    use self::pg_index::dsl::{pg_index, indisprimary, indexrelid, indrelid};
    use self::pg_class::dsl::*;

    let table_oid = pg_class.select(oid).filter(relname.eq(table_name)).limit(1);

    let pk_query = pg_index.select(indexrelid)
        .filter(indrelid.eq_any(table_oid))
        .filter(indisprimary.eq(true));

    pg_attribute.select(attname)
        .filter(attrelid.eq_any(pk_query))
        .order(attnum)
        .load(conn)
}

pub fn load_table_names(connection: &PgConnection) -> Result<Vec<String>, Box<Error>> {
    use diesel::expression::dsl::sql;

    let query = select(sql::<types::VarChar>("table_name FROM information_schema.tables"))
        .filter(sql::<types::Bool>("\
            table_schema = 'public' AND \
            table_name NOT LIKE '\\_\\_%' AND \
            table_type LIKE 'BASE TABLE'\
        "));
    Ok(try!(query.load(connection)))
}

#[test]
#[cfg(feature = "dotenv")]
fn skip_views() {
    use ::dotenv::dotenv;
    dotenv().ok();

    let connection_url = ::std::env::var("DATABASE_URL")
        .expect("DATABASE_URL must be set in order to run tests");
    let connection = PgConnection::establish(&connection_url).unwrap();
    connection.begin_test_transaction().unwrap();

    connection.execute("CREATE TABLE a_regular_table (id SERIAL PRIMARY KEY)").unwrap();
    connection.execute("CREATE VIEW a_view AS SELECT 42").unwrap();

    let table_names = load_table_names(&connection).unwrap();

    assert!(table_names.contains(&"a_regular_table".to_string()));
    assert!(!table_names.contains(&"a_view".to_string()));
}
<commit_msg>Use the query DSL in `load_table_names` on PG<commit_after>use diesel::*;
use diesel::pg::PgConnection;
use std::error::Error;

use super::data_structures::*;

// https://www.postgresql.org/docs/9.5/static/catalog-pg-attribute.html
table! {
    pg_attribute (attrelid) {
        attrelid -> Oid,
        attname -> VarChar,
        atttypid -> Oid,
        attnotnull -> Bool,
        attnum -> SmallInt,
        attisdropped -> Bool,
    }
}

// https://www.postgresql.org/docs/9.5/static/catalog-pg-type.html
table! {
    pg_type (oid) {
        oid -> Oid,
        typname -> VarChar,
    }
}

joinable!(pg_attribute -> pg_type (atttypid));
select_column_workaround!(pg_attribute -> pg_type (attrelid, attname, atttypid, attnotnull, attnum, attisdropped));
select_column_workaround!(pg_type -> pg_attribute (oid, typname));

// https://www.postgresql.org/docs/9.5/static/catalog-pg-index.html
table! {
    pg_index (indrelid) {
        indrelid -> Oid,
        indexrelid -> Oid,
        indkey -> Array<SmallInt>,
        indisprimary -> Bool,
    }
}

// https://www.postgresql.org/docs/9.5/static/catalog-pg-class.html
table! {
    pg_class (oid) {
        oid -> Oid,
        relname -> VarChar,
    }
}

mod information_schema {
    table! {
        information_schema.tables (table_catalog, table_schema, table_name) {
            table_catalog -> VarChar,
            table_schema -> VarChar,
            table_name -> VarChar,
            table_type -> VarChar,
        }
    }
}

pub fn determine_column_type(attr: &ColumnInformation) -> Result<ColumnType, Box<Error>> {
    let is_array = attr.type_name.starts_with("_");
    let tpe = if is_array {
        &attr.type_name[1..]
    } else {
        &attr.type_name
    };

    Ok(ColumnType {
        path: vec!["diesel".into(), "types".into(), capitalize(tpe)],
        is_array: is_array,
        is_nullable: attr.nullable,
    })
}

fn capitalize(name: &str) -> String {
    name[..1].to_uppercase() + &name[1..]
}

pub fn get_table_data(conn: &PgConnection, table_name: &str) -> QueryResult<Vec<ColumnInformation>> {
    use self::pg_attribute::dsl::*;
    use self::pg_type::dsl::{pg_type, typname};
    use self::pg_class::dsl::*;

    let table_oid = pg_class.select(oid).filter(relname.eq(table_name)).limit(1);

    pg_attribute.inner_join(pg_type)
        .select((attname, typname, attnotnull))
        .filter(attrelid.eq_any(table_oid))
        .filter(attnum.gt(0).and(attisdropped.ne(true)))
        .order(attnum)
        .load(conn)
}

pub fn get_primary_keys(conn: &PgConnection, table_name: &str) -> QueryResult<Vec<String>> {
    use self::pg_attribute::dsl::*;
    use self::pg_index::dsl::{pg_index, indisprimary, indexrelid, indrelid};
    use self::pg_class::dsl::*;

    let table_oid = pg_class.select(oid).filter(relname.eq(table_name)).limit(1);

    let pk_query = pg_index.select(indexrelid)
        .filter(indrelid.eq_any(table_oid))
        .filter(indisprimary.eq(true));

    pg_attribute.select(attname)
        .filter(attrelid.eq_any(pk_query))
        .order(attnum)
        .load(conn)
}

pub fn load_table_names(connection: &PgConnection) -> Result<Vec<String>, Box<Error>> {
    use self::information_schema::tables::dsl::*;

    let query = tables.select(table_name)
        .filter(table_schema.eq("public"))
        .filter(table_name.not_like("\\_\\_%"))
        .filter(table_type.like("BASE TABLE"));
    Ok(try!(query.load(connection)))
}

#[test]
#[cfg(feature = "dotenv")]
fn skip_views() {
    use ::dotenv::dotenv;
    dotenv().ok();

    let connection_url = ::std::env::var("DATABASE_URL")
        .expect("DATABASE_URL must be set in order to run tests");
    let connection = PgConnection::establish(&connection_url).unwrap();
    connection.begin_test_transaction().unwrap();

    connection.execute("CREATE TABLE a_regular_table (id SERIAL PRIMARY KEY)").unwrap();
    connection.execute("CREATE VIEW a_view AS SELECT 42").unwrap();

    let table_names = load_table_names(&connection).unwrap();

    assert!(table_names.contains(&"a_regular_table".to_string()));
    assert!(!table_names.contains(&"a_view".to_string()));
}
<|endoftext|>


<commit_before>mod documents;
mod executables;
mod exercises;
mod feeds;
mod git;
mod homebrew;
mod notes;
mod paths;
mod processes;
mod public;

pub fn setup() {
    git::configure("user.name", "Trevor D. Miller");
    git::configure("user.email", "5497885+trevordmiller@users.noreply.github.com");
    homebrew::install_package("vim");
    homebrew::install_package("node");
    paths::create_dir(&paths::vim_plugins());
    git::clone(
        &paths::vim_plugins(),
        "https://github.com/octref/RootIgnore",
    );
    git::clone(&paths::vim_plugins(), "https://github.com/tpope/vim-sleuth");
    git::clone(
        &paths::vim_plugins(),
        "https://github.com/dense-analysis/ale",
    );
}

pub fn clean() {
    git::check_all(&paths::repos());
    processes::stop("vim");
    processes::stop("rls");
    processes::stop("node");
    executables::upgrade("brew");
    executables::upgrade("rustup");
    homebrew::upgrade_package("vim");
    homebrew::upgrade_package("git");
    homebrew::upgrade_package("rustup-init");
    homebrew::upgrade_package("node");
    homebrew::clean_artifacts();
    git::pull_all(&paths::vim_plugins());
}

pub fn study() {
    feeds::next();
    exercises::next();
    documents::next();
    notes::next();
}

pub fn generate() {
    public::clean();
    public::build();
    public::configure();
}
<commit_msg>Format<commit_after>mod documents;
mod executables;
mod exercises;
mod feeds;
mod git;
mod homebrew;
mod notes;
mod paths;
mod processes;
mod public;

pub fn setup() {
    git::configure("user.name", "Trevor D. Miller");
    git::configure(
        "user.email",
        "5497885+trevordmiller@users.noreply.github.com",
    );
    homebrew::install_package("vim");
    homebrew::install_package("node");
    paths::create_dir(&paths::vim_plugins());
    git::clone(
        &paths::vim_plugins(),
        "https://github.com/octref/RootIgnore",
    );
    git::clone(&paths::vim_plugins(), "https://github.com/tpope/vim-sleuth");
    git::clone(
        &paths::vim_plugins(),
        "https://github.com/dense-analysis/ale",
    );
}

pub fn clean() {
    git::check_all(&paths::repos());
    processes::stop("vim");
    processes::stop("rls");
    processes::stop("node");
    executables::upgrade("brew");
    executables::upgrade("rustup");
    homebrew::upgrade_package("vim");
    homebrew::upgrade_package("git");
    homebrew::upgrade_package("rustup-init");
    homebrew::upgrade_package("node");
    homebrew::clean_artifacts();
    git::pull_all(&paths::vim_plugins());
}

pub fn study() {
    feeds::next();
    exercises::next();
    documents::next();
    notes::next();
}

pub fn generate() {
    public::clean();
    public::build();
    public::configure();
}
<|endoftext|>


<commit_before>// Copyright 2016 Mozilla Foundation
//
// 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.

use ::compiler::{
    CompilerArguments,
    ParsedArguments,
};
use std::collections::HashMap;
use std::path::Path;

pub fn parse_arguments(arguments : &[String]) -> CompilerArguments {
    trace!("gcc::parse_arguments");
    let mut output_arg = None;
    let mut input_arg = None;
    let mut dep_target = None;
    let mut common_args = vec!();
    let mut preprocessor_args = vec!();
    let mut compilation = false;
    let mut split_dwarf = false;
    let mut need_explicit_dep_target = false;

    let mut it = arguments.iter();
    loop {
        match it.next() {
            Some(arg) => {
                match arg.as_ref() {
                    "-c" => compilation = true,
                    "-o" => output_arg = it.next(),
                    "-gsplit-dwarf" => {
                        split_dwarf = true;
                        common_args.push(arg.clone());
                    }
                    // Arguments that take a value.
                    // -MF and -MQ are in this set but are handled separately
                    // because they are also preprocessor options.
                    "--param" | "-A" | "-D" | "-F" | "-G" | "-I" | "-L" |
                    "-U" | "-V" | "-Xassembler" | "-Xlinker" |
                    "-Xpreprocessor" | "-aux-info" | "-b" | "-idirafter" |
                    "-iframework" | "-imacros" | "-imultilib" | "-include" |
                    "-install_name" | "-iprefix" | "-iquote" | "-isysroot" |
                    "-isystem" | "-iwithprefix" | "-iwithprefixbefore" |
                    "-u" => {
                        common_args.push(arg.clone());
                        if let Some(arg_val) = it.next() {
                            common_args.push(arg_val.clone());
                        }
                    },
                    "-MF" | "-MQ" => {
                        preprocessor_args.push(arg.clone());
                        if let Some(arg_val) = it.next() {
                            preprocessor_args.push(arg_val.clone());
                        }
                    }
                    "-MT" => dep_target = it.next(),
                    // Can't cache PGO profiled output.
                    "-fprofile-use" => return CompilerArguments::CannotCache,
                    // Can't cache commandlines using a response file.
                    v @ _ if v.starts_with('@') => return CompilerArguments::CannotCache,
                    "-M" | "-MM" | "-MD" | "-MMD" => {
                        // If one of the above options is on the command line, we'll
                        // need -MT on the preprocessor command line, whether it's
                        // been passed already or not
                        need_explicit_dep_target = true;
                        preprocessor_args.push(arg.clone());
                    }
                    // Other options.
                    v @ _ if v.starts_with('-') && v.len() > 1 => {
                        common_args.push(arg.clone());
                    }
                    // Anything else is an input file.
                    v @ _ => {
                        if input_arg.is_some() || v == "-" {
                            // Can't cache compilations with multiple inputs
                            // or compilation from stdin.
                            return CompilerArguments::CannotCache;
                        }
                        input_arg = Some(v);
                    }
                };
            },
            None => break,
        }
    }
    // We only support compilation.
    if !compilation {
        return CompilerArguments::NotCompilation;
    }
    let input = match input_arg {
        Some(i) => {
            // When compiling from the preprocessed output given as stdin, we need
            // to explicitly pass its file type.
            match Path::new(i).extension().and_then(|e| e.to_str()) {
                Some("c") | Some("cc") | Some("cpp") | Some("cxx") => i.to_owned(),
                e @ _ => {
                    trace!("Unknown source extension: {}", e.unwrap_or("(None)"));
                    return CompilerArguments::CannotCache;
                }
            }
        }
        // We can't cache compilation without an input.
        None => return CompilerArguments::CannotCache,
    };
    let mut outputs = HashMap::new();
    match output_arg {
        // We can't cache compilation that doesn't go to a file
        None => return CompilerArguments::CannotCache,
        Some(o) => {
            outputs.insert("obj", o.to_owned());
            if split_dwarf {
                Path::new(o)
                    .with_extension("dwo")
                    //TODO: should really be dealing with OsStr everywhere.
                    .to_str()
                    .and_then(|dwo| outputs.insert("dwo", dwo.to_owned()));
            }
            if need_explicit_dep_target {
                preprocessor_args.push(dep_target.unwrap_or(o).to_owned());
            }
        }
    }

    CompilerArguments::Ok(ParsedArguments {
        input: input,
        outputs: outputs,
        preprocessor_args: preprocessor_args,
        common_args: common_args,
    })
}

#[cfg(test)]
mod test {
    use super::*;
    use ::compiler::*;

    #[test]
    fn test_parse_arguments_simple() {
        match parse_arguments(&stringvec!["-c", "foo.c", "-o", "foo.o"]) {
            CompilerArguments::Ok(ParsedArguments { input, outputs, preprocessor_args, common_args }) => {
                assert!(true, "Parsed ok");
                assert_eq!("foo.c", input);
                assert_map_contains!(outputs, ("obj", "foo.o"));
                //TODO: fix assert_map_contains to assert no extra keys!
                assert_eq!(1, outputs.len());
                assert!(preprocessor_args.is_empty());
                assert!(common_args.is_empty());
            }
            o @ _ => assert!(false, format!("Got unexpected parse result: {:?}", o)),
        }
    }

    #[test]
    fn test_parse_arguments_split_dwarf() {
        match parse_arguments(&stringvec!["-gsplit-dwarf", "-c", "foo.c", "-o", "foo.o"]) {
            CompilerArguments::Ok(ParsedArguments { input, outputs, preprocessor_args, common_args }) => {
                assert!(true, "Parsed ok");
                assert_eq!("foo.c", input);
                assert_map_contains!(outputs, ("obj", "foo.o"), ("dwo", "foo.dwo"));
                //TODO: fix assert_map_contains to assert no extra keys!
                assert_eq!(2, outputs.len());
                assert!(preprocessor_args.is_empty());
                assert_eq!(stringvec!["-gsplit-dwarf"], common_args);
            }
            o @ _ => assert!(false, format!("Got unexpected parse result: {:?}", o)),
        }
    }

    //TODO:
    // * test that other args get persisted
    // * test that args with value get persisted with value
    // * test preprocessor_args
    // * test -MT

    #[test]
    fn test_parse_arguments_empty_args() {
        assert_eq!(CompilerArguments::NotCompilation,
                   parse_arguments(&vec!()));
    }

    #[test]
    fn test_parse_arguments_not_compile() {
        assert_eq!(CompilerArguments::NotCompilation,
                   parse_arguments(&stringvec!["-o", "foo"]));
    }

    #[test]
    fn test_parse_arguments_too_many_inputs() {
        assert_eq!(CompilerArguments::CannotCache,
                   parse_arguments(&stringvec!["-c", "foo.c", "-o", "foo.o", "bar.c"]));
    }

    #[test]
    fn test_parse_arguments_pgo() {
        assert_eq!(CompilerArguments::CannotCache,
                   parse_arguments(&stringvec!["-c", "foo.c", "-fprofile-use", "-o", "foo.o"]));
    }

    #[test]
    fn test_parse_arguments_response_file() {
        assert_eq!(CompilerArguments::CannotCache,
                   parse_arguments(&stringvec!["-c", "foo.c", "@foo", "-o", "foo.o"]));
    }
}
<commit_msg>more gcc::parse_arguments tests<commit_after>// Copyright 2016 Mozilla Foundation
//
// 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.

use ::compiler::{
    CompilerArguments,
    ParsedArguments,
};
use std::collections::HashMap;
use std::path::Path;

pub fn parse_arguments(arguments : &[String]) -> CompilerArguments {
    trace!("gcc::parse_arguments");
    let mut output_arg = None;
    let mut input_arg = None;
    let mut dep_target = None;
    let mut common_args = vec!();
    let mut preprocessor_args = vec!();
    let mut compilation = false;
    let mut split_dwarf = false;
    let mut need_explicit_dep_target = false;

    let mut it = arguments.iter();
    loop {
        match it.next() {
            Some(arg) => {
                match arg.as_ref() {
                    "-c" => compilation = true,
                    "-o" => output_arg = it.next(),
                    "-gsplit-dwarf" => {
                        split_dwarf = true;
                        common_args.push(arg.clone());
                    }
                    // Arguments that take a value.
                    // -MF and -MQ are in this set but are handled separately
                    // because they are also preprocessor options.
                    "--param" | "-A" | "-D" | "-F" | "-G" | "-I" | "-L" |
                    "-U" | "-V" | "-Xassembler" | "-Xlinker" |
                    "-Xpreprocessor" | "-aux-info" | "-b" | "-idirafter" |
                    "-iframework" | "-imacros" | "-imultilib" | "-include" |
                    "-install_name" | "-iprefix" | "-iquote" | "-isysroot" |
                    "-isystem" | "-iwithprefix" | "-iwithprefixbefore" |
                    "-u" => {
                        common_args.push(arg.clone());
                        if let Some(arg_val) = it.next() {
                            common_args.push(arg_val.clone());
                        }
                    },
                    "-MF" | "-MQ" => {
                        preprocessor_args.push(arg.clone());
                        if let Some(arg_val) = it.next() {
                            preprocessor_args.push(arg_val.clone());
                        }
                    }
                    "-MT" => dep_target = it.next(),
                    // Can't cache PGO profiled output.
                    "-fprofile-use" => return CompilerArguments::CannotCache,
                    // Can't cache commandlines using a response file.
                    v @ _ if v.starts_with('@') => return CompilerArguments::CannotCache,
                    "-M" | "-MM" | "-MD" | "-MMD" => {
                        // If one of the above options is on the command line, we'll
                        // need -MT on the preprocessor command line, whether it's
                        // been passed already or not
                        need_explicit_dep_target = true;
                        preprocessor_args.push(arg.clone());
                    }
                    // Other options.
                    v @ _ if v.starts_with('-') && v.len() > 1 => {
                        common_args.push(arg.clone());
                    }
                    // Anything else is an input file.
                    v @ _ => {
                        if input_arg.is_some() || v == "-" {
                            // Can't cache compilations with multiple inputs
                            // or compilation from stdin.
                            return CompilerArguments::CannotCache;
                        }
                        input_arg = Some(v);
                    }
                };
            },
            None => break,
        }
    }
    // We only support compilation.
    if !compilation {
        return CompilerArguments::NotCompilation;
    }
    let input = match input_arg {
        Some(i) => {
            // When compiling from the preprocessed output given as stdin, we need
            // to explicitly pass its file type.
            match Path::new(i).extension().and_then(|e| e.to_str()) {
                Some("c") | Some("cc") | Some("cpp") | Some("cxx") => i.to_owned(),
                e @ _ => {
                    trace!("Unknown source extension: {}", e.unwrap_or("(None)"));
                    return CompilerArguments::CannotCache;
                }
            }
        }
        // We can't cache compilation without an input.
        None => return CompilerArguments::CannotCache,
    };
    let mut outputs = HashMap::new();
    match output_arg {
        // We can't cache compilation that doesn't go to a file
        None => return CompilerArguments::CannotCache,
        Some(o) => {
            outputs.insert("obj", o.to_owned());
            if split_dwarf {
                Path::new(o)
                    .with_extension("dwo")
                    //TODO: should really be dealing with OsStr everywhere.
                    .to_str()
                    .and_then(|dwo| outputs.insert("dwo", dwo.to_owned()));
            }
            if need_explicit_dep_target {
                preprocessor_args.extend_from_slice(&["-MT".to_owned(), dep_target.unwrap_or(o).to_owned()]);
            }
        }
    }

    CompilerArguments::Ok(ParsedArguments {
        input: input,
        outputs: outputs,
        preprocessor_args: preprocessor_args,
        common_args: common_args,
    })
}

#[cfg(test)]
mod test {
    use super::*;
    use ::compiler::*;

    #[test]
    fn test_parse_arguments_simple() {
        match parse_arguments(&stringvec!["-c", "foo.c", "-o", "foo.o"]) {
            CompilerArguments::Ok(ParsedArguments { input, outputs, preprocessor_args, common_args }) => {
                assert!(true, "Parsed ok");
                assert_eq!("foo.c", input);
                assert_map_contains!(outputs, ("obj", "foo.o"));
                //TODO: fix assert_map_contains to assert no extra keys!
                assert_eq!(1, outputs.len());
                assert!(preprocessor_args.is_empty());
                assert!(common_args.is_empty());
            }
            o @ _ => assert!(false, format!("Got unexpected parse result: {:?}", o)),
        }
    }

    #[test]
    fn test_parse_arguments_split_dwarf() {
        match parse_arguments(&stringvec!["-gsplit-dwarf", "-c", "foo.c", "-o", "foo.o"]) {
            CompilerArguments::Ok(ParsedArguments { input, outputs, preprocessor_args, common_args }) => {
                assert!(true, "Parsed ok");
                assert_eq!("foo.c", input);
                assert_map_contains!(outputs, ("obj", "foo.o"), ("dwo", "foo.dwo"));
                //TODO: fix assert_map_contains to assert no extra keys!
                assert_eq!(2, outputs.len());
                assert!(preprocessor_args.is_empty());
                assert_eq!(stringvec!["-gsplit-dwarf"], common_args);
            }
            o @ _ => assert!(false, format!("Got unexpected parse result: {:?}", o)),
        }
    }

    #[test]
    fn test_parse_arguments_extra() {
        match parse_arguments(&stringvec!["-c", "foo.c", "-fabc", "-o", "foo.o", "-mxyz"]) {
            CompilerArguments::Ok(ParsedArguments { input, outputs, preprocessor_args, common_args }) => {
                assert!(true, "Parsed ok");
                assert_eq!("foo.c", input);
                assert_map_contains!(outputs, ("obj", "foo.o"));
                //TODO: fix assert_map_contains to assert no extra keys!
                assert_eq!(1, outputs.len());
                assert!(preprocessor_args.is_empty());
                assert_eq!(stringvec!["-fabc", "-mxyz"], common_args);
            }
            o @ _ => assert!(false, format!("Got unexpected parse result: {:?}", o)),
        }
    }

    #[test]
    fn test_parse_arguments_values() {
        match parse_arguments(&stringvec!["-c", "foo.c", "-fabc", "-I", "include", "-o", "foo.o", "-include", "file"]) {
            CompilerArguments::Ok(ParsedArguments { input, outputs, preprocessor_args, common_args }) => {
                assert!(true, "Parsed ok");
                assert_eq!("foo.c", input);
                assert_map_contains!(outputs, ("obj", "foo.o"));
                //TODO: fix assert_map_contains to assert no extra keys!
                assert_eq!(1, outputs.len());
                assert!(preprocessor_args.is_empty());
                assert_eq!(stringvec!["-fabc", "-I", "include", "-include", "file"], common_args);
            }
            o @ _ => assert!(false, format!("Got unexpected parse result: {:?}", o)),
        }
    }

    #[test]
    fn test_parse_arguments_preprocessor_args() {
        match parse_arguments(&stringvec!["-c", "foo.c", "-fabc", "-MF", "file", "-o", "foo.o", "-MQ", "abc"]) {
            CompilerArguments::Ok(ParsedArguments { input, outputs, preprocessor_args, common_args }) => {
                assert!(true, "Parsed ok");
                assert_eq!("foo.c", input);
                assert_map_contains!(outputs, ("obj", "foo.o"));
                //TODO: fix assert_map_contains to assert no extra keys!
                assert_eq!(1, outputs.len());
                assert_eq!(stringvec!["-MF", "file", "-MQ", "abc"], preprocessor_args);
                assert_eq!(stringvec!["-fabc"], common_args);
            }
            o @ _ => assert!(false, format!("Got unexpected parse result: {:?}", o)),
        }
    }

    #[test]
    fn test_parse_arguments_explicit_dep_target() {
        match parse_arguments(&stringvec!["-c", "foo.c", "-MT", "depfile", "-fabc", "-MF", "file", "-o", "foo.o"]) {
            CompilerArguments::Ok(ParsedArguments { input, outputs, preprocessor_args, common_args }) => {
                assert!(true, "Parsed ok");
                assert_eq!("foo.c", input);
                assert_map_contains!(outputs, ("obj", "foo.o"));
                //TODO: fix assert_map_contains to assert no extra keys!
                assert_eq!(1, outputs.len());
                assert_eq!(stringvec!["-MF", "file"], preprocessor_args);
                assert_eq!(stringvec!["-fabc"], common_args);
            }
            o @ _ => assert!(false, format!("Got unexpected parse result: {:?}", o)),
        }
    }

    #[test]
    fn test_parse_arguments_explicit_dep_target_needed() {
        match parse_arguments(&stringvec!["-c", "foo.c", "-MT", "depfile", "-fabc", "-MF", "file", "-o", "foo.o", "-MD"]) {
            CompilerArguments::Ok(ParsedArguments { input, outputs, preprocessor_args, common_args }) => {
                assert!(true, "Parsed ok");
                assert_eq!("foo.c", input);
                assert_map_contains!(outputs, ("obj", "foo.o"));
                //TODO: fix assert_map_contains to assert no extra keys!
                assert_eq!(1, outputs.len());
                assert_eq!(stringvec!["-MF", "file", "-MD", "-MT", "depfile"], preprocessor_args);
                assert_eq!(stringvec!["-fabc"], common_args);
            }
            o @ _ => assert!(false, format!("Got unexpected parse result: {:?}", o)),
        }
    }

    #[test]
    fn test_parse_arguments_dep_target_needed() {
        match parse_arguments(&stringvec!["-c", "foo.c", "-fabc", "-MF", "file", "-o", "foo.o", "-MD"]) {
            CompilerArguments::Ok(ParsedArguments { input, outputs, preprocessor_args, common_args }) => {
                assert!(true, "Parsed ok");
                assert_eq!("foo.c", input);
                assert_map_contains!(outputs, ("obj", "foo.o"));
                //TODO: fix assert_map_contains to assert no extra keys!
                assert_eq!(1, outputs.len());
                assert_eq!(stringvec!["-MF", "file", "-MD", "-MT", "foo.o"], preprocessor_args);
                assert_eq!(stringvec!["-fabc"], common_args);
            }
            o @ _ => assert!(false, format!("Got unexpected parse result: {:?}", o)),
        }
    }

    #[test]
    fn test_parse_arguments_empty_args() {
        assert_eq!(CompilerArguments::NotCompilation,
                   parse_arguments(&vec!()));
    }

    #[test]
    fn test_parse_arguments_not_compile() {
        assert_eq!(CompilerArguments::NotCompilation,
                   parse_arguments(&stringvec!["-o", "foo"]));
    }

    #[test]
    fn test_parse_arguments_too_many_inputs() {
        assert_eq!(CompilerArguments::CannotCache,
                   parse_arguments(&stringvec!["-c", "foo.c", "-o", "foo.o", "bar.c"]));
    }

    #[test]
    fn test_parse_arguments_pgo() {
        assert_eq!(CompilerArguments::CannotCache,
                   parse_arguments(&stringvec!["-c", "foo.c", "-fprofile-use", "-o", "foo.o"]));
    }

    #[test]
    fn test_parse_arguments_response_file() {
        assert_eq!(CompilerArguments::CannotCache,
                   parse_arguments(&stringvec!["-c", "foo.c", "@foo", "-o", "foo.o"]));
    }
}
<|endoftext|>


<commit_before>extern crate zim;
extern crate clap;
extern crate stopwatch;
extern crate crossbeam;

use clap::{Arg, App};
use zim::{Zim, Target};
use std::fs::File;
use std::io::{Write, BufWriter};
use std::collections::HashMap;
use std::path::Path;
use stopwatch::Stopwatch;

fn main() {
    let matches = App::new("zimextractor")
        .version("0.1")
        .about("Extract zim files")
        .arg(Arg::with_name("out")
                 .short("o")
                 .long("out")
                 .help("Output directory")
                 .takes_value(true))
        .arg(Arg::with_name("skip-link")
                 .long("skip-link")
                 .help("Skip genrating hard links")
                 .takes_value(false))
        .arg(Arg::with_name("INPUT")
                 .help("Set the zim file to extract")
                 .required(true)
                 .index(1))
        .get_matches();

    let skip_link = matches.is_present("skip-link");
    let out = matches.value_of("out").unwrap_or("out");
    let root_output = Path::new(out);

    let input = matches.value_of("INPUT").unwrap();

    println!("Extracting file: {} to {}\n", input, out);

    let sw = Stopwatch::start_new();

    let zim = Zim::new(input).ok().unwrap();

    // map between cluster and directory entry
    let mut cluster_map = HashMap::new();

    println!("  Creating cluster map");
    for i in zim.iterate_by_urls() {
        if let Some(Target::Cluster(cid, _)) = i.target {
            cluster_map.entry(cid).or_insert(Vec::new()).push(i);
        }
    }

    println!("  Extracting entries: {}", zim.header.cluster_count);

    crossbeam::scope(|scope| for (cid, entries) in cluster_map {
                         let mut cluster = zim.get_cluster(cid).unwrap();

                         scope.spawn(move || {
            cluster.decompress();

            for entry in entries {
                if let Some(Target::Cluster(_cid, bid)) = entry.target {
                    assert_eq!(cid, _cid);
                    let mut s = String::new();
                    s.push(entry.namespace);
                    let out_path = root_output.join(&s).join(&entry.url);
                    std::fs::create_dir_all(out_path.parent().unwrap()).unwrap();
                    let data = cluster.get_blob(bid);
                    let f = File::create(&out_path)
                        .ok()
                        .expect(&format!("failed to write file {:?}", out_path));
                    let mut writer = BufWriter::new(&f);
                    writer.write_all(data).unwrap();
                }
            }
        });
                     });

    println!("  Extraction done in {}ms", sw.elapsed_ms());

    if !skip_link {
        println!("  Linking redirects");

        // link all redirects
        for entry in zim.iterate_by_urls() {
            // get redirect entry
            if let Some(Target::Redirect(redir)) = entry.target {
                let redir = zim.get_by_url_index(redir).unwrap();

                let mut s = String::new();
                s.push(redir.namespace);
                let src = root_output.join(&s).join(&redir.url);

                let mut d = String::new();
                d.push(entry.namespace);
                let dst = root_output.join(&s).join(&entry.url);

                if !dst.exists() {
                    // println!("{:?} -> {:?}", src, dst);
                    std::fs::hard_link(src, dst).unwrap();
                }
            }
        }

        println!("  Linking done in {}ms", sw.elapsed_ms());
    } else {
        println!("  Skipping linking...");
    }

    if let Some(main_page_idx) = zim.header.main_page {
        let page = zim.get_by_url_index(main_page_idx).unwrap();
        println!("  Main page is {}", page.url);
    }
}
<commit_msg>improved file error handling<commit_after>extern crate zim;
extern crate clap;
extern crate stopwatch;
extern crate crossbeam;

use std::fs::File;
use std::io::{Write, BufWriter};
use std::error::Error;
use std::collections::HashMap;
use std::path::Path;

use clap::{Arg, App};
use stopwatch::Stopwatch;

use zim::{Zim, Target};

fn main() {
    let matches = App::new("zimextractor")
        .version("0.1")
        .about("Extract zim files")
        .arg(Arg::with_name("out")
                 .short("o")
                 .long("out")
                 .help("Output directory")
                 .takes_value(true))
        .arg(Arg::with_name("skip-link")
                 .long("skip-link")
                 .help("Skip genrating hard links")
                 .takes_value(false))
        .arg(Arg::with_name("INPUT")
                 .help("Set the zim file to extract")
                 .required(true)
                 .index(1))
        .get_matches();

    let skip_link = matches.is_present("skip-link");
    let out = matches.value_of("out").unwrap_or("out");
    let root_output = Path::new(out);

    let input = matches.value_of("INPUT").unwrap();

    println!("Extracting file: {} to {}\n", input, out);

    let sw = Stopwatch::start_new();

    let zim = Zim::new(input).ok().unwrap();

    // map between cluster and directory entry
    let mut cluster_map = HashMap::new();

    println!("  Creating cluster map");
    for i in zim.iterate_by_urls() {
        if let Some(Target::Cluster(cid, _)) = i.target {
            cluster_map.entry(cid).or_insert(Vec::new()).push(i);
        }
    }

    println!("  Extracting entries: {}", zim.header.cluster_count);

    crossbeam::scope(|scope| for (cid, entries) in cluster_map {
                         let mut cluster = zim.get_cluster(cid).unwrap();

                         scope.spawn(move || {
            cluster.decompress();

            for entry in entries {
                if let Some(Target::Cluster(_cid, bid)) = entry.target {
                    assert_eq!(cid, _cid);
                    let mut s = String::new();
                    s.push(entry.namespace);
                    let out_path = root_output.join(&s).join(&entry.url);
                    safe_write(&out_path, cluster.get_blob(bid), 0);
                }
            }
        });
                     });

    println!("  Extraction done in {}ms", sw.elapsed_ms());

    if !skip_link {
        println!("  Linking redirects");

        // link all redirects
        for entry in zim.iterate_by_urls() {
            // get redirect entry
            if let Some(Target::Redirect(redir)) = entry.target {
                let redir = zim.get_by_url_index(redir).unwrap();

                let mut s = String::new();
                s.push(redir.namespace);
                let src = root_output.join(&s).join(&redir.url);

                let mut d = String::new();
                d.push(entry.namespace);
                let dst = root_output.join(&s).join(&entry.url);

                if !dst.exists() {
                    // println!("{:?} -> {:?}", src, dst);
                    std::fs::hard_link(src, dst).unwrap();
                }
            }
        }

        println!("  Linking done in {}ms", sw.elapsed_ms());
    } else {
        println!("  Skipping linking...");
    }

    if let Some(main_page_idx) = zim.header.main_page {
        let page = zim.get_by_url_index(main_page_idx).unwrap();
        println!("  Main page is {}", page.url);
    }
}

fn safe_write(path: &Path, data: &[u8], count: usize) {
    let display = path.display();
    let contain_path = path.parent().unwrap();

    ensure_dir(contain_path);

    match File::create(&path) {
        Err(why) => {
            println!("couldn't create {}: {}", display, why.description());

            if count == 1 {
                safe_write(path, data, 2);
            } else {
                panic!("failed retry: couldn't create {}: {}",
                       display,
                       why.description());
            }
        }
        Ok(file) => {
            let mut writer = BufWriter::new(&file);

            if let Err(why) = writer.write_all(data) {
                println!("couldn't write to {}: {}", display, why.description());
            }
        }
    }
}

fn ensure_dir(path: &Path) {
    match std::fs::create_dir_all(path) {
        Err(e) => {
            use std::io::ErrorKind::*;

            match e.kind() {
                // do not panic if it already exists, that's fine, we just want to make
                // sure we have it before moving on
                AlreadyExists => {}
                _ => {
                    panic!("failed to create {}: {}", path.display(), e.description());
                }
            }
        }
        _ => {}
    }
}
<|endoftext|>


<commit_before>#![cfg(not(debug_assertions))]

use serde_derive::Deserialize;
use serde_yaml;
use state_processing::{per_block_processing, per_slot_processing};
use std::{fs::File, io::prelude::*, path::PathBuf};
use types::*;

#[derive(Debug, Deserialize)]
pub struct ExpectedState {
    pub slot: Option<Slot>,
    pub genesis_time: Option<u64>,
    pub fork: Option<Fork>,
    pub validator_registry: Option<Vec<Validator>>,
    pub validator_balances: Option<Vec<u64>>,
    pub previous_epoch_attestations: Option<Vec<PendingAttestation>>,
    pub current_epoch_attestations: Option<Vec<PendingAttestation>>,
    pub historical_roots: Option<Vec<Hash256>>,
    pub finalized_epoch: Option<Epoch>,
    pub latest_block_roots: Option<TreeHashVector<Hash256>>,
}

impl ExpectedState {
    // Return a list of fields that differ, and a string representation of the beacon state's field.
    fn check(&self, state: &BeaconState) -> Vec<(&str, String)> {
        // Check field equality
        macro_rules! cfe {
            ($field_name:ident) => {
                if self.$field_name.as_ref().map_or(true, |$field_name| {
                    println!("  > Checking {}", stringify!($field_name));
                    $field_name == &state.$field_name
                }) {
                    vec![]
                } else {
                    vec![(stringify!($field_name), format!("{:#?}", state.$field_name))]
                }
            };
        }

        vec![
            cfe!(slot),
            cfe!(genesis_time),
            cfe!(fork),
            cfe!(validator_registry),
            cfe!(validator_balances),
            cfe!(previous_epoch_attestations),
            cfe!(current_epoch_attestations),
            cfe!(historical_roots),
            cfe!(finalized_epoch),
            cfe!(latest_block_roots),
        ]
        .into_iter()
        .flat_map(|x| x)
        .collect()
    }
}

#[derive(Debug, Deserialize)]
pub struct TestCase {
    pub name: String,
    pub config: ChainSpec,
    pub verify_signatures: bool,
    pub initial_state: BeaconState,
    pub blocks: Vec<BeaconBlock>,
    pub expected_state: ExpectedState,
}

#[derive(Debug, Deserialize)]
pub struct TestDoc {
    pub title: String,
    pub summary: String,
    pub fork: String,
    pub test_cases: Vec<TestCase>,
}

fn load_test_case(test_name: &str) -> TestDoc {
    let mut file = {
        let mut file_path_buf = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
        file_path_buf.push(format!("yaml_utils/specs/{}", test_name));

        File::open(file_path_buf).unwrap()
    };
    let mut yaml_str = String::new();
    file.read_to_string(&mut yaml_str).unwrap();
    yaml_str = yaml_str.to_lowercase();

    serde_yaml::from_str(&yaml_str.as_str()).unwrap()
}

fn run_state_transition_test(test_name: &str) {
    let doc = load_test_case(test_name);

    // Run Tests
    let mut ok = true;
    for (i, test_case) in doc.test_cases.iter().enumerate() {
        let fake_crypto = cfg!(feature = "fake_crypto");
        if !test_case.verify_signatures == fake_crypto {
            println!("Running {}", test_case.name);
        } else {
            println!(
                "Skipping {} (fake_crypto: {}, need fake: {})",
                test_case.name, fake_crypto, !test_case.verify_signatures
            );
            continue;
        }
        let mut state = test_case.initial_state.clone();
        for (j, block) in test_case.blocks.iter().enumerate() {
            while block.slot > state.slot {
                per_slot_processing(&mut state, &test_case.config).unwrap();
            }
            let res = per_block_processing(&mut state, &block, &test_case.config);
            if res.is_err() {
                println!("Error in {} (#{}), on block {}", test_case.name, i, j);
                println!("{:?}", res);
                ok = false;
            }
        }

        let mismatched_fields = test_case.expected_state.check(&state);
        if !mismatched_fields.is_empty() {
            println!(
                "Error in expected state, these fields didn't match: {:?}",
                mismatched_fields.iter().map(|(f, _)| f).collect::<Vec<_>>()
            );
            for (field_name, state_val) in mismatched_fields {
                println!("state.{} was: {}", field_name, state_val);
            }
            ok = false;
        }
    }

    assert!(ok, "one or more tests failed, see above");
}

#[test]
#[cfg(not(debug_assertions))]
fn test_read_yaml() {
    load_test_case("sanity-check_small-config_32-vals.yaml");
    load_test_case("sanity-check_default-config_100-vals.yaml");
}

#[test]
#[cfg(not(debug_assertions))]
fn run_state_transition_tests_small() {
    run_state_transition_test("sanity-check_small-config_32-vals.yaml");
}

// Run with --ignored to run this test
#[test]
#[ignore]
fn run_state_transition_tests_large() {
    run_state_transition_test("sanity-check_default-config_100-vals.yaml");
}
<commit_msg>Igoring state_transition_tests_small and test_read_yaml because they are failing to download the correct files.<commit_after>#![cfg(not(debug_assertions))]

use serde_derive::Deserialize;
use serde_yaml;
use state_processing::{per_block_processing, per_slot_processing};
use std::{fs::File, io::prelude::*, path::PathBuf};
use types::*;

#[derive(Debug, Deserialize)]
pub struct ExpectedState {
    pub slot: Option<Slot>,
    pub genesis_time: Option<u64>,
    pub fork: Option<Fork>,
    pub validator_registry: Option<Vec<Validator>>,
    pub validator_balances: Option<Vec<u64>>,
    pub previous_epoch_attestations: Option<Vec<PendingAttestation>>,
    pub current_epoch_attestations: Option<Vec<PendingAttestation>>,
    pub historical_roots: Option<Vec<Hash256>>,
    pub finalized_epoch: Option<Epoch>,
    pub latest_block_roots: Option<TreeHashVector<Hash256>>,
}

impl ExpectedState {
    // Return a list of fields that differ, and a string representation of the beacon state's field.
    fn check(&self, state: &BeaconState) -> Vec<(&str, String)> {
        // Check field equality
        macro_rules! cfe {
            ($field_name:ident) => {
                if self.$field_name.as_ref().map_or(true, |$field_name| {
                    println!("  > Checking {}", stringify!($field_name));
                    $field_name == &state.$field_name
                }) {
                    vec![]
                } else {
                    vec![(stringify!($field_name), format!("{:#?}", state.$field_name))]
                }
            };
        }

        vec![
            cfe!(slot),
            cfe!(genesis_time),
            cfe!(fork),
            cfe!(validator_registry),
            cfe!(validator_balances),
            cfe!(previous_epoch_attestations),
            cfe!(current_epoch_attestations),
            cfe!(historical_roots),
            cfe!(finalized_epoch),
            cfe!(latest_block_roots),
        ]
        .into_iter()
        .flat_map(|x| x)
        .collect()
    }
}

#[derive(Debug, Deserialize)]
pub struct TestCase {
    pub name: String,
    pub config: ChainSpec,
    pub verify_signatures: bool,
    pub initial_state: BeaconState,
    pub blocks: Vec<BeaconBlock>,
    pub expected_state: ExpectedState,
}

#[derive(Debug, Deserialize)]
pub struct TestDoc {
    pub title: String,
    pub summary: String,
    pub fork: String,
    pub test_cases: Vec<TestCase>,
}

fn load_test_case(test_name: &str) -> TestDoc {
    let mut file = {
        let mut file_path_buf = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
        file_path_buf.push(format!("yaml_utils/specs/{}", test_name));

        File::open(file_path_buf).unwrap()
    };
    let mut yaml_str = String::new();
    file.read_to_string(&mut yaml_str).unwrap();
    yaml_str = yaml_str.to_lowercase();

    serde_yaml::from_str(&yaml_str.as_str()).unwrap()
}

fn run_state_transition_test(test_name: &str) {
    let doc = load_test_case(test_name);

    // Run Tests
    let mut ok = true;
    for (i, test_case) in doc.test_cases.iter().enumerate() {
        let fake_crypto = cfg!(feature = "fake_crypto");
        if !test_case.verify_signatures == fake_crypto {
            println!("Running {}", test_case.name);
        } else {
            println!(
                "Skipping {} (fake_crypto: {}, need fake: {})",
                test_case.name, fake_crypto, !test_case.verify_signatures
            );
            continue;
        }
        let mut state = test_case.initial_state.clone();
        for (j, block) in test_case.blocks.iter().enumerate() {
            while block.slot > state.slot {
                per_slot_processing(&mut state, &test_case.config).unwrap();
            }
            let res = per_block_processing(&mut state, &block, &test_case.config);
            if res.is_err() {
                println!("Error in {} (#{}), on block {}", test_case.name, i, j);
                println!("{:?}", res);
                ok = false;
            }
        }

        let mismatched_fields = test_case.expected_state.check(&state);
        if !mismatched_fields.is_empty() {
            println!(
                "Error in expected state, these fields didn't match: {:?}",
                mismatched_fields.iter().map(|(f, _)| f).collect::<Vec<_>>()
            );
            for (field_name, state_val) in mismatched_fields {
                println!("state.{} was: {}", field_name, state_val);
            }
            ok = false;
        }
    }

    assert!(ok, "one or more tests failed, see above");
}

#[test]
// Ignoring because it's failing while downloading stuff
#[ignore]
#[cfg(not(debug_assertions))]
fn test_read_yaml() {
    load_test_case("sanity-check_small-config_32-vals.yaml");
    load_test_case("sanity-check_default-config_100-vals.yaml");
}

#[test]
// Ignoring because it's failing while downloading stuff
#[ignore]
#[cfg(not(debug_assertions))]
fn run_state_transition_tests_small() {
    run_state_transition_test("sanity-check_small-config_32-vals.yaml");
}

// Run with --ignored to run this test
#[test]
#[ignore]
fn run_state_transition_tests_large() {
    run_state_transition_test("sanity-check_default-config_100-vals.yaml");
}
<|endoftext|>


<commit_before>use time::get_time;
use player::Player;
use player::PlayerType;
use arena::Arena;
use super::enums;
use super::moves;
use super::resolve;
use super::pokemon_token::PokemonToken;
use super::movedex::Movedex;
use super::moves::Technique;
use self::rand::{Rng, thread_rng};
use self::regex::Regex;

extern crate rand;
extern crate regex;

#[derive(Debug)]
enum MoveName {
    disable,
    teleport
}

pub fn test(){
    println!("Unique");
    for entry in Movedex::new().get_entries() {
         if entry.get_category() == enums::MoveCategory::Unique {
             println!("{:?}: {:?} - {:?}", entry.get_id(), entry.get_name(), entry.get_type());
         }
    }
}

pub fn test2(){
    println!("Unique");
    for entry in Movedex::new().get_entries() {
         if entry.get_category() == enums::MoveCategory::Unique {
             println!("{:?}", entry.get_name());
         }
    }
}

pub fn unique(attack: &Technique, name: &str, move_type: enums::Types, mut user: PokemonToken, target: PokemonToken, attacker: &mut Player, defender: &mut Player, arena: &mut Arena) {
    let movedex = Movedex::new();
    let mut rng = thread_rng();

    // target.get_moves(dex.move_by_id());
    // match dex.get_entries() {
    match name {
        "disable" => {
            println!("disable" );
        },
        "teleport" => {
            println!("teleport");
        },
        "mimic" => {
            let attack = movedex.move_by_id(defender.get_last_move().unwrap().0.get_id()).unwrap();
            attack.resolve(arena, 1);
        },
        "focus-energy" => {
        },
        "metronome" => {
            let random = rng.gen_range(1, 616);
            let attack = movedex.move_by_id(random).unwrap();
            attack.resolve(arena, 1);
        },
        "mirror-move" => {
            let attack = movedex.move_by_id(defender.get_last_move().unwrap().0.get_id()).unwrap();
            attack.resolve(arena, 1);
        },
        "nature-power" => {
            match arena.get_current_effect().0 {
                enums::Types::Normal => {
                    for entry in Movedex::new().get_entries() {
                        if entry.get_name() == "tri-attack" {
                            let attack = movedex.move_by_id(entry.get_id()).unwrap();
                            attack.resolve(arena, 1);
                        }
                    }
                },
                enums::Types::Flying => {
                    for entry in Movedex::new().get_entries() {
                        if entry.get_name() == "air-slash" {
                            let attack = movedex.move_by_id(entry.get_id()).unwrap();
                            attack.resolve(arena, 1);
                        }
                    }
                },
                enums::Types::Ground => {
                    for entry in Movedex::new().get_entries() {
                        if entry.get_name() == "earth_power" {
                            let attack = movedex.move_by_id(entry.get_id()).unwrap();
                            attack.resolve(arena, 1);
                        }
                    }
                },
                enums::Types::Rock => {
                    for entry in Movedex::new().get_entries() {
                        if entry.get_name() == "power_gem" {
                            let attack = movedex.move_by_id(entry.get_id()).unwrap();
                            attack.resolve(arena, 1);
                        }
                    }
                },
                enums::Types::Fire => {
                    for entry in Movedex::new().get_entries() {
                        if entry.get_name() == "lava_plume" {
                            let attack = movedex.move_by_id(entry.get_id()).unwrap();
                            attack.resolve(arena, 1);
                        }
                    }
                },
                enums::Types::Water => {
                    for entry in Movedex::new().get_entries() {
                        if entry.get_name() == "hydro_pump" {
                            let attack = movedex.move_by_id(entry.get_id()).unwrap();
                            attack.resolve(arena, 1);
                        }
                    }
                },
                enums::Types::Grass => {
                    for entry in Movedex::new().get_entries() {
                        if entry.get_name() == "energy-ball" {
                            let attack = movedex.move_by_id(entry.get_id()).unwrap();
                            attack.resolve(arena, 1);
                        }
                    }
                },
                enums::Types::Electric => {
                    for entry in Movedex::new().get_entries() {
                        if entry.get_name() == "thunderbolt" {
                            let attack = movedex.move_by_id(entry.get_id()).unwrap();
                            attack.resolve(arena, 1);
                        }
                    }
                },
                enums::Types::Ice => {
                    for entry in Movedex::new().get_entries() {
                        if entry.get_name() == "ice_beam" {
                            let attack = movedex.move_by_id(entry.get_id()).unwrap();
                            attack.resolve(arena, 1);
                        }
                    }
                },
                _ => {},
            }
        },
        // "transform" => {
        // },
        "splash" => {
            if arena.get_current_effect().0 == enums::Types::Flying{
                println!("The attack can not be used because {:?} is activated.", enums::Types::Flying);
            }else{
                println!("Nothing happens...");
            }
        },
        "rest" => {
            for entry in Movedex::new().get_entries() {
                if entry.get_name() == "rest" {
                    ////Fehler muss noch behofen werden
                    //let mut user_clone = moves::get_user(1, arena).clone();
                    // resolve::ailment("rest",
                    //                  entry.get_type(),
                    //                  entry.get_ailment(),
                    //                  100,
                    //                  user,
                    //                  target,
                    //                  defender);
                }
            }

        },
        "conversion" => {
            user.set_type(0, attack.get_type());
        },
        // "conversion-2" => {
        // },
        // "substitute" => {
        // },
        // "sketch" => {
        // },
        // "spider-web" => {
        // },
        // "mind-reader" => {
        // },
        // "curse" => {
        // },
        "spite" => {
            // defender.get_last_move().unwrap().0.get_power_points();
            // target.decrement_ap();
        },
        // "protect" => {
        // },
        // "belly-drum" => {
        // },
        // "destiny-bond" => {
        // },
        // "detect" => {
        // },
        // "lock-on" => {
        // },
        // "endure" => {
        // },
        // "mean-look" => {
        // },
        // "sleep-talk" => {
        // },
        // "heal-bell" => {
        // },
        // "pain-split" => {
        // },
        // "baton-pass" => {
        // },
        // "encore" => {
        // },
        // "psych-up" => {
        // },
        // "future-sight" => {
        // },
        // "stockpile" => {
        // },
        // "memento" => {
        // },
        // "follow-me" => {
        // },
        // "taunt" => {
        // },
        // "helping-hand" => {
        // },
        // "trick" => {
        // },
        // "role-play" => {
        // },
        // "wish" => {
        // },
        // "assist" => {
        // },
        // "magic-coat" => {
        // },
        // "recycle" => {
        // },
        // "skill-swap" => {
        // },
        // "imprison" => {
        // },
        // "refresh" => {
        // },
        // "grudge" => {
        // },
        // "snatch" => {
        // },
        // "camouflage" => {
        // },
        // "aromatherapy" => {
        // },
        // "block" => {
        // },
        // "doom-desire" => {
        // },
        // "healing-wish" => {
        // },
        // "acupressure" => {
        // },
        // "psycho-shift" => {
        // },
        // "power-trick" => {
        // },
        // "gastro-acid" => {
        // },
        // "copycat" => {
        // },
        // "power-swap" => {
        // },
        // "guard-swap" => {
        // },
        // "worry-seed" => {
        // },
        // "heart-swap" => {
        // },
        // "aqua-ring" => {
        // },
        // "magnet-rise" => {
        // },
        // "switcheroo" => {
        // },
        // "defog" => {
        // },
        // "lunar-dance" => {
        // },
        // "guard-split" => {
        // },
        // "power-split" => {
        // },
        // "rage-powder" => {
        // },
        // "soak" => {
        // },
        // "simple-beam" => {
        // },
        // "entrainment" => {
        // },
        // "after-you" => {
        // },
        // "ally-switch" => {
        // },
        // "shell-smash" => {
        // },
        // "quash" => {
        // },
        // "reflect-type" => {
        // },
        // "bestow" => {
        // },
        // "trick-or-treat" => {
        // },
        // "forests-curse" => {
        // },
        // "topsy-turvy" => {
        // },
        // "flower-shield" => {
        // },
        // "electrify" => {
        // },
        // "kings-shield" => {
        // },
        // "spiky-shield" => {
        // },
        // "powder" => {
        // },
        // "happy-hour" => {
        // },
        // "celebrate" => {
        // },
        // "hold-hands" => {
        // },
        _ => {},
    };
}
<commit_msg>fix after pull<commit_after>use time::get_time;
use player::Player;
use player::PlayerType;
use arena::Arena;
use super::enums;
use super::moves;
use super::resolve;
use super::pokemon_token::PokemonToken;
use super::movedex::Movedex;
use super::moves::Technique;
use self::rand::{Rng, thread_rng};
use self::regex::Regex;

extern crate rand;
extern crate regex;

#[derive(Debug)]
enum MoveName {
    disable,
    teleport
}

pub fn test(){
    println!("Unique");
    for entry in Movedex::new().get_entries() {
         if entry.get_category() == enums::MoveCategory::Unique {
             println!("{:?}: {:?} - {:?}", entry.get_id(), entry.get_name(), entry.get_type());
         }
    }
}

pub fn test2(){
    println!("Unique");
    for entry in Movedex::new().get_entries() {
         if entry.get_category() == enums::MoveCategory::Unique {
             println!("{:?}", entry.get_name());
         }
    }
}

pub fn unique(attack: &Technique, name: &str, move_type: enums::Types, mut user: PokemonToken, target: PokemonToken, attacker: &mut Player, defender: &mut Player, arena: &mut Arena) {
    let movedex = Movedex::new();
    let mut rng = thread_rng();

    // target.get_moves(dex.move_by_id());
    // match dex.get_entries() {
    match name {
        "disable" => {
            println!("disable" );
        },
        "teleport" => {
            println!("teleport");
        },
        "mimic" => {
            let attack = movedex.move_by_id(defender.get_last_move().unwrap().0.get_id()).unwrap();
            attack.resolve(arena, 1);
        },
        "focus-energy" => {
        },
        "metronome" => {
            let random = rng.gen_range(1, 616);
            let attack = movedex.move_by_id(random).unwrap();
            attack.resolve(arena, 1);
        },
        "mirror-move" => {
            let attack = movedex.move_by_id(defender.get_last_move().unwrap().0.get_id()).unwrap();
            attack.resolve(arena, 1);
        },
        "nature-power" => {
            match arena.get_current_effect().0 {
                enums::Types::Normal => {
                    for entry in Movedex::new().get_entries() {
                        if entry.get_name() == "tri-attack" {
                            let attack = movedex.move_by_id(entry.get_id()).unwrap();
                            attack.resolve(arena, 1);
                        }
                    }
                },
                enums::Types::Flying => {
                    for entry in Movedex::new().get_entries() {
                        if entry.get_name() == "air-slash" {
                            let attack = movedex.move_by_id(entry.get_id()).unwrap();
                            attack.resolve(arena, 1);
                        }
                    }
                },
                enums::Types::Ground => {
                    for entry in Movedex::new().get_entries() {
                        if entry.get_name() == "earth_power" {
                            let attack = movedex.move_by_id(entry.get_id()).unwrap();
                            attack.resolve(arena, 1);
                        }
                    }
                },
                enums::Types::Rock => {
                    for entry in Movedex::new().get_entries() {
                        if entry.get_name() == "power_gem" {
                            let attack = movedex.move_by_id(entry.get_id()).unwrap();
                            attack.resolve(arena, 1);
                        }
                    }
                },
                enums::Types::Fire => {
                    for entry in Movedex::new().get_entries() {
                        if entry.get_name() == "lava_plume" {
                            let attack = movedex.move_by_id(entry.get_id()).unwrap();
                            attack.resolve(arena, 1);
                        }
                    }
                },
                enums::Types::Water => {
                    for entry in Movedex::new().get_entries() {
                        if entry.get_name() == "hydro_pump" {
                            let attack = movedex.move_by_id(entry.get_id()).unwrap();
                            attack.resolve(arena, 1);
                        }
                    }
                },
                enums::Types::Grass => {
                    for entry in Movedex::new().get_entries() {
                        if entry.get_name() == "energy-ball" {
                            let attack = movedex.move_by_id(entry.get_id()).unwrap();
                            attack.resolve(arena, 1);
                        }
                    }
                },
                enums::Types::Electric => {
                    for entry in Movedex::new().get_entries() {
                        if entry.get_name() == "thunderbolt" {
                            let attack = movedex.move_by_id(entry.get_id()).unwrap();
                            attack.resolve(arena, 1);
                        }
                    }
                },
                enums::Types::Ice => {
                    for entry in Movedex::new().get_entries() {
                        if entry.get_name() == "ice_beam" {
                            let attack = movedex.move_by_id(entry.get_id()).unwrap();
                            attack.resolve(arena, 1);
                        }
                    }
                },
                _ => {},
            }
        },
        // "transform" => {
        // },
        "splash" => {
            if arena.get_current_effect().0 == enums::Types::Flying{
                println!("The attack can not be used because {:?} is activated.", enums::Types::Flying);
            }else{
                println!("Nothing happens...");
            }
        },
        "rest" => {
            for entry in Movedex::new().get_entries() {
                if entry.get_name() == "rest" {
                    ////Fehler muss noch behofen werden
                    //let mut user_clone = moves::get_user(1, arena).clone();
                    // resolve::ailment("rest",
                    //                  entry.get_type(),
                    //                  entry.get_ailment(),
                    //                  100,
                    //                  user,
                    //                  target,
                    //                  defender);
                }
            }

        },
        "conversion" => {
            user.set_type(0, attack.get_type());
        },
        "spite" => {
            // defender.get_last_move().unwrap().0.get_power_points();
            // target.decrement_ap();
        },
        "sleep-talk" => {
            if attacker.is_asleep(){
                attacker.get_attack(0);
            }
        },
        // "conversion-2" => {
        // },
        // "substitute" => {
        // },
        // "sketch" => {
        // },
        // "spider-web" => {
        // },
        // "mind-reader" => {
        // },
        // "curse" => {
        // },
        // "protect" => {
        // },
        // "belly-drum" => {
        // },
        // "destiny-bond" => {
        // },
        // "detect" => {
        // },
        // "lock-on" => {
        // },
        // "endure" => {
        // },
        // "mean-look" => {
        // },
        // "heal-bell" => {
        // },
        // "pain-split" => {
        // },
        // "baton-pass" => {
        // },
        // "encore" => {
        // },
        // "psych-up" => {
        // },
        // "future-sight" => {
        // },
        // "stockpile" => {
        // },
        // "memento" => {
        // },
        // "follow-me" => {
        // },
        // "taunt" => {
        // },
        // "helping-hand" => {
        // },
        // "trick" => {
        // },
        // "role-play" => {
        // },
        // "wish" => {
        // },
        // "assist" => {
        // },
        // "magic-coat" => {
        // },
        // "recycle" => {
        // },
        // "skill-swap" => {
        // },
        // "imprison" => {
        // },
        // "refresh" => {
        // },
        // "grudge" => {
        // },
        // "snatch" => {
        // },
        // "camouflage" => {
        // },
        // "aromatherapy" => {
        // },
        // "block" => {
        // },
        // "doom-desire" => {
        // },
        // "healing-wish" => {
        // },
        // "acupressure" => {
        // },
        // "psycho-shift" => {
        // },
        // "power-trick" => {
        // },
        // "gastro-acid" => {
        // },
        // "copycat" => {
        // },
        // "power-swap" => {
        // },
        // "guard-swap" => {
        // },
        // "worry-seed" => {
        // },
        // "heart-swap" => {
        // },
        // "aqua-ring" => {
        // },
        // "magnet-rise" => {
        // },
        // "switcheroo" => {
        // },
        // "defog" => {
        // },
        // "lunar-dance" => {
        // },
        // "guard-split" => {
        // },
        // "power-split" => {
        // },
        // "rage-powder" => {
        // },
        // "soak" => {
        // },
        // "simple-beam" => {
        // },
        // "entrainment" => {
        // },
        // "after-you" => {
        // },
        // "ally-switch" => {
        // },
        // "shell-smash" => {
        // },
        // "quash" => {
        // },
        // "reflect-type" => {
        // },
        // "bestow" => {
        // },
        // "trick-or-treat" => {
        // },
        // "forests-curse" => {
        // },
        // "topsy-turvy" => {
        // },
        // "flower-shield" => {
        // },
        // "electrify" => {
        // },
        // "kings-shield" => {
        // },
        // "spiky-shield" => {
        // },
        // "powder" => {
        // },
        // "happy-hour" => {
        // },
        // "celebrate" => {
        // },
        // "hold-hands" => {
        // },
        _ => {},
    };
}
<|endoftext|>