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

use std::{
    fs::File,
    io::{Read, Write},
    panic::RefUnwindSafe,
    path::{Path, PathBuf},
    sync::Mutex,
};

use autocxx_engine::{Builder, BuilderContext, BuilderError, RebuildDependencyRecorder, HEADER};
use log::info;
use once_cell::sync::OnceCell;
use proc_macro2::{Span, TokenStream};
use quote::{quote, TokenStreamExt};
use syn::Token;
use tempfile::{tempdir, TempDir};

const KEEP_TEMPDIRS: bool = false;

fn get_builder() -> &'static Mutex<LinkableTryBuilder> {
    static INSTANCE: OnceCell<Mutex<LinkableTryBuilder>> = OnceCell::new();
    INSTANCE.get_or_init(|| Mutex::new(LinkableTryBuilder::new()))
}

/// TryBuild which maintains a directory of libraries to link.
/// This is desirable because otherwise, if we alter the RUSTFLAGS
/// then trybuild rebuilds *everything* including all the dev-dependencies.
/// This object exists purely so that we use the same RUSTFLAGS for every
/// test case.
struct LinkableTryBuilder {
    /// Directory in which we'll keep any linkable libraries
    temp_dir: TempDir,
}

impl LinkableTryBuilder {
    fn new() -> Self {
        LinkableTryBuilder {
            temp_dir: tempdir().unwrap(),
        }
    }

    fn move_items_into_temp_dir<P1: AsRef<Path>>(&self, src_path: &P1, pattern: &str) {
        for item in std::fs::read_dir(src_path).unwrap() {
            let item = item.unwrap();
            if item.file_name().into_string().unwrap().contains(pattern) {
                let dest = self.temp_dir.path().join(item.file_name());
                if dest.exists() {
                    std::fs::remove_file(&dest).unwrap();
                }
                if KEEP_TEMPDIRS {
                    std::fs::copy(item.path(), dest).unwrap();
                } else {
                    std::fs::rename(item.path(), dest).unwrap();
                }
            }
        }
    }

    fn build<P1: AsRef<Path>, P2: AsRef<Path>, P3: AsRef<Path> + RefUnwindSafe>(
        &self,
        library_path: &P1,
        library_name: &str,
        header_path: &P2,
        header_names: &[&str],
        rs_path: &P3,
        generated_rs_files: Vec<PathBuf>,
    ) -> std::thread::Result<()> {
        // Copy all items from the source dir into our temporary dir if their name matches
        // the pattern given in `library_name`.
        self.move_items_into_temp_dir(library_path, library_name);
        for header_name in header_names {
            self.move_items_into_temp_dir(header_path, header_name);
        }
        for generated_rs in generated_rs_files {
            self.move_items_into_temp_dir(
                &generated_rs.parent().unwrap(),
                generated_rs.file_name().unwrap().to_str().unwrap(),
            );
        }
        let temp_path = self.temp_dir.path().to_str().unwrap();
        std::env::set_var("RUSTFLAGS", format!("-L {}", temp_path));
        std::env::set_var("AUTOCXX_RS", temp_path);
        std::panic::catch_unwind(|| {
            let test_cases = trybuild::TestCases::new();
            test_cases.pass(rs_path)
        })
    }
}

fn write_to_file(tdir: &TempDir, filename: &str, content: &str) -> PathBuf {
    let path = tdir.path().join(filename);
    let mut f = File::create(&path).unwrap();
    f.write_all(content.as_bytes()).unwrap();
    path
}

/// A positive test, we expect to pass.
pub fn run_test(
    cxx_code: &str,
    header_code: &str,
    rust_code: TokenStream,
    generate: &[&str],
    generate_pods: &[&str],
) {
    do_run_test(
        cxx_code,
        header_code,
        rust_code,
        directives_from_lists(generate, generate_pods, None),
        None,
        None,
        None,
    )
    .unwrap()
}

// A trait for objects which can check the output of the code creation
// process.
pub trait CodeCheckerFns {
    fn check_rust(&self, _rs: syn::File) -> Result<(), TestError> {
        Ok(())
    }
    fn check_cpp(&self, _cpp: &[PathBuf]) -> Result<(), TestError> {
        Ok(())
    }
    fn skip_build(&self) -> bool {
        false
    }
}

// A function applied to the resultant generated Rust code
// which can be used to inspect that code.
pub type CodeChecker = Box<dyn CodeCheckerFns>;

// A trait for objects which can modify builders for testing purposes.
pub trait BuilderModifierFns {
    fn modify_autocxx_builder(
        &self,
        builder: Builder<TestBuilderContext>,
    ) -> Builder<TestBuilderContext>;
    fn modify_cc_builder<'a>(&self, builder: &'a mut cc::Build) -> &'a mut cc::Build {
        builder
    }
}

pub type BuilderModifier = Box<dyn BuilderModifierFns>;

/// A positive test, we expect to pass.
#[allow(clippy::too_many_arguments)] // least typing for each test
pub fn run_test_ex(
    cxx_code: &str,
    header_code: &str,
    rust_code: TokenStream,
    directives: TokenStream,
    builder_modifier: Option<BuilderModifier>,
    code_checker: Option<CodeChecker>,
    extra_rust: Option<TokenStream>,
) {
    do_run_test(
        cxx_code,
        header_code,
        rust_code,
        directives,
        builder_modifier,
        code_checker,
        extra_rust,
    )
    .unwrap()
}

pub fn run_test_expect_fail(
    cxx_code: &str,
    header_code: &str,
    rust_code: TokenStream,
    generate: &[&str],
    generate_pods: &[&str],
) {
    do_run_test(
        cxx_code,
        header_code,
        rust_code,
        directives_from_lists(generate, generate_pods, None),
        None,
        None,
        None,
    )
    .expect_err("Unexpected success");
}

pub fn run_test_expect_fail_ex(
    cxx_code: &str,
    header_code: &str,
    rust_code: TokenStream,
    directives: TokenStream,
    builder_modifier: Option<BuilderModifier>,
    code_checker: Option<CodeChecker>,
    extra_rust: Option<TokenStream>,
) {
    do_run_test(
        cxx_code,
        header_code,
        rust_code,
        directives,
        builder_modifier,
        code_checker,
        extra_rust,
    )
    .expect_err("Unexpected success");
}

/// In the future maybe the tests will distinguish the exact type of failure expected.
#[derive(Debug)]
pub enum TestError {
    AutoCxx(BuilderError),
    CppBuild(cc::Error),
    RsBuild,
    NoRs,
    RsFileOpen(std::io::Error),
    RsFileRead(std::io::Error),
    RsFileParse(syn::Error),
    RsCodeExaminationFail,
    CppCodeExaminationFail,
}

