<commit_before>use std::env;
use std::fs;
use std::io::prelude::*;
use std::path::Path;

use rustc_serialize::{Decodable, Decoder};

use git2::Config as GitConfig;

use term::color::BLACK;

use util::{GitRepo, HgRepo, CargoResult, human, ChainError, internal};
use util::{Config, paths};

use toml;

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum VersionControl { Git, Hg, NoVcs }

pub struct NewOptions<'a> {
    pub version_control: Option<VersionControl>,
    pub bin: bool,
    pub path: &'a str,
    pub name: Option<&'a str>,
}

impl Decodable for VersionControl {
    fn decode<D: Decoder>(d: &mut D) -> Result<VersionControl, D::Error> {
        Ok(match &try!(d.read_str())[..] {
            "git" => VersionControl::Git,
            "hg" => VersionControl::Hg,
            "none" => VersionControl::NoVcs,
            n => {
                let err = format!("could not decode '{}' as version control", n);
                return Err(d.error(&err));
            }
        })
    }
}

struct CargoNewConfig {
    name: Option<String>,
    email: Option<String>,
    version_control: Option<VersionControl>,
}

pub fn new(opts: NewOptions, config: &Config) -> CargoResult<()> {
    let path = config.cwd().join(opts.path);
    if fs::metadata(&path).is_ok() {
        bail!("destination `{}` already exists", path.display())
    }
    let name = match opts.name {
        Some(name) => name,
        None => {
            let dir_name = try!(path.file_name().and_then(|s| s.to_str()).chain_error(|| {
                human(&format!("cannot create a project with a non-unicode name: {:?}",
                               path.file_name().unwrap()))
            }));
            if opts.bin {
                dir_name
            } else {
                let new_name = strip_rust_affixes(dir_name);
                if new_name != dir_name {
                    let message = format!(
                        "note: package will be named `{}`; use --name to override",
                        new_name);
                    try!(config.shell().say(&message, BLACK));
                }
                new_name
            }
        }
    };
    for c in name.chars() {
        if c.is_alphanumeric() { continue }
        if c == '_' || c == '-' { continue }
        bail!("Invalid character `{}` in crate name: `{}`", c, name)
    }
    mk(config, &path, name, &opts).chain_error(|| {
        human(format!("Failed to create project `{}` at `{}`",
                      name, path.display()))
    })
}

fn strip_rust_affixes(name: &str) -> &str {
    for &prefix in &["rust-", "rust_", "rs-", "rs_"] {
        if name.starts_with(prefix) {
            return &name[prefix.len()..];
        }
    }
    for &suffix in &["-rust", "_rust", "-rs", "_rs"] {
        if name.ends_with(suffix) {
            return &name[..name.len()-suffix.len()];
        }
    }
    name
}

fn existing_vcs_repo(path: &Path, cwd: &Path) -> bool {
    GitRepo::discover(path, cwd).is_ok() || HgRepo::discover(path, cwd).is_ok()
}

