<commit_before>// https://leetcode.com/problems/optimal-partition-of-string/
pub fn partition_string(s: String) -> i32 {
    todo!()
}

fn main() {
    println!("{}", partition_string("abacaba".to_string())); // 4
    println!("{}", partition_string("ssssss".to_string())); // 6
}
<commit_msg>Solve problem 2045<commit_after>use std::collections::HashSet;

// https://leetcode.com/problems/optimal-partition-of-string/
pub fn partition_string(s: String) -> i32 {
    let mut answer = 0;
    let mut chars: HashSet<char> = HashSet::new();
    for c in s.chars().into_iter().collect::<Vec<char>>() {
        if chars.contains(&c) {
            answer += 1;
            chars.clear();
        }
        chars.insert(c);
    }
    answer + 1
}

fn main() {
    println!("{}", partition_string("abacaba".to_string())); // 4
    println!("{}", partition_string("ssssss".to_string())); // 6
}
<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate coreutils;
extern crate extra;
extern crate syscall;

use std::{env, fmt, fs};
use std::io::{stdout, stderr, Write};
use coreutils::ArgParser;
use extra::option::OptionalExt;

const MAN_PAGE: &'static str = /* @MANSTART{stat} */ r#"
NAME
    stat - display file status

SYNOPSIS
    stat [ -h | --help ] FILE...

DESCRIPTION
    Displays file status.

OPTIONS
    --help, -h
        print this message
"#; /* @MANEND */

struct Perms(u16);

impl fmt::Display for Perms {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "(0{:o}/", self.0 & 0o777)?;
        let perm = |i, c| {
            if self.0 & ((1 << i) as u16) != 0 {
                c
            } else {
                "-"
            }
        };
        write!(f, "{}{}{}", perm(8, "r"), perm(7, "w"), perm(6, "x"))?;
        write!(f, "{}{}{}", perm(5, "r"), perm(4, "w"), perm(3, "x"))?;
        write!(f, "{}{}{}", perm(2, "r"), perm(1, "w"), perm(0, "x"))?;
        write!(f, ")")?;
        Ok(())
    }
}

fn main() {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();
    let mut parser = ArgParser::new(1)
        .add_flag(&["h", "help"]);
    parser.parse(env::args());

    if parser.found("help") {
        stdout.write_all(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        return;
    }

    for path in &parser.args[0..] {
        let mut st = syscall::Stat::default();
        let fd = syscall::open(path, syscall::O_CLOEXEC | syscall::O_STAT).unwrap();
        syscall::fstat(fd, &mut st).unwrap();
        syscall::close(fd).unwrap();
        let file_type = match st.st_mode & syscall::MODE_TYPE {
            syscall::MODE_FILE => "regular file",
            syscall::MODE_DIR => "directory",
            syscall::MODE_SYMLINK => "symbolic link",
            _ => ""
        };
        if st.st_mode & syscall::MODE_SYMLINK == syscall::MODE_SYMLINK {
            println!("File: {} -> {}", path, fs::read_link(path).unwrap().display());
        } else {
            println!("File: {}", path);
        }
        println!("Size: {}  Blocks: {}  IO Block: {} {}", st.st_size, st.st_blocks, st.st_blksize, file_type);
        println!("Device: {}  Inode: {}  Links: {}", st.st_dev, st.st_ino, st.st_nlink);
        println!("Access: {}  Uid: {}  Gid: {}", Perms(st.st_mode), st.st_uid, st.st_gid);
        println!("Access: {}.{:09}", st.st_atime, st.st_atime_nsec);
        println!("Modify: {}.{:09}", st.st_mtime, st.st_mtime_nsec);
        println!("Change: {}.{:09}", st.st_ctime, st.st_ctime_nsec);
    }
}
<commit_msg>Use O_NOFOLLOW in stat<commit_after>#![deny(warnings)]

extern crate coreutils;
extern crate extra;
extern crate syscall;

use std::{env, fmt, fs};
use std::io::{stdout, stderr, Write};
use coreutils::ArgParser;
use extra::option::OptionalExt;

const MAN_PAGE: &'static str = /* @MANSTART{stat} */ r#"
NAME
    stat - display file status

SYNOPSIS
    stat [ -h | --help ] FILE...

DESCRIPTION
    Displays file status.

OPTIONS
    --help, -h
        print this message
"#; /* @MANEND */

struct Perms(u16);

impl fmt::Display for Perms {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "(0{:o}/", self.0 & 0o777)?;
        let perm = |i, c| {
            if self.0 & ((1 << i) as u16) != 0 {
                c
            } else {
                "-"
            }
        };
        write!(f, "{}{}{}", perm(8, "r"), perm(7, "w"), perm(6, "x"))?;
        write!(f, "{}{}{}", perm(5, "r"), perm(4, "w"), perm(3, "x"))?;
        write!(f, "{}{}{}", perm(2, "r"), perm(1, "w"), perm(0, "x"))?;
        write!(f, ")")?;
        Ok(())
    }
}

