<commit_before>use position::Position;
use cppn::{Cppn, CppnNodeType};
use std::fmt::Debug;

#[derive(Debug, Copy, Clone)]
pub enum NodeConnectivity {
    In,
    Out,
    InOut
}

/// Represents a node in the substrate. `T` stores additional information about that node.
#[derive(Clone, Debug)]
pub struct Node<P, T>
    where P: Position,
{
    pub position: P,
    pub node_info: T,
    pub node_connectivity: NodeConnectivity
}

#[derive(Clone, Debug)]
pub struct Layer<P, T>
    where P: Position,
{
    nodes: Vec<Node<P, T>>,
}

impl<P, T> Layer<P, T>
    where P: Position,
{
    pub fn new() -> Self {
        Layer { nodes: Vec::new() }
    }

    pub fn nodes(&self) -> &[Node<P, T>] {
        &self.nodes
    }

    pub fn add_node(&mut self, position: P, node_info: T, node_connectivity: NodeConnectivity) {
        self.nodes.push(Node {
            position: position,
            node_info: node_info,
            node_connectivity: node_connectivity,
        });
    }
}

#[derive(Clone)]
pub struct Link<'a, P, T>
    where P: Position + 'a,
          T: 'a
{
    pub source: &'a Node<P, T>,
    pub target: &'a Node<P, T>,
    pub source_idx: (usize, usize), // (layer, node)
    pub target_idx: (usize, usize), // (layer, node)
    pub outputs: Vec<f64>,
    pub distance: f64,
}

#[derive(Clone, Debug)]
struct LayerLink {
    from_layer: usize,
    to_layer: usize,
    max_distance: Option<f64>,
}

#[derive(Clone, Debug)]
pub struct Substrate<P, T>
    where P: Position,
{
    layers: Vec<Layer<P, T>>,
    layer_links: Vec<LayerLink>,
}

impl<P, T> Substrate<P, T>
    where P: Position,
{
    pub fn new() -> Self {
        Substrate {
            layers: Vec::new(),
            layer_links: Vec::new(),
        }
    }

    pub fn layers(&self) -> &[Layer<P, T>] {
        &self.layers
    }

    pub fn add_layer(&mut self, layer: Layer<P, T>) -> usize {
        let layer_idx = self.layers.len();
        self.layers.push(layer);
        return layer_idx;
    }

    pub fn add_layer_link(&mut self,
                          from_layer: usize,
                          to_layer: usize,
                          max_distance: Option<f64>) {
        self.layer_links.push(LayerLink {
            from_layer: from_layer,
            to_layer: to_layer,
            max_distance: max_distance,
        });
    }

    /// Iterate over all produced links of Cppn.

    pub fn each_link<'a, N, L, EXTID, F>(&'a self,
                                         cppn: &'a mut Cppn<'a, N, L, EXTID>,
                                         callback: &mut F)
        where N: CppnNodeType,
              L: Copy + Debug + Send + Sized + Into<f64> + 'a,
              EXTID: Copy + Debug + Send + Sized + Ord + 'a,
              F: FnMut(Link<'a, P, T>)
    {
        for layer_link in self.layer_links.iter() {
            for (source_idx, source) in self.layers[layer_link.from_layer]
                                            .nodes
                                            .iter()
                                            .enumerate() {
                // Reject invalid connections.
                match source.node_connectivity {
                    NodeConnectivity::Out | NodeConnectivity::InOut => {}
                    NodeConnectivity::In => {
                        // Node does not allow outgoing connections
                        continue;
                    }
                }

                for (target_idx, target) in self.layers[layer_link.to_layer]
                                                .nodes
                                                .iter()
                                                .enumerate() {
                    // Reject invalid connections.
                    match target.node_connectivity {
                        NodeConnectivity::In | NodeConnectivity::InOut => {}
                        NodeConnectivity::Out => {
                            // Node does not allow incoming connections
                            continue;
                        }
                    }

                    let distance = source.position.distance(&target.position);

                    // reject a pair of nodes based on `max_distance`.
                    if let Some(max_d) = layer_link.max_distance {
                        if distance > max_d {
                            continue;
                        }
                    }

                    // Calculate the weight between source and target using the CPPN.

                    let inputs_to_cppn = [source.position.coords(), target.position.coords()];

                    let outputs_from_cppn = cppn.calculate(&inputs_to_cppn);

                    let link = Link {
                        source: source,
                        target: target,
                        source_idx: (layer_link.from_layer, source_idx),
                        target_idx: (layer_link.to_layer, target_idx),
                        outputs: outputs_from_cppn,
                        distance: distance,
                    };
                    callback(link);
                }
            }
        }
    }
}
<commit_msg>Store distance_square<commit_after>use position::Position;
use cppn::{Cppn, CppnNodeType};
use std::fmt::Debug;

#[derive(Debug, Copy, Clone)]
pub enum NodeConnectivity {
    In,
    Out,
    InOut
}

/// Represents a node in the substrate. `T` stores additional information about that node.
#[derive(Clone, Debug)]
pub struct Node<P, T>
    where P: Position,
{
    pub position: P,
    pub node_info: T,
    pub node_connectivity: NodeConnectivity
}

#[derive(Clone, Debug)]
pub struct Layer<P, T>
    where P: Position,
{
    nodes: Vec<Node<P, T>>,
}

impl<P, T> Layer<P, T>
    where P: Position,
{
    pub fn new() -> Self {
        Layer { nodes: Vec::new() }
    }

    pub fn nodes(&self) -> &[Node<P, T>] {
        &self.nodes
    }

    pub fn add_node(&mut self, position: P, node_info: T, node_connectivity: NodeConnectivity) {
        self.nodes.push(Node {
            position: position,
            node_info: node_info,
            node_connectivity: node_connectivity,
        });
    }
}

#[derive(Clone)]
pub struct Link<'a, P, T>
    where P: Position + 'a,
          T: 'a
{
    pub source: &'a Node<P, T>,
    pub target: &'a Node<P, T>,
    pub source_idx: (usize, usize), // (layer, node)
    pub target_idx: (usize, usize), // (layer, node)
    pub outputs: Vec<f64>,
    pub distance_square: f64,
}

#[derive(Clone, Debug)]
struct LayerLink {
    from_layer: usize,
    to_layer: usize,
    max_distance_square: Option<f64>,
}

#[derive(Clone, Debug)]
pub struct Substrate<P, T>
    where P: Position,
{
    layers: Vec<Layer<P, T>>,
    layer_links: Vec<LayerLink>,
}