pub fn directives_from_lists(
    generate: &[&str],
    generate_pods: &[&str],
    extra_directives: Option<TokenStream>,
) -> TokenStream {
    let generate = generate.iter().map(|s| {
        quote! {
            generate!(#s)
        }
    });
    let generate_pods = generate_pods.iter().map(|s| {
        quote! {
            generate_pod!(#s)
        }
    });
    quote! {
        #(#generate)*
        #(#generate_pods)*
        #extra_directives
    }
}

#[allow(clippy::too_many_arguments)] // least typing for each test
fn do_run_test(
    cxx_code: &str,
    header_code: &str,
    rust_code: TokenStream,
    directives: TokenStream,
    builder_modifier: Option<BuilderModifier>,
    rust_code_checker: Option<CodeChecker>,
    extra_rust: Option<TokenStream>,
) -> Result<(), TestError> {
    let hexathorpe = Token![#](Span::call_site());
    let unexpanded_rust = quote! {
            use autocxx::prelude::*;

            include_cpp!(
                #hexathorpe include "input.h"
                safety!(unsafe_ffi)
                #directives
            );

            #extra_rust

            fn main() {
                #rust_code
            }

    };
    do_run_test_manual(
        cxx_code,
        header_code,
        unexpanded_rust,
        builder_modifier,
        rust_code_checker,
    )
}

/// The [`BuilderContext`] used in autocxx's integration tests.
pub struct TestBuilderContext;

impl BuilderContext for TestBuilderContext {
    fn get_dependency_recorder() -> Option<Box<dyn RebuildDependencyRecorder>> {
        None
    }
}

pub fn do_run_test_manual(
    cxx_code: &str,
    header_code: &str,
    mut rust_code: TokenStream,
    builder_modifier: Option<BuilderModifier>,
    rust_code_checker: Option<CodeChecker>,
) -> Result<(), TestError> {
    const HEADER_NAME: &str = "input.h";
    // Step 2: Write the C++ header snippet to a temp file
    let tdir = tempdir().unwrap();
    write_to_file(
        &tdir,
        HEADER_NAME,
        &format!("#pragma once\n{}", header_code),
    );
    write_to_file(&tdir, "cxx.h", HEADER);

    rust_code.append_all(quote! {
        #[link(name="autocxx-demo")]
        extern {}
    });
    info!("Unexpanded Rust: {}", rust_code);

    let write_rust_to_file = |ts: &TokenStream| -> PathBuf {
        // Step 3: Write the Rust code to a temp file
        let rs_code = format!("{}", ts);
        write_to_file(&tdir, "input.rs", &rs_code)
    };

    let target_dir = tdir.path().join("target");
    std::fs::create_dir(&target_dir).unwrap();

    let rs_path = write_rust_to_file(&rust_code);

    info!("Path is {:?}", tdir.path());
    let builder = Builder::<TestBuilderContext>::new(&rs_path, &[tdir.path()])
        .custom_gendir(target_dir.clone());
    let builder = if let Some(builder_modifier) = &builder_modifier {
        builder_modifier.modify_autocxx_builder(builder)
    } else {
        builder
    };
    let build_results = builder.build_listing_files().map_err(TestError::AutoCxx)?;
    let mut b = build_results.0;
    let generated_rs_files = build_results.1;

    if let Some(code_checker) = &rust_code_checker {
        let mut file = File::open(generated_rs_files.get(0).ok_or(TestError::NoRs)?)
            .map_err(TestError::RsFileOpen)?;
        let mut content = String::new();
        file.read_to_string(&mut content)
            .map_err(TestError::RsFileRead)?;

        let ast = syn::parse_file(&content).map_err(TestError::RsFileParse)?;
        code_checker.check_rust(ast)?;
        code_checker.check_cpp(&build_results.2)?;
        if code_checker.skip_build() {
            return Ok(());
        }
    }

    let target = rust_info::get().target_triple.unwrap();

    if !cxx_code.is_empty() {
        // Step 4: Write the C++ code snippet to a .cc file, along with a #include
        //         of the header emitted in step 5.
        let cxx_code = format!("#include \"input.h\"\n#include \"cxxgen.h\"\n{}", cxx_code);
        let cxx_path = write_to_file(&tdir, "input.cxx", &cxx_code);
        b.file(cxx_path);
    }

    let b = b
        .out_dir(&target_dir)
        .host(&target)
        .target(&target)
        .opt_level(1)
        .flag("-std=c++14") // For clang
        .flag_if_supported("/GX"); // Enable C++ exceptions for msvc
    let b = if let Some(builder_modifier) = builder_modifier {
        builder_modifier.modify_cc_builder(b)
    } else {
        b
    };
    b.include(tdir.path())
        .try_compile("autocxx-demo")
        .map_err(TestError::CppBuild)?;
    if KEEP_TEMPDIRS {
        println!("Generated .rs files: {:?}", generated_rs_files);
    }
    // Step 8: use the trybuild crate to build the Rust file.
    let r = get_builder().lock().unwrap().build(
        &target_dir,
        "autocxx-demo",
        &tdir.path(),
        &["input.h", "cxx.h"],
        &rs_path,
        generated_rs_files,
    );
    if KEEP_TEMPDIRS {
        println!("Tempdir: {:?}", tdir.into_path().to_str());
    }
    if r.is_err() {
        return Err(TestError::RsBuild); // details of Rust panic are a bit messy to include, and
                                        // not important at the moment.
    }
    Ok(())
}
<commit_msg>use `flag_if_supported` for Clang c++14 setting<commit_after>// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{
    fs::File,
    io::{Read, Write},
    panic::RefUnwindSafe,
    path::{Path, PathBuf},
    sync::Mutex,
};

use autocxx_engine::{Builder, BuilderContext, BuilderError, RebuildDependencyRecorder, HEADER};
use log::info;
use once_cell::sync::OnceCell;
use proc_macro2::{Span, TokenStream};
use quote::{quote, TokenStreamExt};
use syn::Token;
use tempfile::{tempdir, TempDir};

const KEEP_TEMPDIRS: bool = false;

fn get_builder() -> &'static Mutex<LinkableTryBuilder> {
    static INSTANCE: OnceCell<Mutex<LinkableTryBuilder>> = OnceCell::new();
    INSTANCE.get_or_init(|| Mutex::new(LinkableTryBuilder::new()))
}

/// TryBuild which maintains a directory of libraries to link.
/// This is desirable because otherwise, if we alter the RUSTFLAGS
/// then trybuild rebuilds *everything* including all the dev-dependencies.
/// This object exists purely so that we use the same RUSTFLAGS for every
/// test case.
struct LinkableTryBuilder {
    /// Directory in which we'll keep any linkable libraries
    temp_dir: TempDir,
}

impl LinkableTryBuilder {
    fn new() -> Self {
        LinkableTryBuilder {
            temp_dir: tempdir().unwrap(),
        }
    }

    fn move_items_into_temp_dir<P1: AsRef<Path>>(&self, src_path: &P1, pattern: &str) {
        for item in std::fs::read_dir(src_path).unwrap() {
            let item = item.unwrap();
            if item.file_name().into_string().unwrap().contains(pattern) {
                let dest = self.temp_dir.path().join(item.file_name());
                if dest.exists() {
                    std::fs::remove_file(&dest).unwrap();
                }
                if KEEP_TEMPDIRS {
                    std::fs::copy(item.path(), dest).unwrap();
                } else {
                    std::fs::rename(item.path(), dest).unwrap();
                }
            }
        }
    }

    fn build<P1: AsRef<Path>, P2: AsRef<Path>, P3: AsRef<Path> + RefUnwindSafe>(
        &self,
        library_path: &P1,
        library_name: &str,
        header_path: &P2,
        header_names: &[&str],
        rs_path: &P3,
        generated_rs_files: Vec<PathBuf>,
    ) -> std::thread::Result<()> {
        // Copy all items from the source dir into our temporary dir if their name matches
        // the pattern given in `library_name`.
        self.move_items_into_temp_dir(library_path, library_name);
        for header_name in header_names {
            self.move_items_into_temp_dir(header_path, header_name);
        }
        for generated_rs in generated_rs_files {
            self.move_items_into_temp_dir(
                &generated_rs.parent().unwrap(),
                generated_rs.file_name().unwrap().to_str().unwrap(),
            );
        }
        let temp_path = self.temp_dir.path().to_str().unwrap();
        std::env::set_var("RUSTFLAGS", format!("-L {}", temp_path));
        std::env::set_var("AUTOCXX_RS", temp_path);
        std::panic::catch_unwind(|| {
            let test_cases = trybuild::TestCases::new();
            test_cases.pass(rs_path)
        })
    }
}

fn write_to_file(tdir: &TempDir, filename: &str, content: &str) -> PathBuf {
    let path = tdir.path().join(filename);
    let mut f = File::create(&path).unwrap();
    f.write_all(content.as_bytes()).unwrap();
    path
}

/// A positive test, we expect to pass.
pub fn run_test(
    cxx_code: &str,
    header_code: &str,
    rust_code: TokenStream,
    generate: &[&str],
    generate_pods: &[&str],
) {
    do_run_test(
        cxx_code,
        header_code,
        rust_code,
        directives_from_lists(generate, generate_pods, None),
        None,
        None,
        None,
    )
    .unwrap()
}

// A trait for objects which can check the output of the code creation
// process.
pub trait CodeCheckerFns {
    fn check_rust(&self, _rs: syn::File) -> Result<(), TestError> {
        Ok(())
    }
    fn check_cpp(&self, _cpp: &[PathBuf]) -> Result<(), TestError> {
        Ok(())
    }
    fn skip_build(&self) -> bool {
        false
    }
}

// A function applied to the resultant generated Rust code
// which can be used to inspect that code.
pub type CodeChecker = Box<dyn CodeCheckerFns>;

// A trait for objects which can modify builders for testing purposes.
pub trait BuilderModifierFns {
    fn modify_autocxx_builder(
        &self,
        builder: Builder<TestBuilderContext>,
    ) -> Builder<TestBuilderContext>;
    fn modify_cc_builder<'a>(&self, builder: &'a mut cc::Build) -> &'a mut cc::Build {
        builder
    }
}

pub type BuilderModifier = Box<dyn BuilderModifierFns>;

/// A positive test, we expect to pass.
#[allow(clippy::too_many_arguments)] // least typing for each test
pub fn run_test_ex(
    cxx_code: &str,
    header_code: &str,
    rust_code: TokenStream,
    directives: TokenStream,
    builder_modifier: Option<BuilderModifier>,
    code_checker: Option<CodeChecker>,
    extra_rust: Option<TokenStream>,
) {
    do_run_test(
        cxx_code,
        header_code,
        rust_code,
        directives,
        builder_modifier,
        code_checker,
        extra_rust,
    )
    .unwrap()
}

pub fn run_test_expect_fail(
    cxx_code: &str,
    header_code: &str,
    rust_code: TokenStream,
    generate: &[&str],
    generate_pods: &[&str],
) {
    do_run_test(
        cxx_code,
        header_code,
        rust_code,
        directives_from_lists(generate, generate_pods, None),
        None,
        None,
        None,
    )
    .expect_err("Unexpected success");
}

pub fn run_test_expect_fail_ex(
    cxx_code: &str,
    header_code: &str,
    rust_code: TokenStream,
    directives: TokenStream,
    builder_modifier: Option<BuilderModifier>,
    code_checker: Option<CodeChecker>,
    extra_rust: Option<TokenStream>,
) {
    do_run_test(
        cxx_code,
        header_code,
        rust_code,
        directives,
        builder_modifier,
        code_checker,
        extra_rust,
    )
    .expect_err("Unexpected success");
}

/// In the future maybe the tests will distinguish the exact type of failure expected.
#[derive(Debug)]
pub enum TestError {
    AutoCxx(BuilderError),
    CppBuild(cc::Error),
    RsBuild,
    NoRs,
    RsFileOpen(std::io::Error),
    RsFileRead(std::io::Error),
    RsFileParse(syn::Error),
    RsCodeExaminationFail,
    CppCodeExaminationFail,
}