fn main() {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();
    let mut parser = ArgParser::new(1)
        .add_flag(&["h", "help"]);
    parser.parse(env::args());

    if parser.found("help") {
        stdout.write_all(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        return;
    }

    for path in &parser.args[0..] {
        let mut st = syscall::Stat::default();
        let fd = syscall::open(path, syscall::O_CLOEXEC | syscall::O_STAT | syscall::O_NOFOLLOW).unwrap();
        syscall::fstat(fd, &mut st).unwrap();
        syscall::close(fd).unwrap();
        let file_type = match st.st_mode & syscall::MODE_TYPE {
            syscall::MODE_FILE => "regular file",
            syscall::MODE_DIR => "directory",
            syscall::MODE_SYMLINK => "symbolic link",
            _ => ""
        };
        if st.st_mode & syscall::MODE_SYMLINK == syscall::MODE_SYMLINK {
            println!("File: {} -> {}", path, fs::read_link(path).unwrap().display());
        } else {
            println!("File: {}", path);
        }
        println!("Size: {}  Blocks: {}  IO Block: {} {}", st.st_size, st.st_blocks, st.st_blksize, file_type);
        println!("Device: {}  Inode: {}  Links: {}", st.st_dev, st.st_ino, st.st_nlink);
        println!("Access: {}  Uid: {}  Gid: {}", Perms(st.st_mode), st.st_uid, st.st_gid);
        println!("Access: {}.{:09}", st.st_atime, st.st_atime_nsec);
        println!("Modify: {}.{:09}", st.st_mtime, st.st_mtime_nsec);
        println!("Change: {}.{:09}", st.st_ctime, st.st_ctime_nsec);
    }
}
<|endoftext|>


<commit_before>use analysis;
use analysis::namespaces;
use analysis::rust_type::rust_type;
use analysis::conversion_type::ConversionType;
use chunk::conversion_from_glib::Mode;
use env::Env;
use library;
use traits::*;

pub trait TranslateFromGlib {
    fn translate_from_glib_as_function(
        &self,
        env: &Env,
        array_length: &Option<(String, String)>,
    ) -> (String, String);
}

impl TranslateFromGlib for Mode {
    fn translate_from_glib_as_function(
        &self,
        env: &Env,
        array_length: &Option<(String, String)>,
    ) -> (String, String) {
        use analysis::conversion_type::ConversionType::*;
        match ConversionType::of(&env.library, self.typ) {
            Direct => (String::new(), String::new()),
            Scalar => ("from_glib(".into(), ")".into()),
            Pointer => {
                let trans = from_glib_xxx(self.transfer, array_length);
                match *env.type_(self.typ) {
                    library::Type::List(..) |
                    library::Type::SList(..) |
                    library::Type::CArray(..) => {
                        if let &Some(_) = array_length {
                            (format!("FromGlibContainer::{}", trans.0), trans.1)
                        } else {
                            (format!("FromGlibPtrContainer::{}", trans.0), trans.1)
                        }
                    }
                    _ => trans,
                }
            }
            Borrow => ("/*TODO: conversion Borrow*/".into(), String::new()),
            Unknown => ("/*Unknown conversion*/".into(), String::new()),
        }
    }
}

impl TranslateFromGlib for analysis::return_value::Info {
    fn translate_from_glib_as_function(
        &self,
        env: &Env,
        array_length: &Option<(String, String)>,
    ) -> (String, String) {
        match self.parameter {
            Some(ref par) => {
                match self.base_tid {
                    Some(tid) => {
                        let rust_type = rust_type(env, tid);
                        let from_glib_xxx = from_glib_xxx(par.transfer, &None);

                        let prefix = if *par.nullable {
                            format!("Option::<{}>::{}", rust_type.into_string(), from_glib_xxx.0)
                        } else {
                            format!("{}::{}", rust_type.into_string(), from_glib_xxx.0)
                        };
                        let suffix_function = if *par.nullable {
                            "map(Downcast::downcast_unchecked)"
                        } else {
                            "downcast_unchecked()"
                        };
                        (prefix, format!("{}.{}", from_glib_xxx.1, suffix_function))
                    }
                    None if self.bool_return_is_error.is_some() => {
                        if env.namespaces.glib_ns_id == namespaces::MAIN {
                            (
                                "error::BoolError::from_glib(".into(),
                                format!(", \"{}\")", self.bool_return_is_error.as_ref().unwrap()),
                            )
                        } else {
                            (
                                "glib::error::BoolError::from_glib(".into(),
                                format!(", \"{}\")", self.bool_return_is_error.as_ref().unwrap()),
                            )
                        }
                    }
                    None => Mode::from(par).translate_from_glib_as_function(env, array_length),
                }
            }
            None => (String::new(), ";".into()),
        }
    }
}

fn from_glib_xxx(
    transfer: library::Transfer,
    array_length: &Option<(String, String)>,
) -> (String, String) {
    use library::Transfer;
    match (transfer, array_length) {
        (Transfer::None, &None) => ("from_glib_none(".into(), ")".into()),
        (Transfer::Full, &None) => ("from_glib_full(".into(), ")".into()),
        (Transfer::Container, &None) => ("from_glib_container(".into(), ")".into()),
        (Transfer::None, &Some((ref array_length_name, _))) => (
            "from_glib_none_num(".into(),
            format!(", {} as usize)", array_length_name),
        ),
        (Transfer::Full, &Some((ref array_length_name, _))) => (
            "from_glib_full_num(".into(),
            format!(", {} as usize)", array_length_name),
        ),
        (Transfer::Container, &Some((ref array_length_name, _))) => (
            "from_glib_container_num(".into(),
            format!(", {} as usize)", array_length_name),
        ),
    }
}
<commit_msg>Fix clippy warning about if let &Some(_) = some_option<commit_after>use analysis;
use analysis::namespaces;
use analysis::rust_type::rust_type;
use analysis::conversion_type::ConversionType;
use chunk::conversion_from_glib::Mode;
use env::Env;
use library;
use traits::*;

pub trait TranslateFromGlib {
    fn translate_from_glib_as_function(
        &self,
        env: &Env,
        array_length: &Option<(String, String)>,
    ) -> (String, String);
}

impl TranslateFromGlib for Mode {
    fn translate_from_glib_as_function(
        &self,
        env: &Env,
        array_length: &Option<(String, String)>,
    ) -> (String, String) {
        use analysis::conversion_type::ConversionType::*;
        match ConversionType::of(&env.library, self.typ) {
            Direct => (String::new(), String::new()),
            Scalar => ("from_glib(".into(), ")".into()),
            Pointer => {
                let trans = from_glib_xxx(self.transfer, array_length);
                match *env.type_(self.typ) {
                    library::Type::List(..) |
                    library::Type::SList(..) |
                    library::Type::CArray(..) => {
                        if array_length.is_some() {
                            (format!("FromGlibContainer::{}", trans.0), trans.1)
                        } else {
                            (format!("FromGlibPtrContainer::{}", trans.0), trans.1)
                        }
                    }
                    _ => trans,
                }
            }
            Borrow => ("/*TODO: conversion Borrow*/".into(), String::new()),
            Unknown => ("/*Unknown conversion*/".into(), String::new()),
        }
    }
}

impl TranslateFromGlib for analysis::return_value::Info {
    fn translate_from_glib_as_function(
        &self,
        env: &Env,
        array_length: &Option<(String, String)>,
    ) -> (String, String) {
        match self.parameter {
            Some(ref par) => {
                match self.base_tid {
                    Some(tid) => {
                        let rust_type = rust_type(env, tid);
                        let from_glib_xxx = from_glib_xxx(par.transfer, &None);

                        let prefix = if *par.nullable {
                            format!("Option::<{}>::{}", rust_type.into_string(), from_glib_xxx.0)
                        } else {
                            format!("{}::{}", rust_type.into_string(), from_glib_xxx.0)
                        };
                        let suffix_function = if *par.nullable {
                            "map(Downcast::downcast_unchecked)"
                        } else {
                            "downcast_unchecked()"
                        };
                        (prefix, format!("{}.{}", from_glib_xxx.1, suffix_function))
                    }
                    None if self.bool_return_is_error.is_some() => {
                        if env.namespaces.glib_ns_id == namespaces::MAIN {
                            (
                                "error::BoolError::from_glib(".into(),
                                format!(", \"{}\")", self.bool_return_is_error.as_ref().unwrap()),
                            )
                        } else {
                            (
                                "glib::error::BoolError::from_glib(".into(),
                                format!(", \"{}\")", self.bool_return_is_error.as_ref().unwrap()),
                            )
                        }
                    }
                    None => Mode::from(par).translate_from_glib_as_function(env, array_length),
                }
            }
            None => (String::new(), ";".into()),
        }
    }
}

fn from_glib_xxx(
    transfer: library::Transfer,
    array_length: &Option<(String, String)>,
) -> (String, String) {
    use library::Transfer;
    match (transfer, array_length) {
        (Transfer::None, &None) => ("from_glib_none(".into(), ")".into()),
        (Transfer::Full, &None) => ("from_glib_full(".into(), ")".into()),
        (Transfer::Container, &None) => ("from_glib_container(".into(), ")".into()),
        (Transfer::None, &Some((ref array_length_name, _))) => (
            "from_glib_none_num(".into(),
            format!(", {} as usize)", array_length_name),
        ),
        (Transfer::Full, &Some((ref array_length_name, _))) => (
            "from_glib_full_num(".into(),
            format!(", {} as usize)", array_length_name),
        ),
        (Transfer::Container, &Some((ref array_length_name, _))) => (
            "from_glib_container_num(".into(),
            format!(", {} as usize)", array_length_name),
        ),
    }
}
<|endoftext|>


<commit_before>use std::collections::hash_map::HashMap;

struct Function {
    blocks: HashMap<Block, BlockData>,
    instructions: HashMap<Inst, InstData>,
    uses: HashMap<Inst, UseList>,
    params: Vec<Type>,
    entry_block: Option<Block>,
    exit_block: Option<Block>,
}

struct Inst(u32);
struct Block(u32);
struct Param(u32);

struct UseList(Vec<Inst>);

struct BlockData {
    predecessors: Vec<Block>,
    successors: Vec<Block>,
    first_inst: Option<Inst>,
    last_inst: Option<Inst>,
}

enum CmpOp {
    Lt, Le, Eq, Ne, Gt, Ge,
}

enum InstData {
    Add {
        ty: Type,
        lhs: Inst,
        rhs: Inst,
    },

    Sub {
        ty: Type,
        lhs: Inst,
        rhs: Inst,
    },

    Goto {
        target: Block,
    },

    If {
        opnd: Inst,
        then_block: Block,
        else_block: Block,
    },

    Cmp {
        ty: Type,
        op: CmpOp,
        lhs: Inst,
        rhs: Inst,
    },

    Ret {
        opnd: Option<Inst>,
    },

    TrueConst,
    FalseConst,
    NilConst,
    Int8Const(u8),
    Int32Const(i32),
    Int64Const(i64),
    Float32Const(f32),
    Float64Const(f64),

    Param {
        ty: Type,
        param: Param,
    },

    Deleted,
}

struct InstLoc {
    block: Option<Block>,
    prev: Option<Inst>,
    next: Option<Inst>,
}

enum Type {
    Bool,
    Int8,
    Int32,
    Int64,
    Float32,
    Float64,
    Reference,
}<commit_msg>boots: start implementing API for IR<commit_after>use std::collections::hash_map::HashMap;

struct Function {
    blocks: HashMap<Block, BlockData>,
    instructions: HashMap<Inst, InstData>,
    uses: HashMap<Inst, UseList>,
    entry_block: Option<Block>,
    exit_block: Option<Block>,
}

impl Function {
    fn new() -> Function {
        Function {
            blocks: HashMap::new(),
            instructions: HashMap::new(),
            uses: HashMap::new(),
            entry_block: None,
            exit_block: None,
        }
    }
}

#[derive(PartialEq, Eq, Hash)]
struct Inst(u32);

#[derive(PartialEq, Eq, Hash)]
struct Block(u32);

struct UseList(Vec<Inst>);

struct BlockData {
    predecessors: Vec<Block>,
    successors: Vec<Block>,
    first_inst: Option<Inst>,
    last_inst: Option<Inst>,
}

impl BlockData {
    fn new() -> BlockData {
        BlockData {
            predecessors: Vec::new(),
            successors: Vec::new(),
            first_inst: None,
            last_inst: None,
        }
    }
}

enum CmpOp {
    Lt, Le, Eq, Ne, Gt, Ge,
}

enum InstData {
    Add {
        ty: Type,
        lhs: Inst,
        rhs: Inst,
    },

    Sub {
        ty: Type,
        lhs: Inst,
        rhs: Inst,
    },

    Goto {
        target: Block,
    },

    If {
        opnd: Inst,
        then_block: Block,
        else_block: Block,
    },

    Cmp {
        ty: Type,
        op: CmpOp,
        lhs: Inst,
        rhs: Inst,
    },

    Ret {
        opnd: Option<Inst>,
    },

    TrueConst,
    FalseConst,
    NilConst,
    Int8Const(u8),
    Int32Const(i32),
    Int64Const(i64),
    Float32Const(f32),
    Float64Const(f64),

    Param {
        ty: Type,
        idx: u32,
    },

    Deleted,
}

struct InstLoc {
    block: Option<Block>,
    prev: Option<Inst>,
    next: Option<Inst>,
}

enum Type {
    Bool,
    Int8,
    Int32,
    Int64,
    Float32,
    Float64,
    Reference,
}

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

    #[test]
    fn simple_fn() {
        let _fct = Function::new();
    }
}<|endoftext|>


<commit_before>pub static RUSTUP_HELP: &str = r"DISCUSSION:
    Rustup installs The Rust Programming Language from the official
    release channels, enabling you to easily switch between stable,
    beta, and nightly compilers and keep them updated. It makes
    cross-compiling simpler with binary builds of the standard library
    for common platforms.

    If you are new to Rust consider running `rustup doc --book` to
    learn Rust.";

pub static SHOW_HELP: &str = r"DISCUSSION:
    Shows the name of the active toolchain and the version of `rustc`.

    If the active toolchain has installed support for additional
    compilation targets, then they are listed as well.

    If there are multiple toolchains installed then all installed
    toolchains are listed as well.";

pub static SHOW_ACTIVE_TOOLCHAIN_HELP: &str = r"DISCUSSION:
    Shows the name of the active toolchain.

    This is useful for figuring out the active tool chain from
    scripts.

    You should use `rustc --print sysroot` to get the sysroot, or
    `rustc --version` to get the toolchain version.";

pub static UPDATE_HELP: &str = r"DISCUSSION:
    With no toolchain specified, the `update` command updates each of
    the installed toolchains from the official release channels, then
    updates rustup itself.

    If given a toolchain argument then `update` updates that
    toolchain, the same as `rustup toolchain install`.";

pub static INSTALL_HELP: &str = r"DISCUSSION:
    Installs a specific rust toolchain.

    The 'install' command is an alias for 'rustup update <toolchain>'.";

pub static DEFAULT_HELP: &str = r"DISCUSSION:
    Sets the default toolchain to the one specified. If the toolchain
    is not already installed then it is installed first.";

pub static TOOLCHAIN_HELP: &str = r"DISCUSSION:
    Many `rustup` commands deal with *toolchains*, a single
    installation of the Rust compiler. `rustup` supports multiple
    types of toolchains. The most basic track the official release
    channels: 'stable', 'beta' and 'nightly'; but `rustup` can also
    install toolchains from the official archives, for alternate host
    platforms, and from local builds.

    Standard release channel toolchain names have the following form:

        <channel>[-<date>][-<host>]

        <channel>       = stable|beta|nightly|<major.minor>|<major.minor.patch>
        <date>          = YYYY-MM-DD
        <host>          = <target-triple>

    'channel' is a named release channel, a major and minor version
    number such as `1.42`, or a fully specified version number, such
    as `1.42.0`. Channel names can be optionally appended with an
    archive date, as in `nightly-2014-12-18`, in which case the
    toolchain is downloaded from the archive for that date.

    The host may be specified as a target triple. This is most useful
    for installing a 32-bit compiler on a 64-bit platform, or for
    installing the [MSVC-based toolchain] on Windows. For example:

        $ rustup toolchain install stable-x86_64-pc-windows-msvc

    For convenience, omitted elements of the target triple will be
    inferred, so the above could be written:

        $ rustup toolchain install stable-msvc

    The `rustup default` command may be used to both install and set
    the desired toolchain as default in a single command:

        $ rustup default stable-msvc

    rustup can also manage symlinked local toolchain builds, which are
    often used for developing Rust itself. For more information see
    `rustup toolchain help link`.";

pub static TOOLCHAIN_LINK_HELP: &str = r"DISCUSSION:
    'toolchain' is the custom name to be assigned to the new toolchain.
    Any name is permitted as long as it does not fully match an initial
    substring of a standard release channel. For example, you can use
    the names 'latest' or '2017-04-01' but you cannot use 'stable' or
    'beta-i686' or 'nightly-x86_64-unknown-linux-gnu'.

    'path' specifies the directory where the binaries and libraries for
    the custom toolchain can be found. For example, when used for
    development of Rust itself, toolchains can be linked directly out of
    the build directory. After building, you can test out different
    compiler versions as follows:

        $ rustup toolchain link latest-stage1 build/x86_64-unknown-linux-gnu/stage1
        $ rustup override set latest-stage1

    If you now compile a crate in the current directory, the custom
    toolchain 'latest-stage1' will be used.";

pub static OVERRIDE_HELP: &str = r"DISCUSSION:
    Overrides configure Rustup to use a specific toolchain when
    running in a specific directory.

    Directories can be assigned their own Rust toolchain with `rustup
    override`. When a directory has an override then any time `rustc`
    or `cargo` is run inside that directory, or one of its child
    directories, the override toolchain will be invoked.

    To pin to a specific nightly:

        $ rustup override set nightly-2014-12-18

    Or a specific stable release:

        $ rustup override set 1.0.0

    To see the active toolchain use `rustup show`. To remove the
    override and use the default toolchain again, `rustup override
    unset`.";

pub static OVERRIDE_UNSET_HELP: &str = r"DISCUSSION:
    If `--path` argument is present, removes the override toolchain
    for the specified directory. If `--nonexistent` argument is
    present, removes the override toolchain for all nonexistent
    directories. Otherwise, removes the override toolchain for the
    current directory.";

