<commit_before>//! Provides functions for maintaining database schema.
//!
//! A database migration always provides procedures to update the schema, as well as to revert
//! itself. Diesel's migrations are versioned, and run in order. Diesel also takes care of tracking
//! which migrations have already been run automatically. Your migrations don't need to be
//! idempotent, as Diesel will ensure no migration is run twice unless it has been reverted.
//!
//! Migrations should be placed in a `/migrations` directory at the root of your project (the same
//! directory as `Cargo.toml`). When any of these functions are run, Diesel will search for the
//! migrations directory in the current directory and its parents, stopping when it finds the
//! directory containing `Cargo.toml`.
//!
//! Individual migrations should be a folder containing exactly two files, `up.sql` and `down.sql`.
//! `up.sql` will be used to run the migration, while `down.sql` will be used for reverting it. The
//! folder itself should have the structure `{version}_{migration_name}`. It is recommended that
//! you use the timestamp of creation for the version.
//!
//! ## Example
//!
//! ```text
//! # Directory Structure
//! - 20151219180527_create_users
//!     - up.sql
//!     - down.sql
//! - 20160107082941_create_posts
//!     - up.sql
//!     - down.sql
//! ```
//!
//! ```sql
//! -- 20151219180527_create_users/up.sql
//! CREATE TABLE users (
//!   id SERIAL PRIMARY KEY,
//!   name VARCHAR NOT NULL,
//!   hair_color VARCHAR
//! );
//! ```
//!
//! ```sql
//! -- 20151219180527_create_users/down.sql
//! DROP TABLE users;
//! ```
//!
//! ```sql
//! -- 20160107082941_create_posts/up.sql
//! CREATE TABLE posts (
//!   id SERIAL PRIMARY KEY,
//!   user_id INTEGER NOT NULL,
//!   title VARCHAR NOT NULL,
//!   body TEXT
//! );
//! ```
//!
//! ```sql
//! -- 20160107082941_create_posts/down.sql
//! DROP TABLE posts;
//! ```
mod migration;
#[doc(hidden)]
pub mod connection;
mod migration_error;
#[doc(hidden)]
pub mod schema;

#[doc(inline)]
pub use self::connection::MigrationConnection;
#[doc(inline)]
pub use self::migration::*;
pub use self::migration_error::*;

use std::fs::DirEntry;
use std::io::{stdout, Write};

use expression_methods::*;
use query_dsl::*;
use self::schema::__diesel_schema_migrations::dsl::*;
use {Connection, QueryResult};

use std::env;
use std::path::{PathBuf, Path};

pub static TIMESTAMP_FORMAT: &'static str ="%Y%m%d%H%M%S";

/// Runs all migrations that have not yet been run. This function will print all progress to
/// stdout. This function will return an `Err` if some error occurs reading the migrations, or if
/// any migration fails to run. Each migration is run in its own transaction, so some migrations
/// may be committed, even if a later migration fails to run.
///
/// It should be noted that this runs all migrations that have not already been run, regardless of
/// whether or not their version is later than the latest run migration. This is generally not a
/// problem, and eases the more common case of two developers generating independent migrations on
/// a branch. Whoever created the second one will eventually need to run the first when both
/// branches are merged.
///
/// See the [module level documentation](index.html) for information on how migrations should be
/// structured, and where Diesel will look for them by default.
pub fn run_pending_migrations<Conn>(conn: &Conn) -> Result<(), RunMigrationsError> where
    Conn: MigrationConnection,
{
    let migrations_dir = try!(find_migrations_directory());
    run_pending_migrations_in_directory(conn, &migrations_dir, &mut stdout())
}

#[doc(hidden)]
pub fn run_pending_migrations_in_directory<Conn>(conn: &Conn, migrations_dir: &Path, output: &mut Write)
    -> Result<(), RunMigrationsError> where
        Conn: MigrationConnection,
{
    let all_migrations = try!(migrations_in_directory(migrations_dir));
    run_migrations(conn, all_migrations, output)
}

/// Compares migrations found in `migrations_dir` to those that have been applied.
/// Returns a list of pathbufs and whether they have been applied.
pub fn mark_migrations_in_directory<Conn>(conn: &Conn, migrations_dir: &Path)
    -> Result<Vec<(Option<PathBuf>, bool)>, RunMigrationsError> where
        Conn: MigrationConnection,
{
    let migrations = migrations_in_directory(migrations_dir)?;
    setup_database(conn)?;
    let already_run = conn.previously_run_migration_versions()?;
    let migrations = migrations.into_iter().map(|m| {
        let applied = already_run.contains(&m.version().to_string());
        (m.file_path().map(|p| p.to_path_buf()), applied)
    }).collect();
    Ok(migrations)
}

// Returns true if there are outstanding migrations in the migrations directory, otherwise
// returns false. Returns an `Err` if there are problems with migration setup.
///
/// See the [module level documentation](index.html) for information on how migrations should be
/// structured, and where Diesel will look for them by default.
pub fn any_pending_migrations<Conn>(conn: &Conn) -> Result<bool, RunMigrationsError> where
    Conn: MigrationConnection
{
    let migrations_dir = find_migrations_directory()?;
    let all_migrations = migrations_in_directory(&migrations_dir)?;
    let already_run = conn.previously_run_migration_versions()?;

    let pending = all_migrations.into_iter()
        .any(|m| !already_run.contains(&m.version().to_string()));

    Ok(pending)
}

/// Reverts the last migration that was run. Returns the version that was reverted. Returns an
/// `Err` if no migrations have ever been run.
///
/// See the [module level documentation](index.html) for information on how migrations should be
/// structured, and where Diesel will look for them by default.
pub fn revert_latest_migration<Conn>(conn: &Conn) -> Result<String, RunMigrationsError> where
    Conn: MigrationConnection,
{
    let migrations_dir = try!(find_migrations_directory());
    revert_latest_migration_in_directory(conn, &migrations_dir)
}

pub fn revert_latest_migration_in_directory<Conn>(conn: &Conn, path: &Path) -> Result<String, RunMigrationsError> where
    Conn: MigrationConnection,
{
    try!(setup_database(conn));
    let latest_migration_version = conn.latest_run_migration_version()?
        .ok_or_else(|| RunMigrationsError::MigrationError(MigrationError::NoMigrationRun))?;
    revert_migration_with_version(conn, path, &latest_migration_version, &mut stdout())
        .map(|_| latest_migration_version)
}

#[doc(hidden)]
pub fn revert_migration_with_version<Conn: Connection>(conn: &Conn, migrations_dir: &Path, ver: &str, output: &mut Write)
    -> Result<(), RunMigrationsError>
{
    migration_with_version(migrations_dir, ver)
        .map_err(|e| e.into())
        .and_then(|m| revert_migration(conn, m, output))
}

#[doc(hidden)]
pub fn run_migration_with_version<Conn>(conn: &Conn, migrations_dir: &Path, ver: &str, output: &mut Write)
    -> Result<(), RunMigrationsError> where
        Conn: MigrationConnection,
{
    migration_with_version(migrations_dir, ver)
        .map_err(|e| e.into())
        .and_then(|m| run_migration(conn, &*m, output))
}

fn migration_with_version(migrations_dir: &Path, ver: &str) -> Result<Box<Migration>, MigrationError> {
    let all_migrations = try!(migrations_in_directory(migrations_dir));
    let migration = all_migrations.into_iter().find(|m| {
        m.version() == ver
    });
    match migration {
        Some(m) => Ok(m),
        None => Err(MigrationError::UnknownMigrationVersion(ver.into())),
    }
}

#[doc(hidden)]
pub fn setup_database<Conn: Connection>(conn: &Conn) -> QueryResult<usize> {
    conn.setup_helper_functions();
    create_schema_migrations_table_if_needed(conn)
}

fn create_schema_migrations_table_if_needed<Conn: Connection>(conn: &Conn) -> QueryResult<usize> {
    conn.silence_notices(|| {
        conn.execute("CREATE TABLE IF NOT EXISTS __diesel_schema_migrations (
            version VARCHAR(50) PRIMARY KEY NOT NULL,
            run_on TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
        )")
    })
}

#[doc(hidden)]
pub fn migration_paths_in_directory(path: &Path) -> Result<Vec<DirEntry>, MigrationError> {
    try!(path.read_dir())
        .filter_map(|entry| {
            let entry = match entry {
                Ok(e) => e,
                Err(e) => return Some(Err(e.into())),
            };
            if entry.file_name().to_string_lossy().starts_with('.') {
                None
            } else {
                Some(Ok(entry))
            }
        }).collect()
}

fn migrations_in_directory(path: &Path) -> Result<Vec<Box<Migration>>, MigrationError> {
    use self::migration::migration_from;

    try!(migration_paths_in_directory(path)).iter().map(|e| {
        migration_from(e.path())
    }).collect()
}

/// Run all pending migrations in the given list. Apps should likely be calling
/// `run_pending_migrations` or `run_pending_migrations_in_directory` instead.
pub fn run_migrations<Conn, List>(
    conn: &Conn,
    migrations: List,
    output: &mut Write,
) -> Result<(), RunMigrationsError> where
    Conn: MigrationConnection,
    List: IntoIterator,
    List::Item: Migration,
{
    try!(setup_database(conn));
    let already_run = try!(conn.previously_run_migration_versions());
    let mut pending_migrations: Vec<_> = migrations.into_iter()
        .filter(|m| {
            !already_run.contains(&m.version().to_string())
        }).collect();

    pending_migrations.sort_by(|a, b| a.version().cmp(b.version()));
    for migration in pending_migrations {
        try!(run_migration(conn, &migration, output));
    }
    Ok(())
}

fn run_migration<Conn>(conn: &Conn, migration: &Migration, output: &mut Write)
    -> Result<(), RunMigrationsError> where
        Conn: MigrationConnection,
{
    conn.transaction(|| {
        try!(writeln!(output, "Running migration {}", migration.version()));
        try!(migration.run(conn));
        try!(conn.insert_new_migration(migration.version()));
        Ok(())
    })
}

fn revert_migration<Conn: Connection>(conn: &Conn, migration: Box<Migration>, output: &mut Write)
    -> Result<(), RunMigrationsError>
{
    conn.transaction(|| {
        try!(writeln!(output, "Rolling back migration {}", migration.version()));
        try!(migration.revert(conn));
        let target = __diesel_schema_migrations.filter(version.eq(migration.version()));
        try!(::delete(target).execute(conn));
        Ok(())
    })
}

/// Returns the directory containing migrations. Will look at for
/// $PWD/migrations. If it is not found, it will search the parents of the
/// current directory, until it reaches the root directory.  Returns
/// `MigrationError::MigrationDirectoryNotFound` if no directory is found.
pub fn find_migrations_directory() -> Result<PathBuf, MigrationError> {
    search_for_migrations_directory(&try!(env::current_dir()))
}

/// Searches for the migrations directory relative to the given path. See
/// `find_migrations_directory` for more details.
pub fn search_for_migrations_directory(path: &Path) -> Result<PathBuf, MigrationError> {
    let migration_path = path.join("migrations");
    if migration_path.is_dir() {
        Ok(migration_path)
    } else {
        path.parent().map(search_for_migrations_directory)
            .unwrap_or(Err(MigrationError::MigrationDirectoryNotFound))
    }
}

#[cfg(test)]
mod tests {
    extern crate tempdir;

    use super::*;

    use self::tempdir::TempDir;
    use std::fs;