pub fn directives_from_lists(
    generate: &[&str],
    generate_pods: &[&str],
    extra_directives: Option<TokenStream>,
) -> TokenStream {
    let generate = generate.iter().map(|s| {
        quote! {
            generate!(#s)
        }
    });
    let generate_pods = generate_pods.iter().map(|s| {
        quote! {
            generate_pod!(#s)
        }
    });
    quote! {
        #(#generate)*
        #(#generate_pods)*
        #extra_directives
    }
}

#[allow(clippy::too_many_arguments)] // least typing for each test
fn do_run_test(
    cxx_code: &str,
    header_code: &str,
    rust_code: TokenStream,
    directives: TokenStream,
    builder_modifier: Option<BuilderModifier>,
    rust_code_checker: Option<CodeChecker>,
    extra_rust: Option<TokenStream>,
) -> Result<(), TestError> {
    let hexathorpe = Token![#](Span::call_site());
    let unexpanded_rust = quote! {
            use autocxx::prelude::*;

            include_cpp!(
                #hexathorpe include "input.h"
                safety!(unsafe_ffi)
                #directives
            );

            #extra_rust

            fn main() {
                #rust_code
            }

    };
    do_run_test_manual(
        cxx_code,
        header_code,
        unexpanded_rust,
        builder_modifier,
        rust_code_checker,
    )
}

/// The [`BuilderContext`] used in autocxx's integration tests.
pub struct TestBuilderContext;

impl BuilderContext for TestBuilderContext {
    fn get_dependency_recorder() -> Option<Box<dyn RebuildDependencyRecorder>> {
        None
    }
}

pub fn do_run_test_manual(
    cxx_code: &str,
    header_code: &str,
    mut rust_code: TokenStream,
    builder_modifier: Option<BuilderModifier>,
    rust_code_checker: Option<CodeChecker>,
) -> Result<(), TestError> {
    const HEADER_NAME: &str = "input.h";
    // Step 2: Write the C++ header snippet to a temp file
    let tdir = tempdir().unwrap();
    write_to_file(
        &tdir,
        HEADER_NAME,
        &format!("#pragma once\n{}", header_code),
    );
    write_to_file(&tdir, "cxx.h", HEADER);

    rust_code.append_all(quote! {
        #[link(name="autocxx-demo")]
        extern {}
    });
    info!("Unexpanded Rust: {}", rust_code);

    let write_rust_to_file = |ts: &TokenStream| -> PathBuf {
        // Step 3: Write the Rust code to a temp file
        let rs_code = format!("{}", ts);
        write_to_file(&tdir, "input.rs", &rs_code)
    };

    let target_dir = tdir.path().join("target");
    std::fs::create_dir(&target_dir).unwrap();

    let rs_path = write_rust_to_file(&rust_code);

    info!("Path is {:?}", tdir.path());
    let builder = Builder::<TestBuilderContext>::new(&rs_path, &[tdir.path()])
        .custom_gendir(target_dir.clone());
    let builder = if let Some(builder_modifier) = &builder_modifier {
        builder_modifier.modify_autocxx_builder(builder)
    } else {
        builder
    };
    let build_results = builder.build_listing_files().map_err(TestError::AutoCxx)?;
    let mut b = build_results.0;
    let generated_rs_files = build_results.1;

    if let Some(code_checker) = &rust_code_checker {
        let mut file = File::open(generated_rs_files.get(0).ok_or(TestError::NoRs)?)
            .map_err(TestError::RsFileOpen)?;
        let mut content = String::new();
        file.read_to_string(&mut content)
            .map_err(TestError::RsFileRead)?;

        let ast = syn::parse_file(&content).map_err(TestError::RsFileParse)?;
        code_checker.check_rust(ast)?;
        code_checker.check_cpp(&build_results.2)?;
        if code_checker.skip_build() {
            return Ok(());
        }
    }

    let target = rust_info::get().target_triple.unwrap();

    if !cxx_code.is_empty() {
        // Step 4: Write the C++ code snippet to a .cc file, along with a #include
        //         of the header emitted in step 5.
        let cxx_code = format!("#include \"input.h\"\n#include \"cxxgen.h\"\n{}", cxx_code);
        let cxx_path = write_to_file(&tdir, "input.cxx", &cxx_code);
        b.file(cxx_path);
    }

    let b = b
        .out_dir(&target_dir)
        .host(&target)
        .target(&target)
        .opt_level(1)
        .flag_if_supported("-std=c++14") // For clang
        .flag_if_supported("/GX"); // Enable C++ exceptions for msvc
    let b = if let Some(builder_modifier) = builder_modifier {
        builder_modifier.modify_cc_builder(b)
    } else {
        b
    };
    b.include(tdir.path())
        .try_compile("autocxx-demo")
        .map_err(TestError::CppBuild)?;
    if KEEP_TEMPDIRS {
        println!("Generated .rs files: {:?}", generated_rs_files);
    }
    // Step 8: use the trybuild crate to build the Rust file.
    let r = get_builder().lock().unwrap().build(
        &target_dir,
        "autocxx-demo",
        &tdir.path(),
        &["input.h", "cxx.h"],
        &rs_path,
        generated_rs_files,
    );
    if KEEP_TEMPDIRS {
        println!("Tempdir: {:?}", tdir.into_path().to_str());
    }
    if r.is_err() {
        return Err(TestError::RsBuild); // details of Rust panic are a bit messy to include, and
                                        // not important at the moment.
    }
    Ok(())
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! Hooks for for the RPC system.
//!
//! Roughly corresponds to capability.h in the C++ implementation.

use any_pointer;
use private::capability::{ClientHook, ParamsHook, RequestHook, ResponseHook, ResultsHook};

#[cfg(feature = "rpc")]
pub type Promise<T,E> = ::gj::Promise<T,E>;

#[cfg(not(feature = "rpc"))]
pub type Promise<T,E> = ::std::result::Result<T,E>;

pub struct RemotePromise<Results> where Results: ::traits::Pipelined + for<'a> ::traits::Owned<'a> + 'static {
    pub promise: Promise<Response<Results>, ::Error>,
    pub pipeline: Results::Pipeline,
}

pub struct ReaderCapTable {
    pub hooks: Vec<Option<Box<ClientHook>>>
}

impl ReaderCapTable {
    pub fn new(hooks: Vec<Option<Box<ClientHook>>>) -> ReaderCapTable {
        ReaderCapTable { hooks: hooks }
    }

    // Do I need an Imbueable trait?
    pub fn imbue<'a, T>(&'a self) -> T {
        &self.hooks;
        unimplemented!();
    }
}

pub struct Response<Results> {
    pub marker: ::std::marker::PhantomData<Results>,
    pub hook: Box<ResponseHook>,
}

impl <Results> Response<Results>
    where Results: ::traits::Pipelined + for<'a> ::traits::Owned<'a>
{
    pub fn new(hook: Box<ResponseHook>) -> Response<Results> {
        Response { marker: ::std::marker::PhantomData, hook: hook }
    }
    pub fn get<'a>(&'a self) -> ::Result<<Results as ::traits::Owned<'a>>::Reader> {
        try!(self.hook.get()).get_as()
    }
}

pub struct Request<Params, Results> {
    pub marker: ::std::marker::PhantomData<(Params, Results)>,
    pub hook: Box<RequestHook>
}

impl <Params, Results> Request <Params, Results>
    where Params: for<'a> ::traits::Owned<'a>
{
    pub fn new(hook: Box<RequestHook>) -> Request <Params, Results> {
        Request { hook: hook, marker: ::std::marker::PhantomData }
    }

    pub fn init<'a>(&'a mut self) -> <Params as ::traits::Owned<'a>>::Builder {
        self.hook.get().init_as()
    }
}

#[cfg(feature = "rpc")]
impl <Params, Results> Request <Params, Results>
where Results: ::traits::Pipelined + for<'a> ::traits::Owned<'a> + 'static,
      <Results as ::traits::Pipelined>::Pipeline: FromTypelessPipeline
{
    pub fn send(self) -> RemotePromise<Results> {
        let RemotePromise {promise, pipeline, ..} = self.hook.send();
        let typed_promise = promise.map(|response| {
            Ok(Response {hook: response.hook,
                        marker: ::std::marker::PhantomData})
        });
        RemotePromise { promise: typed_promise,
                        pipeline: FromTypelessPipeline::new(pipeline)
                      }
    }
}

pub struct Params<T> {
    pub marker: ::std::marker::PhantomData<T>,
    pub hook: Box<ParamsHook>,
}

impl <T> Params <T> {
    pub fn new(hook: Box<ParamsHook>) -> Params<T> {
        Params { marker: ::std::marker::PhantomData, hook: hook }
    }
    pub fn get<'a>(&'a self) -> <T as ::traits::Owned<'a>>::Reader
        where T: ::traits::Owned<'a>
    {
        self.hook.get().unwrap().get_as().unwrap()
    }
}

pub struct Results<T> {
    pub marker: ::std::marker::PhantomData<T>,
    pub hook: Box<ResultsHook>,
}

impl <T> Results<T> {
    pub fn new(hook: Box<ResultsHook>) -> Results<T> {
        Results { marker: ::std::marker::PhantomData, hook: hook }
    }

    pub fn get<'a>(&'a mut self) -> <T as ::traits::Owned<'a>>::Builder
        where T: ::traits::Owned<'a>
    {
        self.hook.get().unwrap().get_as().unwrap()
    }
}

pub trait FromTypelessPipeline {
    fn new (typeless: any_pointer::Pipeline) -> Self;
}

pub trait FromClientHook {
    fn new(Box<ClientHook>) -> Self;
}

pub struct Client {
    pub hook: Box<ClientHook>
}

impl Client {
    pub fn new(hook: Box<ClientHook>) -> Client {
        Client { hook : hook }
    }

    pub fn new_call<Params, Results>(&self,
                                     interface_id : u64,
                                     method_id : u16,
                                     size_hint : Option<::MessageSize>)
                                     -> Request<Params, Results> {
        let typeless = self.hook.new_call(interface_id, method_id, size_hint);
        Request { hook: typeless.hook, marker: ::std::marker::PhantomData }
    }
}

pub trait Server {
    fn dispatch_call(&mut self, interface_id: u64, method_id: u16,
                     params: Params<any_pointer::Owned>,
                     results: Results<any_pointer::Owned>)
                     -> Promise<Results<any_pointer::Owned>, ::Error>;
}

<commit_msg>A fake impl for the fake Promise struct.<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! Hooks for for the RPC system.
//!
//! Roughly corresponds to capability.h in the C++ implementation.

use any_pointer;
use private::capability::{ClientHook, ParamsHook, RequestHook, ResponseHook, ResultsHook};

#[cfg(feature = "rpc")]
pub type Promise<T,E> = ::gj::Promise<T,E>;

/// This fake Promise struct is defined so that the generated code for interfaces
/// can typecheck even if the "rpc" feature is not enabled.
#[cfg(not(feature = "rpc"))]
pub struct Promise<T,E>(::std::result::Result<T,E>);

#[cfg(not(feature = "rpc"))]
impl <T,E> Promise<T,E> {
    pub fn ok(v: T) -> Promise<T,E> {
        Promise(Ok(v))
    }
    pub fn err(e: E) -> Promise<T,E> {
        Promise(Err(e))
    }
    pub fn map<F, R>(self, _func: F) -> Promise<R, E>
        where F: FnOnce(T) -> Result<R, E>,
    {
        unimplemented!()
    }
}

pub struct RemotePromise<Results> where Results: ::traits::Pipelined + for<'a> ::traits::Owned<'a> + 'static {
    pub promise: Promise<Response<Results>, ::Error>,
    pub pipeline: Results::Pipeline,
}

pub struct ReaderCapTable {
    pub hooks: Vec<Option<Box<ClientHook>>>
}

impl ReaderCapTable {
    pub fn new(hooks: Vec<Option<Box<ClientHook>>>) -> ReaderCapTable {
        ReaderCapTable { hooks: hooks }
    }

    // Do I need an Imbueable trait?
    pub fn imbue<'a, T>(&'a self) -> T {
        &self.hooks;
        unimplemented!();
    }
}

pub struct Response<Results> {
    pub marker: ::std::marker::PhantomData<Results>,
    pub hook: Box<ResponseHook>,
}

impl <Results> Response<Results>
    where Results: ::traits::Pipelined + for<'a> ::traits::Owned<'a>
{
    pub fn new(hook: Box<ResponseHook>) -> Response<Results> {
        Response { marker: ::std::marker::PhantomData, hook: hook }
    }
    pub fn get<'a>(&'a self) -> ::Result<<Results as ::traits::Owned<'a>>::Reader> {
        try!(self.hook.get()).get_as()
    }
}

pub struct Request<Params, Results> {
    pub marker: ::std::marker::PhantomData<(Params, Results)>,
    pub hook: Box<RequestHook>
}

impl <Params, Results> Request <Params, Results>
    where Params: for<'a> ::traits::Owned<'a>
{
    pub fn new(hook: Box<RequestHook>) -> Request <Params, Results> {
        Request { hook: hook, marker: ::std::marker::PhantomData }
    }

    pub fn init<'a>(&'a mut self) -> <Params as ::traits::Owned<'a>>::Builder {
        self.hook.get().init_as()
    }
}