pub static RUN_HELP: &str = r"DISCUSSION:
    Configures an environment to use the given toolchain and then runs
    the specified program. The command may be any program, not just
    rustc or cargo. This can be used for testing arbitrary toolchains
    without setting an override.

    Commands explicitly proxied by `rustup` (such as `rustc` and
    `cargo`) also have a shorthand for this available. The toolchain
    can be set by using `+toolchain` as the first argument. These are
    equivalent:

        $ cargo +nightly build

        $ rustup run nightly cargo build";

pub static DOC_HELP: &str = r"DISCUSSION:
    Opens the documentation for the currently active toolchain with
    the default browser.

    By default, it opens the documentation index. Use the various
    flags to open specific pieces of documentation.";

pub static COMPLETIONS_HELP: &str = r"DISCUSSION:
    Enable tab completion for Bash, Fish, Zsh, or PowerShell
    The script is output on `stdout`, allowing one to re-direct the
    output to the file of their choosing. Where you place the file
    will depend on which shell, and which operating system you are
    using. Your particular configuration may also determine where
    these scripts need to be placed.

    Here are some common set ups for the three supported shells under
    Unix and similar operating systems (such as GNU/Linux).

    BASH:

    Completion files are commonly stored in `/etc/bash_completion.d/` for
    system-wide commands, but can be stored in
    `~/.local/share/bash-completion/completions` for user-specific commands.
    Run the command:

        $ mkdir -p ~/.local/share/bash-completion/completions
        $ rustup completions bash >> ~/.local/share/bash-completion/completions/rustup

    This installs the completion script. You may have to log out and
    log back in to your shell session for the changes to take effect.

    BASH (macOS/Homebrew):

    Homebrew stores bash completion files within the Homebrew directory.
    With the `bash-completion` brew formula installed, run the command:

        $ mkdir -p $(brew --prefix)/etc/bash_completion.d
        $ rustup completions bash > $(brew --prefix)/etc/bash_completion.d/rustup.bash-completion

    FISH:

    Fish completion files are commonly stored in
    `$HOME/.config/fish/completions`. Run the command:

        $ mkdir -p ~/.config/fish/completions
        $ rustup completions fish > ~/.config/fish/completions/rustup.fish

    This installs the completion script. You may have to log out and
    log back in to your shell session for the changes to take effect.

    ZSH:

    ZSH completions are commonly stored in any directory listed in
    your `$fpath` variable. To use these completions, you must either
    add the generated script to one of those directories, or add your
    own to this list.

    Adding a custom directory is often the safest bet if you are
    unsure of which directory to use. First create the directory; for
    this example we'll create a hidden directory inside our `$HOME`
    directory:

        $ mkdir ~/.zfunc

    Then add the following lines to your `.zshrc` just before
    `compinit`:

        fpath+=~/.zfunc

    Now you can install the completions script using the following
    command:

        $ rustup completions zsh > ~/.zfunc/_rustup

    You must then either log out and log back in, or simply run

        $ exec zsh

    for the new completions to take effect.

    CUSTOM LOCATIONS:

    Alternatively, you could save these files to the place of your
    choosing, such as a custom directory inside your $HOME. Doing so
    will require you to add the proper directives, such as `source`ing
    inside your login script. Consult your shells documentation for
    how to add such directives.

    POWERSHELL:

    The powershell completion scripts require PowerShell v5.0+ (which
    comes Windows 10, but can be downloaded separately for windows 7
    or 8.1).

    First, check if a profile has already been set

        PS C:\> Test-Path $profile

    If the above command returns `False` run the following

        PS C:\> New-Item -path $profile -type file -force

    Now open the file provided by `$profile` (if you used the
    `New-Item` command it will be
    `${env:USERPROFILE}\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1`

    Next, we either save the completions file into our profile, or
    into a separate file and source it inside our profile. To save the
    completions into our profile simply use

        PS C:\> rustup completions powershell >> ${env:USERPROFILE}\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1

    CARGO:

    Rustup can also generate a completion script for `cargo`. The script output
    by `rustup` will source the completion script distributed with your default
    toolchain. Not all shells are currently supported. Here are examples for
    the currently supported shells.

    BASH:

        $ rustup completions bash cargo >> ~/.local/share/bash-completion/completions/cargo

    ZSH:

        $ rustup completions zsh cargo > ~/.zfunc/_cargo";

pub static TOOLCHAIN_ARG_HELP: &str = "Toolchain name, such as 'stable', 'nightly', \
                                       or '1.8.0'. For more information see `rustup \
                                       help toolchain`";

pub static TOPIC_ARG_HELP: &str = "Topic such as 'core', 'fn', 'usize', 'eprintln!', \
                                   'core::arch', 'alloc::format!', 'std::fs', \
                                   'std::fs::read_dir', 'std::io::Bytes', \
                                   'std::iter::Sum', 'std::io::error::Result' etc...";
<commit_msg>Fixes a typo in rustup completions discussion<commit_after>pub static RUSTUP_HELP: &str = r"DISCUSSION:
    Rustup installs The Rust Programming Language from the official
    release channels, enabling you to easily switch between stable,
    beta, and nightly compilers and keep them updated. It makes
    cross-compiling simpler with binary builds of the standard library
    for common platforms.

    If you are new to Rust consider running `rustup doc --book` to
    learn Rust.";

pub static SHOW_HELP: &str = r"DISCUSSION:
    Shows the name of the active toolchain and the version of `rustc`.

    If the active toolchain has installed support for additional
    compilation targets, then they are listed as well.

    If there are multiple toolchains installed then all installed
    toolchains are listed as well.";

pub static SHOW_ACTIVE_TOOLCHAIN_HELP: &str = r"DISCUSSION:
    Shows the name of the active toolchain.

    This is useful for figuring out the active tool chain from
    scripts.

    You should use `rustc --print sysroot` to get the sysroot, or
    `rustc --version` to get the toolchain version.";

pub static UPDATE_HELP: &str = r"DISCUSSION:
    With no toolchain specified, the `update` command updates each of
    the installed toolchains from the official release channels, then
    updates rustup itself.

    If given a toolchain argument then `update` updates that
    toolchain, the same as `rustup toolchain install`.";

pub static INSTALL_HELP: &str = r"DISCUSSION:
    Installs a specific rust toolchain.

    The 'install' command is an alias for 'rustup update <toolchain>'.";

pub static DEFAULT_HELP: &str = r"DISCUSSION:
    Sets the default toolchain to the one specified. If the toolchain
    is not already installed then it is installed first.";

pub static TOOLCHAIN_HELP: &str = r"DISCUSSION:
    Many `rustup` commands deal with *toolchains*, a single
    installation of the Rust compiler. `rustup` supports multiple
    types of toolchains. The most basic track the official release
    channels: 'stable', 'beta' and 'nightly'; but `rustup` can also
    install toolchains from the official archives, for alternate host
    platforms, and from local builds.

    Standard release channel toolchain names have the following form:

        <channel>[-<date>][-<host>]

        <channel>       = stable|beta|nightly|<major.minor>|<major.minor.patch>
        <date>          = YYYY-MM-DD
        <host>          = <target-triple>

    'channel' is a named release channel, a major and minor version
    number such as `1.42`, or a fully specified version number, such
    as `1.42.0`. Channel names can be optionally appended with an
    archive date, as in `nightly-2014-12-18`, in which case the
    toolchain is downloaded from the archive for that date.

    The host may be specified as a target triple. This is most useful
    for installing a 32-bit compiler on a 64-bit platform, or for
    installing the [MSVC-based toolchain] on Windows. For example:

        $ rustup toolchain install stable-x86_64-pc-windows-msvc

    For convenience, omitted elements of the target triple will be
    inferred, so the above could be written:

        $ rustup toolchain install stable-msvc

    The `rustup default` command may be used to both install and set
    the desired toolchain as default in a single command:

        $ rustup default stable-msvc

    rustup can also manage symlinked local toolchain builds, which are
    often used for developing Rust itself. For more information see
    `rustup toolchain help link`.";

pub static TOOLCHAIN_LINK_HELP: &str = r"DISCUSSION:
    'toolchain' is the custom name to be assigned to the new toolchain.
    Any name is permitted as long as it does not fully match an initial
    substring of a standard release channel. For example, you can use
    the names 'latest' or '2017-04-01' but you cannot use 'stable' or
    'beta-i686' or 'nightly-x86_64-unknown-linux-gnu'.

    'path' specifies the directory where the binaries and libraries for
    the custom toolchain can be found. For example, when used for
    development of Rust itself, toolchains can be linked directly out of
    the build directory. After building, you can test out different
    compiler versions as follows:

        $ rustup toolchain link latest-stage1 build/x86_64-unknown-linux-gnu/stage1
        $ rustup override set latest-stage1

    If you now compile a crate in the current directory, the custom
    toolchain 'latest-stage1' will be used.";

pub static OVERRIDE_HELP: &str = r"DISCUSSION:
    Overrides configure Rustup to use a specific toolchain when
    running in a specific directory.

    Directories can be assigned their own Rust toolchain with `rustup
    override`. When a directory has an override then any time `rustc`
    or `cargo` is run inside that directory, or one of its child
    directories, the override toolchain will be invoked.

    To pin to a specific nightly:

        $ rustup override set nightly-2014-12-18

    Or a specific stable release:

        $ rustup override set 1.0.0

    To see the active toolchain use `rustup show`. To remove the
    override and use the default toolchain again, `rustup override
    unset`.";

pub static OVERRIDE_UNSET_HELP: &str = r"DISCUSSION:
    If `--path` argument is present, removes the override toolchain
    for the specified directory. If `--nonexistent` argument is
    present, removes the override toolchain for all nonexistent
    directories. Otherwise, removes the override toolchain for the
    current directory.";

pub static RUN_HELP: &str = r"DISCUSSION:
    Configures an environment to use the given toolchain and then runs
    the specified program. The command may be any program, not just
    rustc or cargo. This can be used for testing arbitrary toolchains
    without setting an override.

    Commands explicitly proxied by `rustup` (such as `rustc` and
    `cargo`) also have a shorthand for this available. The toolchain
    can be set by using `+toolchain` as the first argument. These are
    equivalent:

        $ cargo +nightly build

        $ rustup run nightly cargo build";

pub static DOC_HELP: &str = r"DISCUSSION:
    Opens the documentation for the currently active toolchain with
    the default browser.

    By default, it opens the documentation index. Use the various
    flags to open specific pieces of documentation.";

pub static COMPLETIONS_HELP: &str = r"DISCUSSION:
    Enable tab completion for Bash, Fish, Zsh, or PowerShell
    The script is output on `stdout`, allowing one to re-direct the
    output to the file of their choosing. Where you place the file
    will depend on which shell, and which operating system you are
    using. Your particular configuration may also determine where
    these scripts need to be placed.

    Here are some common set ups for the three supported shells under
    Unix and similar operating systems (such as GNU/Linux).

    BASH:

    Completion files are commonly stored in `/etc/bash_completion.d/` for
    system-wide commands, but can be stored in
    `~/.local/share/bash-completion/completions` for user-specific commands.
    Run the command:

        $ mkdir -p ~/.local/share/bash-completion/completions
        $ rustup completions bash >> ~/.local/share/bash-completion/completions/rustup

    This installs the completion script. You may have to log out and
    log back in to your shell session for the changes to take effect.

    BASH (macOS/Homebrew):

    Homebrew stores bash completion files within the Homebrew directory.
    With the `bash-completion` brew formula installed, run the command:

        $ mkdir -p $(brew --prefix)/etc/bash_completion.d
        $ rustup completions bash > $(brew --prefix)/etc/bash_completion.d/rustup.bash-completion

    FISH:

    Fish completion files are commonly stored in
    `$HOME/.config/fish/completions`. Run the command:

        $ mkdir -p ~/.config/fish/completions
        $ rustup completions fish > ~/.config/fish/completions/rustup.fish

    This installs the completion script. You may have to log out and
    log back in to your shell session for the changes to take effect.

    ZSH:

    ZSH completions are commonly stored in any directory listed in
    your `$fpath` variable. To use these completions, you must either
    add the generated script to one of those directories, or add your
    own to this list.

    Adding a custom directory is often the safest bet if you are
    unsure of which directory to use. First create the directory; for
    this example we'll create a hidden directory inside our `$HOME`
    directory:

        $ mkdir ~/.zfunc

    Then add the following lines to your `.zshrc` just before
    `compinit`:

        fpath+=~/.zfunc

    Now you can install the completions script using the following
    command:

        $ rustup completions zsh > ~/.zfunc/_rustup

    You must then either log out and log back in, or simply run

        $ exec zsh

    for the new completions to take effect.

    CUSTOM LOCATIONS:

    Alternatively, you could save these files to the place of your
    choosing, such as a custom directory inside your $HOME. Doing so
    will require you to add the proper directives, such as `source`ing
    inside your login script. Consult your shells documentation for
    how to add such directives.

    POWERSHELL:

    The powershell completion scripts require PowerShell v5.0+ (which
    comes with Windows 10, but can be downloaded separately for windows 7
    or 8.1).

    First, check if a profile has already been set

        PS C:\> Test-Path $profile

    If the above command returns `False` run the following

        PS C:\> New-Item -path $profile -type file -force

    Now open the file provided by `$profile` (if you used the
    `New-Item` command it will be
    `${env:USERPROFILE}\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1`

    Next, we either save the completions file into our profile, or
    into a separate file and source it inside our profile. To save the
    completions into our profile simply use

        PS C:\> rustup completions powershell >> ${env:USERPROFILE}\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1

    CARGO:

    Rustup can also generate a completion script for `cargo`. The script output
    by `rustup` will source the completion script distributed with your default
    toolchain. Not all shells are currently supported. Here are examples for
    the currently supported shells.

    BASH:

        $ rustup completions bash cargo >> ~/.local/share/bash-completion/completions/cargo

    ZSH:

        $ rustup completions zsh cargo > ~/.zfunc/_cargo";

pub static TOOLCHAIN_ARG_HELP: &str = "Toolchain name, such as 'stable', 'nightly', \
                                       or '1.8.0'. For more information see `rustup \
                                       help toolchain`";

pub static TOPIC_ARG_HELP: &str = "Topic such as 'core', 'fn', 'usize', 'eprintln!', \
                                   'core::arch', 'alloc::format!', 'std::fs', \
                                   'std::fs::read_dir', 'std::io::Bytes', \
                                   'std::iter::Sum', 'std::io::error::Result' etc...";
<|endoftext|>


<commit_before>#[derive(Eq, PartialEq)]
enum Direction {
    North,
    East,
    South,
    West,
    Empty,
}

struct Table {
    w: i32,
    h: i32,
}

struct Robot {
    x: i32,
    y: i32,
    d: Direction,
    t: Table,
}

impl Direction {
    fn string(&self) -> String {
        let s = match *self {
            Direction::North => "North",
            Direction::East => "East",
            Direction::South => "South",
            Direction::West => "West",
            _ => "Empty",
        };

        s.to_string()
    }
}

impl Default for Robot {
    fn default() -> Robot {
        let table = Table{w: 5, h: 5};

        Robot{x: 0, y: 0, d: Direction::Empty, t: table}
    }
}

impl Table {
    fn valid_pos(&self, x: i32, y: i32) -> bool {
        x >= 0 && x < self.w && y >= 0 && y < self.h
    }
}

impl Robot {
    fn place(&mut self, x: i32, y: i32, d: Direction) {
        if self.t.valid_pos(x, y) {
            self.x = x;
            self.y = y;
            self.d = d;
        }
    }

    fn right(&mut self) {
        let d = match self.d {
            Direction::North => Direction::East,
            Direction::East => Direction::South,
            Direction::South => Direction::West,
            Direction::West => Direction::North,
            _ => Direction::Empty,
        };

        self.d = d;
    }

    fn left(&mut self) {
        let d = match self.d {
            Direction::North => Direction::West,
            Direction::West => Direction::South,
            Direction::South => Direction::East,
            Direction::East => Direction::North,
            _ => Direction::Empty,
        };

        self.d = d;
    }

    fn step(&mut self) {
        match self.d {
            Direction::North => if self.t.valid_pos(self.x, self.y + 1) {self.y += 1;},
            Direction::East => if self.t.valid_pos(self.x + 1, self.y) {self.x += 1;},
            Direction::South => if self.t.valid_pos(self.x, self.y - 1) {self.y -= 1;},
            Direction::West => if self.t.valid_pos(self.x - 1, self.y) {self.y -= 1;},
            _ => (),
        }
    }

    fn report(&self) {
        println!("{}, {}, {}", self.x, self.y, self.d.string());
    }
}

fn main() {
    let mut robot: Robot = Default::default();
}
<commit_msg>Kill space<commit_after>#[derive(Eq, PartialEq)]
enum Direction { North, East, South, West, Empty, }

struct Table {
    w: i32,
    h: i32,
}

struct Robot {
    x: i32,
    y: i32,
    d: Direction,
    t: Table,
}

impl Direction {
    fn string(&self) -> String {
        let s = match *self {
            Direction::North => "North",
            Direction::East => "East",
            Direction::South => "South",
            Direction::West => "West",
            _ => "Empty",
        };

        s.to_string()
    }
}

impl Default for Robot {
    fn default() -> Robot {
        let table = Table{w: 5, h: 5};

        Robot{x: 0, y: 0, d: Direction::Empty, t: table}
    }
}

impl Table {
    fn valid_pos(&self, x: i32, y: i32) -> bool {
        x >= 0 && x < self.w && y >= 0 && y < self.h
    }
}

impl Robot {
    fn place(&mut self, x: i32, y: i32, d: Direction) {
        if self.t.valid_pos(x, y) {
            self.x = x;
            self.y = y;
            self.d = d;
        }
    }

    fn right(&mut self) {
        let d = match self.d {
            Direction::North => Direction::East,
            Direction::East => Direction::South,
            Direction::South => Direction::West,
            Direction::West => Direction::North,
            _ => Direction::Empty,
        };

        self.d = d;
    }

    fn left(&mut self) {
        let d = match self.d {
            Direction::North => Direction::West,
            Direction::West => Direction::South,
            Direction::South => Direction::East,
            Direction::East => Direction::North,
            _ => Direction::Empty,
        };

        self.d = d;
    }

    fn step(&mut self) {
        match self.d {
            Direction::North => if self.t.valid_pos(self.x, self.y + 1) {self.y += 1;},
            Direction::East => if self.t.valid_pos(self.x + 1, self.y) {self.x += 1;},
            Direction::South => if self.t.valid_pos(self.x, self.y - 1) {self.y -= 1;},
            Direction::West => if self.t.valid_pos(self.x - 1, self.y) {self.y -= 1;},
            _ => (),
        }
    }

    fn report(&self) {
        println!("{}, {}, {}", self.x, self.y, self.d.string());
    }
}

fn main() {
    let mut robot: Robot = Default::default();
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

extern crate libc;

use self::libc::execvp;
use std::{env, thread};
use std::ptr::null;
use std::ffi::CString;
use std::process::Command;
use std::io::prelude::*;
use std::path::Path;
use std::fs::OpenOptions;
use config::Config;
use layout::LayoutMsg;
use xlib_window_system::XlibWindowSystem;
use workspaces::{Workspaces, MoveOp};
use xlib::Window;
use failure::*;

pub enum Cmd {
    Exec(String),
    SwitchWorkspace(usize),
    SwitchScreen(usize),
    MoveToWorkspace(usize),
    MoveToScreen(usize),
    SendLayoutMsg(LayoutMsg),
    Reload,
    Exit,
    KillClient,
    FocusUp,
    FocusDown,
    FocusMaster,
    SwapUp,
    SwapDown,
    SwapMaster,
}

impl Cmd {
    pub fn call(&self, ws: &XlibWindowSystem, workspaces: &mut Workspaces, config: &Config) -> Result<(), Error> {
        match *self {
            Cmd::Exec(ref cmd) => {
                debug!("Cmd::Exec: {}", cmd);
                exec(cmd.clone());
            }
            Cmd::SwitchWorkspace(index) => {
                debug!("Cmd::SwitchWorkspace: {}", index);
                workspaces.switch_to(ws, config, index - 1);
            }
            Cmd::SwitchScreen(screen) => {
                debug!("Cmd::SwitchScreen: {}", screen);
                workspaces.switch_to_screen(ws, config, screen - 1);
            }
            Cmd::MoveToWorkspace(index) => {
                debug!("Cmd::MoveToWorkspace: {}", index);
                workspaces.move_window_to(ws, config, index - 1);
            }
            Cmd::MoveToScreen(screen) => {
                debug!("Cmd::MoveToScreen: {}", screen);
                workspaces.move_window_to_screen(ws, config, screen - 1);
            }
            Cmd::SendLayoutMsg(ref msg) => {
                debug!("Cmd::SendLayoutMsg::{:?}", msg);
                workspaces.current_mut().send_layout_message(msg.clone());
                workspaces.current().redraw(ws, config);
            }
            Cmd::Reload => {
                debug!("Cmd::Reload");
                reload(workspaces)
                    .context("failed to reload xr3wm")?;
            }
            Cmd::Exit => {
                debug!("Cmd::Exit");
                ws.close();
            }
            Cmd::KillClient => {
                debug!("Cmd::KillClient: {}",
                       workspaces.current_mut().focused_window());
                ws.kill_window(workspaces.current_mut().focused_window());
            }
            Cmd::FocusUp => {
                debug!("Cmd::FocusUp: {}", workspaces.current().focused_window());
                workspaces.current_mut().move_focus(ws, config, MoveOp::Up);
            }
            Cmd::FocusDown => {
                debug!("Cmd::FocusDown: {}", workspaces.current().focused_window());
                workspaces.current_mut().move_focus(ws, config, MoveOp::Down);
            }
            Cmd::FocusMaster => {
                debug!("Cmd::FocusMaster: {}",
                       workspaces.current().focused_window());
                workspaces.current_mut().move_focus(ws, config, MoveOp::Swap);
            }
            Cmd::SwapUp => {
                debug!("Cmd::SwapUp: {}", workspaces.current().focused_window());
                workspaces.current_mut().move_window(ws, config, MoveOp::Up);
            }
            Cmd::SwapDown => {
                debug!("Cmd::SwapDown: {}", workspaces.current().focused_window());
                workspaces.current_mut().move_window(ws, config, MoveOp::Down);
            }
            Cmd::SwapMaster => {
                debug!("Cmd::SwapMaster: {}", workspaces.current().focused_window());
                workspaces.current_mut().move_window(ws, config, MoveOp::Swap);
            }
        }
        Ok(())
    }
}

fn reload(workspaces: &mut Workspaces) -> Result<(), Error> {
    let curr_exe = env::current_exe()
        .context("failed to get executable path")?;
    let filename = curr_exe.file_name()
        .ok_or_else(|| err_msg("failed to get executable filename"))?
        .to_str()
        .ok_or_else(|| err_msg("failed to convert filename to UTF-8"))?;

    info!("recompiling...");

    let config_build_dir = concat!(env!("HOME"), "/.xr3wm/.build");
    let mut cmd = Command::new("cargo");

    let output = cmd.current_dir(&config_build_dir)
        .arg("build")
        .env("RUST_LOG", "none")
        .output()
        .context("failed to run cargo")?;

    if !output.status.success() {
        let stderr_msg = String::from_utf8(output.stderr)
            .context("failed to convert cargo stderr to UTF-8")?;
        bail!(format_err!("failed to recompile: {}", stderr_msg))
    }

    debug!("Cmd::Reload: restarting xr3wm...");

    let filename = CString::new(filename.as_bytes())
        .context("failed to convert filename to CString")?;
    let args : &mut [*const i8; 2] = &mut [
        filename.as_ptr() as *const i8,
        null()
    ];

    let path = Path::new(concat!(env!("HOME"), "/.xr3wm/.tmp"));

    // save current workspace state to load on restart
    let mut file = OpenOptions::new()
        .create(true)
        .write(true)
        .truncate(true)
        .open(&path)
        .context("failed to open workspace state tmp file")?;
    file.write_all(workspaces.serialize().as_bytes())
        .context("failed to save workspace state")?;
    file.flush()
        .context("failed to flush workspace tmp file")?;

    let curr_exe_str = CString::new(curr_exe.to_str()
        .ok_or_else(|| err_msg("failed to convert executable path to UTF-8"))?
        .as_bytes())
        .context("failed to convert executable path to CString")?;

    unsafe {
        execvp(curr_exe_str.as_ptr() as *const i8, args.as_mut_ptr());
    }
    Ok(())
}

pub struct ManageHook {
    pub class_name: String,
    pub cmd: CmdManage,
}

pub enum CmdManage {
    Move(usize),
    Float,
    Fullscreen,
    Ignore,
}

impl CmdManage {
    pub fn call(&self,
                ws: &XlibWindowSystem,
                workspaces: &mut Workspaces,
                config: &Config,
                window: Window) {
        match *self {
            CmdManage::Move(index) => {
                if let Some(parent) = ws.transient_for(window) {
                    if let Some(workspace) = workspaces.find_window(parent) {
                        workspace.add_window(ws, config, window);
                        workspace.focus_window(ws, config, window);
                    }
                } else {
                    debug!("CmdManage::Move: {}, {}", window, index);
                    workspaces.get_mut(index - 1).add_window(ws, config, window);
                    workspaces.get_mut(index - 1).focus_window(ws, config, window);
                }
            }
            CmdManage::Float => {
                debug!("CmdManage::Float");
                unimplemented!()
            }
            CmdManage::Fullscreen => {
                debug!("CmdManage::Fullscreen");
                unimplemented!()
            }
            CmdManage::Ignore => {
                debug!("CmdManage::Ignore");
                unimplemented!()
            }
        }
    }
}

fn exec(cmd: String) {
    thread::spawn(move || {
        let args: Vec<&str> = cmd[..].split(' ').collect();

        if !args.is_empty() {
            let mut cmd = Command::new(args[0]);

            if args.len() > 1 {
                cmd.args(&args[1..]);
            }

            match cmd.output() {
                Ok(_) => (),
                _ => panic!("failed to start \"{:?}\"", cmd),
            }
        }
    });
}
<commit_msg>Fix missing arguments when reloading<commit_after>#![allow(dead_code)]

extern crate libc;

use self::libc::execvp;
use std::{env, thread};
use std::ptr::null;
use std::ffi::CString;
use std::process::Command;
use std::io::prelude::*;
use std::path::Path;
use std::fs::OpenOptions;
use config::Config;
use layout::LayoutMsg;
use xlib_window_system::XlibWindowSystem;
use workspaces::{Workspaces, MoveOp};
use xlib::Window;
use failure::*;

pub enum Cmd {
    Exec(String),
    SwitchWorkspace(usize),
    SwitchScreen(usize),
    MoveToWorkspace(usize),
    MoveToScreen(usize),
    SendLayoutMsg(LayoutMsg),
    Reload,
    Exit,
    KillClient,
    FocusUp,
    FocusDown,
    FocusMaster,
    SwapUp,
    SwapDown,
    SwapMaster,
}

impl Cmd {
    pub fn call(&self, ws: &XlibWindowSystem, workspaces: &mut Workspaces, config: &Config) -> Result<(), Error> {
        match *self {
            Cmd::Exec(ref cmd) => {
                debug!("Cmd::Exec: {}", cmd);
                exec(cmd.clone());
            }
            Cmd::SwitchWorkspace(index) => {
                debug!("Cmd::SwitchWorkspace: {}", index);
                workspaces.switch_to(ws, config, index - 1);
            }
            Cmd::SwitchScreen(screen) => {
                debug!("Cmd::SwitchScreen: {}", screen);
                workspaces.switch_to_screen(ws, config, screen - 1);
            }
            Cmd::MoveToWorkspace(index) => {
                debug!("Cmd::MoveToWorkspace: {}", index);
                workspaces.move_window_to(ws, config, index - 1);
            }
            Cmd::MoveToScreen(screen) => {
                debug!("Cmd::MoveToScreen: {}", screen);
                workspaces.move_window_to_screen(ws, config, screen - 1);
            }
            Cmd::SendLayoutMsg(ref msg) => {
                debug!("Cmd::SendLayoutMsg::{:?}", msg);
                workspaces.current_mut().send_layout_message(msg.clone());
                workspaces.current().redraw(ws, config);
            }
            Cmd::Reload => {
                debug!("Cmd::Reload");
                reload(workspaces)
                    .context("failed to reload xr3wm")?;
            }
            Cmd::Exit => {
                debug!("Cmd::Exit");
                ws.close();
            }
            Cmd::KillClient => {
                debug!("Cmd::KillClient: {}",
                       workspaces.current_mut().focused_window());
                ws.kill_window(workspaces.current_mut().focused_window());
            }
            Cmd::FocusUp => {
                debug!("Cmd::FocusUp: {}", workspaces.current().focused_window());
                workspaces.current_mut().move_focus(ws, config, MoveOp::Up);
            }
            Cmd::FocusDown => {
                debug!("Cmd::FocusDown: {}", workspaces.current().focused_window());
                workspaces.current_mut().move_focus(ws, config, MoveOp::Down);
            }
            Cmd::FocusMaster => {
                debug!("Cmd::FocusMaster: {}",
                       workspaces.current().focused_window());
                workspaces.current_mut().move_focus(ws, config, MoveOp::Swap);
            }
            Cmd::SwapUp => {
                debug!("Cmd::SwapUp: {}", workspaces.current().focused_window());
                workspaces.current_mut().move_window(ws, config, MoveOp::Up);
            }
            Cmd::SwapDown => {
                debug!("Cmd::SwapDown: {}", workspaces.current().focused_window());
                workspaces.current_mut().move_window(ws, config, MoveOp::Down);
            }
            Cmd::SwapMaster => {
                debug!("Cmd::SwapMaster: {}", workspaces.current().focused_window());
                workspaces.current_mut().move_window(ws, config, MoveOp::Swap);
            }
        }
        Ok(())
    }
}

fn reload(workspaces: &mut Workspaces) -> Result<(), Error> {
    let curr_exe = env::current_exe()
        .context("failed to get executable path")?;

    info!("recompiling...");

    let config_build_dir = concat!(env!("HOME"), "/.xr3wm/.build");
    let mut cmd = Command::new("cargo");

    let output = cmd.current_dir(&config_build_dir)
        .arg("build")
        .env("RUST_LOG", "none")
        .output()
        .context("failed to run cargo")?;

    if !output.status.success() {
        let stderr_msg = String::from_utf8(output.stderr)
            .context("failed to convert cargo stderr to UTF-8")?;
        bail!(format_err!("failed to recompile: {}", stderr_msg))
    }

    debug!("Cmd::Reload: restarting xr3wm...");

    let path = Path::new(concat!(env!("HOME"), "/.xr3wm/.tmp"));

    // save current workspace state to load on restart
    let mut file = OpenOptions::new()
        .create(true)
        .write(true)
        .truncate(true)
        .open(&path)
        .context("failed to open workspace state tmp file")?;
    file.write_all(workspaces.serialize().as_bytes())
        .context("failed to save workspace state")?;
    file.flush()
        .context("failed to flush workspace tmp file")?;

    let mut args: Vec<*const libc::c_char> = env::args()
        .filter_map(|x| CString::new(x).ok())
        .map(|x| x.into_raw() as *const libc::c_char)
        .collect();
    args.push(null());

    let curr_exe_str = CString::new(curr_exe.to_str()
        .ok_or_else(|| err_msg("failed to convert executable path to UTF-8"))?
        .as_bytes())
        .context("failed to convert executable path to CString")?;

    unsafe {
        execvp(curr_exe_str.as_ptr() as *const libc::c_char, args.as_ptr());
    }
    Ok(())
}

pub struct ManageHook {
    pub class_name: String,
    pub cmd: CmdManage,
}

pub enum CmdManage {
    Move(usize),
    Float,
    Fullscreen,
    Ignore,
}

impl CmdManage {
    pub fn call(&self,
                ws: &XlibWindowSystem,
                workspaces: &mut Workspaces,
                config: &Config,
                window: Window) {
        match *self {
            CmdManage::Move(index) => {
                if let Some(parent) = ws.transient_for(window) {
                    if let Some(workspace) = workspaces.find_window(parent) {
                        workspace.add_window(ws, config, window);
                        workspace.focus_window(ws, config, window);
                    }
                } else {
                    debug!("CmdManage::Move: {}, {}", window, index);
                    workspaces.get_mut(index - 1).add_window(ws, config, window);
                    workspaces.get_mut(index - 1).focus_window(ws, config, window);
                }
            }
            CmdManage::Float => {
                debug!("CmdManage::Float");
                unimplemented!()
            }
            CmdManage::Fullscreen => {
                debug!("CmdManage::Fullscreen");
                unimplemented!()
            }
            CmdManage::Ignore => {
                debug!("CmdManage::Ignore");
                unimplemented!()
            }
        }
    }
}

fn exec(cmd: String) {
    thread::spawn(move || {
        let args: Vec<&str> = cmd[..].split(' ').collect();

        if !args.is_empty() {
            let mut cmd = Command::new(args[0]);

            if args.len() > 1 {
                cmd.args(&args[1..]);
            }

            match cmd.output() {
                Ok(_) => (),
                _ => panic!("failed to start \"{:?}\"", cmd),
            }
        }
    });
}
<|endoftext|>


<commit_before>use std::fmt;
use std::fmt::{Show,Formatter};
use std::str;
use std::io::{UserDir,AllPermissions};
use std::io::fs::{mkdir_recursive,rmdir_recursive,chmod};
use serialize::{Encodable,Encoder};

use core::source::{Location, Local, Remote};
use util::{CargoResult, ChainError, ProcessBuilder, process, human};

#[deriving(PartialEq,Clone,Encodable)]
pub enum GitReference {
    Master,
    Other(String)
}

impl GitReference {
    pub fn for_str<S: Str>(string: S) -> GitReference {
        if string.as_slice() == "master" {
            Master
        } else {
            Other(string.as_slice().to_string())
        }
    }
}

impl Str for GitReference {
    fn as_slice<'a>(&'a self) -> &'a str {
        match *self {
            Master => "master",
            Other(ref string) => string.as_slice()
        }
    }
}

impl Show for GitReference {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        self.as_slice().fmt(f)
    }
}