impl<P, T> Substrate<P, T>
    where P: Position,
{
    pub fn new() -> Self {
        Substrate {
            layers: Vec::new(),
            layer_links: Vec::new(),
        }
    }

    pub fn layers(&self) -> &[Layer<P, T>] {
        &self.layers
    }

    pub fn add_layer(&mut self, layer: Layer<P, T>) -> usize {
        let layer_idx = self.layers.len();
        self.layers.push(layer);
        return layer_idx;
    }

    pub fn add_layer_link(&mut self,
                          from_layer: usize,
                          to_layer: usize,
                          max_distance_square: Option<f64>) {
        self.layer_links.push(LayerLink {
            from_layer: from_layer,
            to_layer: to_layer,
            max_distance_square: max_distance_square,
        });
    }

    /// Iterate over all produced links of Cppn.

    pub fn each_link<'a, N, L, EXTID, F>(&'a self,
                                         cppn: &'a mut Cppn<'a, N, L, EXTID>,
                                         callback: &mut F)
        where N: CppnNodeType,
              L: Copy + Debug + Send + Sized + Into<f64> + 'a,
              EXTID: Copy + Debug + Send + Sized + Ord + 'a,
              F: FnMut(Link<'a, P, T>)
    {
        for layer_link in self.layer_links.iter() {
            for (source_idx, source) in self.layers[layer_link.from_layer]
                                            .nodes
                                            .iter()
                                            .enumerate() {
                // Reject invalid connections.
                match source.node_connectivity {
                    NodeConnectivity::Out | NodeConnectivity::InOut => {}
                    NodeConnectivity::In => {
                        // Node does not allow outgoing connections
                        continue;
                    }
                }

                for (target_idx, target) in self.layers[layer_link.to_layer]
                                                .nodes
                                                .iter()
                                                .enumerate() {
                    // Reject invalid connections.
                    match target.node_connectivity {
                        NodeConnectivity::In | NodeConnectivity::InOut => {}
                        NodeConnectivity::Out => {
                            // Node does not allow incoming connections
                            continue;
                        }
                    }

                    let distance_sq = source.position.distance_square(&target.position);

                    // reject a pair of nodes based on `max_distance_square`.
                    if let Some(max_d_sq) = layer_link.max_distance_square {
                        if distance_sq > max_d_sq {
                            continue;
                        }
                    }

                    // Calculate the weight between source and target using the CPPN.

                    let inputs_to_cppn = [source.position.coords(), target.position.coords()];

                    let outputs_from_cppn = cppn.calculate(&inputs_to_cppn);

                    let link = Link {
                        source: source,
                        target: target,
                        source_idx: (layer_link.from_layer, source_idx),
                        target_idx: (layer_link.to_layer, target_idx),
                        outputs: outputs_from_cppn,
                        distance_square: distance_sq,
                    };
                    callback(link);
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate cairo;
extern crate gio;
extern crate glib;
extern crate gtk;

use std::cell::RefCell;
use std::env::args;
use std::rc::Rc;
use std::sync::mpsc;
use std::thread;
use std::time::Duration;

use cairo::prelude::*;
use cairo::{Context, Format, ImageSurface};
use gio::prelude::*;
use gtk::prelude::*;
use gtk::{ApplicationWindow, DrawingArea};

const WIDTH: i32 = 200;
const HEIGHT: i32 = 200;

// make moving clones into closures more convenient
macro_rules! clone {
    (@param _) => ( _ );
    (@param $x:ident) => ( $x );
    ($($n:ident),+ => move || $body:expr) => (
        {
            $( let $n = $n.clone(); )+
            move || $body
        }
    );
    ($($n:ident),+ => move |$($p:tt),+| $body:expr) => (
        {
            $( let $n = $n.clone(); )+
            move |$(clone!(@param $p),)+| $body
        }
    );
}

// Our custom image type. This stores a heap allocated byte array for the pixels for each of our
// images, can be sent safely between threads and can be temporarily converted to a Cairo image
// surface for drawing operations
#[derive(Clone)]
struct Image(Option<Box<[u8]>>);

impl Image {
    // Creates a new, black image
    fn new() -> Self {
        Image(Some(vec![0; 4 * WIDTH as usize * HEIGHT as usize].into()))
    }

    // Calls the given closure with a temporary Cairo image surface. After the closure has returned
    // there must be no further references to the surface.
    fn with_surface<F: FnOnce(&ImageSurface)>(&mut self, func: F) {
        // Helper struct that allows passing the pixels to the Cairo image surface and once the
        // image surface is destroyed the pixels will be stored in the return_location.
        //
        // This allows us to give temporary ownership of the pixels to the Cairo surface and later
        // retrieve them back in a safe way while ensuring that nothing else still has access to
        // it.
        struct ImageHolder {
            image: Option<Box<[u8]>>,
            return_location: Rc<RefCell<Option<Box<[u8]>>>>,
        }

        // This stores the pixels back into the return_location as now nothing
        // references the pixels anymore
        impl Drop for ImageHolder {
            fn drop(&mut self) {
                *self.return_location.borrow_mut() =
                    Some(self.image.take().expect("Holding no image"));
            }
        }

        // Needed for ImageSurface::create_for_data() to be able to access the pixels
        impl AsRef<[u8]> for ImageHolder {
            fn as_ref(&self) -> &[u8] {
                self.image.as_ref().expect("Holding no image").as_ref()
            }
        }

        impl AsMut<[u8]> for ImageHolder {
            fn as_mut(&mut self) -> &mut [u8] {
                self.image.as_mut().expect("Holding no image").as_mut()
            }
        }

        // Temporary move out the pixels
        let image = self.0.take().expect("Empty image");

        // A new return location that is then passed to our helper struct below
        let return_location = Rc::new(RefCell::new(None));
        {
            let holder = ImageHolder {
                image: Some(image),
                return_location: return_location.clone(),
            };

            // The surface will own the image for the scope of the block below
            let surface =
                ImageSurface::create_for_data(holder, Format::Rgb24, WIDTH, HEIGHT, 4 * WIDTH)
                    .expect("Can't create surface");
            func(&surface);

            // Now the surface will be destroyed and the pixels are stored in the return_location
        }

        // And here move the pixels back again
        self.0 = Some(
            return_location
                .borrow_mut()
                .take()
                .expect("Image not returned"),
        );
    }
}

// This example runs four worker threads rendering parts of the image independently at different
// paces in a sort of double buffered way.
//
// +---+---+
// | 0 | 1 |
// +---+---+
// | 2 | 3 |
// +---+---+
//
// Each worker thread waits for an image to render into, sleeps for a while, does the drawing, then
// sends the image back and waits for the next one.
//
// The GUI thread holds an image per image part at all times and these images are painted on a
// DrawingArea in its 'draw' signal handler whenever needed.
//
// Additionally the GUI thread has a channel for receiving the images from the worker threads. If
// there is a new image, the old image stored by the GUI thread is replaced with the new one and
// the old image is sent back to the worker thread. Then the appropriate part of the DrawingArea is
// invalidated prompting a redraw.
//
// The two images per thread are allocated and initialized once and sent back and forth repeatedly.

fn build_ui(application: &gtk::Application) {
    let window = ApplicationWindow::new(application);
    let area = DrawingArea::new();
    window.add(&area);

    area.set_size_request(WIDTH * 2, HEIGHT * 2);

    // Create the initial, green image
    let initial_image = draw_initial();

    // This is the channel for sending results from the worker thread to the main thread
    // For every received image, queue the corresponding part of the DrawingArea for redrawing
    let (ready_tx, ready_rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);

    let mut images = Vec::new();
    let mut origins = Vec::new();
    let mut workers = Vec::new();

    for thread_num in 0..4 {
        // This is the channel for sending image from the GUI thread to the workers so that the
        // worker can draw the new content into them
        let (tx, rx) = mpsc::channel();

        // Copy the initial image in two images for the workers
        let image0 = initial_image.clone();
        let image1 = initial_image.clone();

        // Store the first one in our vec. This is the one that would be drawn in the very
        // beginning by the DrawingArea.
        images.push(RefCell::new(image0));

        // Send the second one immediately to the worker thread for drawing the new content
        let _ = tx.send(image1);

        // Store for each worker thread its render rectangle inside the DrawingArea
        origins.push(match thread_num {
            0 => (0, 0),
            1 => (WIDTH, 0),
            2 => (0, HEIGHT),
            3 => (WIDTH, HEIGHT),
            _ => unreachable!(),
        });

        // And remember the sender side of the channel that allows the GUI thread to send back
        // images to the worker thread
        workers.push(tx);

        let x = (WIDTH - origins[thread_num].0) as f64;
        let y = (HEIGHT - origins[thread_num].1) as f64;
        let delay = Duration::from_millis((100 << thread_num) - 5);

        // Spawn the worker thread
        thread::spawn(clone!(ready_tx => move || {
            let mut n = 0;
            for mut image in rx.iter() {
                n = (n + 1) % 0x10000;

                // Draw an arc with a weirdly calculated radius
                image.with_surface(|surface| {
                    let cr = Context::new(surface);
                    draw_slow(&cr, delay, x, y, 1.2_f64.powi(((n as i32) << thread_num) % 32));
                    surface.flush();
                });

                // Send the finished image back to the GUI thread
                let _ = ready_tx.send((thread_num, image));
            }
        }));
    }

    // The connect-draw signal and the timeout handler closures have to be 'static, and both need
    // to have access to our images and related state.
    let workspace = Rc::new((images, origins, workers));

    // Whenever the drawing area has to be redrawn, render the latest images in the correct
    // locations
    area.connect_draw(clone!(workspace => move |_, cr| {
        let (ref images, ref origins, _) = *workspace;

        for (image, origin) in images.iter().zip(origins.iter()) {
            image.borrow_mut().with_surface(|surface| {
                draw_image_if_dirty(&cr, surface, *origin, (WIDTH, HEIGHT));
            });
        }

        Inhibit(false)
    }));

    ready_rx.attach(None, move |(thread_num, image)| {
        let (ref images, ref origins, ref workers) = *workspace;

        // Swap the newly received image with the old stored one and send the old one back to
        // the worker thread
        let tx = &workers[thread_num];
        let image = images[thread_num].replace(image);
        let _ = tx.send(image);

        area.queue_draw_area(origins[thread_num].0, origins[thread_num].1, WIDTH, HEIGHT);

        Continue(true)
    });

    window.show_all();
}

fn main() {
    let application = gtk::Application::new(
        Some("com.github.gtk-rs.examples.cairo_threads"),
        Default::default(),
    )
    .expect("Initialization failed...");

    application.connect_activate(|app| {
        build_ui(app);
    });

    application.run(&args().collect::<Vec<_>>());
}

// Creates a new image and fill it with green
fn draw_initial() -> Image {
    let mut image = Image::new();

    image.with_surface(|surface| {
        let cr = Context::new(surface);
        cr.set_source_rgb(0., 1., 0.);
        cr.paint();
    });

    image
}

// Sleep for a while and then draw an arc with a given radius
fn draw_slow(cr: &Context, delay: Duration, x: f64, y: f64, radius: f64) {
    use std::f64::consts::PI;

    thread::sleep(delay);
    cr.set_source_rgb(0., 0., 0.);
    cr.paint();
    cr.set_source_rgb(1., 1., 1.);
    cr.arc(x, y, radius, 0.0, 2. * PI);
    cr.stroke();
}

// Render the image surface into the context at the given position
fn draw_image_if_dirty(
    cr: &Context,
    image: &ImageSurface,
    origin: (i32, i32),
    dimensions: (i32, i32),
) {
    let x = origin.0 as f64;
    let y = origin.1 as f64;
    let w = dimensions.0 as f64;
    let h = dimensions.1 as f64;
    let (clip_x1, clip_y1, clip_x2, clip_y2) = cr.clip_extents();
    if clip_x1 >= x + w || clip_y1 >= y + h || clip_x2 <= x || clip_y2 <= y {
        return;
    }
    cr.set_source_surface(image, x, y);
    cr.paint();

    // Release the reference to the surface again
    cr.set_source_rgba(0.0, 0.0, 0.0, 0.0);
}
<commit_msg>update to last cairo version<commit_after>extern crate cairo;
extern crate gio;
extern crate glib;
extern crate gtk;

use std::cell::RefCell;
use std::env::args;
use std::rc::Rc;
use std::sync::mpsc;
use std::thread;
use std::time::Duration;

use cairo::{Context, Format, ImageSurface};
use gio::prelude::*;
use gtk::prelude::*;
use gtk::{ApplicationWindow, DrawingArea};

const WIDTH: i32 = 200;
const HEIGHT: i32 = 200;

// make moving clones into closures more convenient
macro_rules! clone {
    (@param _) => ( _ );
    (@param $x:ident) => ( $x );
    ($($n:ident),+ => move || $body:expr) => (
        {
            $( let $n = $n.clone(); )+
            move || $body
        }
    );
    ($($n:ident),+ => move |$($p:tt),+| $body:expr) => (
        {
            $( let $n = $n.clone(); )+
            move |$(clone!(@param $p),)+| $body
        }
    );
}

// Our custom image type. This stores a heap allocated byte array for the pixels for each of our
// images, can be sent safely between threads and can be temporarily converted to a Cairo image
// surface for drawing operations
#[derive(Clone)]
struct Image(Option<Box<[u8]>>);

impl Image {
    // Creates a new, black image
    fn new() -> Self {
        Image(Some(vec![0; 4 * WIDTH as usize * HEIGHT as usize].into()))
    }

    // Calls the given closure with a temporary Cairo image surface. After the closure has returned
    // there must be no further references to the surface.
    fn with_surface<F: FnOnce(&ImageSurface)>(&mut self, func: F) {
        // Helper struct that allows passing the pixels to the Cairo image surface and once the
        // image surface is destroyed the pixels will be stored in the return_location.
        //
        // This allows us to give temporary ownership of the pixels to the Cairo surface and later
        // retrieve them back in a safe way while ensuring that nothing else still has access to
        // it.
        struct ImageHolder {
            image: Option<Box<[u8]>>,
            return_location: Rc<RefCell<Option<Box<[u8]>>>>,
        }

        // This stores the pixels back into the return_location as now nothing
        // references the pixels anymore
        impl Drop for ImageHolder {
            fn drop(&mut self) {
                *self.return_location.borrow_mut() =
                    Some(self.image.take().expect("Holding no image"));
            }
        }

        // Needed for ImageSurface::create_for_data() to be able to access the pixels
        impl AsRef<[u8]> for ImageHolder {
            fn as_ref(&self) -> &[u8] {
                self.image.as_ref().expect("Holding no image").as_ref()
            }
        }

        impl AsMut<[u8]> for ImageHolder {
            fn as_mut(&mut self) -> &mut [u8] {
                self.image.as_mut().expect("Holding no image").as_mut()
            }
        }

        // Temporary move out the pixels
        let image = self.0.take().expect("Empty image");

        // A new return location that is then passed to our helper struct below
        let return_location = Rc::new(RefCell::new(None));
        {
            let holder = ImageHolder {
                image: Some(image),
                return_location: return_location.clone(),
            };

            // The surface will own the image for the scope of the block below
            let surface =
                ImageSurface::create_for_data(holder, Format::Rgb24, WIDTH, HEIGHT, 4 * WIDTH)
                    .expect("Can't create surface");
            func(&surface);

            // Now the surface will be destroyed and the pixels are stored in the return_location
        }

        // And here move the pixels back again
        self.0 = Some(
            return_location
                .borrow_mut()
                .take()
                .expect("Image not returned"),
        );
    }
}

// This example runs four worker threads rendering parts of the image independently at different
// paces in a sort of double buffered way.
//
// +---+---+
// | 0 | 1 |
// +---+---+
// | 2 | 3 |
// +---+---+
//
// Each worker thread waits for an image to render into, sleeps for a while, does the drawing, then
// sends the image back and waits for the next one.
//
// The GUI thread holds an image per image part at all times and these images are painted on a
// DrawingArea in its 'draw' signal handler whenever needed.
//
// Additionally the GUI thread has a channel for receiving the images from the worker threads. If
// there is a new image, the old image stored by the GUI thread is replaced with the new one and
// the old image is sent back to the worker thread. Then the appropriate part of the DrawingArea is
// invalidated prompting a redraw.
//
// The two images per thread are allocated and initialized once and sent back and forth repeatedly.

fn build_ui(application: &gtk::Application) {
    let window = ApplicationWindow::new(application);
    let area = DrawingArea::new();
    window.add(&area);

    area.set_size_request(WIDTH * 2, HEIGHT * 2);

    // Create the initial, green image
    let initial_image = draw_initial();

    // This is the channel for sending results from the worker thread to the main thread
    // For every received image, queue the corresponding part of the DrawingArea for redrawing
    let (ready_tx, ready_rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);

    let mut images = Vec::new();
    let mut origins = Vec::new();
    let mut workers = Vec::new();

    for thread_num in 0..4 {
        // This is the channel for sending image from the GUI thread to the workers so that the
        // worker can draw the new content into them
        let (tx, rx) = mpsc::channel();

        // Copy the initial image in two images for the workers
        let image0 = initial_image.clone();
        let image1 = initial_image.clone();

        // Store the first one in our vec. This is the one that would be drawn in the very
        // beginning by the DrawingArea.
        images.push(RefCell::new(image0));

        // Send the second one immediately to the worker thread for drawing the new content
        let _ = tx.send(image1);

        // Store for each worker thread its render rectangle inside the DrawingArea
        origins.push(match thread_num {
            0 => (0, 0),
            1 => (WIDTH, 0),
            2 => (0, HEIGHT),
            3 => (WIDTH, HEIGHT),
            _ => unreachable!(),
        });

        // And remember the sender side of the channel that allows the GUI thread to send back
        // images to the worker thread
        workers.push(tx);

        let x = (WIDTH - origins[thread_num].0) as f64;
        let y = (HEIGHT - origins[thread_num].1) as f64;
        let delay = Duration::from_millis((100 << thread_num) - 5);

        // Spawn the worker thread
        thread::spawn(clone!(ready_tx => move || {
            let mut n = 0;
            for mut image in rx.iter() {
                n = (n + 1) % 0x10000;

                // Draw an arc with a weirdly calculated radius
                image.with_surface(|surface| {
                    let cr = Context::new(surface);
                    draw_slow(&cr, delay, x, y, 1.2_f64.powi(((n as i32) << thread_num) % 32));
                    surface.flush();
                });

                // Send the finished image back to the GUI thread
                let _ = ready_tx.send((thread_num, image));
            }
        }));
    }

    // The connect-draw signal and the timeout handler closures have to be 'static, and both need
    // to have access to our images and related state.
    let workspace = Rc::new((images, origins, workers));

    // Whenever the drawing area has to be redrawn, render the latest images in the correct
    // locations
    area.connect_draw(clone!(workspace => move |_, cr| {
        let (ref images, ref origins, _) = *workspace;

        for (image, origin) in images.iter().zip(origins.iter()) {
            image.borrow_mut().with_surface(|surface| {
                draw_image_if_dirty(&cr, surface, *origin, (WIDTH, HEIGHT));
            });
        }

        Inhibit(false)
    }));

    ready_rx.attach(None, move |(thread_num, image)| {
        let (ref images, ref origins, ref workers) = *workspace;

        // Swap the newly received image with the old stored one and send the old one back to
        // the worker thread
        let tx = &workers[thread_num];
        let image = images[thread_num].replace(image);
        let _ = tx.send(image);

        area.queue_draw_area(origins[thread_num].0, origins[thread_num].1, WIDTH, HEIGHT);

        Continue(true)
    });

    window.show_all();
}

fn main() {
    let application = gtk::Application::new(
        Some("com.github.gtk-rs.examples.cairo_threads"),
        Default::default(),
    )
    .expect("Initialization failed...");

    application.connect_activate(|app| {
        build_ui(app);
    });

    application.run(&args().collect::<Vec<_>>());
}

// Creates a new image and fill it with green
fn draw_initial() -> Image {
    let mut image = Image::new();

    image.with_surface(|surface| {
        let cr = Context::new(surface);
        cr.set_source_rgb(0., 1., 0.);
        cr.paint();
    });

    image
}

// Sleep for a while and then draw an arc with a given radius
fn draw_slow(cr: &Context, delay: Duration, x: f64, y: f64, radius: f64) {
    use std::f64::consts::PI;

    thread::sleep(delay);
    cr.set_source_rgb(0., 0., 0.);
    cr.paint();
    cr.set_source_rgb(1., 1., 1.);
    cr.arc(x, y, radius, 0.0, 2. * PI);
    cr.stroke();
}

// Render the image surface into the context at the given position
fn draw_image_if_dirty(
    cr: &Context,
    image: &ImageSurface,
    origin: (i32, i32),
    dimensions: (i32, i32),
) {
    let x = origin.0 as f64;
    let y = origin.1 as f64;
    let w = dimensions.0 as f64;
    let h = dimensions.1 as f64;
    let (clip_x1, clip_y1, clip_x2, clip_y2) = cr.clip_extents();
    if clip_x1 >= x + w || clip_y1 >= y + h || clip_x2 <= x || clip_y2 <= y {
        return;
    }
    cr.set_source_surface(image, x, y);
    cr.paint();

    // Release the reference to the surface again
    cr.set_source_rgba(0.0, 0.0, 0.0, 0.0);
}
<|endoftext|>


<commit_before>

extern crate cratesfyi;
#[macro_use]
extern crate log;
extern crate clap;
extern crate time;

use std::env;
use std::fs;
use std::path::PathBuf;
use std::process::{Command, exit};

use cratesfyi::docbuilder::{DocBuilder, DocBuilderError, command_result};
use cratesfyi::docbuilder::crte::Crate;
use log::{LogLevel, LogLevelFilter, LogRecord, LogMetadata};
use clap::{Arg, App};
use time::now;

// I am using really simple Logger here
// I need to print everything to stdout for this program
struct Logger;

impl log::Log for Logger {
    fn enabled(&self, metadata: &LogMetadata) -> bool {
        metadata.level() <= LogLevel::Info
    }

    fn log(&self, record: &LogRecord) {
        if self.enabled(record.metadata()) {

            println!("{} {} - {}", now().to_utc().rfc822z(), record.level(), record.args());
        }
    }
}

fn update_crates_io_index(path: &PathBuf) -> Result<String, String> {
    info!("Updating crates.io-index");

    if path.exists() {
        let cwd = env::current_dir().unwrap();
        env::set_current_dir(path).unwrap();
        let res = command_result(Command::new("git").arg("pull").output().unwrap());
        env::set_current_dir(cwd).unwrap();
        res
    } else {
        command_result(Command::new("git")
            .arg("clone")
            .arg("https://github.com/rust-lang/crates.io-index.git")
            .arg(path.to_str().unwrap())
            .output().unwrap())
    }
}

// This will remove everything in CWD!!!
fn clean_build_dir() -> Result<(), DocBuilderError> {

    for file in try!(env::current_dir().unwrap()
                     .read_dir().map_err(DocBuilderError::RemoveBuildDir)) {
        let file = try!(file.map_err(DocBuilderError::RemoveBuildDir));
        let path = file.path();

        if path.file_name().unwrap() == ".cargo" ||
            path.file_name().unwrap() == ".crates.io-index" {
                continue;
            }

        if path.is_dir() {
            try!(fs::remove_dir_all(path).map_err(DocBuilderError::RemoveBuildDir));
        } else {
            try!(fs::remove_file(path).map_err(DocBuilderError::RemoveBuildDir));
        }
    }

    Ok(())
}

fn main() {
    log::set_logger(|max_log_level| {
        max_log_level.set(LogLevelFilter::Info);
        Box::new(Logger)
    }).unwrap();

    let matches = App::new("crate_builder")
        .version(env!("CARGO_PKG_VERSION"))
        .about("Crate documentation builder")
        .arg(Arg::with_name("CRATES_IO_INDEX_PATH")
             .short("p")
             .long("crates-io-index-path")
             .help("Sets crates.io-index path")
             .takes_value(true))
        .arg(Arg::with_name("CLEAN")
             .short("c")
             .long("clean")
             .help("Clean build dir before building"))
        .arg(Arg::with_name("CRATE_NAME")
             .index(1)
             .required(true)
             .help("Crate name"))
        .arg(Arg::with_name("CRATE_VERSION")
             .index(2)
             .required(true)
             .help("Version of crate"))
        .get_matches();

    let mut docbuilder = DocBuilder::default();
    let mut crates_io_index_path;

    // set crates.io-index path
    if let Some(crates_io_index_path_conf) = matches.value_of("CRATES_IO_INDEX_PATH") {
        crates_io_index_path = PathBuf::from(crates_io_index_path_conf);
        docbuilder.crates_io_index_path(PathBuf::from(&crates_io_index_path));
    } else {
        crates_io_index_path = env::home_dir().unwrap();
        crates_io_index_path.push(".crates.io-index");
        docbuilder.crates_io_index_path(PathBuf::from(&crates_io_index_path));
    }

    // update crates.io-index path
    if let Err(e) = update_crates_io_index(&crates_io_index_path) {
        panic!("{}", e);
    }

    // crates.io-index required for single crate
    if let Err(e) = docbuilder.check_crates_io_index_path() {
        panic!("{:?}", e);
    }

    let crte_name = matches.value_of("CRATE_NAME").unwrap();
    let version = matches.value_of("CRATE_VERSION").unwrap();

    let crte = Crate::new(crte_name.to_string(), vec![version.to_string()]);

    if matches.is_present("CLEAN") {
        clean_build_dir().unwrap();
    }

    if let Err(e) = crte.build_crate_doc(0, &docbuilder) {
        error!("Failed to build crate\n{:?}", e);
        exit(1);
    } else {
        info!("Crate successfully built!");
    }

}
<commit_msg>Use rfc3339 format in logs<commit_after>

extern crate cratesfyi;
#[macro_use]
extern crate log;
extern crate clap;
extern crate time;

use std::env;
use std::fs;
use std::path::PathBuf;
use std::process::{Command, exit};

use cratesfyi::docbuilder::{DocBuilder, DocBuilderError, command_result};
use cratesfyi::docbuilder::crte::Crate;
use log::{LogLevel, LogLevelFilter, LogRecord, LogMetadata};
use clap::{Arg, App};
use time::now;

// I am using really simple Logger here
// I need to print everything to stdout for this program
struct Logger;

impl log::Log for Logger {
    fn enabled(&self, metadata: &LogMetadata) -> bool {
        metadata.level() <= LogLevel::Info
    }

    fn log(&self, record: &LogRecord) {
        if self.enabled(record.metadata()) {

            println!("{} {} - {}", now().to_utc().rfc3339(), record.level(), record.args());
        }
    }
}

fn update_crates_io_index(path: &PathBuf) -> Result<String, String> {
    info!("Updating crates.io-index");

    if path.exists() {
        let cwd = env::current_dir().unwrap();
        env::set_current_dir(path).unwrap();
        let res = command_result(Command::new("git").arg("pull").output().unwrap());
        env::set_current_dir(cwd).unwrap();
        res
    } else {
        command_result(Command::new("git")
            .arg("clone")
            .arg("https://github.com/rust-lang/crates.io-index.git")
            .arg(path.to_str().unwrap())
            .output().unwrap())
    }
}

// This will remove everything in CWD!!!
fn clean_build_dir() -> Result<(), DocBuilderError> {

    for file in try!(env::current_dir().unwrap()
                     .read_dir().map_err(DocBuilderError::RemoveBuildDir)) {
        let file = try!(file.map_err(DocBuilderError::RemoveBuildDir));
        let path = file.path();

        if path.file_name().unwrap() == ".cargo" ||
            path.file_name().unwrap() == ".crates.io-index" {
                continue;
            }

        if path.is_dir() {
            try!(fs::remove_dir_all(path).map_err(DocBuilderError::RemoveBuildDir));
        } else {
            try!(fs::remove_file(path).map_err(DocBuilderError::RemoveBuildDir));
        }
    }

    Ok(())
}

fn main() {
    log::set_logger(|max_log_level| {
        max_log_level.set(LogLevelFilter::Info);
        Box::new(Logger)
    }).unwrap();

    let matches = App::new("crate_builder")
        .version(env!("CARGO_PKG_VERSION"))
        .about("Crate documentation builder")
        .arg(Arg::with_name("CRATES_IO_INDEX_PATH")
             .short("p")
             .long("crates-io-index-path")
             .help("Sets crates.io-index path")
             .takes_value(true))
        .arg(Arg::with_name("CLEAN")
             .short("c")
             .long("clean")
             .help("Clean build dir before building"))
        .arg(Arg::with_name("CRATE_NAME")
             .index(1)
             .required(true)
             .help("Crate name"))
        .arg(Arg::with_name("CRATE_VERSION")
             .index(2)
             .required(true)
             .help("Version of crate"))
        .get_matches();

    let mut docbuilder = DocBuilder::default();
    let mut crates_io_index_path;

    // set crates.io-index path
    if let Some(crates_io_index_path_conf) = matches.value_of("CRATES_IO_INDEX_PATH") {
        crates_io_index_path = PathBuf::from(crates_io_index_path_conf);
        docbuilder.crates_io_index_path(PathBuf::from(&crates_io_index_path));
    } else {
        crates_io_index_path = env::home_dir().unwrap();
        crates_io_index_path.push(".crates.io-index");
        docbuilder.crates_io_index_path(PathBuf::from(&crates_io_index_path));
    }

    // update crates.io-index path
    if let Err(e) = update_crates_io_index(&crates_io_index_path) {
        panic!("{}", e);
    }

    // crates.io-index required for single crate
    if let Err(e) = docbuilder.check_crates_io_index_path() {
        panic!("{:?}", e);
    }

    let crte_name = matches.value_of("CRATE_NAME").unwrap();
    let version = matches.value_of("CRATE_VERSION").unwrap();

    let crte = Crate::new(crte_name.to_string(), vec![version.to_string()]);

    if matches.is_present("CLEAN") {
        clean_build_dir().unwrap();
    }

    if let Err(e) = crte.build_crate_doc(0, &docbuilder) {
        error!("Failed to build crate\n{:?}", e);
        exit(1);
    } else {
        info!("Crate successfully built!");
    }

}
<|endoftext|>


<commit_before>extern crate dot;
extern crate cripes;
extern crate itertools;
extern crate regex_syntax;

use std::fmt::Display;
use std::io::{self, Write};

use cripes::util::graph::{Graph, DirectedGraph, ConcreteGraph, Id, WeightedNode, WeightedEdge};
use cripes::pattern::Element;
use cripes::automaton::{State, DFA, NFA};

struct G<'a,T>(&'a T) where T: 'a + DirectedGraph;

impl<'a,T: DirectedGraph> dot::GraphWalk<'a,T::NodeId,T::EdgeId> for G<'a,T> {
    fn nodes(&self) -> dot::Nodes<'a,T::NodeId> { self.0.node_ids().collect() }
    fn edges(&self) -> dot::Edges<'a,T::EdgeId> { self.0.edge_ids().collect() }
    fn source(&self, e: &T::EdgeId) -> T::NodeId {
        self.0.edge_source(*e)
    }
    fn target(&self, e: &T::EdgeId) -> T::NodeId {
        self.0.edge_target(*e)
    }
}

impl<'a,T,W> dot::Labeller<'a,T::NodeId,T::EdgeId> for G<'a,T>
    where T: ConcreteGraph<Node=WeightedNode<State,<T as Graph>::EdgeId>,
                           Edge=WeightedEdge<W,<T as Graph>::NodeId>>,
          W: Display + Clone
{
    fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("G0".to_owned()).unwrap() }
    fn node_id(&'a self, n: &T::NodeId) -> dot::Id<'a> { dot::Id::new(format!("N{}", n.index())).unwrap() }
    fn edge_label(&'a self, e: &T::EdgeId) -> dot::LabelText<'a> {
        let edge = &*self.0.edge(*e);
        dot::LabelText::LabelStr(format!("{}", edge.data()).into())
    }
    /*fn edge_style(&'a self, e: &EdgeId) -> dot::Style {
        /*match self.graph.edge(*e).input {
            Transition::Repeat{..} => dot::Style::Dashed,
            _ => */dot::Style::Solid
        // }
    }*/
    fn node_label(&'a self, n: &T::NodeId) -> dot::LabelText<'a> {
        let node = &*self.0.node(*n);
        if node.actions().is_empty() {
            dot::LabelText::LabelStr(format!("{}", n.index()).into())
        } else {
            dot::LabelText::LabelStr(format!("{}", n.index()).into())
                                 //<FlowStructure as NodeAnalysis<GraphReprImpl<char>>>::apply(&self.graph, *n)).into()
        }
    }
    fn node_shape(&'a self, node: &T::NodeId) -> Option<dot::LabelText<'a>> {
        let shape: &'static str =
            if self.0.node(*node).is_accept() { "doublecircle" }
            else { "circle" };
        Some(dot::LabelText::LabelStr(String::from(shape).into()))
    }
}

fn main() {
    let mut args = std::env::args();
    let progname = args.next().unwrap();

    let mut have_args = false;
    let mut nfa_only = false;

    while let Some(arg) = args.next() {
        have_args = true;
        match arg.as_str() {
            "-n" => nfa_only = true,
            "-d" => nfa_only = false,
            s => {
                match regex_syntax::Expr::parse(s) {
                    Ok(expr)
                        => {
                            let nfa = NFA::from(Element::from(expr));
                            if nfa_only {
                                dot::render(&G(nfa.graph()), &mut io::stdout()).unwrap();
                            } else {
                                let dfa = DFA::from(nfa);
                                dot::render(&G(dfa.graph()), &mut io::stdout()).unwrap();
                            }
                        },
                    Err(err)
                        => {writeln!(io::stderr(), "{}", err).unwrap(); },
                }
                break; },
        }
    }
    if ! have_args {
        writeln!(io::stderr(), "Usage: {} REGEXP", progname).unwrap();
    }
}
<commit_msg>bin/regexp-graph: use `ByteOrChar` atom type when converting from regex<commit_after>extern crate dot;
extern crate cripes;
extern crate itertools;
extern crate regex_syntax;

use std::fmt::Display;
use std::io::{self, Write};

use cripes::util::graph::{Graph, DirectedGraph, ConcreteGraph, Id, WeightedNode, WeightedEdge};
use cripes::pattern::{Element, ByteOrChar};
use cripes::automaton::{State, DFA, NFA};

struct G<'a,T>(&'a T) where T: 'a + DirectedGraph;

impl<'a,T: DirectedGraph> dot::GraphWalk<'a,T::NodeId,T::EdgeId> for G<'a,T> {
    fn nodes(&self) -> dot::Nodes<'a,T::NodeId> { self.0.node_ids().collect() }
    fn edges(&self) -> dot::Edges<'a,T::EdgeId> { self.0.edge_ids().collect() }
    fn source(&self, e: &T::EdgeId) -> T::NodeId {
        self.0.edge_source(*e)
    }
    fn target(&self, e: &T::EdgeId) -> T::NodeId {
        self.0.edge_target(*e)
    }
}

impl<'a,T,W> dot::Labeller<'a,T::NodeId,T::EdgeId> for G<'a,T>
    where T: ConcreteGraph<Node=WeightedNode<State,<T as Graph>::EdgeId>,
                           Edge=WeightedEdge<W,<T as Graph>::NodeId>>,
          W: Display + Clone
{
    fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("G0".to_owned()).unwrap() }
    fn node_id(&'a self, n: &T::NodeId) -> dot::Id<'a> { dot::Id::new(format!("N{}", n.index())).unwrap() }
    fn edge_label(&'a self, e: &T::EdgeId) -> dot::LabelText<'a> {
        let edge = &*self.0.edge(*e);
        dot::LabelText::LabelStr(format!("{}", edge.data()).into())
    }
    /*fn edge_style(&'a self, e: &EdgeId) -> dot::Style {
        /*match self.graph.edge(*e).input {
            Transition::Repeat{..} => dot::Style::Dashed,
            _ => */dot::Style::Solid
        // }
    }*/
    fn node_label(&'a self, n: &T::NodeId) -> dot::LabelText<'a> {
        let node = &*self.0.node(*n);
        if node.actions().is_empty() {
            dot::LabelText::LabelStr(format!("{}", n.index()).into())
        } else {
            dot::LabelText::LabelStr(format!("{}", n.index()).into())
                                 //<FlowStructure as NodeAnalysis<GraphReprImpl<char>>>::apply(&self.graph, *n)).into()
        }
    }
    fn node_shape(&'a self, node: &T::NodeId) -> Option<dot::LabelText<'a>> {
        let shape: &'static str =
            if self.0.node(*node).is_accept() { "doublecircle" }
            else { "circle" };
        Some(dot::LabelText::LabelStr(String::from(shape).into()))
    }
}

fn main() {
    let mut args = std::env::args();
    let progname = args.next().unwrap();

    let mut have_args = false;
    let mut nfa_only = false;

    while let Some(arg) = args.next() {
        have_args = true;
        match arg.as_str() {
            "-n" => nfa_only = true,
            "-d" => nfa_only = false,
            s => {
                match regex_syntax::Expr::parse(s) {
                    Ok(expr)
                        => {
                            let nfa = NFA::from(Element::<ByteOrChar>::from(expr));
                            if nfa_only {
                                dot::render(&G(nfa.graph()), &mut io::stdout()).unwrap();
                            } else {
                                let dfa = DFA::from(nfa);
                                dot::render(&G(dfa.graph()), &mut io::stdout()).unwrap();
                            }
                        },
                    Err(err)
                        => {writeln!(io::stderr(), "{}", err).unwrap(); },
                }
                break; },
        }
    }
    if ! have_args {
        writeln!(io::stderr(), "Usage: {} REGEXP", progname).unwrap();
    }
}
<|endoftext|>


<commit_before>//! `cargo upgrade`
#![warn(missing_docs, missing_debug_implementations, missing_copy_implementations, trivial_casts,
        trivial_numeric_casts, unsafe_code, unstable_features, unused_import_braces,
        unused_qualifications)]

extern crate cargo_metadata;
extern crate docopt;
#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate serde_derive;
extern crate toml_edit;

use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::io::Write;
use std::process;

extern crate cargo_edit;
use cargo_edit::{find, get_latest_dependency, CrateName, Dependency, LocalManifest};

extern crate termcolor;
use termcolor::{BufferWriter, Color, ColorChoice, ColorSpec, WriteColor};

mod errors {
    error_chain!{
        links {
            CargoEditLib(::cargo_edit::Error, ::cargo_edit::ErrorKind);
            CargoMetadata(::cargo_metadata::Error, ::cargo_metadata::ErrorKind);
        }
    }
}
use errors::*;

static USAGE: &'static str = r"
Upgrade dependencies as specified in the local manifest file (i.e. Cargo.toml).

Usage:
    cargo upgrade [options] [<dependency>]...
    cargo upgrade (-h | --help)
    cargo upgrade (-V | --version)

Options:
    --all                   Upgrade all packages in the workspace.
    --manifest-path PATH    Path to the manifest to upgrade.
    --allow-prerelease      Include prerelease versions when fetching from crates.io (e.g.
                            '0.6.0-alpha'). Defaults to false.
    --dry-run               Print changes to be made without making them. Defaults to false.
    -h --help               Show this help page.
    -V --version            Show version.

This command differs from `cargo update`, which updates the dependency versions recorded in the
local lock file (Cargo.lock).

If `<dependency>`(s) are provided, only the specified dependencies will be upgraded. The version to
upgrade to for each can be specified with e.g. `docopt@0.8.0` or `serde@>=0.9,<2.0`.

Dev, build, and all target dependencies will also be upgraded. Only dependencies from crates.io are
supported. Git/path dependencies will be ignored.

All packages in the workspace will be upgraded if the `--all` flag is supplied. The `--all` flag may
be supplied in the presence of a virtual manifest.
";

/// Docopts input args.
#[derive(Debug, Deserialize)]
struct Args {
    /// `<dependency>...`
    arg_dependency: Vec<String>,
    /// `--manifest-path PATH`
    flag_manifest_path: Option<String>,
    /// `--all`
    flag_all: bool,
    /// `--allow-prerelease`
    flag_allow_prerelease: bool,
    /// `--dry-run`
    flag_dry_run: bool,
    /// `--version`
    flag_version: bool,
}

/// A collection of manifests.
struct Manifests(Vec<(LocalManifest, cargo_metadata::Package)>);

impl Manifests {
    /// Get all manifests in the workspace.
    fn get_all(manifest_path: &Option<String>) -> Result<Self> {
        let manifest_path = manifest_path.clone().map(PathBuf::from);

        cargo_metadata::metadata(manifest_path.as_ref().map(Path::new))
            .chain_err(|| "Failed to get workspace metadata")?
            .packages
            .into_iter()
            .map(|package| {
                Ok((
                    LocalManifest::try_new(Path::new(&package.manifest_path))?,
                    package,
                ))
            })
            .collect::<Result<Vec<_>>>()
            .map(Manifests)
    }

    /// Get the manifest specified by the manifest path. Try to make an educated guess if no path is
    /// provided.
    fn get_local_one(manifest_path: &Option<String>) -> Result<Self> {
        let manifest_path = manifest_path.clone().map(PathBuf::from);
        let resolved_manifest_path: String = find(&manifest_path)?.to_string_lossy().into();

        let manifest = LocalManifest::find(&manifest_path)?;

        let packages = cargo_metadata::metadata(manifest_path.as_ref().map(Path::new))
            .chain_err(|| "Invalid manifest")?
            .packages;
        let package = packages
            .iter()
            .find(|p| p.manifest_path == resolved_manifest_path)
            // If we have successfully got metadata, but our manifest path does not correspond to a
            // package, we must have been called against a virtual manifest.
            .chain_err(|| "Found virtual manifest, but this command requires running against an \
                           actual package in this workspace. Try adding `--all`.")?;

        Ok(Manifests(vec![(manifest, package.to_owned())]))
    }

    /// Get the the combined set of dependencies to upgrade. If the user has specified
    /// per-dependency desired versions, extract those here.
    fn get_dependencies(&self, only_update: Vec<String>) -> Result<DesiredUpgrades> {
        /// Helper function to check whether a `cargo_metadata::Dependency` is a version dependency.
        fn is_version_dep(dependency: &cargo_metadata::Dependency) -> bool {
            match dependency.source {
                // This is the criterion cargo uses (in `SourceId::from_url`) to decide whether a
                // dependency has the 'registry' kind.
                Some(ref s) => s.splitn(2, '+').next() == Some("registry"),
                _ => false,
            }
        }

        Ok(DesiredUpgrades(if only_update.is_empty() {
            // User hasn't asked for any specific dependencies to be upgraded, so upgrade all the
            // dependencies.
            self.0
                .iter()
                .flat_map(|&(_, ref package)| package.dependencies.clone())
                .filter(is_version_dep)
                .map(|dependency| (dependency.name, None))
                .collect()
        } else {
            only_update
                .into_iter()
                .map(|name| {
                    if let Some(dependency) = CrateName::new(&name.clone()).parse_as_version()? {
                        Ok((
                            dependency.name.clone(),
                            dependency.version().map(String::from),
                        ))
                    } else {
                        Ok((name, None))
                    }
                })
                .collect::<Result<_>>()?
        }))
    }

    /// Upgrade the manifests on disk following the previously-determined upgrade schema.
    fn upgrade(self, upgraded_deps: &ActualUpgrades, dry_run: bool) -> Result<()> {
        if dry_run {
            let bufwtr = BufferWriter::stdout(ColorChoice::Always);
            let mut buffer = bufwtr.buffer();
            buffer
                .set_color(ColorSpec::new().set_fg(Some(Color::Cyan)).set_bold(true))
                .chain_err(|| "Failed to set output colour")?;
            write!(&mut buffer, "Starting dry run. ")
                .chain_err(|| "Failed to write dry run message")?;
            buffer
                .set_color(&ColorSpec::new())
                .chain_err(|| "Failed to clear output colour")?;
            writeln!(&mut buffer, "Changes will not be saved.")
                .chain_err(|| "Failed to write dry run message")?;
            bufwtr
                .print(&buffer)
                .chain_err(|| "Failed to print dry run message")?;
        }

        for (mut manifest, _) in self.0 {
            for (name, version) in &upgraded_deps.0 {
                manifest.upgrade(&Dependency::new(name).set_version(version), dry_run)?;
            }
        }

        Ok(())
    }
}

/// The set of dependencies to be upgraded, alongside desired versions, if specified by the user.
struct DesiredUpgrades(HashMap<String, Option<String>>);

/// The complete specification of the upgrades that will be performed. Map of the dependency names
/// to the new versions.
struct ActualUpgrades(HashMap<String, String>);

impl DesiredUpgrades {
    /// Transform the dependencies into their upgraded forms. If a version is specified, all
    /// dependencies will get that version.
    fn get_upgraded(self, allow_prerelease: bool) -> Result<ActualUpgrades> {
        self.0
            .into_iter()
            .map(|(name, version)| {
                if let Some(v) = version {
                    Ok((name, v))
                } else {
                    get_latest_dependency(&name, allow_prerelease)
                        .map(|new_dep| {
                            (
                                name,
                                new_dep
                                    .version()
                                    .expect("Invalid dependency type")
                                    .to_string(),
                            )
                        })
                        .chain_err(|| "Failed to get new version")
                }
            })
            .collect::<Result<_>>()
            .map(ActualUpgrades)
    }
}

/// Main processing function. Allows us to return a `Result` so that `main` can print pretty error
/// messages.
fn process(args: Args) -> Result<()> {
    let Args {
        arg_dependency,
        flag_manifest_path,
        flag_all,
        flag_allow_prerelease,
        flag_dry_run,
        ..
    } = args;

    let manifests = if flag_all {
        Manifests::get_all(&flag_manifest_path)
    } else {
        Manifests::get_local_one(&flag_manifest_path)
    }?;

    let existing_dependencies = manifests.get_dependencies(arg_dependency)?;

    let upgraded_dependencies = existing_dependencies.get_upgraded(flag_allow_prerelease)?;

    manifests.upgrade(&upgraded_dependencies, flag_dry_run)
}

fn main() {
    let args = docopt::Docopt::new(USAGE)
        .and_then(|d| d.deserialize::<Args>())
        .unwrap_or_else(|err| err.exit());

    if args.flag_version {
        println!("cargo-upgrade version {}", env!("CARGO_PKG_VERSION"));
        process::exit(0);
    }

    if let Err(err) = process(args) {
        eprintln!("Command failed due to unhandled error: {}\n", err);

        for e in err.iter().skip(1) {
            eprintln!("Caused by: {}", e);
        }

        if let Some(backtrace) = err.backtrace() {
            eprintln!("Backtrace: {:?}", backtrace);
        }

        process::exit(1);
    }
}
<commit_msg>cargo-upgrade prints manifests<commit_after>//! `cargo upgrade`
#![warn(missing_docs, missing_debug_implementations, missing_copy_implementations, trivial_casts,
        trivial_numeric_casts, unsafe_code, unstable_features, unused_import_braces,
        unused_qualifications)]

extern crate cargo_metadata;
extern crate docopt;
#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate serde_derive;
extern crate toml_edit;

use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::io::Write;
use std::process;

extern crate cargo_edit;
use cargo_edit::{find, get_latest_dependency, CrateName, Dependency, LocalManifest};

extern crate termcolor;
use termcolor::{BufferWriter, Color, ColorChoice, ColorSpec, WriteColor};

mod errors {
    error_chain!{
        links {
            CargoEditLib(::cargo_edit::Error, ::cargo_edit::ErrorKind);
            CargoMetadata(::cargo_metadata::Error, ::cargo_metadata::ErrorKind);
        }
    }
}
use errors::*;

static USAGE: &'static str = r"
Upgrade dependencies as specified in the local manifest file (i.e. Cargo.toml).

Usage:
    cargo upgrade [options] [<dependency>]...
    cargo upgrade (-h | --help)
    cargo upgrade (-V | --version)

Options:
    --all                   Upgrade all packages in the workspace.
    --manifest-path PATH    Path to the manifest to upgrade.
    --allow-prerelease      Include prerelease versions when fetching from crates.io (e.g.
                            '0.6.0-alpha'). Defaults to false.
    --dry-run               Print changes to be made without making them. Defaults to false.
    -h --help               Show this help page.
    -V --version            Show version.

This command differs from `cargo update`, which updates the dependency versions recorded in the
local lock file (Cargo.lock).

If `<dependency>`(s) are provided, only the specified dependencies will be upgraded. The version to
upgrade to for each can be specified with e.g. `docopt@0.8.0` or `serde@>=0.9,<2.0`.

Dev, build, and all target dependencies will also be upgraded. Only dependencies from crates.io are
supported. Git/path dependencies will be ignored.

All packages in the workspace will be upgraded if the `--all` flag is supplied. The `--all` flag may
be supplied in the presence of a virtual manifest.
";

/// Docopts input args.
#[derive(Debug, Deserialize)]
struct Args {
    /// `<dependency>...`
    arg_dependency: Vec<String>,
    /// `--manifest-path PATH`
    flag_manifest_path: Option<String>,
    /// `--all`
    flag_all: bool,
    /// `--allow-prerelease`
    flag_allow_prerelease: bool,
    /// `--dry-run`
    flag_dry_run: bool,
    /// `--version`
    flag_version: bool,
}

/// A collection of manifests.
struct Manifests(Vec<(LocalManifest, cargo_metadata::Package)>);

impl Manifests {
    /// Get all manifests in the workspace.
    fn get_all(manifest_path: &Option<String>) -> Result<Self> {
        let manifest_path = manifest_path.clone().map(PathBuf::from);

        cargo_metadata::metadata(manifest_path.as_ref().map(Path::new))
            .chain_err(|| "Failed to get workspace metadata")?
            .packages
            .into_iter()
            .map(|package| {
                Ok((
                    LocalManifest::try_new(Path::new(&package.manifest_path))?,
                    package,
                ))
            })
            .collect::<Result<Vec<_>>>()
            .map(Manifests)
    }

    /// Get the manifest specified by the manifest path. Try to make an educated guess if no path is
    /// provided.
    fn get_local_one(manifest_path: &Option<String>) -> Result<Self> {
        let manifest_path = manifest_path.clone().map(PathBuf::from);
        let resolved_manifest_path: String = find(&manifest_path)?.to_string_lossy().into();

        let manifest = LocalManifest::find(&manifest_path)?;

        let packages = cargo_metadata::metadata(manifest_path.as_ref().map(Path::new))
            .chain_err(|| "Invalid manifest")?
            .packages;
        let package = packages
            .iter()
            .find(|p| p.manifest_path == resolved_manifest_path)
            // If we have successfully got metadata, but our manifest path does not correspond to a
            // package, we must have been called against a virtual manifest.
            .chain_err(|| "Found virtual manifest, but this command requires running against an \
                           actual package in this workspace. Try adding `--all`.")?;

        Ok(Manifests(vec![(manifest, package.to_owned())]))
    }

    /// Get the the combined set of dependencies to upgrade. If the user has specified
    /// per-dependency desired versions, extract those here.
    fn get_dependencies(&self, only_update: Vec<String>) -> Result<DesiredUpgrades> {
        /// Helper function to check whether a `cargo_metadata::Dependency` is a version dependency.
        fn is_version_dep(dependency: &cargo_metadata::Dependency) -> bool {
            match dependency.source {
                // This is the criterion cargo uses (in `SourceId::from_url`) to decide whether a
                // dependency has the 'registry' kind.
                Some(ref s) => s.splitn(2, '+').next() == Some("registry"),
                _ => false,
            }
        }

        Ok(DesiredUpgrades(if only_update.is_empty() {
            // User hasn't asked for any specific dependencies to be upgraded, so upgrade all the
            // dependencies.
            self.0
                .iter()
                .flat_map(|&(_, ref package)| package.dependencies.clone())
                .filter(is_version_dep)
                .map(|dependency| (dependency.name, None))
                .collect()
        } else {
            only_update
                .into_iter()
                .map(|name| {
                    if let Some(dependency) = CrateName::new(&name.clone()).parse_as_version()? {
                        Ok((
                            dependency.name.clone(),
                            dependency.version().map(String::from),
                        ))
                    } else {
                        Ok((name, None))
                    }
                })
                .collect::<Result<_>>()?
        }))
    }

    /// Upgrade the manifests on disk following the previously-determined upgrade schema.
    fn upgrade(self, upgraded_deps: &ActualUpgrades, dry_run: bool) -> Result<()> {
        if dry_run {
            let bufwtr = BufferWriter::stdout(ColorChoice::Always);
            let mut buffer = bufwtr.buffer();
            buffer
                .set_color(ColorSpec::new().set_fg(Some(Color::Cyan)).set_bold(true))
                .chain_err(|| "Failed to set output colour")?;
            write!(&mut buffer, "Starting dry run. ")
                .chain_err(|| "Failed to write dry run message")?;
            buffer
                .set_color(&ColorSpec::new())
                .chain_err(|| "Failed to clear output colour")?;
            writeln!(&mut buffer, "Changes will not be saved.")
                .chain_err(|| "Failed to write dry run message")?;
            bufwtr
                .print(&buffer)
                .chain_err(|| "Failed to print dry run message")?;
        }

        for (mut manifest, package) in self.0 {
            println!("{}:", package.name);

            for (name, version) in &upgraded_deps.0 {
                manifest.upgrade(&Dependency::new(name).set_version(version), dry_run)?;
            }
        }

        Ok(())
    }
}

/// The set of dependencies to be upgraded, alongside desired versions, if specified by the user.
struct DesiredUpgrades(HashMap<String, Option<String>>);

/// The complete specification of the upgrades that will be performed. Map of the dependency names
/// to the new versions.
struct ActualUpgrades(HashMap<String, String>);

impl DesiredUpgrades {
    /// Transform the dependencies into their upgraded forms. If a version is specified, all
    /// dependencies will get that version.
    fn get_upgraded(self, allow_prerelease: bool) -> Result<ActualUpgrades> {
        self.0
            .into_iter()
            .map(|(name, version)| {
                if let Some(v) = version {
                    Ok((name, v))
                } else {
                    get_latest_dependency(&name, allow_prerelease)
                        .map(|new_dep| {
                            (
                                name,
                                new_dep
                                    .version()
                                    .expect("Invalid dependency type")
                                    .to_string(),
                            )
                        })
                        .chain_err(|| "Failed to get new version")
                }
            })
            .collect::<Result<_>>()
            .map(ActualUpgrades)
    }
}

/// Main processing function. Allows us to return a `Result` so that `main` can print pretty error
/// messages.
fn process(args: Args) -> Result<()> {
    let Args {
        arg_dependency,
        flag_manifest_path,
        flag_all,
        flag_allow_prerelease,
        flag_dry_run,
        ..
    } = args;

    let manifests = if flag_all {
        Manifests::get_all(&flag_manifest_path)
    } else {
        Manifests::get_local_one(&flag_manifest_path)
    }?;

    let existing_dependencies = manifests.get_dependencies(arg_dependency)?;

    let upgraded_dependencies = existing_dependencies.get_upgraded(flag_allow_prerelease)?;

    manifests.upgrade(&upgraded_dependencies, flag_dry_run)
}

fn main() {
    let args = docopt::Docopt::new(USAGE)
        .and_then(|d| d.deserialize::<Args>())
        .unwrap_or_else(|err| err.exit());

    if args.flag_version {
        println!("cargo-upgrade version {}", env!("CARGO_PKG_VERSION"));
        process::exit(0);
    }

    if let Err(err) = process(args) {
        eprintln!("Command failed due to unhandled error: {}\n", err);

        for e in err.iter().skip(1) {
            eprintln!("Caused by: {}", e);
        }

        if let Some(backtrace) = err.backtrace() {
            eprintln!("Backtrace: {:?}", backtrace);
        }

        process::exit(1);
    }
}
<|endoftext|>


<commit_before>//! Implementation of the install aspects of the compiler.
//!
//! This module is responsible for installing the standard library,
//! compiler, and documentation.

use std::env;
use std::fs;
use std::path::{Component, PathBuf};
use std::process::Command;

use build_helper::t;

use crate::dist::{self, sanitize_sh};
use crate::tarball::GeneratedTarball;
use crate::Compiler;

use crate::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::config::{Config, TargetSelection};

fn install_sh(
    builder: &Builder<'_>,
    package: &str,
    stage: u32,
    host: Option<TargetSelection>,
    tarball: &GeneratedTarball,
) {
    builder.info(&format!("Install {} stage{} ({:?})", package, stage, host));

    let prefix = default_path(&builder.config.prefix, "/usr/local");
    let sysconfdir = prefix.join(default_path(&builder.config.sysconfdir, "/etc"));
    let datadir = prefix.join(default_path(&builder.config.datadir, "share"));
    let docdir = prefix.join(default_path(&builder.config.docdir, "share/doc/rust"));
    let mandir = prefix.join(default_path(&builder.config.mandir, "share/man"));
    let libdir = prefix.join(default_path(&builder.config.libdir, "lib"));
    let bindir = prefix.join(&builder.config.bindir); // Default in config.rs

    let empty_dir = builder.out.join("tmp/empty_dir");
    t!(fs::create_dir_all(&empty_dir));

    let mut cmd = Command::new("sh");
    cmd.current_dir(&empty_dir)
        .arg(sanitize_sh(&tarball.decompressed_output().join("install.sh")))
        .arg(format!("--prefix={}", prepare_dir(prefix)))
        .arg(format!("--sysconfdir={}", prepare_dir(sysconfdir)))
        .arg(format!("--datadir={}", prepare_dir(datadir)))
        .arg(format!("--docdir={}", prepare_dir(docdir)))
        .arg(format!("--bindir={}", prepare_dir(bindir)))
        .arg(format!("--libdir={}", prepare_dir(libdir)))
        .arg(format!("--mandir={}", prepare_dir(mandir)))
        .arg("--disable-ldconfig");
    builder.run(&mut cmd);
    t!(fs::remove_dir_all(&empty_dir));
}

fn default_path(config: &Option<PathBuf>, default: &str) -> PathBuf {
    config.as_ref().cloned().unwrap_or_else(|| PathBuf::from(default))
}

fn prepare_dir(mut path: PathBuf) -> String {
    // The DESTDIR environment variable is a standard way to install software in a subdirectory
    // while keeping the original directory structure, even if the prefix or other directories
    // contain absolute paths.
    //
    // More information on the environment variable is available here:
    // https://www.gnu.org/prep/standards/html_node/DESTDIR.html
    if let Some(destdir) = env::var_os("DESTDIR").map(PathBuf::from) {
        let without_destdir = path.clone();
        path = destdir;
        // Custom .join() which ignores disk roots.
        for part in without_destdir.components() {
            if let Component::Normal(s) = part {
                path.push(s)
            }
        }
    }

    // The installation command is not executed from the current directory, but from a temporary
    // directory. To prevent relative paths from breaking this converts relative paths to absolute
    // paths. std::fs::canonicalize is not used as that requires the path to actually be present.
    if path.is_relative() {
        path = std::env::current_dir().expect("failed to get the current directory").join(path);
        assert!(path.is_absolute(), "could not make the path relative");
    }

    sanitize_sh(&path)
}

macro_rules! install {
    (($sel:ident, $builder:ident, $_config:ident),
       $($name:ident,
       $path:expr,
       $default_cond:expr,
       only_hosts: $only_hosts:expr,
       $run_item:block $(, $c:ident)*;)+) => {
        $(
            #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
        pub struct $name {
            pub compiler: Compiler,
            pub target: TargetSelection,
        }

        impl $name {
            #[allow(dead_code)]
            fn should_build(config: &Config) -> bool {
                config.extended && config.tools.as_ref()
                    .map_or(true, |t| t.contains($path))
            }
        }

        impl Step for $name {
            type Output = ();
            const DEFAULT: bool = true;
            const ONLY_HOSTS: bool = $only_hosts;
            $(const $c: bool = true;)*

            fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
                let $_config = &run.builder.config;
                run.path($path).default_condition($default_cond)
            }

            fn make_run(run: RunConfig<'_>) {
                run.builder.ensure($name {
                    compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build),
                    target: run.target,
                });
            }

            fn run($sel, $builder: &Builder<'_>) {
                $run_item
            }
        })+
    }
}