#[cfg(feature = "rpc")]
impl <Params, Results> Request <Params, Results>
where Results: ::traits::Pipelined + for<'a> ::traits::Owned<'a> + 'static,
      <Results as ::traits::Pipelined>::Pipeline: FromTypelessPipeline
{
    pub fn send(self) -> RemotePromise<Results> {
        let RemotePromise {promise, pipeline, ..} = self.hook.send();
        let typed_promise = promise.map(|response| {
            Ok(Response {hook: response.hook,
                        marker: ::std::marker::PhantomData})
        });
        RemotePromise { promise: typed_promise,
                        pipeline: FromTypelessPipeline::new(pipeline)
                      }
    }
}

pub struct Params<T> {
    pub marker: ::std::marker::PhantomData<T>,
    pub hook: Box<ParamsHook>,
}

impl <T> Params <T> {
    pub fn new(hook: Box<ParamsHook>) -> Params<T> {
        Params { marker: ::std::marker::PhantomData, hook: hook }
    }
    pub fn get<'a>(&'a self) -> <T as ::traits::Owned<'a>>::Reader
        where T: ::traits::Owned<'a>
    {
        self.hook.get().unwrap().get_as().unwrap()
    }
}

pub struct Results<T> {
    pub marker: ::std::marker::PhantomData<T>,
    pub hook: Box<ResultsHook>,
}

impl <T> Results<T> {
    pub fn new(hook: Box<ResultsHook>) -> Results<T> {
        Results { marker: ::std::marker::PhantomData, hook: hook }
    }

    pub fn get<'a>(&'a mut self) -> <T as ::traits::Owned<'a>>::Builder
        where T: ::traits::Owned<'a>
    {
        self.hook.get().unwrap().get_as().unwrap()
    }
}

pub trait FromTypelessPipeline {
    fn new (typeless: any_pointer::Pipeline) -> Self;
}

pub trait FromClientHook {
    fn new(Box<ClientHook>) -> Self;
}

pub struct Client {
    pub hook: Box<ClientHook>
}

impl Client {
    pub fn new(hook: Box<ClientHook>) -> Client {
        Client { hook : hook }
    }

    pub fn new_call<Params, Results>(&self,
                                     interface_id : u64,
                                     method_id : u16,
                                     size_hint : Option<::MessageSize>)
                                     -> Request<Params, Results> {
        let typeless = self.hook.new_call(interface_id, method_id, size_hint);
        Request { hook: typeless.hook, marker: ::std::marker::PhantomData }
    }
}

pub trait Server {
    fn dispatch_call(&mut self, interface_id: u64, method_id: u16,
                     params: Params<any_pointer::Owned>,
                     results: Results<any_pointer::Owned>)
                     -> Promise<Results<any_pointer::Owned>, ::Error>;
}

<|endoftext|>


<commit_before>extern crate coreutils;

use coreutils::to_human_readable_string;
use std::env;
use std::fs::File;
use std::io::{stderr, Read, Write};
use std::time::Instant;

fn main() {
    let stderr = stderr();
    let mut stderr = stderr.lock();

    let mut bs = 512;
    let mut count = None;
    let mut in_path = String::new();
    let mut out_path = String::new();
    let mut status = 1;
    for arg in env::args().skip(1) {
        if arg.starts_with("bs=") {
            bs = arg[3..].parse::<usize>().expect("dd: bs is not a number");
        } else if arg.starts_with("count=") {
            count = Some(arg[6..].parse::<usize>().expect("dd: count is not a number"));
        } else if arg.starts_with("if=") {
            in_path = arg[3..].to_string();
        } else if arg.starts_with("of=") {
            out_path = arg[3..].to_string();
        } else if arg.starts_with("status=") {
            match &arg[7..] {
                "none" => status = 0,
                "noxfer" => status = 1,
                "progress" => status = 2,
                unknown => panic!("dd: status: unrecognized argument '{}'", unknown)
            }
        } else {
            panic!("dd: unrecognized operand '{}'", arg);
        }
    }

    let mut input = File::open(in_path).expect("dd: failed to open if");
    let mut output = File::create(out_path).expect("dd: failed to open of");

    let mut in_recs = 0;
    let mut in_extra = 0;
    let mut out_recs = 0;
    let mut out_extra = 0;
    let mut out_total = 0;
    let mut running = true;
    let mut buffer = vec![0; bs];
    let mut start = Instant::now();
    let mut last_print = 0;
    let mut last_print_out = 0;
    while running {
        let in_count = input.read(&mut buffer).expect("dd: failed to read if");
        if in_count < bs {
            if in_count > 0 {
                in_extra += 1;
            }
            running = false;
        } else {
            in_recs += 1;
            if let Some(count) = count {
                if in_recs >= count {
                    running = false;
                }
            }
        }

        let out_count = output.write(&buffer[.. in_count]).expect("dd: failed to write of");
        if out_count < bs {
            if out_count > 0 {
                out_extra += 1;
            }
            running = false;
        } else {
            out_recs += 1;
        }

        out_total += out_count as u64;

        if status >= 2 {
            let elapsed = start.elapsed().as_secs();
            if elapsed > last_print {
                let _ = write!(stderr, "\r\x1B[K{} bytes ({}B) copied, {} s, {}B/s", out_total, to_human_readable_string(out_total), elapsed, to_human_readable_string(out_total - last_print_out));
                let _ = stderr.flush();
                last_print = elapsed;
                last_print_out = out_total;
            }
        }
    }

    if status >= 1 {
        let elapsed_duration = start.elapsed();
        let elapsed = elapsed_duration.as_secs() as f64 + (elapsed_duration.subsec_nanos() as f64)/1000000000.0;

        if status >= 2 && last_print > 0 {
            let _ = writeln!(stderr, "");
        }

        let _ = writeln!(stderr, "{}+{} records in", in_recs, in_extra);
        let _ = writeln!(stderr, "{}+{} records out", out_recs, out_extra);
        let _ = writeln!(stderr, "{} bytes ({}B) copied, {} s, {}B/s", out_total, to_human_readable_string(out_total), elapsed, to_human_readable_string((out_total as f64/elapsed) as u64));
    }
}
<commit_msg>start does not need to be mut<commit_after>extern crate coreutils;

use coreutils::to_human_readable_string;
use std::env;
use std::fs::File;
use std::io::{stderr, Read, Write};
use std::time::Instant;

fn main() {
    let stderr = stderr();
    let mut stderr = stderr.lock();

    let mut bs = 512;
    let mut count = None;
    let mut in_path = String::new();
    let mut out_path = String::new();
    let mut status = 1;
    for arg in env::args().skip(1) {
        if arg.starts_with("bs=") {
            bs = arg[3..].parse::<usize>().expect("dd: bs is not a number");
        } else if arg.starts_with("count=") {
            count = Some(arg[6..].parse::<usize>().expect("dd: count is not a number"));
        } else if arg.starts_with("if=") {
            in_path = arg[3..].to_string();
        } else if arg.starts_with("of=") {
            out_path = arg[3..].to_string();
        } else if arg.starts_with("status=") {
            match &arg[7..] {
                "none" => status = 0,
                "noxfer" => status = 1,
                "progress" => status = 2,
                unknown => panic!("dd: status: unrecognized argument '{}'", unknown)
            }
        } else {
            panic!("dd: unrecognized operand '{}'", arg);
        }
    }

    let mut input = File::open(in_path).expect("dd: failed to open if");
    let mut output = File::create(out_path).expect("dd: failed to open of");

    let mut in_recs = 0;
    let mut in_extra = 0;
    let mut out_recs = 0;
    let mut out_extra = 0;
    let mut out_total = 0;
    let mut running = true;
    let mut buffer = vec![0; bs];
    let mut last_print = 0;
    let mut last_print_out = 0;
    let start = Instant::now();
    while running {
        let in_count = input.read(&mut buffer).expect("dd: failed to read if");
        if in_count < bs {
            if in_count > 0 {
                in_extra += 1;
            }
            running = false;
        } else {
            in_recs += 1;
            if let Some(count) = count {
                if in_recs >= count {
                    running = false;
                }
            }
        }

        let out_count = output.write(&buffer[.. in_count]).expect("dd: failed to write of");
        if out_count < bs {
            if out_count > 0 {
                out_extra += 1;
            }
            running = false;
        } else {
            out_recs += 1;
        }

        out_total += out_count as u64;

        if status >= 2 {
            let elapsed = start.elapsed().as_secs();
            if elapsed > last_print {
                let _ = write!(stderr, "\r\x1B[K{} bytes ({}B) copied, {} s, {}B/s", out_total, to_human_readable_string(out_total), elapsed, to_human_readable_string(out_total - last_print_out));
                let _ = stderr.flush();
                last_print = elapsed;
                last_print_out = out_total;
            }
        }
    }

    if status >= 1 {
        let elapsed_duration = start.elapsed();
        let elapsed = elapsed_duration.as_secs() as f64 + (elapsed_duration.subsec_nanos() as f64)/1000000000.0;

        if status >= 2 && last_print > 0 {
            let _ = writeln!(stderr, "");
        }

        let _ = writeln!(stderr, "{}+{} records in", in_recs, in_extra);
        let _ = writeln!(stderr, "{}+{} records out", out_recs, out_extra);
        let _ = writeln!(stderr, "{} bytes ({}B) copied, {} s, {}B/s", out_total, to_human_readable_string(out_total), elapsed, to_human_readable_string((out_total as f64/elapsed) as u64));
    }
}
<|endoftext|>


<commit_before>use libimagstore::store::{Entry, EntryHeader};

use error::{TagError, TagErrorKind};
use result::Result;
use tag::Tag;

use toml::Value;

pub trait Tagable {

    fn get_tags(&self) -> Result<Vec<Tag>>;
    fn set_tags(&mut self, ts: Vec<Tag>) -> Result<()>;

    fn add_tag(&mut self, t: Tag) -> Result<()>;
    fn remove_tag(&mut self, t: Tag) -> Result<()>;

    fn has_tag(&self, t: &Tag) -> Result<bool>;
    fn has_tags(&self, ts: &Vec<Tag>) -> Result<bool>;

}

impl Tagable for EntryHeader {

    fn get_tags(&self) -> Result<Vec<Tag>> {
        let tags = self.read("imag.tags");
        if tags.is_err() {
            let kind = TagErrorKind::HeaderReadError;
            return Err(TagError::new(kind, Some(Box::new(tags.err().unwrap()))));
        }
        let tags = tags.unwrap();

        match tags {
            Some(Value::Array(tags)) => {
                if !tags.iter().all(|t| match t { &Value::String(_) => true, _ => false }) {
                    return Err(TagError::new(TagErrorKind::TagTypeError, None));
                }

                Ok(tags.iter()
                    .cloned()
                    .map(|t| {
                        match t {
                           Value::String(s) => s,
                           _ => unreachable!(),
                        }
                    })
                    .collect())
            },
            None => Ok(vec![]),
            _ => Err(TagError::new(TagErrorKind::TagTypeError, None)),
        }
    }