macro_rules! git(
    ($config:expr, $str:expr, $($rest:expr),*) => (
        try!(git_inherit(&$config, format!($str, $($rest),*)))
    );

    ($config:expr, $str:expr) => (
        try!(git_inherit(&$config, format!($str)))
    );
)

macro_rules! git_output(
    ($config:expr, $str:expr, $($rest:expr),*) => ({
        try!(git_output(&$config, format!($str, $($rest),*)))
    });

    ($config:expr, $str:expr) => ({
        try!(git_output(&$config, format!($str)))
    });
)

macro_rules! errln(
    ($($arg:tt)*) => (let _ = writeln!(::std::io::stdio::stderr(), $($arg)*))
)

/// GitRemote represents a remote repository. It gets cloned into a local
/// GitDatabase.
#[deriving(PartialEq,Clone,Show)]
pub struct GitRemote {
    location: Location,
}

#[deriving(PartialEq,Clone,Encodable)]
struct EncodableGitRemote {
    location: String,
}

impl<E, S: Encoder<E>> Encodable<S, E> for GitRemote {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        EncodableGitRemote {
            location: self.location.to_string()
        }.encode(s)
    }
}

/// GitDatabase is a local clone of a remote repository's database. Multiple
/// GitCheckouts can be cloned from this GitDatabase.
#[deriving(PartialEq,Clone)]
pub struct GitDatabase {
    remote: GitRemote,
    path: Path,
}