install!((self, builder, _config),
    Docs, "src/doc", _config.docs, only_hosts: false, {
        let tarball = builder.ensure(dist::Docs { host: self.target }).expect("missing docs");
        install_sh(builder, "docs", self.compiler.stage, Some(self.target), &tarball);
    };
    Std, "library/std", true, only_hosts: false, {
        for target in &builder.targets {
            let tarball = builder.ensure(dist::Std {
                compiler: self.compiler,
                target: *target
            }).expect("missing std");
            install_sh(builder, "std", self.compiler.stage, Some(*target), &tarball);
        }
    };
    Cargo, "cargo", Self::should_build(_config), only_hosts: true, {
        let tarball = builder.ensure(dist::Cargo { compiler: self.compiler, target: self.target });
        install_sh(builder, "cargo", self.compiler.stage, Some(self.target), &tarball);
    };
    Rls, "rls", Self::should_build(_config), only_hosts: true, {
        if let Some(tarball) = builder.ensure(dist::Rls { compiler: self.compiler, target: self.target }) {
            install_sh(builder, "rls", self.compiler.stage, Some(self.target), &tarball);
        } else {
            builder.info(
                &format!("skipping Install RLS stage{} ({})", self.compiler.stage, self.target),
            );
        }
    };
    RustAnalyzer, "rust-analyzer", Self::should_build(_config), only_hosts: true, {
        let tarball = builder
            .ensure(dist::RustAnalyzer { compiler: self.compiler, target: self.target })
            .expect("missing rust-analyzer");
        install_sh(builder, "rust-analyzer", self.compiler.stage, Some(self.target), &tarball);
    };
    Clippy, "clippy", Self::should_build(_config), only_hosts: true, {
        let tarball = builder.ensure(dist::Clippy { compiler: self.compiler, target: self.target });
        install_sh(builder, "clippy", self.compiler.stage, Some(self.target), &tarball);
    };
    Miri, "miri", Self::should_build(_config), only_hosts: true, {
        if let Some(tarball) = builder.ensure(dist::Miri { compiler: self.compiler, target: self.target }) {
            install_sh(builder, "miri", self.compiler.stage, Some(self.target), &tarball);
        } else {
            builder.info(
                &format!("skipping Install miri stage{} ({})", self.compiler.stage, self.target),
            );
        }
    };
    Rustfmt, "rustfmt", Self::should_build(_config), only_hosts: true, {
        if let Some(tarball) = builder.ensure(dist::Rustfmt {
            compiler: self.compiler,
            target: self.target
        }) {
            install_sh(builder, "rustfmt", self.compiler.stage, Some(self.target), &tarball);
        } else {
            builder.info(
                &format!("skipping Install Rustfmt stage{} ({})", self.compiler.stage, self.target),
            );
        }
    };
    RustDemangler, "rust-demangler", Self::should_build(_config), only_hosts: true, {
        // Note: Even though `should_build` may return true for `extended` default tools,
        // dist::RustDemangler may still return None, unless the target-dependent `profiler` config
        // is also true, or the `tools` array explicitly includes "rust-demangler".
        if let Some(tarball) = builder.ensure(dist::RustDemangler {
            compiler: self.compiler,
            target: self.target
        }) {
            install_sh(builder, "rust-demangler", self.compiler.stage, Some(self.target), &tarball);
        } else {
            builder.info(
                &format!("skipping Install RustDemangler stage{} ({})",
                         self.compiler.stage, self.target),
            );
        }
    };
    Analysis, "analysis", Self::should_build(_config), only_hosts: false, {
        let tarball = builder.ensure(dist::Analysis {
            // Find the actual compiler (handling the full bootstrap option) which
            // produced the save-analysis data because that data isn't copied
            // through the sysroot uplifting.
            compiler: builder.compiler_for(builder.top_stage, builder.config.build, self.target),
            target: self.target
        }).expect("missing analysis");
        install_sh(builder, "analysis", self.compiler.stage, Some(self.target), &tarball);
    };
    Rustc, "src/librustc", true, only_hosts: true, {
        let tarball = builder.ensure(dist::Rustc {
            compiler: builder.compiler(builder.top_stage, self.target),
        });
        install_sh(builder, "rustc", self.compiler.stage, Some(self.target), &tarball);
    };
);

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Src {
    pub stage: u32,
}