    #[test]
    fn migration_directory_not_found_if_no_migration_dir_exists() {
        let dir = TempDir::new("diesel").unwrap();

        assert_eq!(Err(MigrationError::MigrationDirectoryNotFound),
            search_for_migrations_directory(dir.path()));
    }

    #[test]
    fn migration_directory_defaults_to_pwd_slash_migrations() {
        let dir = TempDir::new("diesel").unwrap();
        let temp_path = dir.path().canonicalize().unwrap();
        let migrations_path = temp_path.join("migrations");

        fs::create_dir(&migrations_path).unwrap();

        assert_eq!(Ok(migrations_path), search_for_migrations_directory(&temp_path));
    }

    #[test]
    fn migration_directory_checks_parents() {
        let dir = TempDir::new("diesel").unwrap();
        let temp_path = dir.path().canonicalize().unwrap();
        let migrations_path = temp_path.join("migrations");
        let child_path = temp_path.join("child");

        fs::create_dir(&child_path).unwrap();
        fs::create_dir(&migrations_path).unwrap();

        assert_eq!(Ok(migrations_path), search_for_migrations_directory(&child_path));
    }
}
<commit_msg>Added a reference to embed_macros is the migrations module docs.<commit_after>//! Provides functions for maintaining database schema.
//!
//! A database migration always provides procedures to update the schema, as well as to revert
//! itself. Diesel's migrations are versioned, and run in order. Diesel also takes care of tracking
//! which migrations have already been run automatically. Your migrations don't need to be
//! idempotent, as Diesel will ensure no migration is run twice unless it has been reverted.
//!
//! Migrations should be placed in a `/migrations` directory at the root of your project (the same
//! directory as `Cargo.toml`). When any of these functions are run, Diesel will search for the
//! migrations directory in the current directory and its parents, stopping when it finds the
//! directory containing `Cargo.toml`.
//!
//! Individual migrations should be a folder containing exactly two files, `up.sql` and `down.sql`.
//! `up.sql` will be used to run the migration, while `down.sql` will be used for reverting it. The
//! folder itself should have the structure `{version}_{migration_name}`. It is recommended that
//! you use the timestamp of creation for the version.
//!
//! Migrations can either be run with the CLI or embedded into the compiled application
//! and executed with code, for example right after establishing a database connection.
//! For more information, consult the [`embed_migrations!`](../macro.embed_migrations.html) macro.
//!
//! ## Example
//!
//! ```text
//! # Directory Structure
//! - 20151219180527_create_users
//!     - up.sql
//!     - down.sql
//! - 20160107082941_create_posts
//!     - up.sql
//!     - down.sql
//! ```
//!
//! ```sql
//! -- 20151219180527_create_users/up.sql
//! CREATE TABLE users (
//!   id SERIAL PRIMARY KEY,
//!   name VARCHAR NOT NULL,
//!   hair_color VARCHAR
//! );
//! ```
//!
//! ```sql
//! -- 20151219180527_create_users/down.sql
//! DROP TABLE users;
//! ```
//!
//! ```sql
//! -- 20160107082941_create_posts/up.sql
//! CREATE TABLE posts (
//!   id SERIAL PRIMARY KEY,
//!   user_id INTEGER NOT NULL,
//!   title VARCHAR NOT NULL,
//!   body TEXT
//! );
//! ```
//!
//! ```sql
//! -- 20160107082941_create_posts/down.sql
//! DROP TABLE posts;
//! ```
mod migration;
#[doc(hidden)]
pub mod connection;
mod migration_error;
#[doc(hidden)]
pub mod schema;

#[doc(inline)]
pub use self::connection::MigrationConnection;
#[doc(inline)]
pub use self::migration::*;
pub use self::migration_error::*;

use std::fs::DirEntry;
use std::io::{stdout, Write};

use expression_methods::*;
use query_dsl::*;
use self::schema::__diesel_schema_migrations::dsl::*;
use {Connection, QueryResult};

use std::env;
use std::path::{PathBuf, Path};

pub static TIMESTAMP_FORMAT: &'static str ="%Y%m%d%H%M%S";

/// Runs all migrations that have not yet been run. This function will print all progress to
/// stdout. This function will return an `Err` if some error occurs reading the migrations, or if
/// any migration fails to run. Each migration is run in its own transaction, so some migrations
/// may be committed, even if a later migration fails to run.
///
/// It should be noted that this runs all migrations that have not already been run, regardless of
/// whether or not their version is later than the latest run migration. This is generally not a
/// problem, and eases the more common case of two developers generating independent migrations on
/// a branch. Whoever created the second one will eventually need to run the first when both
/// branches are merged.
///
/// See the [module level documentation](index.html) for information on how migrations should be
/// structured, and where Diesel will look for them by default.
pub fn run_pending_migrations<Conn>(conn: &Conn) -> Result<(), RunMigrationsError> where
    Conn: MigrationConnection,
{
    let migrations_dir = try!(find_migrations_directory());
    run_pending_migrations_in_directory(conn, &migrations_dir, &mut stdout())
}

#[doc(hidden)]
pub fn run_pending_migrations_in_directory<Conn>(conn: &Conn, migrations_dir: &Path, output: &mut Write)
    -> Result<(), RunMigrationsError> where
        Conn: MigrationConnection,
{
    let all_migrations = try!(migrations_in_directory(migrations_dir));
    run_migrations(conn, all_migrations, output)
}

/// Compares migrations found in `migrations_dir` to those that have been applied.
/// Returns a list of pathbufs and whether they have been applied.
pub fn mark_migrations_in_directory<Conn>(conn: &Conn, migrations_dir: &Path)
    -> Result<Vec<(Option<PathBuf>, bool)>, RunMigrationsError> where
        Conn: MigrationConnection,
{
    let migrations = migrations_in_directory(migrations_dir)?;
    setup_database(conn)?;
    let already_run = conn.previously_run_migration_versions()?;
    let migrations = migrations.into_iter().map(|m| {
        let applied = already_run.contains(&m.version().to_string());
        (m.file_path().map(|p| p.to_path_buf()), applied)
    }).collect();
    Ok(migrations)
}

// Returns true if there are outstanding migrations in the migrations directory, otherwise
// returns false. Returns an `Err` if there are problems with migration setup.
///
/// See the [module level documentation](index.html) for information on how migrations should be
/// structured, and where Diesel will look for them by default.
pub fn any_pending_migrations<Conn>(conn: &Conn) -> Result<bool, RunMigrationsError> where
    Conn: MigrationConnection
{
    let migrations_dir = find_migrations_directory()?;
    let all_migrations = migrations_in_directory(&migrations_dir)?;
    let already_run = conn.previously_run_migration_versions()?;

    let pending = all_migrations.into_iter()
        .any(|m| !already_run.contains(&m.version().to_string()));

    Ok(pending)
}

/// Reverts the last migration that was run. Returns the version that was reverted. Returns an
/// `Err` if no migrations have ever been run.
///
/// See the [module level documentation](index.html) for information on how migrations should be
/// structured, and where Diesel will look for them by default.
pub fn revert_latest_migration<Conn>(conn: &Conn) -> Result<String, RunMigrationsError> where
    Conn: MigrationConnection,
{
    let migrations_dir = try!(find_migrations_directory());
    revert_latest_migration_in_directory(conn, &migrations_dir)
}

pub fn revert_latest_migration_in_directory<Conn>(conn: &Conn, path: &Path) -> Result<String, RunMigrationsError> where
    Conn: MigrationConnection,
{
    try!(setup_database(conn));
    let latest_migration_version = conn.latest_run_migration_version()?
        .ok_or_else(|| RunMigrationsError::MigrationError(MigrationError::NoMigrationRun))?;
    revert_migration_with_version(conn, path, &latest_migration_version, &mut stdout())
        .map(|_| latest_migration_version)
}

#[doc(hidden)]
pub fn revert_migration_with_version<Conn: Connection>(conn: &Conn, migrations_dir: &Path, ver: &str, output: &mut Write)
    -> Result<(), RunMigrationsError>
{
    migration_with_version(migrations_dir, ver)
        .map_err(|e| e.into())
        .and_then(|m| revert_migration(conn, m, output))
}

#[doc(hidden)]
pub fn run_migration_with_version<Conn>(conn: &Conn, migrations_dir: &Path, ver: &str, output: &mut Write)
    -> Result<(), RunMigrationsError> where
        Conn: MigrationConnection,
{
    migration_with_version(migrations_dir, ver)
        .map_err(|e| e.into())
        .and_then(|m| run_migration(conn, &*m, output))
}

fn migration_with_version(migrations_dir: &Path, ver: &str) -> Result<Box<Migration>, MigrationError> {
    let all_migrations = try!(migrations_in_directory(migrations_dir));
    let migration = all_migrations.into_iter().find(|m| {
        m.version() == ver
    });
    match migration {
        Some(m) => Ok(m),
        None => Err(MigrationError::UnknownMigrationVersion(ver.into())),
    }
}

#[doc(hidden)]
pub fn setup_database<Conn: Connection>(conn: &Conn) -> QueryResult<usize> {
    conn.setup_helper_functions();
    create_schema_migrations_table_if_needed(conn)
}

fn create_schema_migrations_table_if_needed<Conn: Connection>(conn: &Conn) -> QueryResult<usize> {
    conn.silence_notices(|| {
        conn.execute("CREATE TABLE IF NOT EXISTS __diesel_schema_migrations (
            version VARCHAR(50) PRIMARY KEY NOT NULL,
            run_on TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
        )")
    })
}

#[doc(hidden)]
pub fn migration_paths_in_directory(path: &Path) -> Result<Vec<DirEntry>, MigrationError> {
    try!(path.read_dir())
        .filter_map(|entry| {
            let entry = match entry {
                Ok(e) => e,
                Err(e) => return Some(Err(e.into())),
            };
            if entry.file_name().to_string_lossy().starts_with('.') {
                None
            } else {
                Some(Ok(entry))
            }
        }).collect()
}

fn migrations_in_directory(path: &Path) -> Result<Vec<Box<Migration>>, MigrationError> {
    use self::migration::migration_from;

    try!(migration_paths_in_directory(path)).iter().map(|e| {
        migration_from(e.path())
    }).collect()
}

/// Run all pending migrations in the given list. Apps should likely be calling
/// `run_pending_migrations` or `run_pending_migrations_in_directory` instead.
pub fn run_migrations<Conn, List>(
    conn: &Conn,
    migrations: List,
    output: &mut Write,
) -> Result<(), RunMigrationsError> where
    Conn: MigrationConnection,
    List: IntoIterator,
    List::Item: Migration,
{
    try!(setup_database(conn));
    let already_run = try!(conn.previously_run_migration_versions());
    let mut pending_migrations: Vec<_> = migrations.into_iter()
        .filter(|m| {
            !already_run.contains(&m.version().to_string())
        }).collect();

    pending_migrations.sort_by(|a, b| a.version().cmp(b.version()));
    for migration in pending_migrations {
        try!(run_migration(conn, &migration, output));
    }
    Ok(())
}

fn run_migration<Conn>(conn: &Conn, migration: &Migration, output: &mut Write)
    -> Result<(), RunMigrationsError> where
        Conn: MigrationConnection,
{
    conn.transaction(|| {
        try!(writeln!(output, "Running migration {}", migration.version()));
        try!(migration.run(conn));
        try!(conn.insert_new_migration(migration.version()));
        Ok(())
    })
}