#[deriving(Encodable)]
pub struct EncodableGitDatabase {
    remote: GitRemote,
    path: String,
}

impl<E, S: Encoder<E>> Encodable<S, E> for GitDatabase {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        EncodableGitDatabase {
            remote: self.remote.clone(),
            path: self.path.display().to_string()
        }.encode(s)
    }
}

/// GitCheckout is a local checkout of a particular revision. Calling
/// `clone_into` with a reference will resolve the reference into a revision,
/// and return a CargoError if no revision for that reference was found.
pub struct GitCheckout {
    database: GitDatabase,
    location: Path,
    reference: GitReference,
    revision: String,
}

#[deriving(Encodable)]
pub struct EncodableGitCheckout {
    database: GitDatabase,
    location: String,
    reference: String,
    revision: String,
}

impl<E, S: Encoder<E>> Encodable<S, E> for GitCheckout {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        EncodableGitCheckout {
            database: self.database.clone(),
            location: self.location.display().to_string(),
            reference: self.reference.to_string(),
            revision: self.revision.to_string()
        }.encode(s)
    }
}

// Implementations

impl GitRemote {
    pub fn new(location: &Location) -> GitRemote {
        GitRemote { location: location.clone() }
    }

    pub fn get_location<'a>(&'a self) -> &'a Location {
        &self.location
    }

    pub fn has_ref<S: Str>(&self, path: &Path, reference: S) -> CargoResult<()> {
        git_output!(*path, "rev-parse {}", reference.as_slice());
        Ok(())
    }

    pub fn checkout(&self, into: &Path) -> CargoResult<GitDatabase> {
        if into.exists() {
            try!(self.fetch_into(into));
        } else {
            try!(self.clone_into(into));
        }

        Ok(GitDatabase { remote: self.clone(), path: into.clone() })
    }

    pub fn db_at(&self, db_path: &Path) -> GitDatabase {
        GitDatabase { remote: self.clone(), path: db_path.clone() }
    }

    fn fetch_into(&self, path: &Path) -> CargoResult<()> {
        Ok(git!(*path, "fetch --force --quiet --tags {} \
                        refs/heads/*:refs/heads/*", self.fetch_location()))
    }

    fn clone_into(&self, path: &Path) -> CargoResult<()> {
        let dirname = Path::new(path.dirname());

        try!(mkdir_recursive(path, UserDir));

        Ok(git!(dirname, "clone {} {} --bare --no-hardlinks --quiet",
                self.fetch_location(), path.display()))
    }

    fn fetch_location(&self) -> String {
        match self.location {
            Local(ref p) => p.display().to_string(),
            Remote(ref u) => u.to_string(),
        }
    }
}