    fn set_tags(&mut self, ts: Vec<Tag>) -> Result<()> {
        let a = ts.iter().map(|t| Value::String(t.clone())).collect();
        self.set("imag.tags", Value::Array(a))
            .map(|_| ())
            .map_err(|e| TagError::new(TagErrorKind::HeaderWriteError, Some(Box::new(e))))
    }

    fn add_tag(&mut self, t: Tag) -> Result<()> {
        self.get_tags()
            .map(|mut tags| {
                tags.push(t);
                self.set_tags(tags)
            })
            .map(|_| ())
    }

    fn remove_tag(&mut self, t: Tag) -> Result<()> {
        self.get_tags()
            .map(|mut tags| {
                tags.retain(|tag| tag.clone() != t);
                self.set_tags(tags)
            })
            .map(|_| ())
    }

    fn has_tag(&self, t: &Tag) -> Result<bool> {
        let tags = self.read("imag.tags");
        if tags.is_err() {
            let kind = TagErrorKind::HeaderReadError;
            return Err(TagError::new(kind, Some(Box::new(tags.err().unwrap()))));
        }
        let tags = tags.unwrap();

        if !tags.iter().all(|t| match t { &Value::String(_) => true, _ => false }) {
            return Err(TagError::new(TagErrorKind::TagTypeError, None));
        }

        Ok(tags
           .iter()
           .any(|tag| {
               match tag {
                   &Value::String(ref s) => { s == t },
                   _ => unreachable!()
               }
           }))
    }

    fn has_tags(&self, tags: &Vec<Tag>) -> Result<bool> {
        let mut result = true;
        for tag in tags {
            let check = self.has_tag(tag);
            if check.is_err() {
                return Err(check.err().unwrap());
            }
            let check = check.unwrap();

            result = result && check;
        }

        Ok(result)
    }

}

<commit_msg>Impl Tagable for Entry for convenience<commit_after>use libimagstore::store::{Entry, EntryHeader};

use error::{TagError, TagErrorKind};
use result::Result;
use tag::Tag;

use toml::Value;

pub trait Tagable {

    fn get_tags(&self) -> Result<Vec<Tag>>;
    fn set_tags(&mut self, ts: Vec<Tag>) -> Result<()>;

    fn add_tag(&mut self, t: Tag) -> Result<()>;
    fn remove_tag(&mut self, t: Tag) -> Result<()>;

    fn has_tag(&self, t: &Tag) -> Result<bool>;
    fn has_tags(&self, ts: &Vec<Tag>) -> Result<bool>;

}

impl Tagable for EntryHeader {

    fn get_tags(&self) -> Result<Vec<Tag>> {
        let tags = self.read("imag.tags");
        if tags.is_err() {
            let kind = TagErrorKind::HeaderReadError;
            return Err(TagError::new(kind, Some(Box::new(tags.err().unwrap()))));
        }
        let tags = tags.unwrap();

        match tags {
            Some(Value::Array(tags)) => {
                if !tags.iter().all(|t| match t { &Value::String(_) => true, _ => false }) {
                    return Err(TagError::new(TagErrorKind::TagTypeError, None));
                }

                Ok(tags.iter()
                    .cloned()
                    .map(|t| {
                        match t {
                           Value::String(s) => s,
                           _ => unreachable!(),
                        }
                    })
                    .collect())
            },
            None => Ok(vec![]),
            _ => Err(TagError::new(TagErrorKind::TagTypeError, None)),
        }
    }

    fn set_tags(&mut self, ts: Vec<Tag>) -> Result<()> {
        let a = ts.iter().map(|t| Value::String(t.clone())).collect();
        self.set("imag.tags", Value::Array(a))
            .map(|_| ())
            .map_err(|e| TagError::new(TagErrorKind::HeaderWriteError, Some(Box::new(e))))
    }

    fn add_tag(&mut self, t: Tag) -> Result<()> {
        self.get_tags()
            .map(|mut tags| {
                tags.push(t);
                self.set_tags(tags)
            })
            .map(|_| ())
    }

    fn remove_tag(&mut self, t: Tag) -> Result<()> {
        self.get_tags()
            .map(|mut tags| {
                tags.retain(|tag| tag.clone() != t);
                self.set_tags(tags)
            })
            .map(|_| ())
    }

    fn has_tag(&self, t: &Tag) -> Result<bool> {
        let tags = self.read("imag.tags");
        if tags.is_err() {
            let kind = TagErrorKind::HeaderReadError;
            return Err(TagError::new(kind, Some(Box::new(tags.err().unwrap()))));
        }
        let tags = tags.unwrap();

        if !tags.iter().all(|t| match t { &Value::String(_) => true, _ => false }) {
            return Err(TagError::new(TagErrorKind::TagTypeError, None));
        }

        Ok(tags
           .iter()
           .any(|tag| {
               match tag {
                   &Value::String(ref s) => { s == t },
                   _ => unreachable!()
               }
           }))
    }

    fn has_tags(&self, tags: &Vec<Tag>) -> Result<bool> {
        let mut result = true;
        for tag in tags {
            let check = self.has_tag(tag);
            if check.is_err() {
                return Err(check.err().unwrap());
            }
            let check = check.unwrap();

            result = result && check;
        }

        Ok(result)
    }

}

impl Tagable for Entry {

    fn get_tags(&self) -> Result<Vec<Tag>> {
        self.get_header().get_tags()
    }

    fn set_tags(&mut self, ts: Vec<Tag>) -> Result<()> {
        self.get_header_mut().set_tags(ts)
    }

    fn add_tag(&mut self, t: Tag) -> Result<()> {
        self.get_header_mut().add_tag(t)
    }

    fn remove_tag(&mut self, t: Tag) -> Result<()> {
        self.get_header_mut().remove_tag(t)
    }

    fn has_tag(&self, t: &Tag) -> Result<bool> {
        self.get_header().has_tag(t)
    }

    fn has_tags(&self, ts: &Vec<Tag>) -> Result<bool> {
        self.get_header().has_tags(ts)
    }

}
<|endoftext|>


<commit_before>fn main() {
    let mut user_instance = User {
        username: String::from("userrrr"),
        email: String::from("mail@mail.com"),
        sign_in_count: 0,
        active: true
    };

    user_instance.sign_in_count = 1;

    println!("User sign in count: {}", user_instance.sign_in_count);

    let built_user = build_user(
        String::from("mail@mail2.com"),
        String::from("mickey mouse")
    );

    let updated_user = User {
        username: String::from("updated_username"),
        ..user_instance
    };
}

fn build_user(email: String, username: String) -> User {
    User {
        email,
        username,
        sign_in_count: 0,
        active: false
    }
}

struct User {
    username: String,
    email: String,
    sign_in_count: u64,
    active: bool
}
<commit_msg>Example of tuple struct definition<commit_after>fn main() {
    let mut user_instance = User {
        username: String::from("userrrr"),
        email: String::from("mail@mail.com"),
        sign_in_count: 0,
        active: true
    };

    user_instance.sign_in_count = 1;

    println!("User sign in count: {}", user_instance.sign_in_count);

    let built_user = build_user(
        String::from("mail@mail2.com"),
        String::from("mickey mouse")
    );

    let updated_user = User {
        username: String::from("updated_username"),
        ..user_instance
    };
}

fn build_user(email: String, username: String) -> User {
    User {
        email,
        username,
        sign_in_count: 0,
        active: false
    }
}

struct User {
    username: String,
    email: String,
    sign_in_count: u64,
    active: bool
}

struct Color(i32, i32, i32);
<|endoftext|>


<commit_before>extern crate clap;

use std::io::prelude::*;
use std::fs::File;

#[derive(Clone, Copy, Debug)]
enum Turn {
    Left,
    Right,
}

#[derive(Clone, Copy, Debug)]
enum Direction {
    North,
    East,
    South,
    West,
}

impl Direction {
    fn rotate(self, turn: Turn) -> Direction {
        use Turn::*;
        use Direction::*;
        match turn {
            Left => match self {
                North => West,
                East => North,
                South => East,
                West => South,
            },
            Right => match self {
                North => East,
                East => South,
                South => West,
                West => North,
            },
        }
    }
}

#[derive(Clone, Copy, Debug)]
struct Position {
    x: i64,
    y: i64,
}

#[derive(Clone, Copy, Debug)]
struct Traveller {
    pos: Position,
    facing: Direction,
}

impl Traveller {
    fn new() -> Traveller {
        Traveller { pos: Position {x: 0, y: 0}, facing: Direction::North }
    }
    fn rotate(&mut self, turn: Turn) {
        self.facing = self.facing.rotate(turn);
    }
    fn travel(&mut self, distance: u64) {
        match self.facing {
            Direction::North => self.pos.y += distance as i64,
            Direction::East => self.pos.x += distance as i64,
            Direction::South => self.pos.y -= distance as i64,
            Direction::West => self.pos.x -= distance as i64,
        }
    }
    fn distance_from_origin(&self) -> u64 {
        self.pos.x.wrapping_abs() as u64 + self.pos.y.wrapping_abs() as u64
    }
}

struct Instruction {
    rotation: Turn,
    distance: u64,
}

impl std::str::FromStr for Instruction {
    type Err = std::io::Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let s = s.trim();
        fn invalid_data(desc: &str) -> std::io::Error {
           std::io::Error::new(std::io::ErrorKind::InvalidData, desc)
        }
        if s.len() == 0 {
            return Err(invalid_data("Zero-length instruction"));
        }
        let (rot_str, dist_str) = s.split_at(1);
        let rot = match rot_str {
            "L" => Turn::Left,
            "R" => Turn::Right,
            _ => return Err(invalid_data(&format!("Invalid rotation: {}", rot_str))),
        };
        let dist = dist_str.parse()
            .map_err(|e| invalid_data(
                &format!("Invalid distance: {} ({})", dist_str, e)))?;
        Ok(Instruction { rotation: rot, distance: dist })
    }
}

fn parse_args() -> std::io::Result<Box<Read>> {
    let source = clap::App::new("Day 01")
        .author("Devon Hollowood")
        .arg(clap::Arg::with_name("instructions")
             .index(1)
             .short("f")
             .long("instructions")
             .help("file to read instructions from. Reads from stdin otherwise")
             .takes_value(true)
        )
        .get_matches()
        .value_of_os("instructions")
        .map(|str| str.to_owned());
    match source {
        Some(filename) => Ok(Box::new(File::open(filename)?)),
        None => Ok(Box::new(std::io::stdin())),
    }
}