impl Step for Src {
    type Output = ();
    const DEFAULT: bool = true;
    const ONLY_HOSTS: bool = true;

    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
        let config = &run.builder.config;
        let cond = config.extended && config.tools.as_ref().map_or(true, |t| t.contains("src"));
        run.path("src").default_condition(cond)
    }

    fn make_run(run: RunConfig<'_>) {
        run.builder.ensure(Src { stage: run.builder.top_stage });
    }

    fn run(self, builder: &Builder<'_>) {
        let tarball = builder.ensure(dist::Src);
        install_sh(builder, "src", self.stage, None, &tarball);
    }
}
<commit_msg>bootstrap: use bash on illumos to run install scripts<commit_after>//! Implementation of the install aspects of the compiler.
//!
//! This module is responsible for installing the standard library,
//! compiler, and documentation.

use std::env;
use std::fs;
use std::path::{Component, PathBuf};
use std::process::Command;

use build_helper::t;

use crate::dist::{self, sanitize_sh};
use crate::tarball::GeneratedTarball;
use crate::Compiler;

use crate::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::config::{Config, TargetSelection};

#[cfg(target_os = "illumos")]
const SHELL: &str = "bash";
#[cfg(not(target_os = "illumos"))]
const SHELL: &str = "sh";

fn install_sh(
    builder: &Builder<'_>,
    package: &str,
    stage: u32,
    host: Option<TargetSelection>,
    tarball: &GeneratedTarball,
) {
    builder.info(&format!("Install {} stage{} ({:?})", package, stage, host));

    let prefix = default_path(&builder.config.prefix, "/usr/local");
    let sysconfdir = prefix.join(default_path(&builder.config.sysconfdir, "/etc"));
    let datadir = prefix.join(default_path(&builder.config.datadir, "share"));
    let docdir = prefix.join(default_path(&builder.config.docdir, "share/doc/rust"));
    let mandir = prefix.join(default_path(&builder.config.mandir, "share/man"));
    let libdir = prefix.join(default_path(&builder.config.libdir, "lib"));
    let bindir = prefix.join(&builder.config.bindir); // Default in config.rs

    let empty_dir = builder.out.join("tmp/empty_dir");
    t!(fs::create_dir_all(&empty_dir));

    let mut cmd = Command::new(SHELL);
    cmd.current_dir(&empty_dir)
        .arg(sanitize_sh(&tarball.decompressed_output().join("install.sh")))
        .arg(format!("--prefix={}", prepare_dir(prefix)))
        .arg(format!("--sysconfdir={}", prepare_dir(sysconfdir)))
        .arg(format!("--datadir={}", prepare_dir(datadir)))
        .arg(format!("--docdir={}", prepare_dir(docdir)))
        .arg(format!("--bindir={}", prepare_dir(bindir)))
        .arg(format!("--libdir={}", prepare_dir(libdir)))
        .arg(format!("--mandir={}", prepare_dir(mandir)))
        .arg("--disable-ldconfig");
    builder.run(&mut cmd);
    t!(fs::remove_dir_all(&empty_dir));
}