impl GitDatabase {
    fn get_path<'a>(&'a self) -> &'a Path {
        &self.path
    }

    pub fn copy_to<S: Str>(&self, reference: S,
                           dest: &Path) -> CargoResult<GitCheckout> {
        let checkout = try!(GitCheckout::clone_into(dest, self.clone(),
                                  GitReference::for_str(reference.as_slice())));

        try!(checkout.fetch());
        try!(checkout.update_submodules());

        Ok(checkout)
    }

    pub fn rev_for<S: Str>(&self, reference: S) -> CargoResult<String> {
        Ok(git_output!(self.path, "rev-parse {}", reference.as_slice()))
    }

}

impl GitCheckout {
    fn clone_into(into: &Path, database: GitDatabase,
                  reference: GitReference) -> CargoResult<GitCheckout> {
        let revision = try!(database.rev_for(reference.as_slice()));
        let checkout = GitCheckout {
            location: into.clone(),
            database: database,
            reference: reference,
            revision: revision,
        };

        // If the git checkout already exists, we don't need to clone it again
        if !checkout.location.join(".git").exists() {
            try!(checkout.clone_repo());
        }

        Ok(checkout)
    }

    fn get_source<'a>(&'a self) -> &'a Path {
        self.database.get_path()
    }

    fn clone_repo(&self) -> CargoResult<()> {
        let dirname = Path::new(self.location.dirname());

        try!(mkdir_recursive(&dirname, UserDir).chain_error(|| {
            human(format!("Couldn't mkdir {}",
                          Path::new(self.location.dirname()).display()))
        }));

        if self.location.exists() {
            try!(rmdir_recursive(&self.location).chain_error(|| {
                human(format!("Couldn't rmdir {}",
                              Path::new(&self.location).display()))
            }));
        }

        git!(dirname, "clone --no-checkout --quiet {} {}",
             self.get_source().display(), self.location.display());
        try!(chmod(&self.location, AllPermissions));

        Ok(())
    }

    fn fetch(&self) -> CargoResult<()> {
        // In git 1.8, apparently --tags explicitly *only* fetches tags, it does
        // not fetch anything else. In git 1.9, however, git apparently fetches
        // everything when --tags is passed.
        //
        // This means that if we want to fetch everything we need to execute
        // both with and without --tags on 1.8 (apparently), and only with
        // --tags on 1.9. For simplicity, we execute with and without --tags for
        // all gits.
        //
        // FIXME: This is suspicious. I have been informed that, for example,
        //        bundler does not do this, yet bundler appears to work!
        //
        // And to continue the fun, git before 1.7.3 had the fun bug that if a
        // branch was tracking a remote, then `git fetch $url` doesn't work!
        //
        // For details, see
        // https://www.kernel.org/pub/software/scm/git/docs/RelNotes-1.7.3.txt
        //
        // In this case we just use `origin` here instead of the database path.
        git!(self.location, "fetch --force --quiet origin");
        git!(self.location, "fetch --force --quiet --tags origin");
        try!(self.reset(self.revision.as_slice()));
        Ok(())
    }

    fn reset<T: Show>(&self, revision: T) -> CargoResult<()> {
        Ok(git!(self.location, "reset -q --hard {}", revision))
    }

    fn update_submodules(&self) -> CargoResult<()> {
        Ok(git!(self.location, "submodule update --init --recursive --quiet"))
    }
}

fn git(path: &Path, str: &str) -> ProcessBuilder {
    debug!("Executing git {} @ {}", str, path.display());

    process("git").args(str.split(' ').collect::<Vec<&str>>().as_slice())
                  .cwd(path.clone())
}

fn git_inherit(path: &Path, str: String) -> CargoResult<()> {
    git(path, str.as_slice()).exec().chain_error(|| {
        human(format!("Executing `git {}` failed", str))
    })
}

fn git_output(path: &Path, str: String) -> CargoResult<String> {
    let output = try!(git(path, str.as_slice()).exec_with_output()
                                                     .chain_error(||
        human(format!("Executing `git {}` failed", str))));

    Ok(to_str(output.output.as_slice()).as_slice().trim_right().to_string())
}

fn to_str(vec: &[u8]) -> String {
    str::from_utf8_lossy(vec).to_string()
}

<commit_msg>auto merge of #57 : ebfe/cargo/git-chmod, r=alexcrichton<commit_after>use std::fmt;
use std::fmt::{Show,Formatter};
use std::str;
use std::io::{UserDir};
use std::io::fs::{mkdir_recursive,rmdir_recursive};
use serialize::{Encodable,Encoder};

use core::source::{Location, Local, Remote};
use util::{CargoResult, ChainError, ProcessBuilder, process, human};

#[deriving(PartialEq,Clone,Encodable)]
pub enum GitReference {
    Master,
    Other(String)
}

impl GitReference {
    pub fn for_str<S: Str>(string: S) -> GitReference {
        if string.as_slice() == "master" {
            Master
        } else {
            Other(string.as_slice().to_string())
        }
    }
}

impl Str for GitReference {
    fn as_slice<'a>(&'a self) -> &'a str {
        match *self {
            Master => "master",
            Other(ref string) => string.as_slice()
        }
    }
}

impl Show for GitReference {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        self.as_slice().fmt(f)
    }
}

macro_rules! git(
    ($config:expr, $str:expr, $($rest:expr),*) => (
        try!(git_inherit(&$config, format!($str, $($rest),*)))
    );

    ($config:expr, $str:expr) => (
        try!(git_inherit(&$config, format!($str)))
    );
)

macro_rules! git_output(
    ($config:expr, $str:expr, $($rest:expr),*) => ({
        try!(git_output(&$config, format!($str, $($rest),*)))
    });

    ($config:expr, $str:expr) => ({
        try!(git_output(&$config, format!($str)))
    });
)

macro_rules! errln(
    ($($arg:tt)*) => (let _ = writeln!(::std::io::stdio::stderr(), $($arg)*))
)

/// GitRemote represents a remote repository. It gets cloned into a local
/// GitDatabase.
#[deriving(PartialEq,Clone,Show)]
pub struct GitRemote {
    location: Location,
}

#[deriving(PartialEq,Clone,Encodable)]
struct EncodableGitRemote {
    location: String,
}

impl<E, S: Encoder<E>> Encodable<S, E> for GitRemote {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        EncodableGitRemote {
            location: self.location.to_string()
        }.encode(s)
    }
}

/// GitDatabase is a local clone of a remote repository's database. Multiple
/// GitCheckouts can be cloned from this GitDatabase.
#[deriving(PartialEq,Clone)]
pub struct GitDatabase {
    remote: GitRemote,
    path: Path,
}

#[deriving(Encodable)]
pub struct EncodableGitDatabase {
    remote: GitRemote,
    path: String,
}

impl<E, S: Encoder<E>> Encodable<S, E> for GitDatabase {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        EncodableGitDatabase {
            remote: self.remote.clone(),
            path: self.path.display().to_string()
        }.encode(s)
    }
}

/// GitCheckout is a local checkout of a particular revision. Calling
/// `clone_into` with a reference will resolve the reference into a revision,
/// and return a CargoError if no revision for that reference was found.
pub struct GitCheckout {
    database: GitDatabase,
    location: Path,
    reference: GitReference,
    revision: String,
}

#[deriving(Encodable)]
pub struct EncodableGitCheckout {
    database: GitDatabase,
    location: String,
    reference: String,
    revision: String,
}

impl<E, S: Encoder<E>> Encodable<S, E> for GitCheckout {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        EncodableGitCheckout {
            database: self.database.clone(),
            location: self.location.display().to_string(),
            reference: self.reference.to_string(),
            revision: self.revision.to_string()
        }.encode(s)
    }
}

// Implementations

impl GitRemote {
    pub fn new(location: &Location) -> GitRemote {
        GitRemote { location: location.clone() }
    }