fn read_instructions<R: Read>(source: &mut R) -> std::io::Result<Vec<Instruction>> {
    let mut instruction_str = String::new();
    source.read_to_string(&mut instruction_str)?;
    instruction_str.split(", ").map(|instr| instr.parse()).collect()
}

fn main() {
    let mut source = parse_args()
        .unwrap_or_else(|err| panic!("Error reading file: {}", err));
    let mut santa = Traveller::new();
    for instruction in read_instructions(&mut source)
        .unwrap_or_else(|err| panic!("Error reading instructions: {}", err))
    {
        santa.rotate(instruction.rotation);
        santa.travel(instruction.distance);
    }
    println!("Distance traveled: {}", santa.distance_from_origin());
}
<commit_msg>Day 1 part 2<commit_after>extern crate clap;

use std::io::prelude::*;
use std::fs::File;

use std::collections::HashSet;

#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
enum Turn {
    Left,
    Right,
}

#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
enum Direction {
    North,
    East,
    South,
    West,
}

impl Direction {
    fn rotate(self, turn: Turn) -> Direction {
        use Turn::*;
        use Direction::*;
        match turn {
            Left => match self {
                North => West,
                East => North,
                South => East,
                West => South,
            },
            Right => match self {
                North => East,
                East => South,
                South => West,
                West => North,
            },
        }
    }
}

#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
struct Position {
    x: i64,
    y: i64,
}

impl Position {
    fn distance_from_origin(&self) -> u64 {
        self.x.wrapping_abs() as u64 + self.y.wrapping_abs() as u64
    }
}

#[derive(Clone, Copy, Debug)]
struct Traveller {
    pos: Position,
    facing: Direction,
}

impl Traveller {
    fn new() -> Traveller {
        Traveller { pos: Position {x: 0, y: 0}, facing: Direction::North }
    }
    fn rotate(&mut self, turn: Turn) {
        self.facing = self.facing.rotate(turn);
    }
    fn travel(&mut self, distance: u64) {
        match self.facing {
            Direction::North => self.pos.y += distance as i64,
            Direction::East => self.pos.x += distance as i64,
            Direction::South => self.pos.y -= distance as i64,
            Direction::West => self.pos.x -= distance as i64,
        }
    }
}

struct Instruction {
    rotation: Turn,
    distance: u64,
}

impl std::str::FromStr for Instruction {
    type Err = std::io::Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let s = s.trim();
        fn invalid_data(desc: &str) -> std::io::Error {
           std::io::Error::new(std::io::ErrorKind::InvalidData, desc)
        }
        if s.len() == 0 {
            return Err(invalid_data("Zero-length instruction"));
        }
        let (rot_str, dist_str) = s.split_at(1);
        let rot = match rot_str {
            "L" => Turn::Left,
            "R" => Turn::Right,
            _ => return Err(invalid_data(&format!("Invalid rotation: {}", rot_str))),
        };
        let dist = dist_str.parse()
            .map_err(|e| invalid_data(
                &format!("Invalid distance: {} ({})", dist_str, e)))?;
        Ok(Instruction { rotation: rot, distance: dist })
    }
}

fn parse_args() -> std::io::Result<Box<Read>> {
    let source = clap::App::new("Day 01")
        .author("Devon Hollowood")
        .arg(clap::Arg::with_name("instructions")
             .index(1)
             .short("f")
             .long("instructions")
             .help("file to read instructions from. Reads from stdin otherwise")
             .takes_value(true)
        )
        .get_matches()
        .value_of_os("instructions")
        .map(|str| str.to_owned());
    match source {
        Some(filename) => Ok(Box::new(File::open(filename)?)),
        None => Ok(Box::new(std::io::stdin())),
    }
}

fn read_instructions<R: Read>(source: &mut R) -> std::io::Result<Vec<Instruction>> {
    let mut instruction_str = String::new();
    source.read_to_string(&mut instruction_str)?;
    instruction_str.split(", ").map(|instr| instr.parse()).collect()
}

fn main() {
    let mut source = parse_args()
        .unwrap_or_else(|err| panic!("Error reading file: {}", err));
    let mut santa = Traveller::new();
    let mut visited = HashSet::new();
    visited.insert(santa.pos);
    let mut first_repeat = None;
    for instruction in read_instructions(&mut source)
        .unwrap_or_else(|err| panic!("Error reading instructions: {}", err))
    {
        santa.rotate(instruction.rotation);
        for _ in 0..instruction.distance {
            santa.travel(1);
            if first_repeat.is_none() {
                if visited.contains(&santa.pos) {
                    first_repeat = Some(santa.pos);
                } else {
                    visited.insert(santa.pos);
                }
            }
        }
    }
    println!("End distance traveled: {}", santa.pos.distance_from_origin());
    match first_repeat {
        Some(pos) => println!("Distance to first repeat: {}", pos.distance_from_origin()),
        None => println!("No repeated positions!"),
    }
}
<|endoftext|>


<commit_before>use std::f64;

/// The `IterStatistics` trait provides the same host of statistical
/// utilities as the `Statistics` traited ported for use with iterators
pub trait IterStatistics<T>: Iterator<Item = T> {
    /// Returns the minimum absolute value in the data
    ///
    /// # Remarks
    ///
    /// Returns `f64::NAN` if data is empty or an entry is `f64::NAN`
    ///
    /// # Examples
    ///
    /// ```
    /// use std::f64;
    /// use statrs::statistics::IterStatistics;
    ///
    /// let x = vec![];
    /// assert!(x.into_iter().abs_min().is_nan());
    ///
    /// let y = vec![0.0, f64::NAN, 3.0, -2.0];
    /// assert!(y.into_iter().abs_min().is_nan());
    ///
    /// let z = vec![0.0, 3.0, -2.0];
    /// assert_eq!(z.into_iter().abs_min(), 0.0);
    /// ```
    fn abs_min(&mut self) -> T;

    /// Returns the maximum absolute value in the data
    ///
    /// # Remarks
    ///
    /// Returns `f64::NAN` if data is empty or an entry is `f64::NAN`
    ///
    /// # Examples
    ///
    /// ```
    /// use std::f64;
    /// use statrs::statistics::IterStatistics;
    ///
    /// let x = vec![];
    /// assert!(x.into_iter().abs_max().is_nan());
    ///
    /// let y = vec![0.0, f64::NAN, 3.0, -2.0];
    /// assert!(y.into_iter().abs_max().is_nan());
    ///
    /// let z = vec![0.0, 3.0, -2.0, -8.0];
    /// assert_eq!(z.into_iter().abs_max(), 8.0);
    /// ```
    fn abs_max(&mut self) -> T;
}

impl<T: Iterator<Item = f64>> IterStatistics<f64> for T {
    fn abs_min(&mut self) -> f64 {
        match self.next() {
            None => f64::NAN,
            Some(x) => {
                self.map(|x| x.abs())
                    .fold(x.abs(),
                          |acc, x| if x < acc || x.is_nan() { x } else { acc })
            }
        }
    }

    fn abs_max(&mut self) -> f64 {
        match self.next() {
            None => f64::NAN,
            Some(x) => {
                self.map(|x| x.abs())
                    .fold(x.abs(),
                          |acc, x| if x > acc || x.is_nan() { x } else { acc })
            }
        }
    }
}
<commit_msg>begin support for iterators with &f64 vs f64<commit_after>use std::f64;

/// The `IterStatistics` trait provides the same host of statistical
/// utilities as the `Statistics` traited ported for use with iterators
/// which requires a mutable borrow
pub trait IterStatistics<I, T> : Iterator<Item=I> {
    /// Returns the minimum absolute value in the data
    ///
    /// # Remarks
    ///
    /// Returns `f64::NAN` if data is empty or an entry is `f64::NAN`
    ///
    /// # Examples
    ///
    /// ```
    /// use std::f64;
    /// use statrs::statistics::IterStatistics;
    ///
    /// let x: Vec<f64> = vec![];
    /// assert!(x.iter().abs_min().is_nan());
    ///
    /// let y = vec![0.0, f64::NAN, 3.0, -2.0];
    /// assert!(y.iter().abs_min().is_nan());
    ///
    /// let z = vec![0.0, 3.0, -2.0];
    /// assert_eq!(z.iter().abs_min(), 0.0);
    /// ```
    fn abs_min(&mut self) -> T;

    /// Returns the maximum absolute value in the data
    ///
    /// # Remarks
    ///
    /// Returns `f64::NAN` if data is empty or an entry is `f64::NAN`
    ///
    /// # Examples
    ///
    /// ```
    /// use std::f64;
    /// use statrs::statistics::IterStatistics;
    ///
    /// let x: Vec<f64> = vec![];
    /// assert!(x.into_iter().abs_max().is_nan());
    ///
    /// let y = vec![0.0, f64::NAN, 3.0, -2.0];
    /// assert!(y.into_iter().abs_max().is_nan());
    ///
    /// let z = vec![0.0, 3.0, -2.0, -8.0];
    /// assert_eq!(z.into_iter().abs_max(), 8.0);
    /// ```
    fn abs_max(&mut self) -> T;
}

impl<'a, T: Iterator<&'a f64>> IterStatistics<&'a f64, f64> for T
{
    fn abs_min(&mut self) -> f64 {
        match self.next() {
            None => f64::NAN,
            Some(x) => {
                self.map(|x| x.abs())
                    .fold(x.abs(),
                          |acc, x| if x < acc || x.is_nan() { x } else { acc })
            }
        }
    }

    fn abs_max(&mut self) -> f64 {
        match self.next() {
            None => f64::NAN,
            Some(x) => {
                self.map(|x| x.abs())
                    .fold(x.abs(),
                          |acc, x| if x > acc || x.is_nan() { x } else { acc })
            }
        }
    }
}

impl<'a, T: Iterator<f64>> IterStatistics<f64, f64> for T {
    fn abs_min(&mut self) -> f64 {
        match self.next() {
            None => f64::NAN,
            Some(x) => {
                self.map(|x| x.abs())
                    .fold(x.abs(),
                          |acc, x| if x < acc || x.is_nan() { x } else { acc })
            }
        }
    }

    fn abs_max(&mut self) -> f64 {
        match self.next() {
            None => f64::NAN,
            Some(x) => {
                self.map(|x| x.abs())
                    .fold(x.abs(),
                          |acc, x| if x > acc || x.is_nan() { x } else { acc })
            }
        }
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(clippy)]
#![deny(useless_attribute)]

#[allow(dead_code)] //~ ERROR useless lint attribute
//~| HELP if you just forgot a `!`, use
//~| SUGGESTION #![allow(dead_code)]
extern crate clippy_lints;