fn revert_migration<Conn: Connection>(conn: &Conn, migration: Box<Migration>, output: &mut Write)
    -> Result<(), RunMigrationsError>
{
    conn.transaction(|| {
        try!(writeln!(output, "Rolling back migration {}", migration.version()));
        try!(migration.revert(conn));
        let target = __diesel_schema_migrations.filter(version.eq(migration.version()));
        try!(::delete(target).execute(conn));
        Ok(())
    })
}

/// Returns the directory containing migrations. Will look at for
/// $PWD/migrations. If it is not found, it will search the parents of the
/// current directory, until it reaches the root directory.  Returns
/// `MigrationError::MigrationDirectoryNotFound` if no directory is found.
pub fn find_migrations_directory() -> Result<PathBuf, MigrationError> {
    search_for_migrations_directory(&try!(env::current_dir()))
}

/// Searches for the migrations directory relative to the given path. See
/// `find_migrations_directory` for more details.
pub fn search_for_migrations_directory(path: &Path) -> Result<PathBuf, MigrationError> {
    let migration_path = path.join("migrations");
    if migration_path.is_dir() {
        Ok(migration_path)
    } else {
        path.parent().map(search_for_migrations_directory)
            .unwrap_or(Err(MigrationError::MigrationDirectoryNotFound))
    }
}

#[cfg(test)]
mod tests {
    extern crate tempdir;

    use super::*;

    use self::tempdir::TempDir;
    use std::fs;

    #[test]
    fn migration_directory_not_found_if_no_migration_dir_exists() {
        let dir = TempDir::new("diesel").unwrap();

        assert_eq!(Err(MigrationError::MigrationDirectoryNotFound),
            search_for_migrations_directory(dir.path()));
    }

    #[test]
    fn migration_directory_defaults_to_pwd_slash_migrations() {
        let dir = TempDir::new("diesel").unwrap();
        let temp_path = dir.path().canonicalize().unwrap();
        let migrations_path = temp_path.join("migrations");

        fs::create_dir(&migrations_path).unwrap();

        assert_eq!(Ok(migrations_path), search_for_migrations_directory(&temp_path));
    }

    #[test]
    fn migration_directory_checks_parents() {
        let dir = TempDir::new("diesel").unwrap();
        let temp_path = dir.path().canonicalize().unwrap();
        let migrations_path = temp_path.join("migrations");
        let child_path = temp_path.join("child");

        fs::create_dir(&child_path).unwrap();
        fs::create_dir(&migrations_path).unwrap();

        assert_eq!(Ok(migrations_path), search_for_migrations_directory(&child_path));
    }
}
<|endoftext|>


<commit_before><commit_msg>Commented and cleaned up code<commit_after><|endoftext|>


<commit_before>use std::str;

use support::{project, execs, path2url};
use support::{COMPILING, RUNNING};
use hamcrest::{assert_that, existing_file, existing_dir, is_not};

fn setup() {
}