fn mk(config: &Config, path: &Path, name: &str,
      opts: &NewOptions) -> CargoResult<()> {
    let cfg = try!(global_config(config));
    let mut ignore = "target\n".to_string();
    let in_existing_vcs_repo = existing_vcs_repo(path.parent().unwrap(), config.cwd());
    if !opts.bin {
        ignore.push_str("Cargo.lock\n");
    }

    let vcs = match (opts.version_control, cfg.version_control, in_existing_vcs_repo) {
        (None, None, false) => VersionControl::Git,
        (None, Some(option), false) => option,
        (Some(option), _, _) => option,
        (_, _, true) => VersionControl::NoVcs,
    };

    match vcs {
        VersionControl::Git => {
            try!(GitRepo::init(path, config.cwd()));
            try!(paths::write(&path.join(".gitignore"), ignore.as_bytes()));
        },
        VersionControl::Hg => {
            try!(HgRepo::init(path, config.cwd()));
            try!(paths::write(&path.join(".hgignore"), ignore.as_bytes()));
        },
        VersionControl::NoVcs => {
            try!(fs::create_dir(path));
        },
    };

    let (author_name, email) = try!(discover_author());
    // Hoo boy, sure glad we've got exhaustivenes checking behind us.
    let author = match (cfg.name, cfg.email, author_name, email) {
        (Some(name), Some(email), _, _) |
        (Some(name), None, _, Some(email)) |
        (None, Some(email), name, _) |
        (None, None, name, Some(email)) => format!("{} <{}>", name, email),
        (Some(name), None, _, None) |
        (None, None, name, None) => name,
    };

    try!(paths::write(&path.join("Cargo.toml"), format!(
r#"[package]
name = "{}"
version = "0.1.0"
authors = [{}]

[dependencies]
"#, name, toml::Value::String(author)).as_bytes()));

    try!(fs::create_dir(&path.join("src")));

    if opts.bin {
        try!(paths::write(&path.join("src/main.rs"), b"\
fn main() {
    println!(\"Hello, world!\");
}
"));
    } else {
        try!(paths::write(&path.join("src/lib.rs"), b"\
#[test]
fn it_works() {
}
"));
    }

    Ok(())
}

fn discover_author() -> CargoResult<(String, Option<String>)> {
    let git_config = GitConfig::open_default().ok();
    let git_config = git_config.as_ref();
    let name = git_config.and_then(|g| g.get_string("user.name").ok())
                         .map(|s| s.to_string())
                         .or_else(|| env::var("USER").ok())      // unix
                         .or_else(|| env::var("USERNAME").ok()); // windows
    let name = match name {
        Some(name) => name,
        None => {
            let username_var = if cfg!(windows) {"USERNAME"} else {"USER"};
            bail!("could not determine the current user, please set ${}",
                  username_var)
        }
    };
    let email = git_config.and_then(|g| g.get_string("user.email").ok())
                          .or_else(|| env::var("EMAIL").ok());

    let name = name.trim().to_string();
    let email = email.map(|s| s.trim().to_string());

    Ok((name, email))
}

fn global_config(config: &Config) -> CargoResult<CargoNewConfig> {
    let name = try!(config.get_string("cargo-new.name")).map(|s| s.0);
    let email = try!(config.get_string("cargo-new.email")).map(|s| s.0);
    let vcs = try!(config.get_string("cargo-new.vcs"));

    let vcs = match vcs.as_ref().map(|p| (&p.0[..], &p.1)) {
        Some(("git", _)) => Some(VersionControl::Git),
        Some(("hg", _)) => Some(VersionControl::Hg),
        Some(("none", _)) => Some(VersionControl::NoVcs),
        Some((s, p)) => {
            return Err(internal(format!("invalid configuration for key \
                                         `cargo-new.vcs`, unknown vcs `{}` \
                                         (found in {:?})", s, p)))
        }
        None => None
    };
    Ok(CargoNewConfig {
        name: name,
        email: email,
        version_control: vcs,
    })
}

#[cfg(test)]
mod tests {
    use super::strip_rust_affixes;

    #[test]
    fn affixes_stripped() {
        assert_eq!(strip_rust_affixes("rust-foo"), "foo");
        assert_eq!(strip_rust_affixes("foo-rs"), "foo");
        assert_eq!(strip_rust_affixes("rs_foo"), "foo");
        // Only one affix is stripped
        assert_eq!(strip_rust_affixes("rs-foo-rs"), "foo-rs");
        assert_eq!(strip_rust_affixes("foo-rs-rs"), "foo-rs");
        // It shouldn't touch the middle
        assert_eq!(strip_rust_affixes("some-rust-crate"), "some-rust-crate");
    }
}
<commit_msg>Auto merge of #2257 - nrc:lib-template, r=alexcrichton<commit_after>use std::env;
use std::fs;
use std::io::prelude::*;
use std::path::Path;

use rustc_serialize::{Decodable, Decoder};

use git2::Config as GitConfig;

use term::color::BLACK;

use util::{GitRepo, HgRepo, CargoResult, human, ChainError, internal};
use util::{Config, paths};

use toml;

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum VersionControl { Git, Hg, NoVcs }

pub struct NewOptions<'a> {
    pub version_control: Option<VersionControl>,
    pub bin: bool,
    pub path: &'a str,
    pub name: Option<&'a str>,
}

impl Decodable for VersionControl {
    fn decode<D: Decoder>(d: &mut D) -> Result<VersionControl, D::Error> {
        Ok(match &try!(d.read_str())[..] {
            "git" => VersionControl::Git,
            "hg" => VersionControl::Hg,
            "none" => VersionControl::NoVcs,
            n => {
                let err = format!("could not decode '{}' as version control", n);
                return Err(d.error(&err));
            }
        })
    }
}

struct CargoNewConfig {
    name: Option<String>,
    email: Option<String>,
    version_control: Option<VersionControl>,
}

pub fn new(opts: NewOptions, config: &Config) -> CargoResult<()> {
    let path = config.cwd().join(opts.path);
    if fs::metadata(&path).is_ok() {
        bail!("destination `{}` already exists", path.display())
    }
    let name = match opts.name {
        Some(name) => name,
        None => {
            let dir_name = try!(path.file_name().and_then(|s| s.to_str()).chain_error(|| {
                human(&format!("cannot create a project with a non-unicode name: {:?}",
                               path.file_name().unwrap()))
            }));
            if opts.bin {
                dir_name
            } else {
                let new_name = strip_rust_affixes(dir_name);
                if new_name != dir_name {
                    let message = format!(
                        "note: package will be named `{}`; use --name to override",
                        new_name);
                    try!(config.shell().say(&message, BLACK));
                }
                new_name
            }
        }
    };
    for c in name.chars() {
        if c.is_alphanumeric() { continue }
        if c == '_' || c == '-' { continue }
        bail!("Invalid character `{}` in crate name: `{}`", c, name)
    }
    mk(config, &path, name, &opts).chain_error(|| {
        human(format!("Failed to create project `{}` at `{}`",
                      name, path.display()))
    })
}

fn strip_rust_affixes(name: &str) -> &str {
    for &prefix in &["rust-", "rust_", "rs-", "rs_"] {
        if name.starts_with(prefix) {
            return &name[prefix.len()..];
        }
    }
    for &suffix in &["-rust", "_rust", "-rs", "_rs"] {
        if name.ends_with(suffix) {
            return &name[..name.len()-suffix.len()];
        }
    }
    name
}

fn existing_vcs_repo(path: &Path, cwd: &Path) -> bool {
    GitRepo::discover(path, cwd).is_ok() || HgRepo::discover(path, cwd).is_ok()
}

fn mk(config: &Config, path: &Path, name: &str,
      opts: &NewOptions) -> CargoResult<()> {
    let cfg = try!(global_config(config));
    let mut ignore = "target\n".to_string();
    let in_existing_vcs_repo = existing_vcs_repo(path.parent().unwrap(), config.cwd());
    if !opts.bin {
        ignore.push_str("Cargo.lock\n");
    }

    let vcs = match (opts.version_control, cfg.version_control, in_existing_vcs_repo) {
        (None, None, false) => VersionControl::Git,
        (None, Some(option), false) => option,
        (Some(option), _, _) => option,
        (_, _, true) => VersionControl::NoVcs,
    };

    match vcs {
        VersionControl::Git => {
            try!(GitRepo::init(path, config.cwd()));
            try!(paths::write(&path.join(".gitignore"), ignore.as_bytes()));
        },
        VersionControl::Hg => {
            try!(HgRepo::init(path, config.cwd()));
            try!(paths::write(&path.join(".hgignore"), ignore.as_bytes()));
        },
        VersionControl::NoVcs => {
            try!(fs::create_dir(path));
        },
    };

    let (author_name, email) = try!(discover_author());
    // Hoo boy, sure glad we've got exhaustivenes checking behind us.
    let author = match (cfg.name, cfg.email, author_name, email) {
        (Some(name), Some(email), _, _) |
        (Some(name), None, _, Some(email)) |
        (None, Some(email), name, _) |
        (None, None, name, Some(email)) => format!("{} <{}>", name, email),
        (Some(name), None, _, None) |
        (None, None, name, None) => name,
    };

    try!(paths::write(&path.join("Cargo.toml"), format!(
r#"[package]
name = "{}"
version = "0.1.0"
authors = [{}]

[dependencies]
"#, name, toml::Value::String(author)).as_bytes()));

    try!(fs::create_dir(&path.join("src")));

    if opts.bin {
        try!(paths::write(&path.join("src/main.rs"), b"\
fn main() {
    println!(\"Hello, world!\");
}
"));
    } else {
        try!(paths::write(&path.join("src/lib.rs"), b"\
#[cfg(test)]
mod test {
    #[test]
    fn it_works() {
    }
}
"));
    }

    Ok(())
}

fn discover_author() -> CargoResult<(String, Option<String>)> {
    let git_config = GitConfig::open_default().ok();
    let git_config = git_config.as_ref();
    let name = git_config.and_then(|g| g.get_string("user.name").ok())
                         .map(|s| s.to_string())
                         .or_else(|| env::var("USER").ok())      // unix
                         .or_else(|| env::var("USERNAME").ok()); // windows
    let name = match name {
        Some(name) => name,
        None => {
            let username_var = if cfg!(windows) {"USERNAME"} else {"USER"};
            bail!("could not determine the current user, please set ${}",
                  username_var)
        }
    };
    let email = git_config.and_then(|g| g.get_string("user.email").ok())
                          .or_else(|| env::var("EMAIL").ok());

    let name = name.trim().to_string();
    let email = email.map(|s| s.trim().to_string());

    Ok((name, email))
}

fn global_config(config: &Config) -> CargoResult<CargoNewConfig> {
    let name = try!(config.get_string("cargo-new.name")).map(|s| s.0);
    let email = try!(config.get_string("cargo-new.email")).map(|s| s.0);
    let vcs = try!(config.get_string("cargo-new.vcs"));

    let vcs = match vcs.as_ref().map(|p| (&p.0[..], &p.1)) {
        Some(("git", _)) => Some(VersionControl::Git),
        Some(("hg", _)) => Some(VersionControl::Hg),
        Some(("none", _)) => Some(VersionControl::NoVcs),
        Some((s, p)) => {
            return Err(internal(format!("invalid configuration for key \
                                         `cargo-new.vcs`, unknown vcs `{}` \
                                         (found in {:?})", s, p)))
        }
        None => None
    };
    Ok(CargoNewConfig {
        name: name,
        email: email,
        version_control: vcs,
    })
}

#[cfg(test)]
mod tests {
    use super::strip_rust_affixes;

    #[test]
    fn affixes_stripped() {
        assert_eq!(strip_rust_affixes("rust-foo"), "foo");
        assert_eq!(strip_rust_affixes("foo-rs"), "foo");
        assert_eq!(strip_rust_affixes("rs_foo"), "foo");
        // Only one affix is stripped
        assert_eq!(strip_rust_affixes("rs-foo-rs"), "foo-rs");
        assert_eq!(strip_rust_affixes("foo-rs-rs"), "foo-rs");
        // It shouldn't touch the middle
        assert_eq!(strip_rust_affixes("some-rust-crate"), "some-rust-crate");
    }
}
<|endoftext|>


<commit_before>use std::fs::{File, create_dir_all, set_permissions, Permissions};
use std::io::Write;
use std::os::unix::fs::PermissionsExt;
use std::path::Path;

use config::builders::Builder;
use config::builders::Builder as B;
use config::builders::Source as S;
use config::read_config;
use container::util::{clean_dir, copy_dir};

use super::super::path_util::ToRelative;
use super::commands::ubuntu;
use super::commands::alpine;
use super::commands::generic;
use super::commands::pip;
use super::commands::npm;
use super::commands::vcs;
use super::commands::download;
use super::tarcmd;
use version::short_version;
use builder::distrib::{DistroBox};
use builder::guard::Guard;
use builder::error::StepError;

pub trait BuildCommand {
    fn build(&self, ctx: &mut Guard, build: bool) -> Result<(), StepError>;
}

impl BuildCommand for Builder {
    fn build(&self, guard: &mut Guard, build: bool)
        -> Result<(), StepError>
    {
        use builder::error::StepError::*;
        match self {
            &B::Install(ref pkgs) => {
                guard.ctx.packages.extend(pkgs.clone().into_iter());
                for i in pkgs.iter() {
                    guard.ctx.build_deps.remove(i);
                }
                if build {
                    try!(guard.distro.install(&mut guard.ctx, pkgs));
                }
            }
            &B::BuildDeps(ref pkgs) => {
                for i in pkgs.iter() {
                    if !guard.ctx.packages.contains(i) {
                        guard.ctx.build_deps.insert(i.clone());
                    }
                }
                if build {
                    try!(guard.distro.install(&mut guard.ctx, pkgs));
                }
            }
            &B::Container(ref name) => {
                let cont = guard.ctx.config.containers.get(name)
                    .expect("Subcontainer not found");  // TODO
                for b in cont.setup.iter() {
                    try!(b.build(guard, false)
                        .map_err(|e| SubStep(b.clone(), Box::new(e))));
                }
                if build {
                    let version = try!(short_version(&cont, &guard.ctx.config)
                        .map_err(|(s, e)| format!("step {}: {}", s, e)));
                    let path = Path::new("/vagga/base/.roots")
                        .join(format!("{}.{}", name, version)).join("root");
                    try_msg!(copy_dir(&path, &Path::new("/vagga/root")),
                        "Error copying dir {p:?}: {err}", p=path);
                }
            }
            &B::SubConfig(ref sconfig) => {
                let path = match sconfig.source {
                    S::Container(ref container) => {
                        let cont = guard.ctx.config.containers.get(container)
                            .expect("Subcontainer not found");  // TODO
                        let version = try!(short_version(&cont, &guard.ctx.config)
                            .map_err(|(s, e)| format!("step {}: {}", s, e)));
                        Path::new("/vagga/base/.roots")
                            .join(format!("{}.{}", container, version))
                            .join("root").join(&sconfig.path)
                    }
                    S::Git(ref _git) => {
                        unimplemented!();
                    }
                    S::Directory => {
                        Path::new("/work").join(&sconfig.path)
                    }
                };
                let subcfg = try!(read_config(&path));
                let cont = subcfg.containers.get(&sconfig.container)
                    .expect("Subcontainer not found");  // TODO
                for b in cont.setup.iter() {
                    try!(b.build(guard, build)
                        .map_err(|e| SubStep(b.clone(), Box::new(e))));
                }
            }
            &B::Text(ref files) => {
                if build {
                    for (path, text) in files.iter() {
                        let realpath = Path::new("/vagga/root")
                            .join(path.rel());
                        try!(File::create(&realpath)
                            .and_then(|mut f| f.write_all(text.as_bytes()))
                            .map_err(|e| format!("Can't create file: {}", e)));
                        try!(set_permissions(&realpath,
                            Permissions::from_mode(0o755))
                            .map_err(|e| format!("Can't chmod file: {}", e)));
                    }
                }
            }
            &B::Ubuntu(ref codename) => {
                try!(ubuntu::configure_simple(guard, codename));
                if build {
                    try!(guard.distro.bootstrap(&mut guard.ctx));
                }
            }
            &B::UbuntuRelease(ref release_info) => {
                try!(ubuntu::configure(guard, release_info));
                if build {
                    try!(guard.distro.bootstrap(&mut guard.ctx));
                }
            }
            &B::UbuntuRepo(ref repo) => {
                if build {
                    let ref mut ctx = guard.ctx;
                    try!(guard.distro.specific(|u: &mut ubuntu::Ubuntu| {
                        try!(u.add_debian_repo(ctx, repo));
                        Ok(())
                    }));
                }
            }
            &B::UbuntuPPA(ref name) => {
                if build {
                    let ref mut ctx = guard.ctx;
                    try!(guard.distro.specific(|u: &mut ubuntu::Ubuntu| {
                        u.add_ubuntu_ppa(ctx, name)
                    }));
                }
            }
            &B::AptTrust(ref key) => {
                if build {
                    let ref mut ctx = guard.ctx;
                    try!(guard.distro.specific(|u: &mut ubuntu::Ubuntu| {
                        u.add_apt_key(ctx, key)
                    }));
                }
            }
            &B::UbuntuUniverse => {
                let ref mut ctx = guard.ctx;
                try!(guard.distro.specific(|u: &mut ubuntu::Ubuntu| {
                    try!(u.enable_universe());
                    if build {
                        try!(u.add_universe(ctx));
                    }
                    Ok(())
                }));
            }
            &B::Sh(ref text) => {
                if build {
                    try!(generic::run_command(&mut guard.ctx,
                        &["/bin/sh".to_string(),
                          "-exc".to_string(),
                          text.to_string()]));
                }
            }
            &B::Cmd(ref cmd) => {
                if build {
                    try!(generic::run_command(&mut guard.ctx, &cmd));
                }
            }
            &B::Env(ref pairs) => {
                for (k, v) in pairs.iter() {
                    guard.ctx.environ.insert(k.clone(), v.clone());
                }
            }
            &B::Remove(ref path) => {
                let fpath = Path::new("/vagga/root").join(path.rel());
                try!(clean_dir(&fpath, true));
                guard.ctx.add_remove_dir(&path);
            }
            &B::EmptyDir(ref path) => {
                try!(clean_dir(path, false));
                guard.ctx.add_empty_dir(&path);
            }
            &B::EnsureDir(ref path) => {
                let fpath = Path::new("/vagga/root").join(path.rel());
                try!(create_dir_all(&fpath)
                    .map_err(|e| format!("Error creating dir: {}", e)));
                try!(set_permissions(&fpath, Permissions::from_mode(0o755))
                    .map_err(|e| format!("Error setting permissions: {}", e)));
                guard.ctx.add_ensure_dir(path);
            }
            &B::CacheDirs(ref pairs) => {
                for (k, v) in pairs.iter() {
                    try!(guard.ctx.add_cache_dir(k, v.clone()));
                }
            }
            &B::Depends(_) => {
            }
            &B::Git(ref git) => {
                if build {
                    try!(vcs::git_command(&mut guard.ctx, git));
                }
            }
            &B::GitInstall(ref git) => {
                if build {
                    try!(vcs::git_install(&mut guard.ctx, git));
                }
            }
            &B::Tar(ref tar) => {
                if build {
                    try!(tarcmd::tar_command(&mut guard.ctx, tar));
                }
            }
            &B::TarInstall(ref tar_inst) => {
                if build {
                    try!(tarcmd::tar_install(&mut guard.ctx, tar_inst));
                }
            }
            &B::Download(ref dlinfo) => {
                if build {
                    try!(download::download(&mut guard.ctx, dlinfo));
                }
            }
            &B::Alpine(ref version) => {
                try!(alpine::configure(&mut guard.distro, &mut guard.ctx,
                    version));
                if build {
                    try!(guard.distro.bootstrap(&mut guard.ctx));
                }
            }
            &B::PipConfig(ref pip_settings) => {
                guard.ctx.pip_settings = pip_settings.clone();
            }
            &B::Py2Install(ref pkgs) => {
                try!(pip::configure(&mut guard.ctx));
                if build {
                    try!(pip::pip_install(&mut guard.distro, &mut guard.ctx,
                        2, pkgs));
                }
            }
            &B::Py3Install(ref pkgs) => {
                try!(pip::configure(&mut guard.ctx));
                if build {
                    try!(pip::pip_install(&mut guard.distro, &mut guard.ctx,
                        3, pkgs));
                }
            }
            &B::Py2Requirements(ref fname) => {
                try!(pip::configure(&mut guard.ctx));
                if build {
                    try!(pip::pip_requirements(&mut guard.distro,
                        &mut guard.ctx, 2, fname));
                }
            }
            &B::Py3Requirements(ref fname) => {
                try!(pip::configure(&mut guard.ctx));
                if build {
                    try!(pip::pip_requirements(&mut guard.distro,
                        &mut guard.ctx, 3, fname));
                }
            }
            &B::PyFreeze(_) => unimplemented!(),
            &B::NpmInstall(ref pkgs) => {
                try!(guard.distro.npm_configure(&mut guard.ctx));
                if build {
                    try!(npm::npm_install(&mut guard.distro, &mut guard.ctx,
                        pkgs));
                }
            }
        }
        if build {
            try!(guard.ctx.timelog.mark(format_args!("Step: {:?}", self))
                .map_err(|e| format!("Can't write timelog: {}", e)));
        }
        Ok(())
    }
}
<commit_msg>Allow to `!Remove` files (fixes #125)<commit_after>use std::fs::{File, create_dir_all, set_permissions, Permissions, remove_file};
use std::io::Write;
use std::os::unix::fs::PermissionsExt;
use std::path::Path;

use config::builders::Builder;
use config::builders::Builder as B;
use config::builders::Source as S;
use config::read_config;
use container::util::{clean_dir, copy_dir};

use super::super::path_util::ToRelative;
use super::commands::ubuntu;
use super::commands::alpine;
use super::commands::generic;
use super::commands::pip;
use super::commands::npm;
use super::commands::vcs;
use super::commands::download;
use super::tarcmd;
use version::short_version;
use builder::distrib::{DistroBox};
use builder::guard::Guard;
use builder::error::StepError;
use path_util::PathExt;

pub trait BuildCommand {
    fn build(&self, ctx: &mut Guard, build: bool) -> Result<(), StepError>;
}

impl BuildCommand for Builder {
    fn build(&self, guard: &mut Guard, build: bool)
        -> Result<(), StepError>
    {
        use builder::error::StepError::*;
        match self {
            &B::Install(ref pkgs) => {
                guard.ctx.packages.extend(pkgs.clone().into_iter());
                for i in pkgs.iter() {
                    guard.ctx.build_deps.remove(i);
                }
                if build {
                    try!(guard.distro.install(&mut guard.ctx, pkgs));
                }
            }
            &B::BuildDeps(ref pkgs) => {
                for i in pkgs.iter() {
                    if !guard.ctx.packages.contains(i) {
                        guard.ctx.build_deps.insert(i.clone());
                    }
                }
                if build {
                    try!(guard.distro.install(&mut guard.ctx, pkgs));
                }
            }
            &B::Container(ref name) => {
                let cont = guard.ctx.config.containers.get(name)
                    .expect("Subcontainer not found");  // TODO
                for b in cont.setup.iter() {
                    try!(b.build(guard, false)
                        .map_err(|e| SubStep(b.clone(), Box::new(e))));
                }
                if build {
                    let version = try!(short_version(&cont, &guard.ctx.config)
                        .map_err(|(s, e)| format!("step {}: {}", s, e)));
                    let path = Path::new("/vagga/base/.roots")
                        .join(format!("{}.{}", name, version)).join("root");
                    try_msg!(copy_dir(&path, &Path::new("/vagga/root")),
                        "Error copying dir {p:?}: {err}", p=path);
                }
            }
            &B::SubConfig(ref sconfig) => {
                let path = match sconfig.source {
                    S::Container(ref container) => {
                        let cont = guard.ctx.config.containers.get(container)
                            .expect("Subcontainer not found");  // TODO
                        let version = try!(short_version(&cont, &guard.ctx.config)
                            .map_err(|(s, e)| format!("step {}: {}", s, e)));
                        Path::new("/vagga/base/.roots")
                            .join(format!("{}.{}", container, version))
                            .join("root").join(&sconfig.path)
                    }
                    S::Git(ref _git) => {
                        unimplemented!();
                    }
                    S::Directory => {
                        Path::new("/work").join(&sconfig.path)
                    }
                };
                let subcfg = try!(read_config(&path));
                let cont = subcfg.containers.get(&sconfig.container)
                    .expect("Subcontainer not found");  // TODO
                for b in cont.setup.iter() {
                    try!(b.build(guard, build)
                        .map_err(|e| SubStep(b.clone(), Box::new(e))));
                }
            }
            &B::Text(ref files) => {
                if build {
                    for (path, text) in files.iter() {
                        let realpath = Path::new("/vagga/root")
                            .join(path.rel());
                        try!(File::create(&realpath)
                            .and_then(|mut f| f.write_all(text.as_bytes()))
                            .map_err(|e| format!("Can't create file: {}", e)));
                        try!(set_permissions(&realpath,
                            Permissions::from_mode(0o755))
                            .map_err(|e| format!("Can't chmod file: {}", e)));
                    }
                }
            }
            &B::Ubuntu(ref codename) => {
                try!(ubuntu::configure_simple(guard, codename));
                if build {
                    try!(guard.distro.bootstrap(&mut guard.ctx));
                }
            }
            &B::UbuntuRelease(ref release_info) => {
                try!(ubuntu::configure(guard, release_info));
                if build {
                    try!(guard.distro.bootstrap(&mut guard.ctx));
                }
            }
            &B::UbuntuRepo(ref repo) => {
                if build {
                    let ref mut ctx = guard.ctx;
                    try!(guard.distro.specific(|u: &mut ubuntu::Ubuntu| {
                        try!(u.add_debian_repo(ctx, repo));
                        Ok(())
                    }));
                }
            }
            &B::UbuntuPPA(ref name) => {
                if build {
                    let ref mut ctx = guard.ctx;
                    try!(guard.distro.specific(|u: &mut ubuntu::Ubuntu| {
                        u.add_ubuntu_ppa(ctx, name)
                    }));
                }
            }
            &B::AptTrust(ref key) => {
                if build {
                    let ref mut ctx = guard.ctx;
                    try!(guard.distro.specific(|u: &mut ubuntu::Ubuntu| {
                        u.add_apt_key(ctx, key)
                    }));
                }
            }
            &B::UbuntuUniverse => {
                let ref mut ctx = guard.ctx;
                try!(guard.distro.specific(|u: &mut ubuntu::Ubuntu| {
                    try!(u.enable_universe());
                    if build {
                        try!(u.add_universe(ctx));
                    }
                    Ok(())
                }));
            }
            &B::Sh(ref text) => {
                if build {
                    try!(generic::run_command(&mut guard.ctx,
                        &["/bin/sh".to_string(),
                          "-exc".to_string(),
                          text.to_string()]));
                }
            }
            &B::Cmd(ref cmd) => {
                if build {
                    try!(generic::run_command(&mut guard.ctx, &cmd));
                }
            }
            &B::Env(ref pairs) => {
                for (k, v) in pairs.iter() {
                    guard.ctx.environ.insert(k.clone(), v.clone());
                }
            }
            &B::Remove(ref path) => {
                let fpath = Path::new("/vagga/root").join(path.rel());
                if fpath.is_dir() {
                    try!(clean_dir(&fpath, true));
                } else if fpath.exists() {
                    try!(remove_file(&fpath)
                        .map_err(|e| format!("Error removing file {:?}: {}",
                                             &fpath, e)));
                }
                guard.ctx.add_remove_dir(&path);
            }
            &B::EmptyDir(ref path) => {
                try!(clean_dir(path, false));
                guard.ctx.add_empty_dir(&path);
            }
            &B::EnsureDir(ref path) => {
                let fpath = Path::new("/vagga/root").join(path.rel());
                try!(create_dir_all(&fpath)
                    .map_err(|e| format!("Error creating dir: {}", e)));
                try!(set_permissions(&fpath, Permissions::from_mode(0o755))
                    .map_err(|e| format!("Error setting permissions: {}", e)));
                guard.ctx.add_ensure_dir(path);
            }
            &B::CacheDirs(ref pairs) => {
                for (k, v) in pairs.iter() {
                    try!(guard.ctx.add_cache_dir(k, v.clone()));
                }
            }
            &B::Depends(_) => {
            }
            &B::Git(ref git) => {
                if build {
                    try!(vcs::git_command(&mut guard.ctx, git));
                }
            }
            &B::GitInstall(ref git) => {
                if build {
                    try!(vcs::git_install(&mut guard.ctx, git));
                }
            }
            &B::Tar(ref tar) => {
                if build {
                    try!(tarcmd::tar_command(&mut guard.ctx, tar));
                }
            }
            &B::TarInstall(ref tar_inst) => {
                if build {
                    try!(tarcmd::tar_install(&mut guard.ctx, tar_inst));
                }
            }
            &B::Download(ref dlinfo) => {
                if build {
                    try!(download::download(&mut guard.ctx, dlinfo));
                }
            }
            &B::Alpine(ref version) => {
                try!(alpine::configure(&mut guard.distro, &mut guard.ctx,
                    version));
                if build {
                    try!(guard.distro.bootstrap(&mut guard.ctx));
                }
            }
            &B::PipConfig(ref pip_settings) => {
                guard.ctx.pip_settings = pip_settings.clone();
            }
            &B::Py2Install(ref pkgs) => {
                try!(pip::configure(&mut guard.ctx));
                if build {
                    try!(pip::pip_install(&mut guard.distro, &mut guard.ctx,
                        2, pkgs));
                }
            }
            &B::Py3Install(ref pkgs) => {
                try!(pip::configure(&mut guard.ctx));
                if build {
                    try!(pip::pip_install(&mut guard.distro, &mut guard.ctx,
                        3, pkgs));
                }
            }
            &B::Py2Requirements(ref fname) => {
                try!(pip::configure(&mut guard.ctx));
                if build {
                    try!(pip::pip_requirements(&mut guard.distro,
                        &mut guard.ctx, 2, fname));
                }
            }
            &B::Py3Requirements(ref fname) => {
                try!(pip::configure(&mut guard.ctx));
                if build {
                    try!(pip::pip_requirements(&mut guard.distro,
                        &mut guard.ctx, 3, fname));
                }
            }
            &B::PyFreeze(_) => unimplemented!(),
            &B::NpmInstall(ref pkgs) => {
                try!(guard.distro.npm_configure(&mut guard.ctx));
                if build {
                    try!(npm::npm_install(&mut guard.distro, &mut guard.ctx,
                        pkgs));
                }
            }
        }
        if build {
            try!(guard.ctx.timelog.mark(format_args!("Step: {:?}", self))
                .map_err(|e| format!("Can't write timelog: {}", e)));
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>import layers::{ARGB32Format, ContainerLayerKind, Image, ImageLayerKind, RGB24Format};
import scene::Scene;

import geom::matrix::{Matrix4, ortho};
import opengles::gl2::{ARRAY_BUFFER, COLOR_BUFFER_BIT, COMPILE_STATUS};
import opengles::gl2::{FRAGMENT_SHADER, LINEAR, LINK_STATUS, NEAREST, NO_ERROR, REPEAT, RGB, RGBA};
import opengles::gl2::{STATIC_DRAW, TEXTURE_2D, TEXTURE_MAG_FILTER, TEXTURE_MIN_FILTER};
import opengles::gl2::{TEXTURE_WRAP_S, TEXTURE_WRAP_T};
import opengles::gl2::{TRIANGLE_STRIP, UNSIGNED_BYTE, VERTEX_SHADER, GLclampf};
import opengles::gl2::{GLenum, GLint, GLsizei, GLuint, attach_shader, bind_buffer, bind_texture};
import opengles::gl2::{buffer_data, create_program, clear, clear_color};
import opengles::gl2::{compile_shader, create_shader, draw_arrays, enable};
import opengles::gl2::{enable_vertex_attrib_array, gen_buffers, gen_textures};
import opengles::gl2::{get_attrib_location, get_error, get_program_iv};
import opengles::gl2::{get_shader_info_log, get_shader_iv};
import opengles::gl2::{get_uniform_location, link_program, shader_source, tex_image_2d};
import opengles::gl2::{tex_parameter_i, uniform_1i, uniform_matrix_4fv, use_program};
import opengles::gl2::{vertex_attrib_pointer_f32, viewport};

import io::println;
import libc::c_int;
import str::bytes;

fn FRAGMENT_SHADER_SOURCE() -> str {
    "
        #ifdef GLES2
            precision mediump float;
        #endif

        varying vec2 vTextureCoord;

        uniform sampler2D uSampler;

        void main(void) {
            gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
        }
    "
}

fn VERTEX_SHADER_SOURCE() -> str {
    "
        attribute vec3 aVertexPosition;
        attribute vec2 aTextureCoord;

        uniform mat4 uMVMatrix;
        uniform mat4 uPMatrix;

        varying vec2 vTextureCoord;

        void main(void) {
            gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
            vTextureCoord = aTextureCoord;
        }
    "
}

fn load_shader(source_string: str, shader_type: GLenum) -> GLuint {
    let shader_id = create_shader(shader_type);
    shader_source(shader_id, [ bytes(source_string) ]/~);
    compile_shader(shader_id);

    if get_error() != NO_ERROR {
        println(#fmt("error: %d", get_error() as int));
        fail "failed to compile shader";
    }

    if get_shader_iv(shader_id, COMPILE_STATUS) == (0 as GLint) {
        println(#fmt("shader info log: %s", get_shader_info_log(shader_id)));
        fail "failed to compile shader";
    }

    ret shader_id;
}

class RenderContext {
    let program: GLuint;
    let vertex_position_attr: c_int;
    let texture_coord_attr: c_int;
    let modelview_uniform: c_int;
    let projection_uniform: c_int;
    let sampler_uniform: c_int;
    let vertex_buffer: GLuint;
    let texture_coord_buffer: GLuint;

    new(program: GLuint) {
        self.program = program;
        self.vertex_position_attr = get_attrib_location(program, "aVertexPosition");
        self.texture_coord_attr = get_attrib_location(program, "aTextureCoord");
        self.modelview_uniform = get_uniform_location(program, "uMVMatrix");
        self.projection_uniform = get_uniform_location(program, "uPMatrix");
        self.sampler_uniform = get_uniform_location(program, "uSampler");

        let (vertex_buffer, texture_coord_buffer) = init_buffers();
        self.vertex_buffer = vertex_buffer;
        self.texture_coord_buffer = texture_coord_buffer;

        enable_vertex_attrib_array(self.vertex_position_attr as GLuint);
        enable_vertex_attrib_array(self.texture_coord_attr as GLuint);
    }
}

fn init_render_context() -> RenderContext {
    let vertex_shader = load_shader(VERTEX_SHADER_SOURCE(), VERTEX_SHADER);
    let fragment_shader = load_shader(FRAGMENT_SHADER_SOURCE(), FRAGMENT_SHADER);

    let program = create_program();
    attach_shader(program, vertex_shader);
    attach_shader(program, fragment_shader);
    link_program(program);

    if get_program_iv(program, LINK_STATUS) == (0 as GLint) {
        fail "failed to initialize program";
    }

    use_program(program);

    enable(TEXTURE_2D);

    ret RenderContext(program);
}

fn init_buffers() -> (GLuint, GLuint) {
    let triangle_vertex_buffer = gen_buffers(1 as GLsizei)[0];
    bind_buffer(ARRAY_BUFFER, triangle_vertex_buffer);

    let (_0, _1) = (0.0f32, 1.0f32);
    let vertices = [
        _0, _0, _0,
        _0, _1, _0,
        _1, _0, _0,
        _1, _1, _0
    ]/~;

    buffer_data(ARRAY_BUFFER, vertices, STATIC_DRAW);

    let texture_coord_buffer = gen_buffers(1 as GLsizei)[0];
    bind_buffer(ARRAY_BUFFER, texture_coord_buffer);

    let vertices = [
        _0, _0,
        _0, _1,
        _1, _0,
        _1, _1
    ]/~;

    buffer_data(ARRAY_BUFFER, vertices, STATIC_DRAW);

    ret (triangle_vertex_buffer, texture_coord_buffer);
}

fn create_texture_for_image_if_necessary(image: @Image) {
    alt image.texture {
        none {}
        some(_) { ret; /* Nothing to do. */ }
    }

    #debug("making texture");

    let texture = gen_textures(1 as GLsizei)[0];
    bind_texture(TEXTURE_2D, texture);

    tex_parameter_i(TEXTURE_2D, TEXTURE_WRAP_S, REPEAT as GLint);
    tex_parameter_i(TEXTURE_2D, TEXTURE_WRAP_T, REPEAT as GLint);
    tex_parameter_i(TEXTURE_2D, TEXTURE_MAG_FILTER, LINEAR as GLint);
    tex_parameter_i(TEXTURE_2D, TEXTURE_MIN_FILTER, LINEAR as GLint);

    alt image.format {
        RGB24Format {
            tex_image_2d(TEXTURE_2D, 0 as GLint, RGB as GLint, image.width as GLsizei,
                         image.height as GLsizei, 0 as GLint, RGB, UNSIGNED_BYTE, image.data);
        }
        ARGB32Format {
            tex_image_2d(TEXTURE_2D, 0 as GLint, RGBA as GLint, image.width as GLsizei,
                         image.height as GLsizei, 0 as GLint, RGBA, UNSIGNED_BYTE, image.data);
        }
    }

    image.texture = some(texture);
}

fn render_scene(render_context: RenderContext, &scene: Scene) {
    // Set the viewport.
    viewport(0 as GLint, 0 as GLint, scene.size.width as GLsizei, scene.size.height as GLsizei);

    let mut image_layer;
    alt scene.root {
        ContainerLayerKind(*) {
            fail "container layers unsupported";
        }
        ImageLayerKind(embedded_image_layer) {
            image_layer = embedded_image_layer;
        }
    }

    create_texture_for_image_if_necessary(image_layer.image);

    let _0 = 0.0f32;
    let _1 = 1.0f32;
    let _2 = 2.0f32;

    clear_color(0.0f32, 0.0f32, 1.0f32, 1.0f32);
    clear(COLOR_BUFFER_BIT);

    uniform_matrix_4fv(render_context.modelview_uniform, false,
                       image_layer.common.transform.to_array());

    let modelview_matrix = ortho(0.0f32, copy scene.size.width, copy scene.size.height, 0.0f32,
                                 -10.0f32, 10.0f32);
    uniform_matrix_4fv(render_context.projection_uniform, false, modelview_matrix.to_array());

    // FIXME: option.get should be pure
    let mut texture;
    alt image_layer.image.texture {
        none { fail; }
        some(tex) {
            texture = tex;
        }
    }
    bind_texture(TEXTURE_2D, texture);

    uniform_1i(render_context.sampler_uniform, 0);

    bind_buffer(ARRAY_BUFFER, render_context.vertex_buffer);
    vertex_attrib_pointer_f32(render_context.vertex_position_attr as GLuint, 3 as GLint, false,
                              0 as GLsizei, 0 as GLuint);

    bind_buffer(ARRAY_BUFFER, render_context.texture_coord_buffer);
    vertex_attrib_pointer_f32(render_context.texture_coord_attr as GLuint, 2 as GLint, false,
                              0 as GLsizei, 0 as GLuint);

    draw_arrays(TRIANGLE_STRIP, 0 as GLint, 4 as GLint);
}

<commit_msg>Switch to BGRA<commit_after>import layers::{ARGB32Format, ContainerLayerKind, Image, ImageLayerKind, RGB24Format};
import scene::Scene;

import geom::matrix::{Matrix4, ortho};
import opengles::gl2::{ARRAY_BUFFER, COLOR_BUFFER_BIT, COMPILE_STATUS};
import opengles::gl2::{FRAGMENT_SHADER, LINEAR, LINK_STATUS, NEAREST, NO_ERROR, REPEAT, RGB, RGBA};
import opengles::gl2::{STATIC_DRAW, TEXTURE_2D, TEXTURE_MAG_FILTER, TEXTURE_MIN_FILTER};
import opengles::gl2::{TEXTURE_WRAP_S, TEXTURE_WRAP_T};
import opengles::gl2::{TRIANGLE_STRIP, UNSIGNED_BYTE, VERTEX_SHADER, GLclampf};
import opengles::gl2::{GLenum, GLint, GLsizei, GLuint, attach_shader, bind_buffer, bind_texture};
import opengles::gl2::{buffer_data, create_program, clear, clear_color};
import opengles::gl2::{compile_shader, create_shader, draw_arrays, enable};
import opengles::gl2::{enable_vertex_attrib_array, gen_buffers, gen_textures};
import opengles::gl2::{get_attrib_location, get_error, get_program_iv};
import opengles::gl2::{get_shader_info_log, get_shader_iv};
import opengles::gl2::{get_uniform_location, link_program, shader_source, tex_image_2d};
import opengles::gl2::{tex_parameter_i, uniform_1i, uniform_matrix_4fv, use_program};
import opengles::gl2::{vertex_attrib_pointer_f32, viewport};

import io::println;
import libc::c_int;
import str::bytes;

fn FRAGMENT_SHADER_SOURCE() -> str {
    "
        #ifdef GLES2
            precision mediump float;
        #endif

        varying vec2 vTextureCoord;

        uniform sampler2D uSampler;

        void main(void) {
            gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
        }
    "
}

fn VERTEX_SHADER_SOURCE() -> str {
    "
        attribute vec3 aVertexPosition;
        attribute vec2 aTextureCoord;

        uniform mat4 uMVMatrix;
        uniform mat4 uPMatrix;

        varying vec2 vTextureCoord;

        void main(void) {
            gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
            vTextureCoord = aTextureCoord;
        }
    "
}

fn load_shader(source_string: str, shader_type: GLenum) -> GLuint {
    let shader_id = create_shader(shader_type);
    shader_source(shader_id, [ bytes(source_string) ]/~);
    compile_shader(shader_id);

    if get_error() != NO_ERROR {
        println(#fmt("error: %d", get_error() as int));
        fail "failed to compile shader";
    }

    if get_shader_iv(shader_id, COMPILE_STATUS) == (0 as GLint) {
        println(#fmt("shader info log: %s", get_shader_info_log(shader_id)));
        fail "failed to compile shader";
    }

    ret shader_id;
}

class RenderContext {
    let program: GLuint;
    let vertex_position_attr: c_int;
    let texture_coord_attr: c_int;
    let modelview_uniform: c_int;
    let projection_uniform: c_int;
    let sampler_uniform: c_int;
    let vertex_buffer: GLuint;
    let texture_coord_buffer: GLuint;

    new(program: GLuint) {
        self.program = program;
        self.vertex_position_attr = get_attrib_location(program, "aVertexPosition");
        self.texture_coord_attr = get_attrib_location(program, "aTextureCoord");
        self.modelview_uniform = get_uniform_location(program, "uMVMatrix");
        self.projection_uniform = get_uniform_location(program, "uPMatrix");
        self.sampler_uniform = get_uniform_location(program, "uSampler");

        let (vertex_buffer, texture_coord_buffer) = init_buffers();
        self.vertex_buffer = vertex_buffer;
        self.texture_coord_buffer = texture_coord_buffer;

        enable_vertex_attrib_array(self.vertex_position_attr as GLuint);
        enable_vertex_attrib_array(self.texture_coord_attr as GLuint);
    }
}

fn init_render_context() -> RenderContext {
    let vertex_shader = load_shader(VERTEX_SHADER_SOURCE(), VERTEX_SHADER);
    let fragment_shader = load_shader(FRAGMENT_SHADER_SOURCE(), FRAGMENT_SHADER);

    let program = create_program();
    attach_shader(program, vertex_shader);
    attach_shader(program, fragment_shader);
    link_program(program);

    if get_program_iv(program, LINK_STATUS) == (0 as GLint) {
        fail "failed to initialize program";
    }

    use_program(program);

    enable(TEXTURE_2D);

    ret RenderContext(program);
}

fn init_buffers() -> (GLuint, GLuint) {
    let triangle_vertex_buffer = gen_buffers(1 as GLsizei)[0];
    bind_buffer(ARRAY_BUFFER, triangle_vertex_buffer);

    let (_0, _1) = (0.0f32, 1.0f32);
    let vertices = [
        _0, _0, _0,
        _0, _1, _0,
        _1, _0, _0,
        _1, _1, _0
    ]/~;

    buffer_data(ARRAY_BUFFER, vertices, STATIC_DRAW);

    let texture_coord_buffer = gen_buffers(1 as GLsizei)[0];
    bind_buffer(ARRAY_BUFFER, texture_coord_buffer);

    let vertices = [
        _0, _0,
        _0, _1,
        _1, _0,
        _1, _1
    ]/~;

    buffer_data(ARRAY_BUFFER, vertices, STATIC_DRAW);

    ret (triangle_vertex_buffer, texture_coord_buffer);
}

fn create_texture_for_image_if_necessary(image: @Image) {
    alt image.texture {
        none {}
        some(_) { ret; /* Nothing to do. */ }
    }

    #debug("making texture");

    let texture = gen_textures(1 as GLsizei)[0];
    bind_texture(TEXTURE_2D, texture);

    tex_parameter_i(TEXTURE_2D, TEXTURE_WRAP_S, REPEAT as GLint);
    tex_parameter_i(TEXTURE_2D, TEXTURE_WRAP_T, REPEAT as GLint);
    tex_parameter_i(TEXTURE_2D, TEXTURE_MAG_FILTER, LINEAR as GLint);
    tex_parameter_i(TEXTURE_2D, TEXTURE_MIN_FILTER, LINEAR as GLint);

    alt image.format {
        RGB24Format {
            tex_image_2d(TEXTURE_2D, 0 as GLint, RGB as GLint, image.width as GLsizei,
                         image.height as GLsizei, 0 as GLint, RGB, UNSIGNED_BYTE, image.data);
        }
        ARGB32Format {
            tex_image_2d(TEXTURE_2D, 0 as GLint, RGBA as GLint, image.width as GLsizei,
                         image.height as GLsizei, 0 as GLint, BGRA, UNSIGNED_BYTE, image.data);
        }
    }

    image.texture = some(texture);
}

fn render_scene(render_context: RenderContext, &scene: Scene) {
    // Set the viewport.
    viewport(0 as GLint, 0 as GLint, scene.size.width as GLsizei, scene.size.height as GLsizei);

    let mut image_layer;
    alt scene.root {
        ContainerLayerKind(*) {
            fail "container layers unsupported";
        }
        ImageLayerKind(embedded_image_layer) {
            image_layer = embedded_image_layer;
        }
    }

    create_texture_for_image_if_necessary(image_layer.image);

    let _0 = 0.0f32;
    let _1 = 1.0f32;
    let _2 = 2.0f32;

    clear_color(0.0f32, 0.0f32, 1.0f32, 1.0f32);
    clear(COLOR_BUFFER_BIT);

    uniform_matrix_4fv(render_context.modelview_uniform, false,
                       image_layer.common.transform.to_array());

    let modelview_matrix = ortho(0.0f32, copy scene.size.width, copy scene.size.height, 0.0f32,
                                 -10.0f32, 10.0f32);
    uniform_matrix_4fv(render_context.projection_uniform, false, modelview_matrix.to_array());

    // FIXME: option.get should be pure
    let mut texture;
    alt image_layer.image.texture {
        none { fail; }
        some(tex) {
            texture = tex;
        }
    }
    bind_texture(TEXTURE_2D, texture);

    uniform_1i(render_context.sampler_uniform, 0);

    bind_buffer(ARRAY_BUFFER, render_context.vertex_buffer);
    vertex_attrib_pointer_f32(render_context.vertex_position_attr as GLuint, 3 as GLint, false,
                              0 as GLsizei, 0 as GLuint);

    bind_buffer(ARRAY_BUFFER, render_context.texture_coord_buffer);
    vertex_attrib_pointer_f32(render_context.texture_coord_attr as GLuint, 2 as GLint, false,
                              0 as GLsizei, 0 as GLuint);

    draw_arrays(TRIANGLE_STRIP, 0 as GLint, 4 as GLint);
}

<|endoftext|>


<commit_before>/* Sample swap sort program in Rust.
   Tested to compile with rust-0.6-f1ddb8d.
*/
extern crate extra;
extern crate benchmark;

use benchmark::Benchmark;

fn swap_sort<T:Ord+Clone>(arr: ~[T]) -> ~[T] {
    let mut left = 0;
    let mut right: uint;
    let mut result = arr.clone();
    let max = result.len();

    while left < max {
        right = left + 1;
        while right < max {
            if result[right] < result[left] {
                // swap the two values
                //vec::swap(result, left, right);
                result.swap(left, right);
            }
            right += 1;
        }

        left += 1;
    }

    return result;
}

fn main() {
    let mut bench = Benchmark::new();
    bench.run(swap_sort);
}
<commit_msg>Remove exern crate extra<commit_after>/* Sample swap sort program in Rust.
   Tested to compile with rust-0.6-f1ddb8d.
*/
extern crate benchmark;

use benchmark::Benchmark;

fn swap_sort<T:Ord+Clone>(arr: ~[T]) -> ~[T] {
    let mut left = 0;
    let mut right: uint;
    let mut result = arr.clone();
    let max = result.len();

    while left < max {
        right = left + 1;
        while right < max {
            if result[right] < result[left] {
                // swap the two values
                //vec::swap(result, left, right);
                result.swap(left, right);
            }
            right += 1;
        }

        left += 1;
    }

    return result;
}

fn main() {
    let mut bench = Benchmark::new();
    bench.run(swap_sort);
}
<|endoftext|>


<commit_before>
import syntax::ast;
import ast::method;
import ast::item;
import ast::item_fn;
import ast::_fn;
import ast::obj_field;
import ast::_obj;
import ast::stmt;
import ast::ident;
import ast::fn_ident;
import ast::node_id;
import ast::def_id;
import ast::local_def;
import ast::ty_param;
import ast::crate;
import ast::return;
import ast::noreturn;
import ast::expr;
import syntax::visit;
import syntax::codemap::span;
import middle::ty::type_is_nil;
import middle::ty::ret_ty_of_fn;
import tstate::ann::ts_ann;
import tstate::ann::empty_poststate;
import tstate::ann::true_precond;
import tstate::ann::true_postcond;
import tstate::ann::false_postcond;
import tstate::ann::precond;
import tstate::ann::postcond;
import tstate::ann::poststate;
import tstate::ann::prestate;
import tstate::ann::implies;
import tstate::ann::ann_precond;
import tstate::ann::ann_prestate;
import std::option;
import std::option::t;
import std::option::some;
import std::option::none;
import aux::*;
import syntax::print::pprust::ty_to_str;
import util::common::log_stmt_err;
import bitvectors::*;
import annotate::annotate_crate;
import collect_locals::mk_f_to_fn_info;
import pre_post_conditions::fn_pre_post;
import states::find_pre_post_state_fn;

fn check_unused_vars(fcx: &fn_ctxt) {

    // FIXME: could be more efficient
    for c: norm_constraint in constraints(fcx) {
        alt c.c.node {
          ninit(id, v) {
            if !vec_contains(fcx.enclosing.used_vars, id) {
                fcx.ccx.tcx.sess.span_warn(c.c.span, "Unused variable " + v);
            }
          }
          _ {/* ignore pred constraints */ }
        }
    }
}

fn check_states_expr(e: &@expr, fcx: &fn_ctxt, v: &visit::vt<fn_ctxt>) {
    visit::visit_expr(e, fcx, v);

    let prec: precond = expr_precond(fcx.ccx, e);
    let pres: prestate = expr_prestate(fcx.ccx, e);

    /*
    log_err("check_states_expr:");
      util::common::log_expr_err(*e);
      log_err("prec = ");
      log_tritv_err(fcx, prec);
      log_err("pres = ");
      log_tritv_err(fcx, pres);
    */

    if !implies(pres, prec) {
        let s = "";
        let diff = first_difference_string(fcx, prec, pres);
        s +=
            "Unsatisfied precondition constraint (for example, " + diff +
                ") for expression:\n";
        s += syntax::print::pprust::expr_to_str(e);
        s += "\nPrecondition:\n";
        s += tritv_to_str(fcx, prec);
        s += "\nPrestate:\n";
        s += tritv_to_str(fcx, pres);
        fcx.ccx.tcx.sess.span_fatal(e.span, s);
    }
}

fn check_states_stmt(s: &@stmt, fcx: &fn_ctxt, v: &visit::vt<fn_ctxt>) {
    visit::visit_stmt(s, fcx, v);

    let a = stmt_to_ann(fcx.ccx, *s);
    let prec: precond = ann_precond(a);
    let pres: prestate = ann_prestate(a);

    /*
      log_err("check_states_stmt:");
      log_stmt_err(*s);
      log_err("prec = ");
      log_tritv_err(fcx, prec);
      log_err("pres = ");
      log_tritv_err(fcx, pres);
    */

    if !implies(pres, prec) {
        let ss = "";
        let diff = first_difference_string(fcx, prec, pres);
        ss +=
            "Unsatisfied precondition constraint (for example, " + diff +
                ") for statement:\n";
        ss += syntax::print::pprust::stmt_to_str(*s);
        ss += "\nPrecondition:\n";
        ss += tritv_to_str(fcx, prec);
        ss += "\nPrestate: \n";
        ss += tritv_to_str(fcx, pres);
        fcx.ccx.tcx.sess.span_fatal(s.span, ss);
    }
}

fn check_states_against_conditions(fcx: &fn_ctxt, f: &_fn,
                                   tps: &[ast::ty_param], id: node_id,
                                   sp: &span, i: &fn_ident) {
    /* Postorder traversal instead of pre is important
       because we want the smallest possible erroneous statement
       or expression. */

    let visitor = visit::default_visitor::<fn_ctxt>();

    visitor =
        @{visit_stmt: check_states_stmt,
          visit_expr: check_states_expr,
          visit_fn: do_nothing with *visitor};
    visit::visit_fn(f, tps, sp, i, id, fcx, visit::mk_vt(visitor));

    /* Check that the return value is initialized */
    let post = aux::block_poststate(fcx.ccx, f.body);
    if f.proto == ast::proto_fn &&
        !promises(fcx, post, fcx.enclosing.i_return) &&
        !type_is_nil(fcx.ccx.tcx, ret_ty_of_fn(fcx.ccx.tcx, id)) &&
        f.decl.cf == return {
        fcx.ccx.tcx.sess.span_err(f.body.span,
                                   "In function " + fcx.name +
                                       ", not all control paths \
                                        return a value");
        fcx.ccx.tcx.sess.span_fatal(f.decl.output.span,
                                    "see declared return type of '" +
                                        ty_to_str(f.decl.output) + "'");
    } else if (f.decl.cf == noreturn) {
        // check that this really always fails
        // Note that it's ok for i_diverge and i_return to both be true.
        // In fact, i_diverge implies i_return. (But not vice versa!)

        if !promises(fcx, post, fcx.enclosing.i_diverge) {
            fcx.ccx.tcx.sess.span_fatal(f.body.span,
                                        "In non-returning function " +
                                            fcx.name +
                                            ", some control paths may \
                                           return to the caller");
        }
    }

    /* Finally, check for unused variables */
    check_unused_vars(fcx);
}

fn check_fn_states(fcx: &fn_ctxt, f: &_fn, tps: &[ast::ty_param], id: node_id,
                   sp: &span, i: &fn_ident) {
    /* Compute the pre- and post-states for this function */

    // Fixpoint iteration
    while find_pre_post_state_fn(fcx, f) { }

    /* Now compare each expr's pre-state to its precondition
       and post-state to its postcondition */

    check_states_against_conditions(fcx, f, tps, id, sp, i);
}

fn fn_states(f: &_fn, tps: &[ast::ty_param], sp: &span, i: &fn_ident,
             id: node_id, ccx: &crate_ctxt, v: &visit::vt<crate_ctxt>) {
    visit::visit_fn(f, tps, sp, i, id, ccx, v);
    /* Look up the var-to-bit-num map for this function */

    assert (ccx.fm.contains_key(id));
    let f_info = ccx.fm.get(id);
    let name = option::from_maybe("anon", i);
    let fcx = {enclosing: f_info, id: id, name: name, ccx: ccx};
    check_fn_states(fcx, f, tps, id, sp, i);
}

fn check_crate(cx: ty::ctxt, crate: @crate) {
    let ccx: crate_ctxt = new_crate_ctxt(cx);
    /* Build the global map from function id to var-to-bit-num-map */

    mk_f_to_fn_info(ccx, crate);
    /* Add a blank ts_ann for every statement (and expression) */

    annotate_crate(ccx, *crate);
    /* Compute the pre and postcondition for every subexpression */

    let vtor = visit::default_visitor::<crate_ctxt>();
    vtor = @{visit_fn: fn_pre_post with *vtor};
    visit::visit_crate(*crate, ccx, visit::mk_vt(vtor));

    /* Check the pre- and postcondition against the pre- and poststate
       for every expression */
    vtor = @{visit_fn: fn_states with *vtor};
    visit::visit_crate(*crate, ccx, visit::mk_vt(vtor));
}
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//
<commit_msg>Don't warn about unused vars whose name starts with _<commit_after>
import syntax::ast;
import ast::method;
import ast::item;
import ast::item_fn;
import ast::_fn;
import ast::obj_field;
import ast::_obj;
import ast::stmt;
import ast::ident;
import ast::fn_ident;
import ast::node_id;
import ast::def_id;
import ast::local_def;
import ast::ty_param;
import ast::crate;
import ast::return;
import ast::noreturn;
import ast::expr;
import syntax::visit;
import syntax::codemap::span;
import middle::ty::type_is_nil;
import middle::ty::ret_ty_of_fn;
import tstate::ann::ts_ann;
import tstate::ann::empty_poststate;
import tstate::ann::true_precond;
import tstate::ann::true_postcond;
import tstate::ann::false_postcond;
import tstate::ann::precond;
import tstate::ann::postcond;
import tstate::ann::poststate;
import tstate::ann::prestate;
import tstate::ann::implies;
import tstate::ann::ann_precond;
import tstate::ann::ann_prestate;
import std::option;
import std::option::t;
import std::option::some;
import std::option::none;
import aux::*;
import syntax::print::pprust::ty_to_str;
import util::common::log_stmt_err;
import bitvectors::*;
import annotate::annotate_crate;
import collect_locals::mk_f_to_fn_info;
import pre_post_conditions::fn_pre_post;
import states::find_pre_post_state_fn;

fn check_unused_vars(fcx: &fn_ctxt) {

    // FIXME: could be more efficient
    for c: norm_constraint in constraints(fcx) {
        alt c.c.node {
          ninit(id, v) {
            if !vec_contains(fcx.enclosing.used_vars, id) &&
               v.(0) != ('_' as u8) {
                fcx.ccx.tcx.sess.span_warn(c.c.span, "unused variable " + v);
            }
          }
          _ {/* ignore pred constraints */ }
        }
    }
}

fn check_states_expr(e: &@expr, fcx: &fn_ctxt, v: &visit::vt<fn_ctxt>) {
    visit::visit_expr(e, fcx, v);

    let prec: precond = expr_precond(fcx.ccx, e);
    let pres: prestate = expr_prestate(fcx.ccx, e);

    /*
    log_err("check_states_expr:");
      util::common::log_expr_err(*e);
      log_err("prec = ");
      log_tritv_err(fcx, prec);
      log_err("pres = ");
      log_tritv_err(fcx, pres);
    */

    if !implies(pres, prec) {
        let s = "";
        let diff = first_difference_string(fcx, prec, pres);
        s +=
            "Unsatisfied precondition constraint (for example, " + diff +
                ") for expression:\n";
        s += syntax::print::pprust::expr_to_str(e);
        s += "\nPrecondition:\n";
        s += tritv_to_str(fcx, prec);
        s += "\nPrestate:\n";
        s += tritv_to_str(fcx, pres);
        fcx.ccx.tcx.sess.span_fatal(e.span, s);
    }
}

fn check_states_stmt(s: &@stmt, fcx: &fn_ctxt, v: &visit::vt<fn_ctxt>) {
    visit::visit_stmt(s, fcx, v);

    let a = stmt_to_ann(fcx.ccx, *s);
    let prec: precond = ann_precond(a);
    let pres: prestate = ann_prestate(a);

    /*
      log_err("check_states_stmt:");
      log_stmt_err(*s);
      log_err("prec = ");
      log_tritv_err(fcx, prec);
      log_err("pres = ");
      log_tritv_err(fcx, pres);
    */

    if !implies(pres, prec) {
        let ss = "";
        let diff = first_difference_string(fcx, prec, pres);
        ss +=
            "Unsatisfied precondition constraint (for example, " + diff +
                ") for statement:\n";
        ss += syntax::print::pprust::stmt_to_str(*s);
        ss += "\nPrecondition:\n";
        ss += tritv_to_str(fcx, prec);
        ss += "\nPrestate: \n";
        ss += tritv_to_str(fcx, pres);
        fcx.ccx.tcx.sess.span_fatal(s.span, ss);
    }
}

fn check_states_against_conditions(fcx: &fn_ctxt, f: &_fn,
                                   tps: &[ast::ty_param], id: node_id,
                                   sp: &span, i: &fn_ident) {
    /* Postorder traversal instead of pre is important
       because we want the smallest possible erroneous statement
       or expression. */

    let visitor = visit::default_visitor::<fn_ctxt>();

    visitor =
        @{visit_stmt: check_states_stmt,
          visit_expr: check_states_expr,
          visit_fn: do_nothing with *visitor};
    visit::visit_fn(f, tps, sp, i, id, fcx, visit::mk_vt(visitor));

    /* Check that the return value is initialized */
    let post = aux::block_poststate(fcx.ccx, f.body);
    if f.proto == ast::proto_fn &&
        !promises(fcx, post, fcx.enclosing.i_return) &&
        !type_is_nil(fcx.ccx.tcx, ret_ty_of_fn(fcx.ccx.tcx, id)) &&
        f.decl.cf == return {
        fcx.ccx.tcx.sess.span_err(f.body.span,
                                   "In function " + fcx.name +
                                       ", not all control paths \
                                        return a value");
        fcx.ccx.tcx.sess.span_fatal(f.decl.output.span,
                                    "see declared return type of '" +
                                        ty_to_str(f.decl.output) + "'");
    } else if (f.decl.cf == noreturn) {
        // check that this really always fails
        // Note that it's ok for i_diverge and i_return to both be true.
        // In fact, i_diverge implies i_return. (But not vice versa!)

        if !promises(fcx, post, fcx.enclosing.i_diverge) {
            fcx.ccx.tcx.sess.span_fatal(f.body.span,
                                        "In non-returning function " +
                                            fcx.name +
                                            ", some control paths may \
                                           return to the caller");
        }
    }

    /* Finally, check for unused variables */
    check_unused_vars(fcx);
}

fn check_fn_states(fcx: &fn_ctxt, f: &_fn, tps: &[ast::ty_param], id: node_id,
                   sp: &span, i: &fn_ident) {
    /* Compute the pre- and post-states for this function */

    // Fixpoint iteration
    while find_pre_post_state_fn(fcx, f) { }

    /* Now compare each expr's pre-state to its precondition
       and post-state to its postcondition */

    check_states_against_conditions(fcx, f, tps, id, sp, i);
}

fn fn_states(f: &_fn, tps: &[ast::ty_param], sp: &span, i: &fn_ident,
             id: node_id, ccx: &crate_ctxt, v: &visit::vt<crate_ctxt>) {
    visit::visit_fn(f, tps, sp, i, id, ccx, v);
    /* Look up the var-to-bit-num map for this function */

    assert (ccx.fm.contains_key(id));
    let f_info = ccx.fm.get(id);
    let name = option::from_maybe("anon", i);
    let fcx = {enclosing: f_info, id: id, name: name, ccx: ccx};
    check_fn_states(fcx, f, tps, id, sp, i);
}

fn check_crate(cx: ty::ctxt, crate: @crate) {
    let ccx: crate_ctxt = new_crate_ctxt(cx);
    /* Build the global map from function id to var-to-bit-num-map */

    mk_f_to_fn_info(ccx, crate);
    /* Add a blank ts_ann for every statement (and expression) */

    annotate_crate(ccx, *crate);
    /* Compute the pre and postcondition for every subexpression */

    let vtor = visit::default_visitor::<crate_ctxt>();
    vtor = @{visit_fn: fn_pre_post with *vtor};
    visit::visit_crate(*crate, ccx, visit::mk_vt(vtor));

    /* Check the pre- and postcondition against the pre- and poststate
       for every expression */
    vtor = @{visit_fn: fn_states with *vtor};
    visit::visit_crate(*crate, ccx, visit::mk_vt(vtor));
}
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//
<|endoftext|>


<commit_before>extern crate linked_list;
use linked_list::*;

fn to_raw_ptr<T>(opt: Option<&T>) -> *const T {
    opt.map_or(std::ptr::null(), |r| r as *const T)
}

#[test]
fn empty_list() {
    let list: LinkedList<i32> = LinkedList::new();
    assert_eq!(list.len(), 0);
}

#[test]
fn single_element() {
    let mut list: LinkedList<i32> = LinkedList::new();
    list.push_back(5);

    assert_eq!(list.len(), 1);
    assert_eq!(
        to_raw_ptr(list.front()),
        to_raw_ptr(list.back())
    );
    assert_eq!(list.pop_front(), Some(5));
}

#[test]
fn push_pop_back_multiple() {
    let mut list: LinkedList<i32> = LinkedList::new();
    for i in 0..10 {
        list.push_back(i);
    }
    assert_eq!(list.len(), 10);

    for i in (0..10).rev() {
        assert_eq!(i, list.pop_back().unwrap());
    }
    assert_eq!(list.len(), 0);
}

#[test]
fn push_pop_front_multiple() {
    let mut list: LinkedList<i32> = LinkedList::new();
    for i in 0..10 {
        list.push_front(i);
    }
    assert_eq!(list.len(), 10);

    for i in (0..10).rev() {
        assert_eq!(i, list.pop_front().unwrap());
    }
    assert_eq!(list.len(), 0);
}

#[test]
fn push_front_pop_back() {
    let mut list: LinkedList<i32> = LinkedList::new();
    for i in 0..10 {
        list.push_front(i);
    }
    for i in 0..10 {
        assert_eq!(i, list.pop_back().unwrap());
    }
}

#[test]
fn many_list() {
    let mut list: LinkedList<i32> = LinkedList::new();
    for num in 0..10 {
        list.push_back(num);
    }
    assert_eq!(list.len(), 10);

    for (num, &entered_num) in (0..10).zip(list.iter()) {
        assert_eq!(num, entered_num);
    }
}

// or same number of leaks as double frees
#[test]
fn no_leaks_or_double_frees() {
    use std::cell::Cell;
    struct Counter<'a>(&'a Cell<usize>);

    impl<'a> Drop for Counter<'a> {
        fn drop(&mut self) {
            let num = self.0.get();
            self.0.set(num-1);
        }
    }

    const N: usize  = 15;

    let counter = Cell::new(N);
    let list = std::iter::repeat_with(|| Counter(&counter))
        .take(N)
        .collect::<LinkedList<_>>();

    assert_eq!(list.len(), N);
    drop(list);
    assert_eq!(counter.get(), 0);
}

#[test]
fn clone_is_equal() {
    let list = (0..10).collect::<LinkedList<_>>();
    let list2 = list.clone();

    assert!(
        list.iter().eq(list2.iter())
    );
}

#[test]
fn insert_middle() {
    let mut list = LinkedList::new();
    for i in 0..10 {
        list.push_back(i);
    }

    {
        let mut cursor = list.cursor_front();
        let didnt_run_into_end = cursor.seek_forward(4);
        assert!(didnt_run_into_end);

        for n in (0..10).rev() {
            cursor.insert_after(n);
        }
    }

    assert_eq!(list.len(), 20);

    let expected = (0..5).chain(0..10).chain(5..10);

    assert!(
        expected.eq( list.iter().cloned() )
    );
}

#[test]
fn back_front_changes_on_push_back() {
    let mut backs = vec![];
    let mut fronts = vec![];
    let mut list = LinkedList::new();

    for i in 0..10 {
        list.push_back(i);
        backs.push( to_raw_ptr(list.back()) );
        fronts.push( to_raw_ptr(list.front()) );
    }
    fronts.dedup();

    assert_eq!(fronts.len(), 1);
    assert_eq!(fronts[0], backs[0]);

    backs.sort();
    backs.dedup();

    assert_eq!(backs.len(), 10);
}

#[test]
fn back_front_changes_on_push_front() {
    let mut backs = vec![];
    let mut fronts = vec![];
    let mut list = LinkedList::new();

    for i in 0..10 {
        list.push_front(i);
        backs.push( to_raw_ptr(list.back()) );
        fronts.push( to_raw_ptr(list.front()) );
    }
    backs.dedup();

    assert_eq!(backs.len(), 1);
    assert_eq!(backs[0], fronts[0]);

    fronts.sort();
    fronts.dedup();

    assert_eq!(fronts.len(), 10);
}

#[test]
fn linked_list_is_send_sync() {
    trait AssertSend: Send {}
    trait AssertSync: Sync {}

    impl<T: Send> AssertSend for LinkedList<T> {}
    impl<T: Sync> AssertSync for LinkedList<T> {}
}

#[allow(dead_code)]
#[test]
fn is_covariant() {
    fn a<'a>(x: LinkedList<&'static str>) -> LinkedList<&'a str> {
        x
    }
}

#[test]
fn is_generic() {
    struct Foo;
    LinkedList::<Foo>::new();
}
<commit_msg>linked-list: add covariance test for Iter<commit_after>extern crate linked_list;
use linked_list::*;

fn to_raw_ptr<T>(opt: Option<&T>) -> *const T {
    opt.map_or(std::ptr::null(), |r| r as *const T)
}

#[test]
fn empty_list() {
    let list: LinkedList<i32> = LinkedList::new();
    assert_eq!(list.len(), 0);
}

#[test]
fn single_element() {
    let mut list: LinkedList<i32> = LinkedList::new();
    list.push_back(5);

    assert_eq!(list.len(), 1);
    assert_eq!(
        to_raw_ptr(list.front()),
        to_raw_ptr(list.back())
    );
    assert_eq!(list.pop_front(), Some(5));
}

#[test]
fn push_pop_back_multiple() {
    let mut list: LinkedList<i32> = LinkedList::new();
    for i in 0..10 {
        list.push_back(i);
    }
    assert_eq!(list.len(), 10);

    for i in (0..10).rev() {
        assert_eq!(i, list.pop_back().unwrap());
    }
    assert_eq!(list.len(), 0);
}

#[test]
fn push_pop_front_multiple() {
    let mut list: LinkedList<i32> = LinkedList::new();
    for i in 0..10 {
        list.push_front(i);
    }
    assert_eq!(list.len(), 10);

    for i in (0..10).rev() {
        assert_eq!(i, list.pop_front().unwrap());
    }
    assert_eq!(list.len(), 0);
}

#[test]
fn push_front_pop_back() {
    let mut list: LinkedList<i32> = LinkedList::new();
    for i in 0..10 {
        list.push_front(i);
    }
    for i in 0..10 {
        assert_eq!(i, list.pop_back().unwrap());
    }
}

#[test]
fn many_list() {
    let mut list: LinkedList<i32> = LinkedList::new();
    for num in 0..10 {
        list.push_back(num);
    }
    assert_eq!(list.len(), 10);

    for (num, &entered_num) in (0..10).zip(list.iter()) {
        assert_eq!(num, entered_num);
    }
}

// or same number of leaks as double frees
#[test]
fn no_leaks_or_double_frees() {
    use std::cell::Cell;
    struct Counter<'a>(&'a Cell<usize>);

    impl<'a> Drop for Counter<'a> {
        fn drop(&mut self) {
            let num = self.0.get();
            self.0.set(num-1);
        }
    }

    const N: usize  = 15;

    let counter = Cell::new(N);
    let list = std::iter::repeat_with(|| Counter(&counter))
        .take(N)
        .collect::<LinkedList<_>>();

    assert_eq!(list.len(), N);
    drop(list);
    assert_eq!(counter.get(), 0);
}

#[test]
fn clone_is_equal() {
    let list = (0..10).collect::<LinkedList<_>>();
    let list2 = list.clone();

    assert!(
        list.iter().eq(list2.iter())
    );
}

#[test]
fn insert_middle() {
    let mut list = LinkedList::new();
    for i in 0..10 {
        list.push_back(i);
    }

    {
        let mut cursor = list.cursor_front();
        let didnt_run_into_end = cursor.seek_forward(4);
        assert!(didnt_run_into_end);

        for n in (0..10).rev() {
            cursor.insert_after(n);
        }
    }

    assert_eq!(list.len(), 20);

    let expected = (0..5).chain(0..10).chain(5..10);

    assert!(
        expected.eq( list.iter().cloned() )
    );
}

#[test]
fn back_front_changes_on_push_back() {
    let mut backs = vec![];
    let mut fronts = vec![];
    let mut list = LinkedList::new();

    for i in 0..10 {
        list.push_back(i);
        backs.push( to_raw_ptr(list.back()) );
        fronts.push( to_raw_ptr(list.front()) );
    }
    fronts.dedup();

    assert_eq!(fronts.len(), 1);
    assert_eq!(fronts[0], backs[0]);

    backs.sort();
    backs.dedup();

    assert_eq!(backs.len(), 10);
}

#[test]
fn back_front_changes_on_push_front() {
    let mut backs = vec![];
    let mut fronts = vec![];
    let mut list = LinkedList::new();

    for i in 0..10 {
        list.push_front(i);
        backs.push( to_raw_ptr(list.back()) );
        fronts.push( to_raw_ptr(list.front()) );
    }
    backs.dedup();

    assert_eq!(backs.len(), 1);
    assert_eq!(backs[0], fronts[0]);

    fronts.sort();
    fronts.dedup();

    assert_eq!(fronts.len(), 10);
}

#[test]
fn linked_list_is_send_sync() {
    trait AssertSend: Send {}
    trait AssertSync: Sync {}

    impl<T: Send> AssertSend for LinkedList<T> {}
    impl<T: Sync> AssertSync for LinkedList<T> {}
}

#[allow(dead_code)]
#[test]
fn is_covariant() {
    fn a<'a>(x: LinkedList<&'static str>) -> LinkedList<&'a str> {
        x
    }

    fn a_iter<'a>(i: Iter<'static, &'static str>) -> Iter<'a, &'a str> {
        i
    }
}

#[test]
fn is_generic() {
    struct Foo;
    LinkedList::<Foo>::new();
}
<|endoftext|>


<commit_before>use std::env;

pub fn configure() {
    println!("cargo:rerun-if-changed=build.rs");
    println!("cargo:rerun-if-env-changed=PROFILE");

    let wants_debug = env::var("PROFILE").unwrap() == "debug";

    let artifacts = zeromq_src::Build::new().link_static(true).build_debug(wants_debug).build();
    artifacts.print_cargo_metadata();
}
<commit_msg>Fix rebuilding `zmq-sys` every time<commit_after>use std::env;

pub fn configure() {
    println!("cargo:rerun-if-changed=build/main.rs");
    println!("cargo:rerun-if-env-changed=PROFILE");

    let wants_debug = env::var("PROFILE").unwrap() == "debug";

    let artifacts = zeromq_src::Build::new().link_static(true).build_debug(wants_debug).build();
    artifacts.print_cargo_metadata();
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;
use std::mem;

#[cfg(feature = "winit")]
use winit;

use winapi::shared::dxgi1_4;
use winapi::shared::windef::{HWND, RECT};
use winapi::um::winuser::GetClientRect;
use wio::com::ComPtr;

use hal::{self, format as f, image as i};
use {native as n, Backend, Instance, PhysicalDevice, QueueFamily};

use std::os::raw::c_void;

impl Instance {
    pub fn create_surface_from_hwnd(&self, hwnd: *mut c_void) -> Surface {
        let (width, height) = unsafe {
            let mut rect: RECT = mem::zeroed();
            if GetClientRect(hwnd as *mut _, &mut rect as *mut RECT) == 0 {
                panic!("GetClientRect failed");
            }
            ((rect.right - rect.left) as u32, (rect.bottom - rect.top) as u32)
        };

        Surface {
            factory: self.factory.clone(),
            wnd_handle: hwnd as *mut _,
            width: width,
            height: height,
        }
    }

    #[cfg(feature = "winit")]
    pub fn create_surface(&self, window: &winit::Window) -> Surface {
        use winit::os::windows::WindowExt;
        self.create_surface_from_hwnd(window.get_hwnd() as *mut _)
    }
}

pub struct Surface {
    pub(crate) factory: ComPtr<dxgi1_4::IDXGIFactory4>,
    pub(crate) wnd_handle: HWND,
    pub(crate) width: i::Size,
    pub(crate) height: i::Size,
}

unsafe impl Send for Surface { }
unsafe impl Sync for Surface { }

impl hal::Surface<Backend> for Surface {
    fn supports_queue_family(&self, _queue_family: &QueueFamily) -> bool { true }
    fn kind(&self) -> i::Kind {
        i::Kind::D2(self.width, self.height, 1, 1)
    }

    fn capabilities_and_formats(
        &self, _: &PhysicalDevice,
    ) -> (hal::SurfaceCapabilities, Option<Vec<f::Format>>) {
        let extent = hal::window::Extent2D {
            width: self.width,
            height: self.height,
        };

        let capabilities = hal::SurfaceCapabilities {
            image_count: 2..16, // we currently use a flip effect which supports 2..16 buffers
            current_extent: Some(extent),
            extents: extent..extent,
            max_image_layers: 1,
        };

        // Sticking to FLIP swap effects for the moment.
        // We also expose sRGB buffers but they are handled internally as UNORM.
        // Roughly ordered by popularity..
        let formats = vec![
            f::Format::Bgra8Srgb,
            f::Format::Bgra8Unorm,
            f::Format::Rgba8Srgb,
            f::Format::Rgba8Unorm,
            f::Format::A2b10g10r10Unorm,
            f::Format::Rgba16Float,
        ];

        (capabilities, Some(formats))
    }
}

pub struct Swapchain {
    pub(crate) inner: ComPtr<dxgi1_4::IDXGISwapChain3>,
    pub(crate) next_frame: usize,
    pub(crate) frame_queue: VecDeque<usize>,
    #[allow(dead_code)]
    pub(crate) rtv_heap: n::DescriptorHeap,
}

impl hal::Swapchain<Backend> for Swapchain {
    fn acquire_frame(&mut self, _sync: hal::FrameSync<Backend>) -> hal::Frame {
        // TODO: sync

        if false {
            // TODO: we need to block this at some point? (running out of backbuffers)
            //let num_images = self.images.len();
            let num_images = 1;
            let index = self.next_frame;
            self.frame_queue.push_back(index);
            self.next_frame = (self.next_frame + 1) % num_images;
        }

        // TODO:
        let index = unsafe { self.inner.GetCurrentBackBufferIndex() };
        hal::Frame::new(index as usize)
    }
}

unsafe impl Send for Swapchain { }
unsafe impl Sync for Swapchain { }
<commit_msg>Only support surface on present queue<commit_after>use std::collections::VecDeque;
use std::mem;

#[cfg(feature = "winit")]
use winit;

use winapi::shared::dxgi1_4;
use winapi::shared::windef::{HWND, RECT};
use winapi::um::winuser::GetClientRect;
use wio::com::ComPtr;

use hal::{self, format as f, image as i};
use {native as n, Backend, Instance, PhysicalDevice, QueueFamily};

use std::os::raw::c_void;

impl Instance {
    pub fn create_surface_from_hwnd(&self, hwnd: *mut c_void) -> Surface {
        let (width, height) = unsafe {
            let mut rect: RECT = mem::zeroed();
            if GetClientRect(hwnd as *mut _, &mut rect as *mut RECT) == 0 {
                panic!("GetClientRect failed");
            }
            ((rect.right - rect.left) as u32, (rect.bottom - rect.top) as u32)
        };

        Surface {
            factory: self.factory.clone(),
            wnd_handle: hwnd as *mut _,
            width: width,
            height: height,
        }
    }

    #[cfg(feature = "winit")]
    pub fn create_surface(&self, window: &winit::Window) -> Surface {
        use winit::os::windows::WindowExt;
        self.create_surface_from_hwnd(window.get_hwnd() as *mut _)
    }
}

pub struct Surface {
    pub(crate) factory: ComPtr<dxgi1_4::IDXGIFactory4>,
    pub(crate) wnd_handle: HWND,
    pub(crate) width: i::Size,
    pub(crate) height: i::Size,
}

unsafe impl Send for Surface { }
unsafe impl Sync for Surface { }

impl hal::Surface<Backend> for Surface {
    fn supports_queue_family(&self, queue_family: &QueueFamily) -> bool {
        match queue_family {
            &QueueFamily::Present => true,
            _ => false
        }
    }

    fn kind(&self) -> i::Kind {
        i::Kind::D2(self.width, self.height, 1, 1)
    }

    fn capabilities_and_formats(
        &self, _: &PhysicalDevice,
    ) -> (hal::SurfaceCapabilities, Option<Vec<f::Format>>) {
        let extent = hal::window::Extent2D {
            width: self.width,
            height: self.height,
        };

        let capabilities = hal::SurfaceCapabilities {
            image_count: 2..16, // we currently use a flip effect which supports 2..16 buffers
            current_extent: Some(extent),
            extents: extent..extent,
            max_image_layers: 1,
        };

        // Sticking to FLIP swap effects for the moment.
        // We also expose sRGB buffers but they are handled internally as UNORM.
        // Roughly ordered by popularity..
        let formats = vec![
            f::Format::Bgra8Srgb,
            f::Format::Bgra8Unorm,
            f::Format::Rgba8Srgb,
            f::Format::Rgba8Unorm,
            f::Format::A2b10g10r10Unorm,
            f::Format::Rgba16Float,
        ];

        (capabilities, Some(formats))
    }
}

pub struct Swapchain {
    pub(crate) inner: ComPtr<dxgi1_4::IDXGISwapChain3>,
    pub(crate) next_frame: usize,
    pub(crate) frame_queue: VecDeque<usize>,
    #[allow(dead_code)]
    pub(crate) rtv_heap: n::DescriptorHeap,
}

impl hal::Swapchain<Backend> for Swapchain {
    fn acquire_frame(&mut self, _sync: hal::FrameSync<Backend>) -> hal::Frame {
        // TODO: sync

        if false {
            // TODO: we need to block this at some point? (running out of backbuffers)
            //let num_images = self.images.len();
            let num_images = 1;
            let index = self.next_frame;
            self.frame_queue.push_back(index);
            self.next_frame = (self.next_frame + 1) % num_images;
        }

        // TODO:
        let index = unsafe { self.inner.GetCurrentBackBufferIndex() };
        hal::Frame::new(index as usize)
    }
}

unsafe impl Send for Swapchain { }
unsafe impl Sync for Swapchain { }
<|endoftext|>


<commit_before>use crate::util::{json_response, EndpointResult};

pub(crate) mod pagination;

pub(crate) use self::pagination::Paginate;

pub fn ok_true() -> EndpointResult {
    #[derive(Serialize)]
    struct R {
        ok: bool,
    }

    Ok(json_response(&R { ok: true }))
}
<commit_msg>controllers::helpers: Use `json!` macro to simplify JSON serialization code<commit_after>use crate::util::{json_response, EndpointResult};

pub(crate) mod pagination;

pub(crate) use self::pagination::Paginate;

pub fn ok_true() -> EndpointResult {
    let json = json!({ "ok": true });
    Ok(json_response(&json))
}
<|endoftext|>