fn main() {}
<commit_msg>add regression test<commit_after>#![feature(plugin)]
#![plugin(clippy)]
#![deny(useless_attribute)]

#[allow(dead_code)] //~ ERROR useless lint attribute
//~| HELP if you just forgot a `!`, use
//~| SUGGESTION #![allow(dead_code)]
extern crate clippy_lints;

// don't lint on unused_import for `use` items
#[allow(unused_imports)]
use std::collections;

fn main() {}
<|endoftext|>


<commit_before>use std::str;
use libc;

use {raw, Repository, Error, Reference, Commit, Signature, BranchType};

/// A structure to represent a git [branch][1]
///
/// [1]: http://git-scm.com/book/en/Git-Branching-What-a-Branch-Is
pub struct Branch<'a> {
    inner: Reference<'a>,
}

/// dox
pub struct Branches<'a> {
    repo: &'a Repository,
    raw: *mut raw::git_branch_iterator,
}

impl<'a> Branch<'a> {
    /// Creates a new branch from a reference
    pub fn wrap(reference: Reference) -> Branch { Branch { inner: reference } }

    /// Create a new branch pointing at a target commit
    ///
    /// A new direct reference will be created pointing to this target commit.
    /// If `force` is true and a reference already exists with the given name,
    /// it'll be replaced.
    pub fn new<'a>(repo: &'a Repository,
                   branch_name: &str,
                   target: &Commit<'a>,
                   force: bool,
                   signature: &Signature,
                   log_message: &str) -> Result<Branch<'a>, Error> {
        let mut raw = 0 as *mut raw::git_reference;
        unsafe {
            try_call!(raw::git_branch_create(&mut raw,
                                             repo.raw(),
                                             branch_name.to_c_str(),
                                             &*target.raw(),
                                             force,
                                             &*signature.raw(),
                                             log_message.to_c_str()));
            Ok(Branch::wrap(Reference::from_raw(repo, raw)))
        }
    }

    /// Lookup a branch by its name in a repository.
    pub fn lookup<'a>(repo: &'a Repository, name: &str,
                      branch_type: BranchType)
                      -> Result<Branch<'a>, Error> {
        let mut ret = 0 as *mut raw::git_reference;
        unsafe {
            try_call!(raw::git_branch_lookup(&mut ret, repo.raw(),
                                             name.to_c_str(), branch_type));
            Ok(Branch::wrap(Reference::from_raw(repo, ret)))
        }
    }

    /// Gain access to the reference that is this branch
    pub fn get(&self) -> &Reference<'a> { &self.inner }

    /// Take ownership of the underlying reference.
    pub fn unwrap(self) -> Reference<'a> { self.inner }

    /// Delete an existing branch reference.
    pub fn delete(&mut self) -> Result<(), Error> {
        unsafe { try_call!(raw::git_branch_delete(self.get().raw())); }
        Ok(())
    }

    /// Determine if the current local branch is pointed at by HEAD.
    pub fn is_head(&self) -> bool {
        unsafe { raw::git_branch_is_head(&*self.get().raw()) == 1 }
    }

    /// Move/rename an existing local branch reference.
    pub fn move(&mut self, new_branch_name: &str, force: bool,
                signature: &Signature,
                log_message: &str) -> Result<Branch<'a>, Error> {
        let mut ret = 0 as *mut raw::git_reference;
        unsafe {
            try_call!(raw::git_branch_move(&mut ret, self.get().raw(),
                                           new_branch_name.to_c_str(),
                                           force, &*signature.raw(),
                                           log_message.to_c_str()));
            Ok(Branch::wrap(Reference::from_raw_ptr(ret)))
        }
    }

    /// Return the name of the given local or remote branch.
    ///
    /// May return `Ok(None)` if the name is not valid utf-8.
    pub fn name(&self) -> Result<Option<&str>, Error> {
        self.name_bytes().map(str::from_utf8)
    }

    /// Return the name of the given local or remote branch.
    pub fn name_bytes(&self) -> Result<&[u8], Error> {
        let mut ret = 0 as *const libc::c_char;
        unsafe {
            try_call!(raw::git_branch_name(&mut ret, &*self.get().raw()));
            Ok(::opt_bytes(self, ret).unwrap())
        }
    }

    /// Return the reference supporting the remote tracking branch, given a
    /// local branch reference.
    pub fn upstream<'a>(&'a self) -> Result<Branch<'a>, Error> {
        let mut ret = 0 as *mut raw::git_reference;
        unsafe {
            try_call!(raw::git_branch_upstream(&mut ret, &*self.get().raw()));
            Ok(Branch::wrap(Reference::from_raw_ptr(ret)))
        }
    }

    /// Set the upstream configuration for a given local branch.
    ///
    /// If `None` is specified, then the upstream branch is unset. The name
    /// provided is the name of the branch to set as upstream.
    pub fn set_upstream(&mut self,
                        upstream_name: Option<&str>) -> Result<(), Error> {
        let upstream_name = upstream_name.map(|s| s.to_c_str());
        unsafe {
            try_call!(raw::git_branch_set_upstream(self.get().raw(),
                                                   upstream_name));
            Ok(())
        }
    }
}

impl<'a> Branches<'a> {
    /// Creates a new iterator from the raw pointer given.
    ///
    /// This function is unsafe as it is not guaranteed that `raw` is a valid
    /// pointer.
    pub unsafe fn from_raw(repo: &Repository,
                           raw: *mut raw::git_branch_iterator) -> Branches {
        Branches { repo: repo, raw: raw }
    }
}

impl<'a> Iterator<(Branch<'a>, BranchType)> for Branches<'a> {
    fn next(&mut self) -> Option<(Branch<'a>, BranchType)> {
        let mut ret = 0 as *mut raw::git_reference;
        let mut typ = raw::GIT_BRANCH_LOCAL;
        unsafe {
            let rc = raw::git_branch_next(&mut ret, &mut typ, self.raw);
            if rc == raw::GIT_ITEROVER as libc::c_int {
                return None
            }
            assert_eq!(rc, 0);
            let typ = match typ {
                raw::GIT_BRANCH_LOCAL => ::Local,
                raw::GIT_BRANCH_REMOTE => ::Remote,
                raw::GIT_BRANCH_ALL => fail!("unexected branch type"),
            };
            Some((Branch::wrap(Reference::from_raw(self.repo, ret)), typ))
        }
    }
}

#[unsafe_destructor]
impl<'a> Drop for Branches<'a> {
    fn drop(&mut self) {
        unsafe { raw::git_branch_iterator_free(self.raw) }
    }
}

#[cfg(test)]
mod tests {
    use std::io::{TempDir, File};
    use {Repository, Commit, Signature, Branch};

    #[test]
    fn smoke() {
        let td = TempDir::new("test").unwrap();
        git!(td.path(), "init");
        git!(td.path(), "config", "user.name", "foo");
        git!(td.path(), "config", "user.email", "bar");
        File::create(&td.path().join("foo")).write_str("foobar").unwrap();
        git!(td.path(), "add", ".");
        git!(td.path(), "commit", "-m", "foo");

        let repo = Repository::open(td.path()).unwrap();
        let head = repo.head().unwrap();
        let target = head.target().unwrap();
        let commit = Commit::lookup(&repo, target).unwrap();

        let sig = Signature::default(&repo).unwrap();
        let mut b1 = Branch::new(&repo, "foo", &commit, false, &sig, "bar").unwrap();
        assert!(!b1.is_head());

        assert_eq!(repo.branches(None).unwrap().count(), 2);
        Branch::lookup(&repo, "foo", ::Local).unwrap();
        let mut b1 = b1.move("bar", false, &sig, "bar2").unwrap();
        assert_eq!(b1.name().unwrap(), Some("bar"));
        assert!(b1.upstream().is_err());
        b1.set_upstream(Some("master")).unwrap();
        b1.upstream().unwrap();
        b1.set_upstream(None).unwrap();

        b1.delete().unwrap();
    }
}
<commit_msg>Clarify what a branch is<commit_after>use std::str;
use libc;

use {raw, Repository, Error, Reference, Commit, Signature, BranchType};

/// A structure to represent a git [branch][1]
///
/// A branch is currently just a wrapper to an underlying `Reference`. The
/// reference can be accessed through the `get` and `unwrap` methods.
///
/// [1]: http://git-scm.com/book/en/Git-Branching-What-a-Branch-Is
pub struct Branch<'a> {
    inner: Reference<'a>,
}

/// dox
pub struct Branches<'a> {
    repo: &'a Repository,
    raw: *mut raw::git_branch_iterator,
}

impl<'a> Branch<'a> {
    /// Creates a new branch from a reference
    pub fn wrap(reference: Reference) -> Branch { Branch { inner: reference } }

    /// Create a new branch pointing at a target commit
    ///
    /// A new direct reference will be created pointing to this target commit.
    /// If `force` is true and a reference already exists with the given name,
    /// it'll be replaced.
    pub fn new<'a>(repo: &'a Repository,
                   branch_name: &str,
                   target: &Commit<'a>,
                   force: bool,
                   signature: &Signature,
                   log_message: &str) -> Result<Branch<'a>, Error> {
        let mut raw = 0 as *mut raw::git_reference;
        unsafe {
            try_call!(raw::git_branch_create(&mut raw,
                                             repo.raw(),
                                             branch_name.to_c_str(),
                                             &*target.raw(),
                                             force,
                                             &*signature.raw(),
                                             log_message.to_c_str()));
            Ok(Branch::wrap(Reference::from_raw(repo, raw)))
        }
    }

    /// Lookup a branch by its name in a repository.
    pub fn lookup<'a>(repo: &'a Repository, name: &str,
                      branch_type: BranchType)
                      -> Result<Branch<'a>, Error> {
        let mut ret = 0 as *mut raw::git_reference;
        unsafe {
            try_call!(raw::git_branch_lookup(&mut ret, repo.raw(),
                                             name.to_c_str(), branch_type));
            Ok(Branch::wrap(Reference::from_raw(repo, ret)))
        }
    }

    /// Gain access to the reference that is this branch
    pub fn get(&self) -> &Reference<'a> { &self.inner }

    /// Take ownership of the underlying reference.
    pub fn unwrap(self) -> Reference<'a> { self.inner }

    /// Delete an existing branch reference.
    pub fn delete(&mut self) -> Result<(), Error> {
        unsafe { try_call!(raw::git_branch_delete(self.get().raw())); }
        Ok(())
    }

    /// Determine if the current local branch is pointed at by HEAD.
    pub fn is_head(&self) -> bool {
        unsafe { raw::git_branch_is_head(&*self.get().raw()) == 1 }
    }

    /// Move/rename an existing local branch reference.
    pub fn move(&mut self, new_branch_name: &str, force: bool,
                signature: &Signature,
                log_message: &str) -> Result<Branch<'a>, Error> {
        let mut ret = 0 as *mut raw::git_reference;
        unsafe {
            try_call!(raw::git_branch_move(&mut ret, self.get().raw(),
                                           new_branch_name.to_c_str(),
                                           force, &*signature.raw(),
                                           log_message.to_c_str()));
            Ok(Branch::wrap(Reference::from_raw_ptr(ret)))
        }
    }

    /// Return the name of the given local or remote branch.
    ///
    /// May return `Ok(None)` if the name is not valid utf-8.
    pub fn name(&self) -> Result<Option<&str>, Error> {
        self.name_bytes().map(str::from_utf8)
    }

    /// Return the name of the given local or remote branch.
    pub fn name_bytes(&self) -> Result<&[u8], Error> {
        let mut ret = 0 as *const libc::c_char;
        unsafe {
            try_call!(raw::git_branch_name(&mut ret, &*self.get().raw()));
            Ok(::opt_bytes(self, ret).unwrap())
        }
    }

    /// Return the reference supporting the remote tracking branch, given a
    /// local branch reference.
    pub fn upstream<'a>(&'a self) -> Result<Branch<'a>, Error> {
        let mut ret = 0 as *mut raw::git_reference;
        unsafe {
            try_call!(raw::git_branch_upstream(&mut ret, &*self.get().raw()));
            Ok(Branch::wrap(Reference::from_raw_ptr(ret)))
        }
    }

    /// Set the upstream configuration for a given local branch.
    ///
    /// If `None` is specified, then the upstream branch is unset. The name
    /// provided is the name of the branch to set as upstream.
    pub fn set_upstream(&mut self,
                        upstream_name: Option<&str>) -> Result<(), Error> {
        let upstream_name = upstream_name.map(|s| s.to_c_str());
        unsafe {
            try_call!(raw::git_branch_set_upstream(self.get().raw(),
                                                   upstream_name));
            Ok(())
        }
    }
}