fn default_path(config: &Option<PathBuf>, default: &str) -> PathBuf {
    config.as_ref().cloned().unwrap_or_else(|| PathBuf::from(default))
}

fn prepare_dir(mut path: PathBuf) -> String {
    // The DESTDIR environment variable is a standard way to install software in a subdirectory
    // while keeping the original directory structure, even if the prefix or other directories
    // contain absolute paths.
    //
    // More information on the environment variable is available here:
    // https://www.gnu.org/prep/standards/html_node/DESTDIR.html
    if let Some(destdir) = env::var_os("DESTDIR").map(PathBuf::from) {
        let without_destdir = path.clone();
        path = destdir;
        // Custom .join() which ignores disk roots.
        for part in without_destdir.components() {
            if let Component::Normal(s) = part {
                path.push(s)
            }
        }
    }

    // The installation command is not executed from the current directory, but from a temporary
    // directory. To prevent relative paths from breaking this converts relative paths to absolute
    // paths. std::fs::canonicalize is not used as that requires the path to actually be present.
    if path.is_relative() {
        path = std::env::current_dir().expect("failed to get the current directory").join(path);
        assert!(path.is_absolute(), "could not make the path relative");
    }

    sanitize_sh(&path)
}

macro_rules! install {
    (($sel:ident, $builder:ident, $_config:ident),
       $($name:ident,
       $path:expr,
       $default_cond:expr,
       only_hosts: $only_hosts:expr,
       $run_item:block $(, $c:ident)*;)+) => {
        $(
            #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
        pub struct $name {
            pub compiler: Compiler,
            pub target: TargetSelection,
        }

        impl $name {
            #[allow(dead_code)]
            fn should_build(config: &Config) -> bool {
                config.extended && config.tools.as_ref()
                    .map_or(true, |t| t.contains($path))
            }
        }

        impl Step for $name {
            type Output = ();
            const DEFAULT: bool = true;
            const ONLY_HOSTS: bool = $only_hosts;
            $(const $c: bool = true;)*

            fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
                let $_config = &run.builder.config;
                run.path($path).default_condition($default_cond)
            }

            fn make_run(run: RunConfig<'_>) {
                run.builder.ensure($name {
                    compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build),
                    target: run.target,
                });
            }

            fn run($sel, $builder: &Builder<'_>) {
                $run_item
            }
        })+
    }
}