    pub fn get_location<'a>(&'a self) -> &'a Location {
        &self.location
    }

    pub fn has_ref<S: Str>(&self, path: &Path, reference: S) -> CargoResult<()> {
        git_output!(*path, "rev-parse {}", reference.as_slice());
        Ok(())
    }

    pub fn checkout(&self, into: &Path) -> CargoResult<GitDatabase> {
        if into.exists() {
            try!(self.fetch_into(into));
        } else {
            try!(self.clone_into(into));
        }

        Ok(GitDatabase { remote: self.clone(), path: into.clone() })
    }

    pub fn db_at(&self, db_path: &Path) -> GitDatabase {
        GitDatabase { remote: self.clone(), path: db_path.clone() }
    }

    fn fetch_into(&self, path: &Path) -> CargoResult<()> {
        Ok(git!(*path, "fetch --force --quiet --tags {} \
                        refs/heads/*:refs/heads/*", self.fetch_location()))
    }

    fn clone_into(&self, path: &Path) -> CargoResult<()> {
        let dirname = Path::new(path.dirname());

        try!(mkdir_recursive(path, UserDir));

        Ok(git!(dirname, "clone {} {} --bare --no-hardlinks --quiet",
                self.fetch_location(), path.display()))
    }

    fn fetch_location(&self) -> String {
        match self.location {
            Local(ref p) => p.display().to_string(),
            Remote(ref u) => u.to_string(),
        }
    }
}

impl GitDatabase {
    fn get_path<'a>(&'a self) -> &'a Path {
        &self.path
    }

    pub fn copy_to<S: Str>(&self, reference: S,
                           dest: &Path) -> CargoResult<GitCheckout> {
        let checkout = try!(GitCheckout::clone_into(dest, self.clone(),
                                  GitReference::for_str(reference.as_slice())));

        try!(checkout.fetch());
        try!(checkout.update_submodules());

        Ok(checkout)
    }

    pub fn rev_for<S: Str>(&self, reference: S) -> CargoResult<String> {
        Ok(git_output!(self.path, "rev-parse {}", reference.as_slice()))
    }

}

impl GitCheckout {
    fn clone_into(into: &Path, database: GitDatabase,
                  reference: GitReference) -> CargoResult<GitCheckout> {
        let revision = try!(database.rev_for(reference.as_slice()));
        let checkout = GitCheckout {
            location: into.clone(),
            database: database,
            reference: reference,
            revision: revision,
        };

        // If the git checkout already exists, we don't need to clone it again
        if !checkout.location.join(".git").exists() {
            try!(checkout.clone_repo());
        }

        Ok(checkout)
    }

    fn get_source<'a>(&'a self) -> &'a Path {
        self.database.get_path()
    }

    fn clone_repo(&self) -> CargoResult<()> {
        let dirname = Path::new(self.location.dirname());

        try!(mkdir_recursive(&dirname, UserDir).chain_error(|| {
            human(format!("Couldn't mkdir {}",
                          Path::new(self.location.dirname()).display()))
        }));

        if self.location.exists() {
            try!(rmdir_recursive(&self.location).chain_error(|| {
                human(format!("Couldn't rmdir {}",
                              Path::new(&self.location).display()))
            }));
        }

        git!(dirname, "clone --no-checkout --quiet {} {}",
             self.get_source().display(), self.location.display());

        Ok(())
    }

    fn fetch(&self) -> CargoResult<()> {
        // In git 1.8, apparently --tags explicitly *only* fetches tags, it does
        // not fetch anything else. In git 1.9, however, git apparently fetches
        // everything when --tags is passed.
        //
        // This means that if we want to fetch everything we need to execute
        // both with and without --tags on 1.8 (apparently), and only with
        // --tags on 1.9. For simplicity, we execute with and without --tags for
        // all gits.
        //
        // FIXME: This is suspicious. I have been informed that, for example,
        //        bundler does not do this, yet bundler appears to work!
        //
        // And to continue the fun, git before 1.7.3 had the fun bug that if a
        // branch was tracking a remote, then `git fetch $url` doesn't work!
        //
        // For details, see
        // https://www.kernel.org/pub/software/scm/git/docs/RelNotes-1.7.3.txt
        //
        // In this case we just use `origin` here instead of the database path.
        git!(self.location, "fetch --force --quiet origin");
        git!(self.location, "fetch --force --quiet --tags origin");
        try!(self.reset(self.revision.as_slice()));
        Ok(())
    }

    fn reset<T: Show>(&self, revision: T) -> CargoResult<()> {
        Ok(git!(self.location, "reset -q --hard {}", revision))
    }

    fn update_submodules(&self) -> CargoResult<()> {
        Ok(git!(self.location, "submodule update --init --recursive --quiet"))
    }
}

fn git(path: &Path, str: &str) -> ProcessBuilder {
    debug!("Executing git {} @ {}", str, path.display());

    process("git").args(str.split(' ').collect::<Vec<&str>>().as_slice())
                  .cwd(path.clone())
}

fn git_inherit(path: &Path, str: String) -> CargoResult<()> {
    git(path, str.as_slice()).exec().chain_error(|| {
        human(format!("Executing `git {}` failed", str))
    })
}

fn git_output(path: &Path, str: String) -> CargoResult<String> {
    let output = try!(git(path, str.as_slice()).exec_with_output()
                                                     .chain_error(||
        human(format!("Executing `git {}` failed", str))));

    Ok(to_str(output.output.as_slice()).as_slice().trim_right().to_string())
}

fn to_str(vec: &[u8]) -> String {
    str::from_utf8_lossy(vec).to_string()
}

<|endoftext|>


<commit_before>extern crate resp;
extern crate rusqlite;

use self::resp::{Value};
use self::rusqlite::{Connection, Error};
use std::sync::{Arc, Mutex, MutexGuard};

struct Command<'a> {
    name: String,
    arguments: Vec<&'a String>,
    connection_mutex: &'a Arc<Mutex<Connection>>
}

struct CommandSettings {
    name: &'static str,
    argument_count: i32,
    //handler: fn(&'a Command<'a>) -> Result<Value, &'static str>
}

const COMMAND_SETTINGS: [CommandSettings; 5] = [
    CommandSettings { name: "LLEN", argument_count: 1 }, //, handler: Command::llen }
    CommandSettings { name: "LPOP", argument_count: 1 },
    CommandSettings { name: "RPOP", argument_count: 1 },
    CommandSettings { name: "LPUSH", argument_count: -2 },
    CommandSettings { name: "RPUSH", argument_count: -2 },
];

pub fn handle_input(ref value: Value, connection_mutex: &Arc<Mutex<Connection>>) -> (Value, bool) {
    match parse_command(value, connection_mutex) {
        Ok(mut command) => { command.handle_command() }
        Err(error)  => { (Value::Error(format!("ERR {}", error)), false) }
    }
}

fn parse_command<'a>(value: &'a Value, connection_mutex: &'a Arc<Mutex<Connection>>) -> Result<Command<'a>, &'static str> {
    if let &Value::Array(ref array) = value {
        parse_command_array(array, connection_mutex)
    }
    else {
        Err("expected array")
    }
}

fn parse_command_array<'a>(array: &'a Vec<Value>, connection_mutex: &'a Arc<Mutex<Connection>>) -> Result<Command<'a>, &'static str> {
    let iter = array.iter().map(|value|
        match *value {
            Value::String(ref string) | Value::Bulk(ref string) => Ok(string),
            _ => Err("all arguments should be strings")
        }
    );

    let strings = iter.collect::<Result<Vec<&String>, &'static str>>()?;
    let (head, tail) = strings.split_at(1);

    Ok(Command {
        name: head[0].to_uppercase(),
        arguments: tail.to_vec(),
        connection_mutex: connection_mutex
    })
}

impl<'a> Command<'a> {
    fn handle_command(&mut self) -> (Value, bool) {
        print!("command {}\n", self.name);

        match self.name.as_ref() {
            "QUIT" => (Value::String("OK".to_string()), true),
            _      => (self.handle_nonterminal_command(), false)
        }
    }

    fn valid_argument_count(&self, command: &CommandSettings) -> bool {
        (command.argument_count < 0 && self.arguments.len() as i32 >= -command.argument_count) ||
            (command.argument_count >= 0 && self.arguments.len() as i32 == command.argument_count)
    }

    fn handle_nonterminal_command(&mut self) -> Value {
        let all = COMMAND_SETTINGS;
        let settings = all.iter().find(|settings| settings.name == self.name);

        match settings {
            Some(settings) => {
                if self.valid_argument_count(settings) {
                    let result = match settings.name {
                        "LLEN" => self.llen(),
                        "LPUSH" => self.lpush(),
                        "RPUSH" => self.rpush(),
                        "LPOP" => self.lpop(),
                        "RPOP" => self.rpop(),
                        _ => unimplemented!(),
                    };

                    match result {
                        Ok(value)  => value,
                        Err(error) => Value::Error(format!("ERR {}", error))
                    }
                }
                else {
                    Value::Error("ERR wrong number of arguments".to_string())
                }
            }

            None => Value::Error("ERR unsupported".to_string())
        }
    }

    fn llen(&self) -> Result<Value, &'static str> {
        let key = self.arguments[0];

        let connection = self.lock_connection();
        self.count_list_items(&*connection, key)
    }

    fn lpop(&self) -> Result<Value, &'static str> {
        self.pop("ASC")
    }

    fn rpop(&self) -> Result<Value, &'static str> {
        self.pop("DESC")
    }

    fn lpush(&self) -> Result<Value, &'static str> {
        let key = self.arguments[0];
        let value = self.arguments[1];

        let connection = self.lock_connection();
        connection.execute("INSERT INTO list_items (key, value, position) SELECT ?1, ?2, coalesce(MIN(position), 0) - 1 FROM list_items WHERE key = ?1", &[key, value]).unwrap();

        self.count_list_items(&*connection, key)
    }

    fn rpush(&self) -> Result<Value, &'static str> {
        let key = self.arguments[0];

        let mut connection = self.lock_connection();

        {
            let tx = connection.transaction().unwrap();

            self.arguments.iter().skip(1).map(|value|
                tx.execute("INSERT INTO list_items (key, value, position) SELECT ?1, ?2, coalesce(MAX(position), 0) + 1 FROM list_items WHERE key = ?1", &[key, *value])
            ).collect::<Result<Vec<_>, _>>().unwrap();

            tx.commit().unwrap();
        }

        self.count_list_items(&*connection, key)
    }

    // private

    fn pop(&self, order: &'static str) -> Result<Value, &'static str> {
        let key = self.arguments[0];

        let connection = self.lock_connection();
        let mut statement = connection.prepare(&format!("SELECT id, value FROM list_items WHERE key = ?1 ORDER BY position {} LIMIT 1", order)).unwrap();

        match statement.query_row(&[key], |row| (row.get(0), row.get(1))) {
            Ok(result) => {
                let (id, value): (i64, String) = result;

                connection.execute("DELETE FROM list_items WHERE id = ?1", &[&id]).unwrap();
                Ok(Value::Bulk(value))
            }

            Err(Error::QueryReturnedNoRows) => Ok(Value::NullArray),

            Err(e) => Err(e).unwrap()
        }
    }

    fn lock_connection(&self) -> MutexGuard<Connection> {
        (*self.connection_mutex).lock().unwrap()
    }

    fn count_list_items(&self, connection: &Connection, key: &String) -> Result<Value, &'static str> {
        let mut statement = connection.prepare("SELECT COUNT(*) AS c FROM list_items WHERE key = ?1").unwrap();
        let count = statement.query_row(&[key], |row| row.get(0)).unwrap();

        Ok(Value::Integer(count))
    }
}
<commit_msg>lrange<commit_after>extern crate resp;
extern crate rusqlite;

use self::resp::{Value};
use self::rusqlite::{Connection};
use std::sync::{Arc, Mutex, MutexGuard};
use std::cmp;

type CommandResult = Result<Value, String>;

struct Command<'a> {
    name: String,
    arguments: Vec<&'a String>,
    connection_mutex: &'a Arc<Mutex<Connection>>
}

struct CommandSettings {
    name: &'static str,
    argument_count: i32,
    //handler: fn(&'a Command<'a>) -> CommandResult
}