impl<'a> Branches<'a> {
    /// Creates a new iterator from the raw pointer given.
    ///
    /// This function is unsafe as it is not guaranteed that `raw` is a valid
    /// pointer.
    pub unsafe fn from_raw(repo: &Repository,
                           raw: *mut raw::git_branch_iterator) -> Branches {
        Branches { repo: repo, raw: raw }
    }
}

impl<'a> Iterator<(Branch<'a>, BranchType)> for Branches<'a> {
    fn next(&mut self) -> Option<(Branch<'a>, BranchType)> {
        let mut ret = 0 as *mut raw::git_reference;
        let mut typ = raw::GIT_BRANCH_LOCAL;
        unsafe {
            let rc = raw::git_branch_next(&mut ret, &mut typ, self.raw);
            if rc == raw::GIT_ITEROVER as libc::c_int {
                return None
            }
            assert_eq!(rc, 0);
            let typ = match typ {
                raw::GIT_BRANCH_LOCAL => ::Local,
                raw::GIT_BRANCH_REMOTE => ::Remote,
                raw::GIT_BRANCH_ALL => fail!("unexected branch type"),
            };
            Some((Branch::wrap(Reference::from_raw(self.repo, ret)), typ))
        }
    }
}

#[unsafe_destructor]
impl<'a> Drop for Branches<'a> {
    fn drop(&mut self) {
        unsafe { raw::git_branch_iterator_free(self.raw) }
    }
}

#[cfg(test)]
mod tests {
    use std::io::{TempDir, File};
    use {Repository, Commit, Signature, Branch};

    #[test]
    fn smoke() {
        let td = TempDir::new("test").unwrap();
        git!(td.path(), "init");
        git!(td.path(), "config", "user.name", "foo");
        git!(td.path(), "config", "user.email", "bar");
        File::create(&td.path().join("foo")).write_str("foobar").unwrap();
        git!(td.path(), "add", ".");
        git!(td.path(), "commit", "-m", "foo");

        let repo = Repository::open(td.path()).unwrap();
        let head = repo.head().unwrap();
        let target = head.target().unwrap();
        let commit = Commit::lookup(&repo, target).unwrap();

        let sig = Signature::default(&repo).unwrap();
        let mut b1 = Branch::new(&repo, "foo", &commit, false, &sig, "bar").unwrap();
        assert!(!b1.is_head());

        assert_eq!(repo.branches(None).unwrap().count(), 2);
        Branch::lookup(&repo, "foo", ::Local).unwrap();
        let mut b1 = b1.move("bar", false, &sig, "bar2").unwrap();
        assert_eq!(b1.name().unwrap(), Some("bar"));
        assert!(b1.upstream().is_err());
        b1.set_upstream(Some("master")).unwrap();
        b1.upstream().unwrap();
        b1.set_upstream(None).unwrap();

        b1.delete().unwrap();
    }
}
<|endoftext|>


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

// ignore-cloudabi no environment variables present
// ignore-emscripten env vars don't work?

#![feature(path)]

use std::env::*;
use std::path::PathBuf;

#[cfg(unix)]
fn main() {
    let oldhome = var("HOME");

    set_var("HOME", "/home/MountainView");
    assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));

    remove_var("HOME");
    if cfg!(target_os = "android") {
        assert!(home_dir().is_none());
    } else {
        assert!(home_dir().is_some());
    }
}

#[cfg(windows)]
fn main() {
    let oldhome = var("HOME");
    let olduserprofile = var("USERPROFILE");

    remove_var("HOME");
    remove_var("USERPROFILE");

    assert!(home_dir().is_some());

    set_var("HOME", "/home/MountainView");
    assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));

    remove_var("HOME");

    set_var("USERPROFILE", "/home/MountainView");
    assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));

    set_var("HOME", "/home/MountainView");
    set_var("USERPROFILE", "/home/PaloAlto");
    assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));
}
<commit_msg>Rollup merge of #47718 - malbarbo:env-home-dir, r=nikomatsakis<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-cloudabi no environment variables present
// ignore-emscripten env vars don't work?

#![feature(path)]

use std::env::*;
use std::path::PathBuf;

#[cfg(unix)]
fn main() {
    let oldhome = var("HOME");

    set_var("HOME", "/home/MountainView");
    assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));

    remove_var("HOME");
    if cfg!(target_os = "android") {
        assert!(home_dir().is_none());
    } else {
        // When HOME is not set, some platforms return `None`,
        // but others return `Some` with a default.
        // Just check that it is not "/home/MountainView".
        assert_ne!(home_dir(), Some(PathBuf::from("/home/MountainView")));
    }
}

#[cfg(windows)]
fn main() {
    let oldhome = var("HOME");
    let olduserprofile = var("USERPROFILE");

    remove_var("HOME");
    remove_var("USERPROFILE");

    assert!(home_dir().is_some());

    set_var("HOME", "/home/MountainView");
    assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));

    remove_var("HOME");

    set_var("USERPROFILE", "/home/MountainView");
    assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));

    set_var("HOME", "/home/MountainView");
    set_var("USERPROFILE", "/home/PaloAlto");
    assert_eq!(home_dir(), Some(PathBuf::from("/home/MountainView")));
}
<|endoftext|>


<commit_before>//! A trace implementation for updates with a common time.

use ::Delta;

/// An immutable collection of updates with a common time.
pub struct Layer<Key, Val, Time> {
	time: Time,
	keys: Vec<Key>,
	offs: Vec<usize>,
	vals: Vec<(Val, Delta)>,
}<commit_msg>more prototyping<commit_after>//! A trace implementation for updates with relatively few distinct times.
//!
//! This implementation is similar to the initial differential dataflow implementation,
//! except it lacks an index from keys into the batches. On the other hand, it does give
//! the more efficient representation, where we avoid repeating times all over the place.
//!
//! This implementation keeps separate batches for each distinct time, and may keep multiple
//! batches for equivalent times until it finds reason to merge them (e.g. two of similar
//! size). Ideally, the number of batches to merge at run time should be at most linear in
//! the numbers of distinct times, and logarithmic in something else (inserts for each time?)

use ::Delta;

/// An append only collection of updates, optimized for relatively few distinct times.
///
/// This implementation maintains separate allocations for each distinct time, and may keep
/// multiple allocations for the same time if merging would be disproportionately expensive.
pub struct Spine<Key, Val, Time> {
	// ideally we keep this sorted by (time, size), to easily notice merge options.
	// we keep a second `Time` to mutate in response to `advance_by`.
	layers: Vec<(Time, Layer<Key, Val, Time>)>,
	// the current frontier.
	frontier: Vec<Time>,
	/// number of inserted tuples size last reorganization.
	effort: usize,
}

impl<Key: Ord, Val: Ord, Time: Ord>  Trace<Key, Val, Time> for Spine<Key, Val, Time> {

	type Batch = Rc<Layer<Key, Val, Time>>;
	type Cursor = CursorList<LayerCursor<Key, Val, Time>>;

	fn new(default: Time) -> Self {
		Spine {
			layers: Vec::new(),
			frontier: vec![default],
		}
	}
	fn insert(&mut self, batch: Self::Batch) {
		self.effort += batch.len();
		self.layers.push(batch);

		// think about advancing times, re-sorting, merging?
		if self.effort > self.layers.len() {
			for entry in self.layers.iter_mut() {
				entry.0 = entry.0.advance_by(&self.frontier[..]);
			}

			// sort layers first by time, then by length. merge options emerge.
			self.layers.sort_by(|x,y| (x.0, x.1.len()).cmp(&(y.0, y.1.len())));

			let mut cursor = 0;
			for i in 1 .. self.layers.len() {
				if self.layers[i].0 == self.layers[cursor].0 && self.layers[i].len() < self.layers[cursor].len() * 2 {
					// merge layers[i] and layers[cursor] into position cursor.
					self.layers[cursor] = Layer::merge(&self.layers[i], &self.layers[cursor], &self.frontier[..]);
				}
				else {
					cursor += 1;
				}
			}

			self.effort = 0;
		}
	}
	fn cursor(&self) -> Self::Cursor {
		let mut cursors = Vec::new();
		for layer in &self.layers[..] {
			cursors.push(layer.cursor());
		}

		CursorList::new(cursors)
	}
	fn advance_by(&mut self, frontier: &[Time]) {
		self.frontier = frontier.to_vec();
	}
}

/// An immutable collection of updates with a common time.
#[derive(Clone)]
pub struct Layer<Key, Val, Time> {
	time: Time,
	keys: Vec<Key>,
	offs: Vec<usize>,
	vals: Vec<(Val, Delta)>,
}

pub struct LayerCursor<Key, Val, Time> {

}

pub struct LayerBuilder<Key, Val, Time> {
	time: Time,

}<|endoftext|>