install!((self, builder, _config),
    Docs, "src/doc", _config.docs, only_hosts: false, {
        let tarball = builder.ensure(dist::Docs { host: self.target }).expect("missing docs");
        install_sh(builder, "docs", self.compiler.stage, Some(self.target), &tarball);
    };
    Std, "library/std", true, only_hosts: false, {
        for target in &builder.targets {
            let tarball = builder.ensure(dist::Std {
                compiler: self.compiler,
                target: *target
            }).expect("missing std");
            install_sh(builder, "std", self.compiler.stage, Some(*target), &tarball);
        }
    };
    Cargo, "cargo", Self::should_build(_config), only_hosts: true, {
        let tarball = builder.ensure(dist::Cargo { compiler: self.compiler, target: self.target });
        install_sh(builder, "cargo", self.compiler.stage, Some(self.target), &tarball);
    };
    Rls, "rls", Self::should_build(_config), only_hosts: true, {
        if let Some(tarball) = builder.ensure(dist::Rls { compiler: self.compiler, target: self.target }) {
            install_sh(builder, "rls", self.compiler.stage, Some(self.target), &tarball);
        } else {
            builder.info(
                &format!("skipping Install RLS stage{} ({})", self.compiler.stage, self.target),
            );
        }
    };
    RustAnalyzer, "rust-analyzer", Self::should_build(_config), only_hosts: true, {
        let tarball = builder
            .ensure(dist::RustAnalyzer { compiler: self.compiler, target: self.target })
            .expect("missing rust-analyzer");
        install_sh(builder, "rust-analyzer", self.compiler.stage, Some(self.target), &tarball);
    };
    Clippy, "clippy", Self::should_build(_config), only_hosts: true, {
        let tarball = builder.ensure(dist::Clippy { compiler: self.compiler, target: self.target });
        install_sh(builder, "clippy", self.compiler.stage, Some(self.target), &tarball);
    };
    Miri, "miri", Self::should_build(_config), only_hosts: true, {
        if let Some(tarball) = builder.ensure(dist::Miri { compiler: self.compiler, target: self.target }) {
            install_sh(builder, "miri", self.compiler.stage, Some(self.target), &tarball);
        } else {
            builder.info(
                &format!("skipping Install miri stage{} ({})", self.compiler.stage, self.target),
            );
        }
    };
    Rustfmt, "rustfmt", Self::should_build(_config), only_hosts: true, {
        if let Some(tarball) = builder.ensure(dist::Rustfmt {
            compiler: self.compiler,
            target: self.target
        }) {
            install_sh(builder, "rustfmt", self.compiler.stage, Some(self.target), &tarball);
        } else {
            builder.info(
                &format!("skipping Install Rustfmt stage{} ({})", self.compiler.stage, self.target),
            );
        }
    };
    RustDemangler, "rust-demangler", Self::should_build(_config), only_hosts: true, {
        // Note: Even though `should_build` may return true for `extended` default tools,
        // dist::RustDemangler may still return None, unless the target-dependent `profiler` config
        // is also true, or the `tools` array explicitly includes "rust-demangler".
        if let Some(tarball) = builder.ensure(dist::RustDemangler {
            compiler: self.compiler,
            target: self.target
        }) {
            install_sh(builder, "rust-demangler", self.compiler.stage, Some(self.target), &tarball);
        } else {
            builder.info(
                &format!("skipping Install RustDemangler stage{} ({})",
                         self.compiler.stage, self.target),
            );
        }
    };
    Analysis, "analysis", Self::should_build(_config), only_hosts: false, {
        let tarball = builder.ensure(dist::Analysis {
            // Find the actual compiler (handling the full bootstrap option) which
            // produced the save-analysis data because that data isn't copied
            // through the sysroot uplifting.
            compiler: builder.compiler_for(builder.top_stage, builder.config.build, self.target),
            target: self.target
        }).expect("missing analysis");
        install_sh(builder, "analysis", self.compiler.stage, Some(self.target), &tarball);
    };
    Rustc, "src/librustc", true, only_hosts: true, {
        let tarball = builder.ensure(dist::Rustc {
            compiler: builder.compiler(builder.top_stage, self.target),
        });
        install_sh(builder, "rustc", self.compiler.stage, Some(self.target), &tarball);
    };
);

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Src {
    pub stage: u32,
}