const COMMAND_SETTINGS: [CommandSettings; 6] = [
    CommandSettings { name: "LLEN", argument_count: 1 }, //, handler: Command::llen }
    CommandSettings { name: "LPOP", argument_count: 1 },
    CommandSettings { name: "RPOP", argument_count: 1 },
    CommandSettings { name: "LPUSH", argument_count: -2 },
    CommandSettings { name: "RPUSH", argument_count: -2 },
    CommandSettings { name: "LRANGE", argument_count: 3 },
];

pub fn handle_input(ref value: Value, connection_mutex: &Arc<Mutex<Connection>>) -> (Value, bool) {
    match parse_command(value, connection_mutex) {
        Ok(mut command) => { command.handle_command() }
        Err(error)  => { (Value::Error(format!("ERR {}", error)), false) }
    }
}

fn parse_command<'a>(value: &'a Value, connection_mutex: &'a Arc<Mutex<Connection>>) -> Result<Command<'a>, &'static str> {
    if let &Value::Array(ref array) = value {
        parse_command_array(array, connection_mutex)
    }
    else {
        Err("expected array")
    }
}

fn parse_command_array<'a>(array: &'a Vec<Value>, connection_mutex: &'a Arc<Mutex<Connection>>) -> Result<Command<'a>, &'static str> {
    let iter = array.iter().map(|value|
        match *value {
            Value::String(ref string) | Value::Bulk(ref string) => Ok(string),
            _ => Err("all arguments should be strings")
        }
    );

    let strings = iter.collect::<Result<Vec<&String>, &'static str>>()?;
    let (head, tail) = strings.split_at(1);

    Ok(Command {
        name: head[0].to_uppercase(),
        arguments: tail.to_vec(),
        connection_mutex: connection_mutex
    })
}

impl<'a> Command<'a> {
    fn handle_command(&mut self) -> (Value, bool) {
        print!("command {}\n", self.name);

        match self.name.as_ref() {
            "QUIT" => (Value::String("OK".to_string()), true),
            _      => (self.handle_nonterminal_command(), false)
        }
    }

    fn valid_argument_count(&self, command: &CommandSettings) -> bool {
        (command.argument_count < 0 && self.arguments.len() as i32 >= -command.argument_count) ||
            (command.argument_count >= 0 && self.arguments.len() as i32 == command.argument_count)
    }

    fn handle_nonterminal_command(&mut self) -> Value {
        let all = COMMAND_SETTINGS;
        let settings = all.iter().find(|settings| settings.name == self.name);

        match settings {
            Some(settings) => {
                if self.valid_argument_count(settings) {
                    let result = match settings.name {
                        "LLEN" => self.llen(),
                        "LPUSH" => self.lpush(),
                        "RPUSH" => self.rpush(),
                        "LPOP" => self.lpop(),
                        "RPOP" => self.rpop(),
                        "LRANGE" => self.lrange(),
                        _ => unimplemented!(),
                    };

                    match result {
                        Ok(value)  => value,
                        Err(error) => Value::Error(format!("ERR {}", error))
                    }
                }
                else {
                    Value::Error("ERR wrong number of arguments".to_string())
                }
            }

            None => Value::Error("ERR unsupported".to_string())
        }
    }

    fn llen(&self) -> CommandResult {
        let key = self.arguments[0];

        let connection = self.lock_connection();
        self.count_list_items_value(&*connection, key)
    }

    fn lpop(&self) -> CommandResult {
        self.pop("ASC")
    }

    fn rpop(&self) -> CommandResult {
        self.pop("DESC")
    }

    fn lpush(&self) -> CommandResult {
        let key = self.arguments[0];
        let value = self.arguments[1];

        let connection = self.lock_connection();
        connection.execute("INSERT INTO list_items (key, value, position) SELECT ?1, ?2, coalesce(MIN(position), 0) - 1 FROM list_items WHERE key = ?1", &[key, value]).unwrap();

        self.count_list_items_value(&*connection, key)
    }

    fn rpush(&self) -> CommandResult {
        let key = self.arguments[0];

        let mut connection = self.lock_connection();

        {
            let tx = connection.transaction().unwrap();

            self.arguments.iter().skip(1).map(|value|
                tx.execute("INSERT INTO list_items (key, value, position) SELECT ?1, ?2, coalesce(MAX(position), 0) + 1 FROM list_items WHERE key = ?1", &[key, *value])
            ).collect::<Result<Vec<_>, _>>().unwrap();

            tx.commit().unwrap();
        }

        self.count_list_items_value(&*connection, key)
    }

    fn lrange(&self) -> CommandResult {
        let key = self.arguments[0];
        let mut start: i64 = self.arguments[1].parse().map_err(|_| "start must be an integer")?;
        let mut stop: i64 = self.arguments[2].parse().map_err(|_| "stop must be an integer")?;

        let connection = self.lock_connection();

        if start < 0 || stop < -1 {
            let count = self.count_list_items(&connection, key);

            if start < 0  { start = cmp::max(0, count + start) }

            if stop < -1 {
                stop = count + stop;
                if stop < 0 { return Ok(Value::Array(vec![])); }
            }
        }

        if stop != -1 && start > stop { return Ok(Value::Array(vec![])); }

        let sql = match (start, stop) {
            (0, -1) => "".to_string(),
            (a, -1) => format!("LIMIT -1 OFFSET {}", a),
            (0, b)  => format!("LIMIT {}", b + 1),
            (a, b)  => format!("LIMIT {} OFFSET {}", b - a + 1, a),
        };

        let mut statement = connection.prepare(&format!("SELECT value FROM list_items WHERE key = ?1 ORDER BY position {}", sql)).unwrap();
        let rows = statement.query_map(&[key], |row| row.get(0)).unwrap();
        let result: Result<Vec<String>, _> = rows.collect();
        let values = result.unwrap().iter().map(|value| Value::String(value.clone())).collect();

        Ok(Value::Array(values))
    }

    // private

    fn pop(&self, order: &'static str) -> CommandResult {
        let key = self.arguments[0];

        let connection = self.lock_connection();
        let mut statement = connection.prepare(&format!("SELECT id, value FROM list_items WHERE key = ?1 ORDER BY position {} LIMIT 1", order)).unwrap();

        match statement.query_row(&[key], |row| (row.get(0), row.get(1))) {
            Ok(result) => {
                let (id, value): (i64, String) = result;

                connection.execute("DELETE FROM list_items WHERE id = ?1", &[&id]).unwrap();
                Ok(Value::Bulk(value))
            }

            Err(rusqlite::Error::QueryReturnedNoRows) => Ok(Value::NullArray),

            Err(e) => Err(e).unwrap()
        }
    }

    fn lock_connection(&self) -> MutexGuard<Connection> {
        (*self.connection_mutex).lock().unwrap()
    }

    fn count_list_items(&self, connection: &Connection, key: &String) -> i64 {
        let mut statement = connection.prepare("SELECT COUNT(*) AS c FROM list_items WHERE key = ?1").unwrap();
        statement.query_row(&[key], |row| row.get(0)).unwrap()
    }

    fn count_list_items_value(&self, connection: &Connection, key: &String) -> CommandResult {
        Ok(Value::Integer(self.count_list_items(connection, key)))
    }
}
<|endoftext|>


<commit_before>// src/controllers/test_controller.rs

/// Test Controller

//Import
//External
use nickel::{JsonBody, Request};
//Utilities
use ::dao::dao_manager::DAOManager;
use ::common::api_result::{ApiResult};
//Models
use ::models::test_model::{TestModel};
//Controllers
use ::controllers::controller_manager::ControllerManager;

#[derive(Clone)]
pub struct TestController{
    dao_manager: DAOManager
}

impl TestController{

    pub fn new(dao_manager: DAOManager) -> TestController{
        TestController{
            dao_manager: dao_manager
        }
    }

    /// Retrieve a Test
    ///
    /// # Arguments
    /// &self
    ///
    /// # Returns
    /// `APIResult` - Result
    pub fn retrieve(&self) -> ApiResult<TestModel>{
        let test = TestModel{
            field_1: Some(String::from("Field One")),
            field_2: Some(String::from("Field Two")),
            field_3: Some(String::from("Field Three"))
        };
        ApiResult::Success{result:test}
    }//end retrieve

    /// Imitate Saving a Test object
    /// Performs validation and returns result. Does not perform an actual save to the DB
    ///
    /// # Arguments
    /// &self
    /// req - nickel::Request
    ///
    /// # Returns
    /// `APIResult` - Result
    pub fn save(&self, req: &mut Request<ControllerManager>) -> ApiResult<TestModel>{
        let result;
        match req.json_as::<TestModel>(){
            Ok(mut test) => {
                let validationResult = test.validate();

                if validationResult.is_valid(){
                    result = ApiResult::Success{result:test}
                }else{
                    result = ApiResult::Invalid{validation:validationResult, request:test}
                }
            },
            Err(e) => {
                error!("{}",e);
                result = ApiResult::Failure{msg:"Invalid format. Unable to parse data."}
            }
        }
        result
    }//end save

    /// Imitate a hard failure
    /// Returns failure ApiResult
    ///
    /// # Arguments
    /// &self
    /// req - nickel::Request
    ///
    /// # Returns
    /// `APIResult` - Result
    pub fn failure(&self) -> ApiResult<TestModel>{
        error!("(Test) Fatal error occurred");
        ApiResult::Failure{msg:"Fatal error occurred"}
    }

}
<commit_msg>Remove unused mutability from test var<commit_after>// src/controllers/test_controller.rs

/// Test Controller

//Import
//External
use nickel::{JsonBody, Request};
//Utilities
use ::dao::dao_manager::DAOManager;
use ::common::api_result::{ApiResult};
//Models
use ::models::test_model::{TestModel};
//Controllers
use ::controllers::controller_manager::ControllerManager;

#[derive(Clone)]
pub struct TestController{
    dao_manager: DAOManager
}

impl TestController{

    pub fn new(dao_manager: DAOManager) -> TestController{
        TestController{
            dao_manager: dao_manager
        }
    }

    /// Retrieve a Test
    ///
    /// # Arguments
    /// &self
    ///
    /// # Returns
    /// `APIResult` - Result
    pub fn retrieve(&self) -> ApiResult<TestModel>{
        let test = TestModel{
            field_1: Some(String::from("Field One")),
            field_2: Some(String::from("Field Two")),
            field_3: Some(String::from("Field Three"))
        };
        ApiResult::Success{result:test}
    }//end retrieve

    /// Imitate Saving a Test object
    /// Performs validation and returns result. Does not perform an actual save to the DB
    ///
    /// # Arguments
    /// &self
    /// req - nickel::Request
    ///
    /// # Returns
    /// `APIResult` - Result
    pub fn save(&self, req: &mut Request<ControllerManager>) -> ApiResult<TestModel>{
        let result;
        match req.json_as::<TestModel>(){
            Ok(test) => {
                let validationResult = test.validate();

                if validationResult.is_valid(){
                    result = ApiResult::Success{result:test}
                }else{
                    result = ApiResult::Invalid{validation:validationResult, request:test}
                }
            },
            Err(e) => {
                error!("{}",e);
                result = ApiResult::Failure{msg:"Invalid format. Unable to parse data."}
            }
        }
        result
    }//end save

    /// Imitate a hard failure
    /// Returns failure ApiResult
    ///
    /// # Arguments
    /// &self
    /// req - nickel::Request
    ///
    /// # Returns
    /// `APIResult` - Result
    pub fn failure(&self) -> ApiResult<TestModel>{
        error!("(Test) Fatal error occurred");
        ApiResult::Failure{msg:"Fatal error occurred"}
    }

}
<|endoftext|>