test!(simple {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []
            build = "build.rs"
        "#)
        .file("build.rs", "fn main() {}")
        .file("src/lib.rs", r#"
            pub fn foo() {}
        "#);

    assert_that(p.cargo_process("doc"),
                execs().with_status(0).with_stdout(&format!("\
{compiling} foo v0.0.1 ({dir})
",
        compiling = COMPILING,
        dir = path2url(p.root()))));
    assert_that(&p.root().join("target/doc"), existing_dir());
    assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
});

test!(doc_no_libs {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [[bin]]
            name = "foo"
            doc = false
        "#)
        .file("src/main.rs", r#"
            bad code
        "#);

    assert_that(p.cargo_process("doc"),
                execs().with_status(0));
});

test!(doc_twice {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []
        "#)
        .file("src/lib.rs", r#"
            pub fn foo() {}
        "#);

    assert_that(p.cargo_process("doc"),
                execs().with_status(0).with_stdout(&format!("\
{compiling} foo v0.0.1 ({dir})
",
        compiling = COMPILING,
        dir = path2url(p.root()))));

    assert_that(p.cargo("doc"),
                execs().with_status(0).with_stdout(""))
});

test!(doc_deps {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies.bar]
            path = "bar"
        "#)
        .file("src/lib.rs", r#"
            extern crate bar;
            pub fn foo() {}
        "#)
        .file("bar/Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.0.1"
            authors = []
        "#)
        .file("bar/src/lib.rs", r#"
            pub fn bar() {}
        "#);

    assert_that(p.cargo_process("doc"),
                execs().with_status(0).with_stdout(&format!("\
{compiling} bar v0.0.1 ({dir})
{compiling} foo v0.0.1 ({dir})
",
        compiling = COMPILING,
        dir = path2url(p.root()))));

    assert_that(&p.root().join("target/doc"), existing_dir());
    assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
    assert_that(&p.root().join("target/doc/bar/index.html"), existing_file());

    assert_that(p.cargo("doc")
                 .env("RUST_LOG", "cargo::ops::cargo_rustc::fingerprint"),
                execs().with_status(0).with_stdout(""));

    assert_that(&p.root().join("target/doc"), existing_dir());
    assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
    assert_that(&p.root().join("target/doc/bar/index.html"), existing_file());
});

test!(doc_no_deps {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies.bar]
            path = "bar"
        "#)
        .file("src/lib.rs", r#"
            extern crate bar;
            pub fn foo() {}
        "#)
        .file("bar/Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.0.1"
            authors = []
        "#)
        .file("bar/src/lib.rs", r#"
            pub fn bar() {}
        "#);

    assert_that(p.cargo_process("doc").arg("--no-deps"),
                execs().with_status(0).with_stdout(&format!("\
{compiling} bar v0.0.1 ({dir})
{compiling} foo v0.0.1 ({dir})
",
        compiling = COMPILING,
        dir = path2url(p.root()))));

    assert_that(&p.root().join("target/doc"), existing_dir());
    assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
    assert_that(&p.root().join("target/doc/bar/index.html"), is_not(existing_file()));
});

test!(doc_only_bin {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies.bar]
            path = "bar"
        "#)
        .file("src/main.rs", r#"
            extern crate bar;
            pub fn foo() {}
        "#)
        .file("bar/Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.0.1"
            authors = []
        "#)
        .file("bar/src/lib.rs", r#"
            pub fn bar() {}
        "#);

    assert_that(p.cargo_process("doc").arg("-v"),
                execs().with_status(0));

    assert_that(&p.root().join("target/doc"), existing_dir());
    assert_that(&p.root().join("target/doc/bar/index.html"), existing_file());
    assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
});

test!(doc_lib_bin_same_name {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []
        "#)
        .file("src/main.rs", "fn main() {}")
        .file("src/lib.rs", "fn foo() {}");

    assert_that(p.cargo_process("doc"),
                execs().with_status(101)
                       .with_stderr("\
Cannot document a package where a library and a binary have the same name. \
Consider renaming one or marking the target as `doc = false`
"));
});

test!(doc_dash_p {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies.a]
            path = "a"
        "#)
        .file("src/lib.rs", "extern crate a;")
        .file("a/Cargo.toml", r#"
            [package]
            name = "a"
            version = "0.0.1"
            authors = []

            [dependencies.b]
            path = "../b"
        "#)
        .file("a/src/lib.rs", "extern crate b;")
        .file("b/Cargo.toml", r#"
            [package]
            name = "b"
            version = "0.0.1"
            authors = []
        "#)
        .file("b/src/lib.rs", "");

    assert_that(p.cargo_process("doc").arg("-p").arg("a"),
                execs().with_status(0)
                       .with_stdout(&format!("\
{compiling} b v0.0.1 (file://[..])
{compiling} a v0.0.1 (file://[..])
", compiling = COMPILING)));
});

test!(doc_same_name {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []
        "#)
        .file("src/lib.rs", "")
        .file("src/bin/main.rs", "fn main() {}")
        .file("examples/main.rs", "fn main() {}")
        .file("tests/main.rs", "fn main() {}");

    assert_that(p.cargo_process("doc"),
                execs().with_status(0));
});

test!(doc_target {
    const TARGET: &'static str = "arm-unknown-linux-gnueabihf";

    if !::is_nightly() { return }

    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []
        "#)
        .file("src/lib.rs", r#"
            #![feature(no_core)]
            #![no_core]

            extern {
                pub static A: u32;
            }
        "#);

    assert_that(p.cargo_process("doc").arg("--target").arg(TARGET).arg("--verbose"),
                execs().with_status(0));
    assert_that(&p.root().join(&format!("target/{}/doc", TARGET)), existing_dir());
    assert_that(&p.root().join(&format!("target/{}/doc/foo/index.html", TARGET)), existing_file());
});

test!(target_specific_not_documented {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [target.foo.dependencies]
            a = { path = "a" }
        "#)
        .file("src/lib.rs", "")
        .file("a/Cargo.toml", r#"
            [package]
            name = "a"
            version = "0.0.1"
            authors = []
        "#)
        .file("a/src/lib.rs", "not rust");

    assert_that(p.cargo_process("doc"),
                execs().with_status(0));
});

test!(output_not_captured {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies]
            a = { path = "a" }
        "#)
        .file("src/lib.rs", "")
        .file("a/Cargo.toml", r#"
            [package]
            name = "a"
            version = "0.0.1"
            authors = []
        "#)
        .file("a/src/lib.rs", "
            /// ```
            /// ☃
            /// ```
            pub fn foo() {}
        ");

    let output = p.cargo_process("doc").exec_with_output().err().unwrap()
                                                          .output.unwrap();
    let stderr = str::from_utf8(&output.stderr).unwrap();
    assert!(stderr.contains("☃"), "no snowman\n{}", stderr);
    assert!(stderr.contains("unknown start of token"), "no message\n{}", stderr);
});

test!(target_specific_documented {
    let p = project("foo")
        .file("Cargo.toml", &format!(r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [target.foo.dependencies]
            a = {{ path = "a" }}
            [target.{}.dependencies]
            a = {{ path = "a" }}
        "#, ::rustc_host()))
        .file("src/lib.rs", "
            extern crate a;

            /// test
            pub fn foo() {}
        ")
        .file("a/Cargo.toml", r#"
            [package]
            name = "a"
            version = "0.0.1"
            authors = []
        "#)
        .file("a/src/lib.rs", "
            /// test
            pub fn foo() {}
        ");

    assert_that(p.cargo_process("doc"),
                execs().with_status(0));
});

test!(no_document_build_deps {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [build-dependencies]
            a = { path = "a" }
        "#)
        .file("src/lib.rs", "
            pub fn foo() {}
        ")
        .file("a/Cargo.toml", r#"
            [package]
            name = "a"
            version = "0.0.1"
            authors = []
        "#)
        .file("a/src/lib.rs", "
            /// ```
            /// ☃
            /// ```
            pub fn foo() {}
        ");

    assert_that(p.cargo_process("doc"),
                execs().with_status(0));
});

test!(doc_release {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []
        "#)
        .file("src/lib.rs", "");

    assert_that(p.cargo_process("build").arg("--release"),
                execs().with_status(0));
    assert_that(p.cargo("doc").arg("--release").arg("-v"),
                execs().with_status(0)
                       .with_stdout(&format!("\
{compiling} foo v0.0.1 ([..])
{running} `rustdoc src[..]lib.rs [..]`
", compiling = COMPILING, running = RUNNING)));
});

test!(doc_multiple_deps {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies.bar]
            path = "bar"

            [dependencies.baz]
            path = "baz"
        "#)
        .file("src/lib.rs", r#"
            extern crate bar;
            pub fn foo() {}
        "#)
        .file("bar/Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.0.1"
            authors = []
        "#)
        .file("bar/src/lib.rs", r#"
            pub fn bar() {}
        "#)
        .file("baz/Cargo.toml", r#"
            [package]
            name = "baz"
            version = "0.0.1"
            authors = []
        "#)
        .file("baz/src/lib.rs", r#"
            pub fn baz() {}
        "#);

    assert_that(p.cargo_process("doc").arg("-p").arg("bar").arg("-p").arg("baz"),
                execs().with_status(0));

    assert_that(&p.root().join("target/doc"), existing_dir());
    assert_that(&p.root().join("target/doc/bar/index.html"), existing_file());
    assert_that(&p.root().join("target/doc/baz/index.html"), existing_file());
});
<commit_msg>Add features test to cardo doc tests<commit_after>use std::str;

use support::{project, execs, path2url};
use support::{COMPILING, RUNNING};
use hamcrest::{assert_that, existing_file, existing_dir, is_not};

fn setup() {
}

test!(simple {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []
            build = "build.rs"
        "#)
        .file("build.rs", "fn main() {}")
        .file("src/lib.rs", r#"
            pub fn foo() {}
        "#);

    assert_that(p.cargo_process("doc"),
                execs().with_status(0).with_stdout(&format!("\
{compiling} foo v0.0.1 ({dir})
",
        compiling = COMPILING,
        dir = path2url(p.root()))));
    assert_that(&p.root().join("target/doc"), existing_dir());
    assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
});

test!(doc_no_libs {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [[bin]]
            name = "foo"
            doc = false
        "#)
        .file("src/main.rs", r#"
            bad code
        "#);

    assert_that(p.cargo_process("doc"),
                execs().with_status(0));
});

test!(doc_twice {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []
        "#)
        .file("src/lib.rs", r#"
            pub fn foo() {}
        "#);

    assert_that(p.cargo_process("doc"),
                execs().with_status(0).with_stdout(&format!("\
{compiling} foo v0.0.1 ({dir})
",
        compiling = COMPILING,
        dir = path2url(p.root()))));

    assert_that(p.cargo("doc"),
                execs().with_status(0).with_stdout(""))
});

test!(doc_deps {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies.bar]
            path = "bar"
        "#)
        .file("src/lib.rs", r#"
            extern crate bar;
            pub fn foo() {}
        "#)
        .file("bar/Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.0.1"
            authors = []
        "#)
        .file("bar/src/lib.rs", r#"
            pub fn bar() {}
        "#);

    assert_that(p.cargo_process("doc"),
                execs().with_status(0).with_stdout(&format!("\
{compiling} bar v0.0.1 ({dir})
{compiling} foo v0.0.1 ({dir})
",
        compiling = COMPILING,
        dir = path2url(p.root()))));

    assert_that(&p.root().join("target/doc"), existing_dir());
    assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
    assert_that(&p.root().join("target/doc/bar/index.html"), existing_file());

    assert_that(p.cargo("doc")
                 .env("RUST_LOG", "cargo::ops::cargo_rustc::fingerprint"),
                execs().with_status(0).with_stdout(""));

    assert_that(&p.root().join("target/doc"), existing_dir());
    assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
    assert_that(&p.root().join("target/doc/bar/index.html"), existing_file());
});

test!(doc_no_deps {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies.bar]
            path = "bar"
        "#)
        .file("src/lib.rs", r#"
            extern crate bar;
            pub fn foo() {}
        "#)
        .file("bar/Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.0.1"
            authors = []
        "#)
        .file("bar/src/lib.rs", r#"
            pub fn bar() {}
        "#);

    assert_that(p.cargo_process("doc").arg("--no-deps"),
                execs().with_status(0).with_stdout(&format!("\
{compiling} bar v0.0.1 ({dir})
{compiling} foo v0.0.1 ({dir})
",
        compiling = COMPILING,
        dir = path2url(p.root()))));

    assert_that(&p.root().join("target/doc"), existing_dir());
    assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
    assert_that(&p.root().join("target/doc/bar/index.html"), is_not(existing_file()));
});

test!(doc_only_bin {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies.bar]
            path = "bar"
        "#)
        .file("src/main.rs", r#"
            extern crate bar;
            pub fn foo() {}
        "#)
        .file("bar/Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.0.1"
            authors = []
        "#)
        .file("bar/src/lib.rs", r#"
            pub fn bar() {}
        "#);

    assert_that(p.cargo_process("doc").arg("-v"),
                execs().with_status(0));

    assert_that(&p.root().join("target/doc"), existing_dir());
    assert_that(&p.root().join("target/doc/bar/index.html"), existing_file());
    assert_that(&p.root().join("target/doc/foo/index.html"), existing_file());
});

test!(doc_lib_bin_same_name {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []
        "#)
        .file("src/main.rs", "fn main() {}")
        .file("src/lib.rs", "fn foo() {}");

    assert_that(p.cargo_process("doc"),
                execs().with_status(101)
                       .with_stderr("\
Cannot document a package where a library and a binary have the same name. \
Consider renaming one or marking the target as `doc = false`
"));
});

test!(doc_dash_p {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies.a]
            path = "a"
        "#)
        .file("src/lib.rs", "extern crate a;")
        .file("a/Cargo.toml", r#"
            [package]
            name = "a"
            version = "0.0.1"
            authors = []

            [dependencies.b]
            path = "../b"
        "#)
        .file("a/src/lib.rs", "extern crate b;")
        .file("b/Cargo.toml", r#"
            [package]
            name = "b"
            version = "0.0.1"
            authors = []
        "#)
        .file("b/src/lib.rs", "");

    assert_that(p.cargo_process("doc").arg("-p").arg("a"),
                execs().with_status(0)
                       .with_stdout(&format!("\
{compiling} b v0.0.1 (file://[..])
{compiling} a v0.0.1 (file://[..])
", compiling = COMPILING)));
});

test!(doc_same_name {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []
        "#)
        .file("src/lib.rs", "")
        .file("src/bin/main.rs", "fn main() {}")
        .file("examples/main.rs", "fn main() {}")
        .file("tests/main.rs", "fn main() {}");

    assert_that(p.cargo_process("doc"),
                execs().with_status(0));
});

test!(doc_target {
    const TARGET: &'static str = "arm-unknown-linux-gnueabihf";

    if !::is_nightly() { return }

    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []
        "#)
        .file("src/lib.rs", r#"
            #![feature(no_core)]
            #![no_core]

            extern {
                pub static A: u32;
            }
        "#);

    assert_that(p.cargo_process("doc").arg("--target").arg(TARGET).arg("--verbose"),
                execs().with_status(0));
    assert_that(&p.root().join(&format!("target/{}/doc", TARGET)), existing_dir());
    assert_that(&p.root().join(&format!("target/{}/doc/foo/index.html", TARGET)), existing_file());
});

test!(target_specific_not_documented {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [target.foo.dependencies]
            a = { path = "a" }
        "#)
        .file("src/lib.rs", "")
        .file("a/Cargo.toml", r#"
            [package]
            name = "a"
            version = "0.0.1"
            authors = []
        "#)
        .file("a/src/lib.rs", "not rust");

    assert_that(p.cargo_process("doc"),
                execs().with_status(0));
});

test!(output_not_captured {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies]
            a = { path = "a" }
        "#)
        .file("src/lib.rs", "")
        .file("a/Cargo.toml", r#"
            [package]
            name = "a"
            version = "0.0.1"
            authors = []
        "#)
        .file("a/src/lib.rs", "
            /// ```
            /// ☃
            /// ```
            pub fn foo() {}
        ");

    let output = p.cargo_process("doc").exec_with_output().err().unwrap()
                                                          .output.unwrap();
    let stderr = str::from_utf8(&output.stderr).unwrap();
    assert!(stderr.contains("☃"), "no snowman\n{}", stderr);
    assert!(stderr.contains("unknown start of token"), "no message\n{}", stderr);
});

test!(target_specific_documented {
    let p = project("foo")
        .file("Cargo.toml", &format!(r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [target.foo.dependencies]
            a = {{ path = "a" }}
            [target.{}.dependencies]
            a = {{ path = "a" }}
        "#, ::rustc_host()))
        .file("src/lib.rs", "
            extern crate a;

            /// test
            pub fn foo() {}
        ")
        .file("a/Cargo.toml", r#"
            [package]
            name = "a"
            version = "0.0.1"
            authors = []
        "#)
        .file("a/src/lib.rs", "
            /// test
            pub fn foo() {}
        ");

    assert_that(p.cargo_process("doc"),
                execs().with_status(0));
});

test!(no_document_build_deps {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [build-dependencies]
            a = { path = "a" }
        "#)
        .file("src/lib.rs", "
            pub fn foo() {}
        ")
        .file("a/Cargo.toml", r#"
            [package]
            name = "a"
            version = "0.0.1"
            authors = []
        "#)
        .file("a/src/lib.rs", "
            /// ```
            /// ☃
            /// ```
            pub fn foo() {}
        ");

    assert_that(p.cargo_process("doc"),
                execs().with_status(0));
});

test!(doc_release {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []
        "#)
        .file("src/lib.rs", "");

    assert_that(p.cargo_process("build").arg("--release"),
                execs().with_status(0));
    assert_that(p.cargo("doc").arg("--release").arg("-v"),
                execs().with_status(0)
                       .with_stdout(&format!("\
{compiling} foo v0.0.1 ([..])
{running} `rustdoc src[..]lib.rs [..]`
", compiling = COMPILING, running = RUNNING)));
});

test!(doc_multiple_deps {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies.bar]
            path = "bar"

            [dependencies.baz]
            path = "baz"
        "#)
        .file("src/lib.rs", r#"
            extern crate bar;
            pub fn foo() {}
        "#)
        .file("bar/Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.0.1"
            authors = []
        "#)
        .file("bar/src/lib.rs", r#"
            pub fn bar() {}
        "#)
        .file("baz/Cargo.toml", r#"
            [package]
            name = "baz"
            version = "0.0.1"
            authors = []
        "#)
        .file("baz/src/lib.rs", r#"
            pub fn baz() {}
        "#);

    assert_that(p.cargo_process("doc").arg("-p").arg("bar").arg("-p").arg("baz"),
                execs().with_status(0));

    assert_that(&p.root().join("target/doc"), existing_dir());
    assert_that(&p.root().join("target/doc/bar/index.html"), existing_file());
    assert_that(&p.root().join("target/doc/baz/index.html"), existing_file());
});

test!(features {
    let p = project("foo")
        .file("Cargo.toml", r#"
            [package]
            name = "foo"
            version = "0.0.1"
            authors = []

            [dependencies.bar]
            path = "bar"

            [features]
            foo = ["bar/bar"]
        "#)
        .file("src/lib.rs", r#"
            #[cfg(feature = "foo")]
            pub fn foo() {}
        "#)
        .file("bar/Cargo.toml", r#"
            [package]
            name = "bar"
            version = "0.0.1"
            authors = []

            [features]
            bar = []
        "#)
        .file("bar/build.rs", r#"
            fn main() {
                println!("cargo:rustc-cfg=bar");
            }
        "#)
        .file("bar/src/lib.rs", r#"
            #[cfg(feature = "bar")]
            pub fn bar() {}
        "#);
    assert_that(p.cargo_process("doc").arg("--features").arg("foo"),
                execs().with_status(0));
    assert_that(&p.root().join("target/doc"), existing_dir());
    assert_that(&p.root().join("target/doc/foo/fn.foo.html"), existing_file());
    assert_that(&p.root().join("target/doc/bar/fn.bar.html"), existing_file());
});
<|endoftext|>


<commit_before>fn user(_i: int) {}

fn foo() {
    // Here, i is *moved* into the closure: Not actually OK
    let mut i = 0;
    do task::spawn {
        user(i); //~ ERROR mutable variables cannot be implicitly captured
    }
}

fn bar() {
    // Here, i would be implicitly *copied* but it
    // is mutable: bad
    let mut i = 0;
    while i < 10 {
        do task::spawn {
            use(i); //~ ERROR mutable variables cannot be implicitly captured
        }
        i += 1;
    }
}

fn car() {
    // Here, i is mutable, but *explicitly* copied:
    let mut i = 0;
    while i < 10 {
        do task::spawn |copy i| {
            use(i);
        }
        i += 1;
    }
}

fn main() {
}
<commit_msg>Fix another broken test<commit_after>fn user(_i: int) {}

fn foo() {
    // Here, i is *moved* into the closure: Not actually OK
    let mut i = 0;
    do task::spawn {
        user(i); //~ ERROR mutable variables cannot be implicitly captured
    }
}

fn bar() {
    // Here, i would be implicitly *copied* but it
    // is mutable: bad
    let mut i = 0;
    while i < 10 {
        do task::spawn {
            user(i); //~ ERROR mutable variables cannot be implicitly captured
        }
        i += 1;
    }
}

fn car() {
    // Here, i is mutable, but *explicitly* copied:
    let mut i = 0;
    while i < 10 {
        do task::spawn |copy i| {
            user(i);
        }
        i += 1;
    }
}

fn main() {
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use yaml_rust::Yaml;
use tmux;

pub struct Command {
    //commands: Vec<Command>,
    key: String,
    value: String
}

pub fn main(yaml_string: &Vec<Yaml>) -> Vec<Command> {
    let mut commands: Vec<Command> = vec!();
    //println!("{:?}", yaml_string);

    //fn yaml_match(y: &Yaml) {
    //    match y {
    //        &Yaml::Array(ref v) => {
    //            for x in v {
    //                yaml_match(x);
    //            }
    //        },
    //        &Yaml::Hash(ref h) => {
    //            for (k, v) in h {
    //                println!("hash: {:?}:", k);
    //                yaml_match(v);
    //            }
    //        },
    //        _ => print!("{:?}", y)
    //    }
    //};

    //for line in yaml_string {
    //    for window in yaml_match(line["windows"]) {
    //        let value = yaml_match(window);
    //        let command = Command{key: "window", value: value};
    //        commands.push(command);
    //    };
    //};

    commands
}
<commit_msg>Parse and create build commands for new windows.<commit_after>use std::collections::BTreeMap;
use yaml_rust::Yaml;
use tmux;

#[derive(Debug)]
pub struct Command {
    //commands: Vec<Command>,
    key: String,
    value: String
}

pub fn main(yaml_string: &Vec<Yaml>) -> Vec<Command> {
    let mut commands: Vec<Command> = vec!();
    //println!("{:?}", yaml_string);

    fn yaml_match(y: &Yaml) {
        match y {
            &Yaml::Array(ref v) => {
                for x in v {
                    yaml_match(x);
                }
            },
            &Yaml::Hash(ref h) => {
                for (k, v) in h {
                    println!("hash: {:?}:", k);
                    yaml_match(v);
                }
            },
            _ => print!("{:?}", y)
        };
    };

    for doc in yaml_string {
        for window in doc["windows"].as_vec().unwrap() {
            match window {
                &Yaml::Array(ref a) => {
                    for w in a {
                      commands.push(Command{key: "window".to_string(), value: w.as_str().unwrap().to_string()})
                    }
                },
                &Yaml::Hash(ref h)  => {
                    for (k, v) in h {
                        commands.push(Command{key: "window".to_string(), value: k.as_str().unwrap().to_string()})
                    }
                },
                _ => panic!("wtf")
            };
        };
    };

    println!("{:?}", commands);
    commands
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::env;
use std::ffi::OsString;
use std::path::PathBuf;

#[derive(Default)]
pub struct Crate {
    pub include_prefix: Option<PathBuf>,
    pub links: Option<OsString>,
    pub exported_header_dirs: Vec<PathBuf>,
}

impl Crate {
    pub fn print_to_cargo(&self) {
        if let Some(include_prefix) = &self.include_prefix {
            println!(
                "cargo:CXXBRIDGE_PREFIX={}",
                include_prefix.to_string_lossy(),
            );
        }
        if let Some(links) = &self.links {
            println!("cargo:CXXBRIDGE_LINKS={}", links.to_string_lossy());
        }
        for (i, exported_dir) in self.exported_header_dirs.iter().enumerate() {
            println!(
                "cargo:CXXBRIDGE_DIR{}={}",
                i,
                exported_dir.to_string_lossy(),
            );
        }
    }
}

pub fn direct_dependencies() -> Vec<Crate> {
    let mut crates: BTreeMap<String, Crate> = BTreeMap::new();

    // Only variables set from a build script of direct dependencies are
    // observable. That's exactly what we want! Your crate needs to declare a
    // direct dependency on the other crate in order to be able to #include its
    // headers.
    //
    // Also, they're only observable if the dependency's manifest contains a
    // `links` key. This is important because Cargo imposes no ordering on the
    // execution of build scripts without a `links` key. When exposing a
    // generated header for the current crate to #include, we need to be sure
    // the dependency's build script has already executed and emitted that
    // generated header.
    //
    // References:
    //   - https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key
    //   - https://doc.rust-lang.org/cargo/reference/build-script-examples.html#using-another-sys-crate
    for (k, v) in env::vars_os() {
        let mut k = k.to_string_lossy().into_owned();
        if !k.starts_with("DEP_") {
            continue;
        }

        if k.ends_with("_CXXBRIDGE_PREFIX") {
            k.truncate(k.len() - "_CXXBRIDGE_PREFIX".len());
            crates.entry(k).or_default().include_prefix = Some(PathBuf::from(v));
            continue;
        }

        if k.ends_with("_CXXBRIDGE_LINKS") {
            k.truncate(k.len() - "_CXXBRIDGE_LINKS".len());
            crates.entry(k).or_default().links = Some(v);
            continue;
        }

        let without_counter = k.trim_end_matches(|ch: char| ch.is_ascii_digit());
        let counter_len = k.len() - without_counter.len();
        if counter_len == 0 || !without_counter.ends_with("_CXXBRIDGE_DIR") {
            continue;
        }

        k.truncate(k.len() - counter_len - "_CXXBRIDGE_DIR".len());
        crates
            .entry(k)
            .or_default()
            .exported_header_dirs
            .push(PathBuf::from(v));
    }

    crates.into_iter().map(|entry| entry.1).collect()
}
<commit_msg>Preserve counter order of exported dirs<commit_after>use std::collections::BTreeMap;
use std::env;
use std::ffi::OsString;
use std::path::PathBuf;

#[derive(Default)]
pub struct Crate {
    pub include_prefix: Option<PathBuf>,
    pub links: Option<OsString>,
    pub exported_header_dirs: Vec<PathBuf>,
}

impl Crate {
    pub fn print_to_cargo(&self) {
        if let Some(include_prefix) = &self.include_prefix {
            println!(
                "cargo:CXXBRIDGE_PREFIX={}",
                include_prefix.to_string_lossy(),
            );
        }
        if let Some(links) = &self.links {
            println!("cargo:CXXBRIDGE_LINKS={}", links.to_string_lossy());
        }
        for (i, exported_dir) in self.exported_header_dirs.iter().enumerate() {
            println!(
                "cargo:CXXBRIDGE_DIR{}={}",
                i,
                exported_dir.to_string_lossy(),
            );
        }
    }
}

pub fn direct_dependencies() -> Vec<Crate> {
    let mut crates: BTreeMap<String, Crate> = BTreeMap::new();
    let mut exported_header_dirs: BTreeMap<String, Vec<(usize, PathBuf)>> = BTreeMap::new();

    // Only variables set from a build script of direct dependencies are
    // observable. That's exactly what we want! Your crate needs to declare a
    // direct dependency on the other crate in order to be able to #include its
    // headers.
    //
    // Also, they're only observable if the dependency's manifest contains a
    // `links` key. This is important because Cargo imposes no ordering on the
    // execution of build scripts without a `links` key. When exposing a
    // generated header for the current crate to #include, we need to be sure
    // the dependency's build script has already executed and emitted that
    // generated header.
    //
    // References:
    //   - https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key
    //   - https://doc.rust-lang.org/cargo/reference/build-script-examples.html#using-another-sys-crate
    for (k, v) in env::vars_os() {
        let mut k = k.to_string_lossy().into_owned();
        if !k.starts_with("DEP_") {
            continue;
        }

        if k.ends_with("_CXXBRIDGE_PREFIX") {
            k.truncate(k.len() - "_CXXBRIDGE_PREFIX".len());
            crates.entry(k).or_default().include_prefix = Some(PathBuf::from(v));
            continue;
        }

        if k.ends_with("_CXXBRIDGE_LINKS") {
            k.truncate(k.len() - "_CXXBRIDGE_LINKS".len());
            crates.entry(k).or_default().links = Some(v);
            continue;
        }

        let without_counter = k.trim_end_matches(|ch: char| ch.is_ascii_digit());
        let counter_len = k.len() - without_counter.len();
        if counter_len == 0 || !without_counter.ends_with("_CXXBRIDGE_DIR") {
            continue;
        }

        let sort_key = k[k.len() - counter_len..]
            .parse::<usize>()
            .unwrap_or(usize::MAX);
        k.truncate(k.len() - counter_len - "_CXXBRIDGE_DIR".len());
        exported_header_dirs
            .entry(k)
            .or_default()
            .push((sort_key, PathBuf::from(v)));
    }

    for (k, mut dirs) in exported_header_dirs {
        dirs.sort_by_key(|(sort_key, _dir)| *sort_key);
        crates
            .entry(k)
            .or_default()
            .exported_header_dirs
            .extend(dirs.into_iter().map(|(_sort_key, dir)| dir));
    }

    crates.into_iter().map(|entry| entry.1).collect()
}
<|endoftext|>


<commit_before>use mem_map::*;
use device::Device;

#[allow(dead_code)] // TODO - remove when the rendering is written
const COLOUR_MAP: [u32; 4] = [0xff7e8429, 0xff527a4b, 0xff315d4b, 0xff29473e];
const WIDTH: usize = 160;
const HEIGHT: usize = 144;

pub struct Gpu {
    vram: Box<[u8]>, // VRAM - mapped to 0x8000 - 0x9FFF
    obj_attr_table: Box<[u8]>, // Obj/Sprite Attribute Table (OAM) - mapped to 0xfe00 - 0xfea0

    lcd_control: LcdControlReg, // 0xff40 - LCDC
    lcdc_status: LcdcStatusReg, // 0xff41 - STAT
    scy: u8, // 0xff42 - SCY scroll background Y position
    scx: u8, // 0xff43 - SCX scroll background X position
    ly: u8, // 0xff44 - LY scanline being sent to LCD driver, reset on write
    lyc: u8, // 0xff45 - LYC if equal to LY STAT.coincident is set
    dma_transfer: u8, // 0xff46 - when set initiates DMA transfer (~160 microseconds)
    bg_palette_data: PaletteDataReg, // 0xff47 - BG & Window palette data
    obj0_palette_data: PaletteDataReg, // 0xff48 OBJ0 palette data
    obj1_palette_data: PaletteDataReg, // 0xff49 OBJ1 palette data
    wy: u8, // 0xff4a - window Y position
    wx: u8, // 0xff4b - window X position, offset from screen coords by 7
}

impl Gpu {
    pub fn new() -> Self {
        Gpu {
            vram: vec![0; VRAM_LENGTH as usize].into_boxed_slice(),
            obj_attr_table: vec![0; OAM_LENGTH as usize].into_boxed_slice(),

            lcd_control: LcdControlReg::default(),
            lcdc_status: LcdcStatusReg::default(),
            scy: 0,
            scx: 0,
            ly: 0,
            lyc: 0,
            wy: 0,
            wx: 0,
            bg_palette_data: PaletteDataReg::default(),
            obj0_palette_data: PaletteDataReg::default(),
            obj1_palette_data: PaletteDataReg::default(),
            dma_transfer: 0,
        }
    }

    pub fn read_vram(&self, addr: u16) -> u8 {
        self.vram[addr as usize]
    }

    pub fn write_vram(&mut self, addr: u16, val: u8) {
        self.vram[addr as usize] = val;
    }

    pub fn read_oam(&self, addr: u16) -> u8 {
        self.obj_attr_table[addr as usize]
    }

    pub fn write_oam(&mut self, addr: u16, val: u8) {
        self.obj_attr_table[addr as usize] = val;
    }

    pub fn read_reg(&self, addr: u16) -> u8 {
        match addr {
            0xff40 => self.lcd_control.clone().into(),
            0xff41 => self.lcdc_status.clone().into(),
            0xff42 => self.scy,
            0xff43 => self.scx,
            0xff44 => self.ly,
            0xff45 => self.lyc,
            0xff46 => self.dma_transfer,
            0xff47 => self.bg_palette_data.clone().into(),
            0xff48 => self.obj0_palette_data.clone().into(),
            0xff49 => self.obj1_palette_data.clone().into(),
            0xff4a => self.wy,
            0xff4b => self.wx,
            _ => panic!("Read from non-gpu register in gpu {:04x}", addr),
        }
    }

    pub fn write_reg(&mut self, addr: u16, val: u8) {
        match addr {
            0xff40 => self.lcd_control = val.into(),
            0xff41 => self.lcdc_status = val.into(),
            0xff42 => self.scy = val,
            0xff43 => self.scx = val,
            0xff44 => self.ly = val,
            0xff45 => self.lyc = val,
            0xff46 => self.dma_transfer = val,
            0xff47 => self.bg_palette_data = val.into(),
            0xff48 => self.obj0_palette_data = val.into(),
            0xff49 => self.obj1_palette_data = val.into(),
            0xff4a => self.wy = val,
            0xff4b => self.wx = val,
            _ => {
                panic!("Write to non-gpu register in gpu {:04x} = {:02x}",
                       addr,
                       val)
            }
        }
    }

    pub fn step(&mut self, _: u16, device: &mut Device) {
        let buffer: Vec<u32> = vec![0xff7e8429; WIDTH * HEIGHT];

        device.set_frame_buffer(&buffer);
    }

    pub fn get_width(&self) -> usize {
        WIDTH
    }

    pub fn get_height(&self) -> usize {
        HEIGHT
    }
}

#[derive(Default, Clone)]
pub struct LcdControlReg {
    bg_window_display: bool,
    obj_display: bool,
    obj_size: bool,
    bg_tile_map_display: bool,
    bg_win_tile_data: bool,
    window_display: bool,
    win_tile_map_display: bool,
    lcd_control_op: bool,
}

impl LcdControlReg {
    fn default() -> Self {
        // bg_window_display | bg_win_tile_data | lcd_control_op
        0x91.into()
    }
}

impl From<u8> for LcdControlReg {
    fn from(val: u8) -> Self {
        LcdControlReg {
            bg_window_display: val & (1 << 0) != 0,
            obj_display: val & (1 << 1) != 0,
            obj_size: val & (1 << 2) != 0,
            bg_tile_map_display: val & (1 << 3) != 0,
            bg_win_tile_data: val & (1 << 4) != 0,
            window_display: val & (1 << 5) != 0,
            win_tile_map_display: val & (1 << 6) != 0,
            lcd_control_op: val & (1 << 7) != 0,
        }
    }
}

impl Into<u8> for LcdControlReg {
    fn into(self) -> u8 {
        let mut ret: u8 = 0;
        if self.bg_window_display {
            ret |= 1 << 0;
        }
        if self.obj_display {
            ret |= 1 << 1;
        }
        if self.obj_size {
            ret |= 1 << 2;
        }
        if self.bg_tile_map_display {
            ret |= 1 << 3;
        }
        if self.bg_win_tile_data {
            ret |= 1 << 4;
        }
        if self.window_display {
            ret |= 1 << 5;
        }
        if self.win_tile_map_display {
            ret |= 1 << 6;
        }
        if self.lcd_control_op {
            ret |= 1 << 7;
        }
        ret
    }
}

#[derive(Default, Clone)]
pub struct LcdcStatusReg {
    coincidence_interrupt_enable: bool,
    oam_interrupt_enable: bool,
    vblank_interrupt_enable: bool,
    hblank_interrupt_enable: bool,
    coincidence_flag: bool,
    mode_flag: u8,
}

impl From<u8> for LcdcStatusReg {
    fn from(val: u8) -> Self {
        LcdcStatusReg {
            coincidence_interrupt_enable: val & (1 << 6) != 0,
            oam_interrupt_enable: val & (1 << 5) != 0,
            vblank_interrupt_enable: val & (1 << 4) != 0,
            hblank_interrupt_enable: val & (1 << 3) != 0,
            coincidence_flag: val & (1 << 2) != 0,
            mode_flag: val & 0x3,
        }
    }
}

impl Into<u8> for LcdcStatusReg {
    fn into(self) -> u8 {
        let mut ret = self.mode_flag;

        if self.coincidence_interrupt_enable {
            ret |= 1 << 6;
        }
        if self.oam_interrupt_enable {
            ret |= 1 << 5;
        }
        if self.vblank_interrupt_enable {
            ret |= 1 << 4;
        }
        if self.hblank_interrupt_enable {
            ret |= 1 << 3;
        }
        if self.coincidence_flag {
            ret |= 1 << 2;
        }
        ret
    }
}

#[derive(Default, Clone)]
pub struct PaletteDataReg {
    col0_shade: u8,
    col1_shade: u8,
    col2_shade: u8,
    col3_shade: u8,
}

impl From<u8> for PaletteDataReg {
    fn from(val: u8) -> Self {
        PaletteDataReg {
            col0_shade: val & 0x3,
            col1_shade: (val >> 2) & 0x3,
            col2_shade: (val >> 4) & 0x3,
            col3_shade: (val >> 6) & 0x3,
        }
    }
}

impl Into<u8> for PaletteDataReg {
    fn into(self) -> u8 {
        self.col0_shade | (self.col1_shade << 2) | (self.col2_shade << 4) | (self.col3_shade << 6)
    }
}
<commit_msg>more preparation for rendering<commit_after>use mem_map::*;
use device::Device;

#[allow(dead_code)] // TODO - remove when the rendering is written
const COLOUR_MAP: [u32; 4] = [0xff7e8429, 0xff527a4b, 0xff315d4b, 0xff29473e];
const WIDTH: usize = 160;
const HEIGHT: usize = 144;

pub struct Gpu {
    vram: Box<[u8]>, // VRAM - mapped to 0x8000 - 0x9FFF
    obj_attr_table: Box<[u8]>, // Obj/Sprite Attribute Table (OAM) - mapped to 0xfe00 - 0xfea0
    frame_buffer: Box<[u32]>,

    lcd_control: LcdControlReg, // 0xff40 - LCDC
    lcdc_status: LcdcStatusReg, // 0xff41 - STAT
    scy: u8, // 0xff42 - SCY scroll background Y position
    scx: u8, // 0xff43 - SCX scroll background X position
    ly: u8, // 0xff44 - LY scanline being sent to LCD driver, reset on write
    lyc: u8, // 0xff45 - LYC if equal to LY STAT.coincident is set
    dma_transfer: u8, // 0xff46 - when set initiates DMA transfer (~160 microseconds)
    bg_palette_data: PaletteDataReg, // 0xff47 - BG & Window palette data
    obj0_palette_data: PaletteDataReg, // 0xff48 OBJ0 palette data
    obj1_palette_data: PaletteDataReg, // 0xff49 OBJ1 palette data
    wy: u8, // 0xff4a - window Y position
    wx: u8, // 0xff4b - window X position, offset from screen coords by 7

    cycles: u16,
}

impl Gpu {
    pub fn new() -> Self {
        Gpu {
            vram: vec![0; VRAM_LENGTH as usize].into_boxed_slice(),
            obj_attr_table: vec![0; OAM_LENGTH as usize].into_boxed_slice(),
            frame_buffer: vec![COLOUR_MAP[0]; WIDTH * HEIGHT].into_boxed_slice(),

            lcd_control: LcdControlReg::default(),
            lcdc_status: LcdcStatusReg::default(),
            scy: 0,
            scx: 0,
            ly: 0,
            lyc: 0,
            wy: 0,
            wx: 0,
            bg_palette_data: PaletteDataReg::default(),
            obj0_palette_data: PaletteDataReg::default(),
            obj1_palette_data: PaletteDataReg::default(),
            dma_transfer: 0,

            cycles: 0,
        }
    }

    pub fn read_vram(&self, addr: u16) -> u8 {
        self.vram[addr as usize]
    }

    pub fn write_vram(&mut self, addr: u16, val: u8) {
        self.vram[addr as usize] = val;
    }

    pub fn read_oam(&self, addr: u16) -> u8 {
        self.obj_attr_table[addr as usize]
    }

    pub fn write_oam(&mut self, addr: u16, val: u8) {
        self.obj_attr_table[addr as usize] = val;
    }

    pub fn read_reg(&self, addr: u16) -> u8 {
        match addr {
            0xff40 => self.lcd_control.clone().into(),
            0xff41 => self.lcdc_status.clone().into(),
            0xff42 => self.scy,
            0xff43 => self.scx,
            0xff44 => self.ly,
            0xff45 => self.lyc,
            0xff46 => self.dma_transfer,
            0xff47 => self.bg_palette_data.clone().into(),
            0xff48 => self.obj0_palette_data.clone().into(),
            0xff49 => self.obj1_palette_data.clone().into(),
            0xff4a => self.wy,
            0xff4b => self.wx,
            _ => panic!("Read from non-gpu register in gpu {:04x}", addr),
        }
    }

    pub fn write_reg(&mut self, addr: u16, val: u8) {
        match addr {
            0xff40 => self.lcd_control = val.into(),
            0xff41 => self.lcdc_status = val.into(),
            0xff42 => self.scy = val,
            0xff43 => self.scx = val,
            0xff44 => self.ly = val,
            0xff45 => self.lyc = val,
            0xff46 => self.dma_transfer = val,
            0xff47 => self.bg_palette_data = val.into(),
            0xff48 => self.obj0_palette_data = val.into(),
            0xff49 => self.obj1_palette_data = val.into(),
            0xff4a => self.wy = val,
            0xff4b => self.wx = val,
            _ => {
                panic!("Write to non-gpu register in gpu {:04x} = {:02x}",
                       addr,
                       val)
            }
        }
    }

    pub fn step(&mut self, cycles: u16, device: &mut Device) {
        if !self.lcd_control.lcd_control_op {
            return
        }

        for _ in 0..cycles {
            self.inner_step(device);
        }
    }

    pub fn get_width(&self) -> usize {
        WIDTH
    }

    pub fn get_height(&self) -> usize {
        HEIGHT
    }

    fn inner_step(&mut self, device: &mut Device) {
        self.cycles += 1;

        if self.lcdc_status.mode == 0 && self.cycles == 4 {
            if self.ly < 144 {
                self.lcdc_status.mode = 2;
            } else {
                self.lcdc_status.mode = 1;
                // TODO - trigger vblank

                device.set_frame_buffer(&self.frame_buffer);
            }
        } else if self.lcdc_status.mode == 0 && self.cycles == 456 {
            self.ly += 1;
            self.cycles = 0;
        } else if self.lcdc_status.mode == 1 {
            if self.cycles == 456 {
                self.cycles = 0;

                if self.ly == 0 {
                    self.lcdc_status.mode = 0;
                } else {
                    self.ly += 1;
                }
            } else if self.ly == 153 && self.cycles == 5 {
                self.ly = 0;
            }
        } else if self.lcdc_status.mode == 2 && self.cycles == 85 {
            self.lcdc_status.mode = 3;

            self.render_background();
        } else if self.lcdc_status.mode == 3 && self.cycles == 260 {
            // TODO - this mode should have variable length
            self.lcdc_status.mode = 0
        }
    }

    fn render_background(&mut self) {
    }
}

#[derive(Default, Clone)]
pub struct LcdControlReg {
    bg_window_display: bool,
    obj_display: bool,
    obj_size: bool,
    bg_tile_map_display: bool,
    bg_win_tile_data: bool,
    window_display: bool,
    win_tile_map_display: bool,
    lcd_control_op: bool,
}

impl LcdControlReg {
    fn default() -> Self {
        // bg_window_display | bg_win_tile_data | lcd_control_op
        0x91.into()
    }
}

impl From<u8> for LcdControlReg {
    fn from(val: u8) -> Self {
        LcdControlReg {
            bg_window_display: val & (1 << 0) != 0,
            obj_display: val & (1 << 1) != 0,
            obj_size: val & (1 << 2) != 0,
            bg_tile_map_display: val & (1 << 3) != 0,
            bg_win_tile_data: val & (1 << 4) != 0,
            window_display: val & (1 << 5) != 0,
            win_tile_map_display: val & (1 << 6) != 0,
            lcd_control_op: val & (1 << 7) != 0,
        }
    }
}

impl Into<u8> for LcdControlReg {
    fn into(self) -> u8 {
        let mut ret: u8 = 0;
        if self.bg_window_display {
            ret |= 1 << 0;
        }
        if self.obj_display {
            ret |= 1 << 1;
        }
        if self.obj_size {
            ret |= 1 << 2;
        }
        if self.bg_tile_map_display {
            ret |= 1 << 3;
        }
        if self.bg_win_tile_data {
            ret |= 1 << 4;
        }
        if self.window_display {
            ret |= 1 << 5;
        }
        if self.win_tile_map_display {
            ret |= 1 << 6;
        }
        if self.lcd_control_op {
            ret |= 1 << 7;
        }
        ret
    }
}

#[derive(Default, Clone)]
pub struct LcdcStatusReg {
    coincidence_interrupt_enable: bool,
    oam_interrupt_enable: bool,
    vblank_interrupt_enable: bool,
    hblank_interrupt_enable: bool,
    coincidence_flag: bool,
    mode: u8,
}

impl From<u8> for LcdcStatusReg {
    fn from(val: u8) -> Self {
        LcdcStatusReg {
            coincidence_interrupt_enable: val & (1 << 6) != 0,
            oam_interrupt_enable: val & (1 << 5) != 0,
            vblank_interrupt_enable: val & (1 << 4) != 0,
            hblank_interrupt_enable: val & (1 << 3) != 0,
            coincidence_flag: val & (1 << 2) != 0,
            mode: val & 0x3,
        }
    }
}

impl Into<u8> for LcdcStatusReg {
    fn into(self) -> u8 {
        let mut ret = self.mode;

        if self.coincidence_interrupt_enable {
            ret |= 1 << 6;
        }
        if self.oam_interrupt_enable {
            ret |= 1 << 5;
        }
        if self.vblank_interrupt_enable {
            ret |= 1 << 4;
        }
        if self.hblank_interrupt_enable {
            ret |= 1 << 3;
        }
        if self.coincidence_flag {
            ret |= 1 << 2;
        }
        ret
    }
}

#[derive(Default, Clone)]
pub struct PaletteDataReg {
    col0_shade: u8,
    col1_shade: u8,
    col2_shade: u8,
    col3_shade: u8,
}

impl From<u8> for PaletteDataReg {
    fn from(val: u8) -> Self {
        PaletteDataReg {
            col0_shade: val & 0x3,
            col1_shade: (val >> 2) & 0x3,
            col2_shade: (val >> 4) & 0x3,
            col3_shade: (val >> 6) & 0x3,
        }
    }
}

impl Into<u8> for PaletteDataReg {
    fn into(self) -> u8 {
        self.col0_shade | (self.col1_shade << 2) | (self.col2_shade << 4) | (self.col3_shade << 6)
    }
}
<|endoftext|>


<commit_before>// #![feature(scoped)]
// #![feature(collections)]

extern crate mmap;
extern crate time;
extern crate timely;
extern crate columnar;
extern crate dataflow_join;

extern crate docopt;
use docopt::Docopt;

use std::thread;

use dataflow_join::graph::{GraphTrait, GraphMMap};

use timely::progress::timestamp::RootTimestamp;
use timely::progress::scope::Scope;
use timely::progress::nested::Summary::Local;
use timely::example_static::*;
use timely::communication::*;
use timely::communication::pact::Exchange;

use timely::networking::initialize_networking;
use timely::networking::initialize_networking_from_file;

use timely::drain::DrainExt;

static USAGE: &'static str = "
Usage: pagerank <source> [options] [<arguments>...]

Options:
    -w <arg>, --workers <arg>    number of workers per process [default: 1]
    -p <arg>, --processid <arg>  identity of this process      [default: 0]
    -n <arg>, --processes <arg>  number of processes involved  [default: 1]
    -h <arg>, --hosts <arg>      list of host:port for workers
";

fn main () {
    let args = Docopt::new(USAGE).and_then(|dopt| dopt.parse()).unwrap_or_else(|e| e.exit());

    // let workers = if let Ok(threads) = args.get_str("<workers>").parse() { threads }
    //               else { panic!("invalid setting for workers: {}", args.get_str("<workers>")) };
    // println!("starting pagerank dataflow with {:?} worker{}", workers, if workers == 1 { "" } else { "s" });
    let source = args.get_str("<source>").to_owned();

    let workers: u64 = if let Ok(threads) = args.get_str("-w").parse() { threads }
                       else { panic!("invalid setting for --workers: {}", args.get_str("-t")) };
    let process_id: u64 = if let Ok(proc_id) = args.get_str("-p").parse() { proc_id }
                          else { panic!("invalid setting for --processid: {}", args.get_str("-p")) };
    let processes: u64 = if let Ok(processes) = args.get_str("-n").parse() { processes }
                         else { panic!("invalid setting for --processes: {}", args.get_str("-n")) };

    println!("Starting pagerank dataflow with");
    println!("\tworkers:\t{}", workers);
    println!("\tprocesses:\t{}", processes);
    println!("\tprocessid:\t{}", process_id);

    // vector holding communicators to use; one per local worker.
    if processes > 1 {
        println!("Initializing BinaryCommunicator");

        let hosts = args.get_str("-h");
        let communicators = if hosts != "" {
            initialize_networking_from_file(hosts, process_id, workers).ok().expect("error initializing networking")
        }
        else {
            let addresses = (0..processes).map(|index| format!("localhost:{}", 2101 + index).to_string()).collect();
            initialize_networking(addresses, process_id, workers).ok().expect("error initializing networking")
        };

        pagerank_multi(communicators, source);
    }
    else if workers > 1 {
        println!("Initializing ProcessCommunicator");
        pagerank_multi(ProcessCommunicator::new_vector(workers), source);
    }
    else {
        println!("Initializing ThreadCommunicator");
        pagerank_multi(vec![ThreadCommunicator], source);
    };
}

fn pagerank_multi<C>(communicators: Vec<C>, filename: String)
where C: Communicator+Send {
    let mut guards = Vec::new();
    let workers = communicators.len();
    for communicator in communicators.into_iter() {
        let filename = filename.clone();
        guards.push(thread::Builder::new().name(format!("timely worker {}", communicator.index()))
                                          .spawn(move || pagerank(communicator, filename, workers))
                                          .unwrap());
    }

    for guard in guards { guard.join().unwrap(); }
}

fn pagerank<C>(communicator: C, filename: String, workers: usize)
where C: Communicator {
    let index = communicator.index() as usize;
    let peers = communicator.peers() as usize;

    let mut root = GraphRoot::new(communicator);

    {   // new scope avoids long borrow on root
        let mut builder = root.new_subgraph();

        // establish the beginnings of a loop,
        // 20 iterations, each time around += 1.
        let (helper, stream) = builder.loop_variable::<(u32, f32)>(RootTimestamp::new(20), Local(1));

        let graph = GraphMMap::<u32>::new(&filename);

        let nodes = graph.nodes();

        let mut src = vec![1.0; 1 + (nodes / peers as usize)];  // local rank accumulation
        let mut dst = vec![0.0; nodes];                         // local rank accumulation

        let mut start = time::precise_time_s();

        // from feedback, place an operator that
        // aggregates and broadcasts ranks along edges.
        let ranks = stream.enable(builder).unary_notify(

            Exchange::new(|x: &(u32, f32)| x.0 as u64),     // 1. how data should be exchanged
            format!("PageRank"),                            // 2. a tasteful, descriptive name
            vec![RootTimestamp::new(0)],                    // 3. indicate an initial capability
            move |input, output, iterator| {                // 4. provide the operator logic

                while let Some((iter, _)) = iterator.next() {

                    // /---- should look familiar! ----\
                    for node in 0..src.len() {
                        src[node] = 0.15 + 0.85 * src[node];
                    }

                    let mut counter = 0u64;
                    for node in 0..src.len() {
                        let edges = graph.edges(index + peers * node);
                        let value = src[node] / edges.len() as f32;
                        for &b in edges {
                            dst[b as usize] += value;
                        }
                    }
                    // \------ end familiar part ------/

                    output.give_at(&iter, dst.drain_temp()
                                             .enumerate()
                                             .filter(|&(_,f)| f != 0.0)
                                             .map(|(u,f)| (u as u32, f)));

                    for _ in 0..graph.nodes() { dst.push(0.0); }

                    println!("iteration {:?}: {}s", iter, time::precise_time_s() - start);
                    start = time::precise_time_s();
                }

                while let Some((iter, data)) = input.pull() {
                    iterator.notify_at(&iter);
                    for (node, rank) in data.drain_temp() {
                        src[node as usize / peers] += rank;
                    }
                }
            }
        );

        let local_index = index as usize % workers;

        let mut acc = vec![0.0; 1 + (nodes / workers)];

        ranks
        // .unary_notify(
        //     Exchange::new(move |x: &(u32, f32)| (workers * (index / workers)) as u64 + (x.0 as u64 % workers as u64)),
        //     format!("Aggregation"),
        //     vec![],
        //     move |input, output, iterator| {
        //         while let Some((iter, data)) = input.pull() {
        //             iterator.notify_at(&iter);
        //             for (node, rank) in data.drain_temp() {
        //                 acc[node as usize / workers] += rank;
        //             }
        //         }
        //
        //         while let Some((item, _)) = iterator.next() {
        //
        //             output.give_at(&item, acc.drain_temp().enumerate().filter(|x| x.1 != 0.0)
        //                                      .map(|(u,f)| (((u * workers + local_index) as u32), f)));
        //
        //             for _ in 0..(nodes/workers) { acc.push(0.0); }
        //             assert!(acc.len() == nodes/workers);
        //         }
        //     }
        // )
        .connect_loop(helper);
    }

    while root.step() { }
}
<commit_msg>fixed that error<commit_after>// #![feature(scoped)]
// #![feature(collections)]

extern crate mmap;
extern crate time;
extern crate timely;
extern crate columnar;
extern crate dataflow_join;

extern crate docopt;
use docopt::Docopt;

use std::thread;

use dataflow_join::graph::{GraphTrait, GraphMMap};

use timely::progress::timestamp::RootTimestamp;
use timely::progress::scope::Scope;
use timely::progress::nested::Summary::Local;
use timely::example_static::*;
use timely::communication::*;
use timely::communication::pact::Exchange;

use timely::networking::initialize_networking;
use timely::networking::initialize_networking_from_file;

use timely::drain::DrainExt;

static USAGE: &'static str = "
Usage: pagerank <source> [options] [<arguments>...]

Options:
    -w <arg>, --workers <arg>    number of workers per process [default: 1]
    -p <arg>, --processid <arg>  identity of this process      [default: 0]
    -n <arg>, --processes <arg>  number of processes involved  [default: 1]
    -h <arg>, --hosts <arg>      list of host:port for workers
";

fn main () {
    let args = Docopt::new(USAGE).and_then(|dopt| dopt.parse()).unwrap_or_else(|e| e.exit());

    // let workers = if let Ok(threads) = args.get_str("<workers>").parse() { threads }
    //               else { panic!("invalid setting for workers: {}", args.get_str("<workers>")) };
    // println!("starting pagerank dataflow with {:?} worker{}", workers, if workers == 1 { "" } else { "s" });
    let source = args.get_str("<source>").to_owned();

    let workers: u64 = if let Ok(threads) = args.get_str("-w").parse() { threads }
                       else { panic!("invalid setting for --workers: {}", args.get_str("-t")) };
    let process_id: u64 = if let Ok(proc_id) = args.get_str("-p").parse() { proc_id }
                          else { panic!("invalid setting for --processid: {}", args.get_str("-p")) };
    let processes: u64 = if let Ok(processes) = args.get_str("-n").parse() { processes }
                         else { panic!("invalid setting for --processes: {}", args.get_str("-n")) };

    println!("Starting pagerank dataflow with");
    println!("\tworkers:\t{}", workers);
    println!("\tprocesses:\t{}", processes);
    println!("\tprocessid:\t{}", process_id);

    // vector holding communicators to use; one per local worker.
    if processes > 1 {
        println!("Initializing BinaryCommunicator");

        let hosts = args.get_str("-h");
        let communicators = if hosts != "" {
            initialize_networking_from_file(hosts, process_id, workers).ok().expect("error initializing networking")
        }
        else {
            let addresses = (0..processes).map(|index| format!("localhost:{}", 2101 + index).to_string()).collect();
            initialize_networking(addresses, process_id, workers).ok().expect("error initializing networking")
        };

        pagerank_multi(communicators, source);
    }
    else if workers > 1 {
        println!("Initializing ProcessCommunicator");
        pagerank_multi(ProcessCommunicator::new_vector(workers), source);
    }
    else {
        println!("Initializing ThreadCommunicator");
        pagerank_multi(vec![ThreadCommunicator], source);
    };
}

fn pagerank_multi<C>(communicators: Vec<C>, filename: String)
where C: Communicator+Send {
    let mut guards = Vec::new();
    let workers = communicators.len();
    for communicator in communicators.into_iter() {
        let filename = filename.clone();
        guards.push(thread::Builder::new().name(format!("timely worker {}", communicator.index()))
                                          .spawn(move || pagerank(communicator, filename, workers))
                                          .unwrap());
    }

    for guard in guards { guard.join().unwrap(); }
}

fn pagerank<C>(communicator: C, filename: String, workers: usize)
where C: Communicator {
    let index = communicator.index() as usize;
    let peers = communicator.peers() as usize;

    let mut root = GraphRoot::new(communicator);

    {   // new scope avoids long borrow on root
        let mut builder = root.new_subgraph();

        // establish the beginnings of a loop,
        // 20 iterations, each time around += 1.
        let (helper, stream) = builder.loop_variable::<(u32, f32)>(RootTimestamp::new(20), Local(1));

        let graph = GraphMMap::<u32>::new(&filename);

        let nodes = graph.nodes();

        let mut src = vec![1.0; 1 + (nodes / peers as usize)];  // local rank accumulation
        let mut dst = vec![0.0; nodes];                         // local rank accumulation

        let mut start = time::precise_time_s();

        // from feedback, place an operator that
        // aggregates and broadcasts ranks along edges.
        let ranks = stream.enable(builder).unary_notify(

            Exchange::new(|x: &(u32, f32)| x.0 as u64),     // 1. how data should be exchanged
            format!("PageRank"),                            // 2. a tasteful, descriptive name
            vec![RootTimestamp::new(0)],                    // 3. indicate an initial capability
            move |input, output, iterator| {                // 4. provide the operator logic

                while let Some((iter, _)) = iterator.next() {

                    // /---- should look familiar! ----\
                    for node in 0..src.len() {
                        src[node] = 0.15 + 0.85 * src[node];
                    }

                    let mut counter = 0u64;
                    for node in 0..src.len() {
                        let edges = graph.edges(index + peers * node);
                        let value = src[node] / edges.len() as f32;
                        for &b in edges {
                            dst[b as usize] += value;
                        }
                    }
                    // \------ end familiar part ------/

                    output.give_at(&iter, dst.drain_temp()
                                             .enumerate()
                                             .filter(|&(_,f)| f != 0.0)
                                             .map(|(u,f)| (u as u32, f)));

                    for _ in 0..(graph.nodes() + 1) { dst.push(0.0); }

                    println!("iteration {:?}: {}s", iter, time::precise_time_s() - start);
                    start = time::precise_time_s();
                }

                while let Some((iter, data)) = input.pull() {
                    iterator.notify_at(&iter);
                    for (node, rank) in data.drain_temp() {
                        src[node as usize / peers] += rank;
                    }
                }
            }
        );

        let local_index = index as usize % workers;

        let mut acc = vec![0.0; 1 + (nodes / workers)];

        ranks
        .unary_notify(
            Exchange::new(move |x: &(u32, f32)| (workers * (index / workers)) as u64 + (x.0 as u64 % workers as u64)),
            format!("Aggregation"),
            vec![],
            move |input, output, iterator| {
                while let Some((iter, data)) = input.pull() {
                    iterator.notify_at(&iter);
                    for (node, rank) in data.drain_temp() {
                        acc[node as usize / workers] += rank;
                    }
                }

                while let Some((item, _)) = iterator.next() {

                    output.give_at(&item, acc.drain_temp().enumerate().filter(|x| x.1 != 0.0)
                                             .map(|(u,f)| (((u * workers + local_index) as u32), f)));

                    for _ in 0..(1 + (nodes/workers)) { acc.push(0.0); }
                    assert!(acc.len() == nodes/workers);
                }
            }
        )
        .connect_loop(helper);
    }

    while root.step() { }
}
<|endoftext|>


<commit_before>use std::io::Cursor;

use juniper_rocket::{graphiql_source, GraphQLRequest, GraphQLResponse};
use rocket::http::ContentType;
use rocket::response::content::Html;
use rocket::{Response, Route};

use crate::database::DatabaseConnection;
use crate::graphql::{Database, Mutation, Query, Schema};

#[get("/graphiql")]
fn graphiql() -> Html<String> {
    graphiql_source("/graphiql")
}

fn execute_graphql_request<'a>(
    connection: DatabaseConnection,
    request: GraphQLRequest,
) -> Response<'a> {
    let context = Database::new(connection);
    let schema = Schema::new(Query, Mutation);
    let GraphQLResponse(status, json) = request.execute(&schema, &context);
    Response::build()
        .raw_header("Access-Control-Allow-Origin", "*")
        .raw_header("Access-Control-Allow-Methods", "OPTIONS, GET, POST")
        .raw_header("Access-Control-Allow-Headers", "Content-Type")
        .header(ContentType::new("application", "json"))
        .status(status)
        .sized_body(Cursor::new(json))
        .finalize()
}

#[options("/graphql")]
fn graphql_options_handler<'a>() -> Response<'a> {
    Response::build()
        .raw_header("Access-Control-Allow-Origin", "*")
        .raw_header("Access-Control-Allow-Methods", "OPTIONS, GET, POST")
        .raw_header("Access-Control-Allow-Headers", "Content-Type")
        .finalize()
}

#[get("/graphql?<request>")]
fn graphql_get_handler<'a>(
    connection: DatabaseConnection,
    request: GraphQLRequest,
) -> Response<'a> {
    execute_graphql_request(connection, request)
}

#[post("/graphql", data = "<request>")]
fn graphql_post_handler<'a>(
    connection: DatabaseConnection,
    request: GraphQLRequest,
) -> Response<'a> {
    execute_graphql_request(connection, request)
}

pub fn routes() -> Vec<Route> {
    routes![
        graphiql,
        graphql_options_handler,
        graphql_get_handler,
        graphql_post_handler
    ]
}
<commit_msg>Use correct path to GraphQL endpoint<commit_after>use std::io::Cursor;

use juniper_rocket::{graphiql_source, GraphQLRequest, GraphQLResponse};
use rocket::http::ContentType;
use rocket::response::content::Html;
use rocket::{Response, Route};

use crate::database::DatabaseConnection;
use crate::graphql::{Database, Mutation, Query, Schema};

#[get("/graphiql")]
fn graphiql() -> Html<String> {
    graphiql_source("/graphql")
}

fn execute_graphql_request<'a>(
    connection: DatabaseConnection,
    request: GraphQLRequest,
) -> Response<'a> {
    let context = Database::new(connection);
    let schema = Schema::new(Query, Mutation);
    let GraphQLResponse(status, json) = request.execute(&schema, &context);
    Response::build()
        .raw_header("Access-Control-Allow-Origin", "*")
        .raw_header("Access-Control-Allow-Methods", "OPTIONS, GET, POST")
        .raw_header("Access-Control-Allow-Headers", "Content-Type")
        .header(ContentType::new("application", "json"))
        .status(status)
        .sized_body(Cursor::new(json))
        .finalize()
}

#[options("/graphql")]
fn graphql_options_handler<'a>() -> Response<'a> {
    Response::build()
        .raw_header("Access-Control-Allow-Origin", "*")
        .raw_header("Access-Control-Allow-Methods", "OPTIONS, GET, POST")
        .raw_header("Access-Control-Allow-Headers", "Content-Type")
        .finalize()
}

#[get("/graphql?<request>")]
fn graphql_get_handler<'a>(
    connection: DatabaseConnection,
    request: GraphQLRequest,
) -> Response<'a> {
    execute_graphql_request(connection, request)
}

#[post("/graphql", data = "<request>")]
fn graphql_post_handler<'a>(
    connection: DatabaseConnection,
    request: GraphQLRequest,
) -> Response<'a> {
    execute_graphql_request(connection, request)
}

pub fn routes() -> Vec<Route> {
    routes![
        graphiql,
        graphql_options_handler,
        graphql_get_handler,
        graphql_post_handler
    ]
}
<|endoftext|>