impl Step for Src {
    type Output = ();
    const DEFAULT: bool = true;
    const ONLY_HOSTS: bool = true;

    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
        let config = &run.builder.config;
        let cond = config.extended && config.tools.as_ref().map_or(true, |t| t.contains("src"));
        run.path("src").default_condition(cond)
    }

    fn make_run(run: RunConfig<'_>) {
        run.builder.ensure(Src { stage: run.builder.top_stage });
    }

    fn run(self, builder: &Builder<'_>) {
        let tarball = builder.ensure(dist::Src);
        install_sh(builder, "src", self.stage, None, &tarball);
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code, unused_imports)]
use super::*;
use std::env;

const ENV_KEY: &str = "PROXER_API_KEY";

#[test]
fn api_response()
{
	// is the api structured as we want it to be?
	info!("creating client");
	let mut client = Client::with_env_key(ENV_KEY).expect("can't read api-key from environment");

	info!("build request");
	let req = api::info::GetFullEntry { id: 53 };

	info!("send request");
	let res = client.execute(req);
	info!("request sent");

	match res
	{
		Err(e) => {
			error!("error...");
			eprintln!("response {:#?}", e);

			match e
			{
				error::Error::Api(e) => {
					info!("api error");

					match e.error()
					{
						error::api::Errcode::NoApiPermissions => return,
						_ => panic!("unexpected api error: {}", e),
					}
				}
				error::Error::Json(e) => panic!("can't parse json: {}", e),
				error::Error::Unknown => panic!("unknown error"),
				_ => return,
			}
		}

		Ok(r) => {
			info!("Ok");
			assert_eq!(r.medium, "animeseries");
		}
	}
}
<commit_msg>optimize test for different environments<commit_after>#![allow(dead_code, unused_imports)]
use super::*;
use std::env;

const ENV_KEY: &str = "PROXER_API_KEY";

#[test]
fn api_response()
{
	// is the api structured as we want it to be?
	info!("creating client");
	let mut client = match Client::with_env_key(ENV_KEY) {
		None => return,
		Some(client) => client
	};

	info!("build request");
	let req = api::info::GetFullEntry { id: 53 };

	info!("send request");
	let res = client.execute(req);
	info!("request sent");

	match res
	{
		Err(e) => {
			error!("error...");
			eprintln!("response {:#?}", e);

			match e
			{
				error::Error::Api(e) => {
					info!("api error");

					match e.error()
					{
						error::api::Errcode::NoApiPermissions => return,
						_ => panic!("unexpected api error: {}", e),
					}
				}
				error::Error::Json(e) => panic!("can't parse json: {}", e),
				error::Error::Unknown => panic!("unknown error"),
				_ => return,
			}
		}

		Ok(r) => {
			info!("Ok");
			assert_eq!(r.medium, "animeseries");
		}
	}
}
<|endoftext|>


<commit_before>use std::collections::BTreeSet;
use std::iter::{FromIterator, Extend};

/// A `GSet` is an implementation of a grow-only set.
/// The underlying data-structure is a `BTreeSet`
#[derive(Clone, Hash, Debug)]
pub struct GSet<T> {
    set: BTreeSet<T>,
}

/// This is used to iterate over the elements of a GSet
pub struct IntoIter<T> {
    iter: <BTreeSet<T> as IntoIterator>::IntoIter,
}

impl<T: Ord + Clone> GSet<T> {
    /// Creates a new, empty `GSet`
    pub fn new() -> GSet<T> {
        GSet { set: BTreeSet::new() }
    }

    /// Inserts an element of type `T` into the
    /// given `GSet`. Returns `true` if the element
    /// was already in the set. Otherwise, it inserts
    /// the element and returns `false`
    pub fn insert(&mut self, value: T) -> bool {
        self.set.insert(value)
    }

    /// Checks if the given value of type `T` is in
    /// the set. If the check is successful, returns
    /// `true`. Otherwise returns `false`.
    pub fn contains(&mut self, value: &T) -> bool {
        self.set.contains(&value)
    }

    /// Returns the number of elements in the given `GSet`
    pub fn len(&self) -> usize {
        self.set.len()
    }

    /// Checks if the given `GSet` is empty
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns the set difference between two `GSet`s as another `GSet`
    pub fn difference(&mut self, other: &GSet<T>) -> GSet<T> {
        let difference: BTreeSet<_> = self.set.difference(&other.set).cloned().collect();
        GSet { set: difference }
    }

    /// Returns the intersection between two `GSet`s as another `GSet`
    pub fn intersection(&mut self, other: &GSet<T>) -> GSet<T> {
        let intersection: BTreeSet<_> = self.set.intersection(&other.set).cloned().collect();
        GSet { set: intersection }
    }

    /// Returns the union between two `GSet`s as another `GSet`
    pub fn union(&mut self, other: &GSet<T>) -> GSet<T> {
        let union: BTreeSet<_> = self.set.union(&other.set).cloned().collect();
        GSet { set: union }
    }
}

impl<T: Ord + Clone> FromIterator<T> for GSet<T> {
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> GSet<T> {
        let mut set = GSet::new();
        set.extend(iter);
        set
    }
}

impl<T: Ord + Clone> Extend<T> for GSet<T> {
    #[inline]
    fn extend<Iter: IntoIterator<Item = T>>(&mut self, iter: Iter) {
        for elem in iter {
        self.insert(elem);
        }
    }
}

impl<T> IntoIterator for GSet<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;

    fn into_iter(self) -> IntoIter<T> {
        IntoIter { iter: self.set.into_iter() }
    }
}

impl<T> Iterator for IntoIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        self.iter.next()
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}
<commit_msg>Add test for insert<commit_after>use std::collections::BTreeSet;
use std::iter::{FromIterator, Extend};

/// A `GSet` is an implementation of a grow-only set.
/// The underlying data-structure is a `BTreeSet`
#[derive(Clone, Hash, Debug)]
pub struct GSet<T> {
    set: BTreeSet<T>,
}

/// This is used to iterate over the elements of a GSet
pub struct IntoIter<T> {
    iter: <BTreeSet<T> as IntoIterator>::IntoIter,
}

impl<T: Ord + Clone> GSet<T> {
    /// Creates a new, empty `GSet`
    pub fn new() -> GSet<T> {
        GSet { set: BTreeSet::new() }
    }

    /// Inserts an element of type `T` into the
    /// given `GSet`. Returns `true` if the element
    /// was already in the set. Otherwise, it inserts
    /// the element and returns `false`
    pub fn insert(&mut self, value: T) -> bool {
        self.set.insert(value)
    }

    /// Checks if the given value of type `T` is in
    /// the set. If the check is successful, returns
    /// `true`. Otherwise returns `false`.
    pub fn contains(&mut self, value: &T) -> bool {
        self.set.contains(&value)
    }

    /// Returns the number of elements in the given `GSet`
    pub fn len(&self) -> usize {
        self.set.len()
    }

    /// Checks if the given `GSet` is empty
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns the set difference between two `GSet`s as another `GSet`
    pub fn difference(&mut self, other: &GSet<T>) -> GSet<T> {
        let difference: BTreeSet<_> = self.set.difference(&other.set).cloned().collect();
        GSet { set: difference }
    }

    /// Returns the intersection between two `GSet`s as another `GSet`
    pub fn intersection(&mut self, other: &GSet<T>) -> GSet<T> {
        let intersection: BTreeSet<_> = self.set.intersection(&other.set).cloned().collect();
        GSet { set: intersection }
    }

    /// Returns the union between two `GSet`s as another `GSet`
    pub fn union(&mut self, other: &GSet<T>) -> GSet<T> {
        let union: BTreeSet<_> = self.set.union(&other.set).cloned().collect();
        GSet { set: union }
    }
}

impl<T: Ord + Clone> FromIterator<T> for GSet<T> {
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> GSet<T> {
        let mut set = GSet::new();
        set.extend(iter);
        set
    }
}

impl<T: Ord + Clone> Extend<T> for GSet<T> {
    #[inline]
    fn extend<Iter: IntoIterator<Item = T>>(&mut self, iter: Iter) {
        for elem in iter {
        self.insert(elem);
        }
    }
}

impl<T> IntoIterator for GSet<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;

    fn into_iter(self) -> IntoIter<T> {
        IntoIter { iter: self.set.into_iter() }
    }
}

impl<T> Iterator for IntoIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        self.iter.next()
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

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

    #[test]
    fn test_gset_insert() {
        let mut a: GSet<i32> = GSet::new();
        a.insert(1);
        a.insert(2);

        let elements = a.into_iter().collect::<Vec<_>>();
        assert_eq!(elements, [1,2]);
    }
}
<|endoftext|>