<commit_before>use std::cell::RefCell;
use calx_cache::{ImageStore, IndexCache};

brush!(Brush {
    ["../assets/logo.png",
        [Logo,
        0, 0, 92, 24, 0, 0]
    ]

    ["../assets/icon.png",
        [IconHeart,
            0, 8, 8, 8, 0, 0,   // Full
            0, 8, 8, 8, 8, 0,   // Half
            0, 8, 8, 8, 16, 0]  // Empty
        [IconShard,
            0, 8, 8, 8, 24, 0,  // Full
            0, 8, 8, 8, 32, 0,  // Half
            0, 8, 8, 8, 40, 0]  // Empty
    ]

    ["../assets/blocks.png",
        [BlockVertical,
            16, 16, 16, 32,   0,   0, // Top
             0, 16, 16, 32,  16,   0,
            16, 16, 16, 32,  32,   0, // Middle
             0, 16, 16, 32,  48,   0,
            16, 16, 16, 32,  64,   0, // Bottom
             0, 16, 16, 32,  80,   0]
        [BlockRear,
            // Left half
            16, 16, 10, 32,   0,  32, // 0
            // Front
             6, 16,  6, 32,  10,  32, // 1
             0, 16,  6, 32,  16,  32, // 2
            // Right half
            -6, 16, 10, 32,  22,  32, // 3
            // Y-axis slope
            16, 16, 10, 32,  32,  32, // 4 (empty for front-slope)
             6, 16,  6, 32,  42,  32, // 5
             0, 16,  6, 32,  48,  32, // 6
            -6, 16, 10, 32,  54,  32, // 7 (empty for back-slope)
            // X-axis slope
            16, 16, 10, 32,  64,  32, // 8 (empty for back-slope)
             6, 16,  6, 32,  74,  32, // 9
             0, 16,  6, 32,  80,  32, // 10
            -6, 16, 10, 32,  86,  32] // 11 (empty for front-slope)
        [BlockRock,
            16, 16, 10, 32,   0,  64,
             6, 16,  6, 32,  10,  64,
             0, 16,  6, 32,  16,  64,
            -6, 16, 10, 32,  22,  64,
            16, 16, 10, 32,  32,  64,
             6, 16,  6, 32,  42,  64,
             0, 16,  6, 32,  48,  64,
            -6, 16, 10, 32,  54,  64,
            16, 16, 10, 32,  64,  64,
             6, 16,  6, 32,  74,  64,
             0, 16,  6, 32,  80,  64,
            -6, 16, 10, 32,  86,  64]
    ]

    ["../assets/walls.png",
        [BrickWall,
            16, 16, 16, 32,   0,   0,
             0, 16, 16, 32,  16,   0,
            16, 16, 16, 32,  32,   0,
             0, 16, 16, 32,  48,   0]
        [BrickWindowWall,
            16, 16, 16, 32,   0,   0,
             0, 16, 16, 32,  16,   0,
            16, 16, 16, 32,  64,   0,
             0, 16, 16, 32,  80,   0]
        [BrickOpenWall,
            16, 16, 16, 32,   0,   0,
             0, 16, 16, 32,  16,   0,
            16, 16, 16, 32,  96,   0,
             0, 16, 16, 32, 112,   0]
        [DoorWall,
            16, 16, 16, 32, 128,   0,
             0, 16, 16, 32, 144,   0,
            16, 16, 16, 32, 160,   0,
             0, 16, 16, 32, 176,   0]
        [BarsWall,
            16, 16, 16, 32, 192,   0,
             0, 16, 16, 32, 208,   0,
            16, 16, 16, 32, 224,   0,
             0, 16, 16, 32, 240,   0]
        [FenceWall,
            16, 16, 16, 32,   0,  32,
             0, 16, 16, 32,  16,  32,
            16, 16, 16, 32,  32,  32,
             0, 16, 16, 32,  48,  32]
        [HouseWall,
            16, 16, 16, 32,  64,  32,
             0, 16, 16, 32,  80,  32,
            16, 16, 16, 32,  96,  32,
             0, 16, 16, 32, 112,  32]
        [RockWall,
            16, 16, 16, 32, 128,  32,
             0, 16, 16, 32, 144,  32,
            16, 16, 16, 32, 160,  32,
             0, 16, 16, 32, 176,  32]
    ]

    ["../assets/floors.png",
        [BlankFloor,
            16, 16, 32, 32,   0,   0]
        [Floor,
            16, 16, 32, 32,  32,   0]
        [Grass,
            16, 16, 32, 32,  64,   0]
        [Water,
            16, 16, 32, 32,  96,   0]
        [Shallows,
            16, 16, 32, 32, 128,   0]
    ]

    ["../assets/mobs.png",
        [Human,
            16, 16, 32, 32,   0,   0]
        [Snake,
            16, 16, 32, 32,  32,   0]
        [Dreg,
            16, 16, 32, 32,  64,   0]
        [Ogre,
            16, 16, 32, 32,  96,   0]
        [Wraith,
            16, 16, 32, 32, 128,   0]
        [Octopus,
            16, 16, 32, 32, 160,   0]
        [Bug,
            16, 16, 32, 32, 192,   0]
        [Ooze,
            16, 16, 32, 32, 224,   0]
        [Efreet,
            16, 16, 32, 32,   0,  32]
        [Serpent,
            // Head
            16, 16, 32, 32,  32,  32,
            // Burrow mound
            16, 16, 32, 32,  64,  32]
    ]

    ["../assets/props.png",
        [CursorBottom,
            16, 16, 32, 32,   0,   0]
        [CursorTop,
            16, 16, 32, 32,  32,   0]
        [Table,
            16, 16, 32, 32,  64,   0]
        [Stone,
            16, 16, 32, 32,  96,   0]
        [Fountain,
            16, 16, 32, 32, 128,   0]
        [Altar,
            16, 16, 32, 32, 160,   0]
        [Barrell,
            16, 16, 32, 32, 192,   0]
        [Stalagmite,
            16, 16, 32, 32, 224,   0]
        [Pillar,
            16, 16, 32, 32,   0,  32]
        [Grave,
            16, 16, 32, 32,  32,  32]
        [Crystal,
            16, 16, 32, 32,  64,  32]
        [Menhir,
            16, 16, 32, 32,  96,  32]
        [Sword,
            16, 16, 32, 32, 128,  32]
        [Helmet,
            16, 16, 32, 32, 160,  32]
        [Potion,
            16, 16, 32, 32, 192,  32]
        [Wand,
            16, 16, 32, 32, 224,  32]
        [Health,
            16, 16, 32, 32,   0,  64]
        [Knives,
            16, 16, 32, 32,  32,  64]
        [Armor,
            16, 16, 32, 32,  64,  64]
        [Ring,
            16, 16, 32, 32,  96,  64]
        [StairsDown,
            16, 16, 32, 32, 128,  64]
        [TreeTrunk,
            16, 16, 32, 32, 160,  64]
        [TreeFoliage,
            16, 16, 32, 32, 192,  64]
    ]

    ["../assets/splatter.png",
        [Splatter,
            16, 16, 32, 32,   0,   0,
            16, 16, 32, 32,  32,   0,
            16, 16, 32, 32,  64,   0,
            16, 16, 32, 32,  96,   0,
            16, 16, 32, 32, 128,   0]
    ]

    ["../assets/portals.png",
        [UniPortal,
            16, 16, 32, 32,   0,   0]
        [DirPortal,
            16, 16, 32, 32,  32,   0,
            16, 16, 32, 32,  64,   0,
            16, 16, 32, 32,  96,   0,
            16, 16, 32, 32, 128,   0,
            16, 16, 32, 32, 160,   0,
            16, 16, 32, 32, 192,   0,
            16, 16, 32, 32, 224,   0,
            16, 16, 32, 32, 256,   0,
            16, 16, 32, 32, 288,   0,
            16, 16, 32, 32, 320,   0,
            16, 16, 32, 32, 352,   0,
            16, 16, 32, 32, 384,   0]
    ]
});
<commit_msg>You don't need imporst for brush macro anymore<commit_after>brush!(Brush {
    ["../assets/logo.png",
        [Logo,
        0, 0, 92, 24, 0, 0]
    ]

    ["../assets/icon.png",
        [IconHeart,
            0, 8, 8, 8, 0, 0,   // Full
            0, 8, 8, 8, 8, 0,   // Half
            0, 8, 8, 8, 16, 0]  // Empty
        [IconShard,
            0, 8, 8, 8, 24, 0,  // Full
            0, 8, 8, 8, 32, 0,  // Half
            0, 8, 8, 8, 40, 0]  // Empty
    ]

    ["../assets/blocks.png",
        [BlockVertical,
            16, 16, 16, 32,   0,   0, // Top
             0, 16, 16, 32,  16,   0,
            16, 16, 16, 32,  32,   0, // Middle
             0, 16, 16, 32,  48,   0,
            16, 16, 16, 32,  64,   0, // Bottom
             0, 16, 16, 32,  80,   0]
        [BlockRear,
            // Left half
            16, 16, 10, 32,   0,  32, // 0
            // Front
             6, 16,  6, 32,  10,  32, // 1
             0, 16,  6, 32,  16,  32, // 2
            // Right half
            -6, 16, 10, 32,  22,  32, // 3
            // Y-axis slope
            16, 16, 10, 32,  32,  32, // 4 (empty for front-slope)
             6, 16,  6, 32,  42,  32, // 5
             0, 16,  6, 32,  48,  32, // 6
            -6, 16, 10, 32,  54,  32, // 7 (empty for back-slope)
            // X-axis slope
            16, 16, 10, 32,  64,  32, // 8 (empty for back-slope)
             6, 16,  6, 32,  74,  32, // 9
             0, 16,  6, 32,  80,  32, // 10
            -6, 16, 10, 32,  86,  32] // 11 (empty for front-slope)
        [BlockRock,
            16, 16, 10, 32,   0,  64,
             6, 16,  6, 32,  10,  64,
             0, 16,  6, 32,  16,  64,
            -6, 16, 10, 32,  22,  64,
            16, 16, 10, 32,  32,  64,
             6, 16,  6, 32,  42,  64,
             0, 16,  6, 32,  48,  64,
            -6, 16, 10, 32,  54,  64,
            16, 16, 10, 32,  64,  64,
             6, 16,  6, 32,  74,  64,
             0, 16,  6, 32,  80,  64,
            -6, 16, 10, 32,  86,  64]
    ]

    ["../assets/walls.png",
        [BrickWall,
            16, 16, 16, 32,   0,   0,
             0, 16, 16, 32,  16,   0,
            16, 16, 16, 32,  32,   0,
             0, 16, 16, 32,  48,   0]
        [BrickWindowWall,
            16, 16, 16, 32,   0,   0,
             0, 16, 16, 32,  16,   0,
            16, 16, 16, 32,  64,   0,
             0, 16, 16, 32,  80,   0]
        [BrickOpenWall,
            16, 16, 16, 32,   0,   0,
             0, 16, 16, 32,  16,   0,
            16, 16, 16, 32,  96,   0,
             0, 16, 16, 32, 112,   0]
        [DoorWall,
            16, 16, 16, 32, 128,   0,
             0, 16, 16, 32, 144,   0,
            16, 16, 16, 32, 160,   0,
             0, 16, 16, 32, 176,   0]
        [BarsWall,
            16, 16, 16, 32, 192,   0,
             0, 16, 16, 32, 208,   0,
            16, 16, 16, 32, 224,   0,
             0, 16, 16, 32, 240,   0]
        [FenceWall,
            16, 16, 16, 32,   0,  32,
             0, 16, 16, 32,  16,  32,
            16, 16, 16, 32,  32,  32,
             0, 16, 16, 32,  48,  32]
        [HouseWall,
            16, 16, 16, 32,  64,  32,
             0, 16, 16, 32,  80,  32,
            16, 16, 16, 32,  96,  32,
             0, 16, 16, 32, 112,  32]
        [RockWall,
            16, 16, 16, 32, 128,  32,
             0, 16, 16, 32, 144,  32,
            16, 16, 16, 32, 160,  32,
             0, 16, 16, 32, 176,  32]
    ]

    ["../assets/floors.png",
        [BlankFloor,
            16, 16, 32, 32,   0,   0]
        [Floor,
            16, 16, 32, 32,  32,   0]
        [Grass,
            16, 16, 32, 32,  64,   0]
        [Water,
            16, 16, 32, 32,  96,   0]
        [Shallows,
            16, 16, 32, 32, 128,   0]
    ]

    ["../assets/mobs.png",
        [Human,
            16, 16, 32, 32,   0,   0]
        [Snake,
            16, 16, 32, 32,  32,   0]
        [Dreg,
            16, 16, 32, 32,  64,   0]
        [Ogre,
            16, 16, 32, 32,  96,   0]
        [Wraith,
            16, 16, 32, 32, 128,   0]
        [Octopus,
            16, 16, 32, 32, 160,   0]
        [Bug,
            16, 16, 32, 32, 192,   0]
        [Ooze,
            16, 16, 32, 32, 224,   0]
        [Efreet,
            16, 16, 32, 32,   0,  32]
        [Serpent,
            // Head
            16, 16, 32, 32,  32,  32,
            // Burrow mound
            16, 16, 32, 32,  64,  32]
    ]

    ["../assets/props.png",
        [CursorBottom,
            16, 16, 32, 32,   0,   0]
        [CursorTop,
            16, 16, 32, 32,  32,   0]
        [Table,
            16, 16, 32, 32,  64,   0]
        [Stone,
            16, 16, 32, 32,  96,   0]
        [Fountain,
            16, 16, 32, 32, 128,   0]
        [Altar,
            16, 16, 32, 32, 160,   0]
        [Barrell,
            16, 16, 32, 32, 192,   0]
        [Stalagmite,
            16, 16, 32, 32, 224,   0]
        [Pillar,
            16, 16, 32, 32,   0,  32]
        [Grave,
            16, 16, 32, 32,  32,  32]
        [Crystal,
            16, 16, 32, 32,  64,  32]
        [Menhir,
            16, 16, 32, 32,  96,  32]
        [Sword,
            16, 16, 32, 32, 128,  32]
        [Helmet,
            16, 16, 32, 32, 160,  32]
        [Potion,
            16, 16, 32, 32, 192,  32]
        [Wand,
            16, 16, 32, 32, 224,  32]
        [Health,
            16, 16, 32, 32,   0,  64]
        [Knives,
            16, 16, 32, 32,  32,  64]
        [Armor,
            16, 16, 32, 32,  64,  64]
        [Ring,
            16, 16, 32, 32,  96,  64]
        [StairsDown,
            16, 16, 32, 32, 128,  64]
        [TreeTrunk,
            16, 16, 32, 32, 160,  64]
        [TreeFoliage,
            16, 16, 32, 32, 192,  64]
    ]

    ["../assets/splatter.png",
        [Splatter,
            16, 16, 32, 32,   0,   0,
            16, 16, 32, 32,  32,   0,
            16, 16, 32, 32,  64,   0,
            16, 16, 32, 32,  96,   0,
            16, 16, 32, 32, 128,   0]
    ]

    ["../assets/portals.png",
        [UniPortal,
            16, 16, 32, 32,   0,   0]
        [DirPortal,
            16, 16, 32, 32,  32,   0,
            16, 16, 32, 32,  64,   0,
            16, 16, 32, 32,  96,   0,
            16, 16, 32, 32, 128,   0,
            16, 16, 32, 32, 160,   0,
            16, 16, 32, 32, 192,   0,
            16, 16, 32, 32, 224,   0,
            16, 16, 32, 32, 256,   0,
            16, 16, 32, 32, 288,   0,
            16, 16, 32, 32, 320,   0,
            16, 16, 32, 32, 352,   0,
            16, 16, 32, 32, 384,   0]
    ]
});
<|endoftext|>


<commit_before>// Copyright © 2018, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

extern crate cosmogony;
extern crate failure;
#[macro_use]
extern crate log;
extern crate mimir;
extern crate mimirsbrunn;
extern crate serde_json;
#[macro_use]
extern crate structopt;

use cosmogony::{Cosmogony, Zone};
use failure::Error;
use mimir::objects::{Admin, AdminType};
use mimir::rubber::Rubber;
use mimirsbrunn::osm_reader::admin;
use std::cell::Cell;

trait IntoAdmin {
    fn into_admin(self) -> Admin;
}

impl IntoAdmin for Zone {
    fn into_admin(self) -> Admin {
        let insee = admin::read_insee(&self.tags).unwrap_or("");
        let zip_codes = admin::read_zip_codes(&self.tags);
        let label = self.label;
        let weight = Cell::new(0.); //TODO, what do we want ?
        let admin_type = AdminType::City; //TODO use ZoneType
        let center = self.center.map_or(mimir::Coord::default(), |c| {
            mimir::Coord::new(c.lng(), c.lat())
        });
        Admin {
            id: format!("admin:osm:{}", self.osm_id),
            insee: insee.into(),
            level: self.admin_level.unwrap_or(0),
            label: label,
            name: self.name,
            zip_codes: zip_codes,
            weight: weight,
            boundary: self.boundary,
            coord: center,
            admin_type: admin_type,
        }
    }
}

fn send_to_es<I>(admins: I, cnx_string: &str, dataset: &str) -> Result<(), Error>
where
    I: Iterator<Item = Admin>,
{
    let mut rubber = Rubber::new(cnx_string);
    let nb_admins = rubber.index(dataset, admins)?;
    info!("{} admins added.", nb_admins);
    Ok(())
}

fn load_cosmogony(input: &str) -> Result<Cosmogony, Error> {
    serde_json::from_reader(std::fs::File::open(&input)?)
        .map_err(|e| failure::err_msg(e.to_string()))
}

fn index_cosmogony(args: Args) -> Result<(), Error> {
    info!("importing cosmogony into Mimir");
    let cosmogony = load_cosmogony(&args.input)?;

    let admins = cosmogony.zones.into_iter().map(|z| z.into_admin());

    send_to_es(admins, &args.connection_string, &args.dataset)?;

    Ok(())
}

#[derive(StructOpt, Debug)]
struct Args {
    /// cosmogony file
    #[structopt(short = "i", long = "input")]
    input: String,
    /// Elasticsearch parameters.
    #[structopt(short = "c", long = "connection-string",
                default_value = "http://localhost:9200/munin")]
    connection_string: String,
    /// Name of the dataset.
    #[structopt(short = "d", long = "dataset", default_value = "fr")]
    dataset: String,
}

fn main() {
    mimirsbrunn::utils::launch_run(index_cosmogony);
}
<commit_msg>initialize the template at startup<commit_after>// Copyright © 2018, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

extern crate cosmogony;
extern crate failure;
#[macro_use]
extern crate log;
extern crate mimir;
extern crate mimirsbrunn;
extern crate serde_json;
#[macro_use]
extern crate structopt;

use cosmogony::{Cosmogony, Zone};
use failure::Error;
use mimir::objects::{Admin, AdminType};
use mimir::rubber::Rubber;
use mimirsbrunn::osm_reader::admin;
use std::cell::Cell;

trait IntoAdmin {
    fn into_admin(self) -> Admin;
}

impl IntoAdmin for Zone {
    fn into_admin(self) -> Admin {
        let insee = admin::read_insee(&self.tags).unwrap_or("");
        let zip_codes = admin::read_zip_codes(&self.tags);
        let label = self.label;
        let weight = Cell::new(0.); //TODO, what do we want ?
        let admin_type = AdminType::City; //TODO use ZoneType
        let center = self.center.map_or(mimir::Coord::default(), |c| {
            mimir::Coord::new(c.lng(), c.lat())
        });
        Admin {
            id: format!("admin:osm:{}", self.osm_id),
            insee: insee.into(),
            level: self.admin_level.unwrap_or(0),
            label: label,
            name: self.name,
            zip_codes: zip_codes,
            weight: weight,
            boundary: self.boundary,
            coord: center,
            admin_type: admin_type,
        }
    }
}

fn send_to_es<I>(admins: I, cnx_string: &str, dataset: &str) -> Result<(), Error>
where
    I: Iterator<Item = Admin>,
{
    let mut rubber = Rubber::new(cnx_string);
    rubber.initialize_templates()?;
    let nb_admins = rubber.index(dataset, admins)?;
    info!("{} admins added.", nb_admins);
    Ok(())
}

fn load_cosmogony(input: &str) -> Result<Cosmogony, Error> {
    serde_json::from_reader(std::fs::File::open(&input)?)
        .map_err(|e| failure::err_msg(e.to_string()))
}

fn index_cosmogony(args: Args) -> Result<(), Error> {
    info!("importing cosmogony into Mimir");
    let cosmogony = load_cosmogony(&args.input)?;

    let admins = cosmogony.zones.into_iter().map(|z| z.into_admin());

    send_to_es(admins, &args.connection_string, &args.dataset)?;

    Ok(())
}

#[derive(StructOpt, Debug)]
struct Args {
    /// cosmogony file
    #[structopt(short = "i", long = "input")]
    input: String,
    /// Elasticsearch parameters.
    #[structopt(short = "c", long = "connection-string",
                default_value = "http://localhost:9200/munin")]
    connection_string: String,
    /// Name of the dataset.
    #[structopt(short = "d", long = "dataset", default_value = "fr")]
    dataset: String,
}

fn main() {
    mimirsbrunn::utils::launch_run(index_cosmogony);
}
<|endoftext|>


<commit_before>use std::fmt;

use crate::core::{Dependency, PackageId, Registry, Summary};
use crate::util::lev_distance::lev_distance;
use crate::util::Config;
use failure::{Error, Fail};
use semver;

use super::context::Context;
use super::types::{ConflictMap, ConflictReason};

/// Error during resolution providing a path of `PackageId`s.
pub struct ResolveError {
    cause: Error,
    package_path: Vec<PackageId>,
}

impl ResolveError {
    pub fn new<E: Into<Error>>(cause: E, package_path: Vec<PackageId>) -> Self {
        Self {
            cause: cause.into(),
            package_path,
        }
    }

    /// Returns a path of packages from the package whose requirements could not be resolved up to
    /// the root.
    pub fn package_path(&self) -> &[PackageId] {
        &self.package_path
    }
}

impl Fail for ResolveError {
    fn cause(&self) -> Option<&dyn Fail> {
        self.cause.as_fail().cause()
    }
}

impl fmt::Debug for ResolveError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.cause.fmt(f)
    }
}

impl fmt::Display for ResolveError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.cause.fmt(f)
    }
}

pub type ActivateResult<T> = Result<T, ActivateError>;

#[derive(Debug)]
pub enum ActivateError {
    Fatal(failure::Error),
    Conflict(PackageId, ConflictReason),
}

impl From<::failure::Error> for ActivateError {
    fn from(t: ::failure::Error) -> Self {
        ActivateError::Fatal(t)
    }
}

impl From<(PackageId, ConflictReason)> for ActivateError {
    fn from(t: (PackageId, ConflictReason)) -> Self {
        ActivateError::Conflict(t.0, t.1)
    }
}

pub(super) fn activation_error(
    cx: &Context,
    registry: &mut dyn Registry,
    parent: &Summary,
    dep: &Dependency,
    conflicting_activations: &ConflictMap,
    candidates: &[Summary],
    config: Option<&Config>,
) -> ResolveError {
    let to_resolve_err = |err| {
        ResolveError::new(
            err,
            cx.parents
                .path_to_bottom(&parent.package_id())
                .into_iter()
                .cloned()
                .collect(),
        )
    };

    if !candidates.is_empty() {
        let mut msg = format!("failed to select a version for `{}`.", dep.package_name());
        msg.push_str("\n    ... required by ");
        msg.push_str(&describe_path(
            &cx.parents.path_to_bottom(&parent.package_id()),
        ));

        msg.push_str("\nversions that meet the requirements `");
        msg.push_str(&dep.version_req().to_string());
        msg.push_str("` are: ");
        msg.push_str(
            &candidates
                .iter()
                .map(|v| v.version())
                .map(|v| v.to_string())
                .collect::<Vec<_>>()
                .join(", "),
        );

        let mut conflicting_activations: Vec<_> = conflicting_activations.iter().collect();
        conflicting_activations.sort_unstable();
        let (links_errors, mut other_errors): (Vec<_>, Vec<_>) = conflicting_activations
            .drain(..)
            .rev()
            .partition(|&(_, r)| r.is_links());

        for &(p, r) in links_errors.iter() {
            if let ConflictReason::Links(ref link) = *r {
                msg.push_str("\n\nthe package `");
                msg.push_str(&*dep.package_name());
                msg.push_str("` links to the native library `");
                msg.push_str(link);
                msg.push_str("`, but it conflicts with a previous package which links to `");
                msg.push_str(link);
                msg.push_str("` as well:\n");
            }
            msg.push_str(&describe_path(&cx.parents.path_to_bottom(p)));
        }

        let (features_errors, mut other_errors): (Vec<_>, Vec<_>) = other_errors
            .drain(..)
            .partition(|&(_, r)| r.is_missing_features());

        for &(p, r) in features_errors.iter() {
            if let ConflictReason::MissingFeatures(ref features) = *r {
                msg.push_str("\n\nthe package `");
                msg.push_str(&*p.name());
                msg.push_str("` depends on `");
                msg.push_str(&*dep.package_name());
                msg.push_str("`, with features: `");
                msg.push_str(features);
                msg.push_str("` but `");
                msg.push_str(&*dep.package_name());
                msg.push_str("` does not have these features.\n");
            }
            // p == parent so the full path is redundant.
        }

        let (required_dependency_as_features_errors, other_errors): (Vec<_>, Vec<_>) = other_errors
            .drain(..)
            .partition(|&(_, r)| r.is_required_dependency_as_features());

        for &(p, r) in required_dependency_as_features_errors.iter() {
            if let ConflictReason::RequiredDependencyAsFeatures(ref features) = *r {
                msg.push_str("\n\nthe package `");
                msg.push_str(&*p.name());
                msg.push_str("` depends on `");
                msg.push_str(&*dep.package_name());
                msg.push_str("`, with features: `");
                msg.push_str(features);
                msg.push_str("` but `");
                msg.push_str(&*dep.package_name());
                msg.push_str("` does not have these features.\n");
                msg.push_str(
                    " It has a required dependency with that name, \
                     but only optional dependencies can be used as features.\n",
                );
            }
            // p == parent so the full path is redundant.
        }

        if !other_errors.is_empty() {
            msg.push_str(
                "\n\nall possible versions conflict with \
                 previously selected packages.",
            );
        }

        for &(p, _) in other_errors.iter() {
            msg.push_str("\n\n  previously selected ");
            msg.push_str(&describe_path(&cx.parents.path_to_bottom(p)));
        }

        msg.push_str("\n\nfailed to select a version for `");
        msg.push_str(&*dep.package_name());
        msg.push_str("` which could resolve this conflict");

        return to_resolve_err(failure::format_err!("{}", msg));
    }

    // We didn't actually find any candidates, so we need to
    // give an error message that nothing was found.
    //
    // Maybe the user mistyped the ver_req? Like `dep="2"` when `dep="0.2"`
    // was meant. So we re-query the registry with `deb="*"` so we can
    // list a few versions that were actually found.
    let all_req = semver::VersionReq::parse("*").unwrap();
    let mut new_dep = dep.clone();
    new_dep.set_version_req(all_req);
    let mut candidates = match registry.query_vec(&new_dep, false) {
        Ok(candidates) => candidates,
        Err(e) => return to_resolve_err(e),
    };
    candidates.sort_unstable_by(|a, b| b.version().cmp(a.version()));

    let mut msg = if !candidates.is_empty() {
        let versions = {
            let mut versions = candidates
                .iter()
                .take(3)
                .map(|cand| cand.version().to_string())
                .collect::<Vec<_>>();

            if candidates.len() > 3 {
                versions.push("...".into());
            }

            versions.join(", ")
        };

        let mut msg = format!(
            "failed to select a version for the requirement `{} = \"{}\"`\n  \
             candidate versions found which didn't match: {}\n  \
             location searched: {}\n",
            dep.package_name(),
            dep.version_req(),
            versions,
            registry.describe_source(dep.source_id()),
        );
        msg.push_str("required by ");
        msg.push_str(&describe_path(
            &cx.parents.path_to_bottom(&parent.package_id()),
        ));

        // If we have a path dependency with a locked version, then this may
        // indicate that we updated a sub-package and forgot to run `cargo
        // update`. In this case try to print a helpful error!
        if dep.source_id().is_path() && dep.version_req().to_string().starts_with('=') {
            msg.push_str(
                "\nconsider running `cargo update` to update \
                 a path dependency's locked version",
            );
        }

        if registry.is_replaced(dep.source_id()) {
            msg.push_str("\nperhaps a crate was updated and forgotten to be re-vendored?");
        }

        msg
    } else {
        // Maybe the user mistyped the name? Like `dep-thing` when `Dep_Thing`
        // was meant. So we try asking the registry for a `fuzzy` search for suggestions.
        let mut candidates = Vec::new();
        if let Err(e) = registry.query(&new_dep, &mut |s| candidates.push(s.clone()), true) {
            return to_resolve_err(e);
        };
        candidates.sort_unstable_by(|a, b| a.name().cmp(&b.name()));
        candidates.dedup_by(|a, b| a.name() == b.name());
        let mut candidates: Vec<_> = candidates
            .iter()
            .map(|n| (lev_distance(&*new_dep.package_name(), &*n.name()), n))
            .filter(|&(d, _)| d < 4)
            .collect();
        candidates.sort_by_key(|o| o.0);
        let mut msg = format!(
            "no matching package named `{}` found\n\
             location searched: {}\n",
            dep.package_name(),
            dep.source_id()
        );
        if !candidates.is_empty() {
            // If dependency package name is equal to the name of the candidate here
            // it may be a prerelease package which hasn't been speficied correctly
            if dep.package_name() == candidates[0].1.name() &&
                candidates[0].1.package_id().version().is_prerelease() {
                msg.push_str("prerelease package needs to be specified explicitly\n");
                msg.push_str(&format!(
                    "{name} = {{ version = \"{version}\" }}",
                    name = candidates[0].1.name(),
                    version = candidates[0].1.package_id().version()
                ));
            } else {
                let mut names = candidates
                    .iter()
                    .take(3)
                    .map(|c| c.1.name().as_str())
                    .collect::<Vec<_>>();

                if candidates.len() > 3 {
                    names.push("...");
                }

                msg.push_str("perhaps you meant: ");
                msg.push_str(&names.iter().enumerate().fold(
                    String::default(),
                    |acc, (i, el)| match i {
                        0 => acc + el,
                        i if names.len() - 1 == i && candidates.len() <= 3 => acc + " or " + el,
                        _ => acc + ", " + el,
                    },
                ));
            }

            msg.push_str("\n");
        }
        msg.push_str("required by ");
        msg.push_str(&describe_path(
            &cx.parents.path_to_bottom(&parent.package_id()),
        ));

        msg
    };

    if let Some(config) = config {
        if config.offline() {
            msg.push_str(
                "\nAs a reminder, you're using offline mode (--offline) \
                 which can sometimes cause surprising resolution failures, \
                 if this error is too confusing you may wish to retry \
                 without the offline flag.",
            );
        }
    }

    to_resolve_err(failure::format_err!("{}", msg))
}

/// Returns String representation of dependency chain for a particular `pkgid`.
pub(super) fn describe_path(path: &[&PackageId]) -> String {
    use std::fmt::Write;
    let mut dep_path_desc = format!("package `{}`", path[0]);
    for dep in path[1..].iter() {
        write!(dep_path_desc, "\n    ... which is depended on by `{}`", dep).unwrap();
    }
    dep_path_desc
}
<commit_msg>cargo fmt<commit_after>use std::fmt;

use crate::core::{Dependency, PackageId, Registry, Summary};
use crate::util::lev_distance::lev_distance;
use crate::util::Config;
use failure::{Error, Fail};
use semver;

use super::context::Context;
use super::types::{ConflictMap, ConflictReason};

/// Error during resolution providing a path of `PackageId`s.
pub struct ResolveError {
    cause: Error,
    package_path: Vec<PackageId>,
}

impl ResolveError {
    pub fn new<E: Into<Error>>(cause: E, package_path: Vec<PackageId>) -> Self {
        Self {
            cause: cause.into(),
            package_path,
        }
    }

    /// Returns a path of packages from the package whose requirements could not be resolved up to
    /// the root.
    pub fn package_path(&self) -> &[PackageId] {
        &self.package_path
    }
}

impl Fail for ResolveError {
    fn cause(&self) -> Option<&dyn Fail> {
        self.cause.as_fail().cause()
    }
}

impl fmt::Debug for ResolveError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.cause.fmt(f)
    }
}

impl fmt::Display for ResolveError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.cause.fmt(f)
    }
}

pub type ActivateResult<T> = Result<T, ActivateError>;

#[derive(Debug)]
pub enum ActivateError {
    Fatal(failure::Error),
    Conflict(PackageId, ConflictReason),
}

impl From<::failure::Error> for ActivateError {
    fn from(t: ::failure::Error) -> Self {
        ActivateError::Fatal(t)
    }
}

impl From<(PackageId, ConflictReason)> for ActivateError {
    fn from(t: (PackageId, ConflictReason)) -> Self {
        ActivateError::Conflict(t.0, t.1)
    }
}

pub(super) fn activation_error(
    cx: &Context,
    registry: &mut dyn Registry,
    parent: &Summary,
    dep: &Dependency,
    conflicting_activations: &ConflictMap,
    candidates: &[Summary],
    config: Option<&Config>,
) -> ResolveError {
    let to_resolve_err = |err| {
        ResolveError::new(
            err,
            cx.parents
                .path_to_bottom(&parent.package_id())
                .into_iter()
                .cloned()
                .collect(),
        )
    };

    if !candidates.is_empty() {
        let mut msg = format!("failed to select a version for `{}`.", dep.package_name());
        msg.push_str("\n    ... required by ");
        msg.push_str(&describe_path(
            &cx.parents.path_to_bottom(&parent.package_id()),
        ));

        msg.push_str("\nversions that meet the requirements `");
        msg.push_str(&dep.version_req().to_string());
        msg.push_str("` are: ");
        msg.push_str(
            &candidates
                .iter()
                .map(|v| v.version())
                .map(|v| v.to_string())
                .collect::<Vec<_>>()
                .join(", "),
        );

        let mut conflicting_activations: Vec<_> = conflicting_activations.iter().collect();
        conflicting_activations.sort_unstable();
        let (links_errors, mut other_errors): (Vec<_>, Vec<_>) = conflicting_activations
            .drain(..)
            .rev()
            .partition(|&(_, r)| r.is_links());

        for &(p, r) in links_errors.iter() {
            if let ConflictReason::Links(ref link) = *r {
                msg.push_str("\n\nthe package `");
                msg.push_str(&*dep.package_name());
                msg.push_str("` links to the native library `");
                msg.push_str(link);
                msg.push_str("`, but it conflicts with a previous package which links to `");
                msg.push_str(link);
                msg.push_str("` as well:\n");
            }
            msg.push_str(&describe_path(&cx.parents.path_to_bottom(p)));
        }

        let (features_errors, mut other_errors): (Vec<_>, Vec<_>) = other_errors
            .drain(..)
            .partition(|&(_, r)| r.is_missing_features());

        for &(p, r) in features_errors.iter() {
            if let ConflictReason::MissingFeatures(ref features) = *r {
                msg.push_str("\n\nthe package `");
                msg.push_str(&*p.name());
                msg.push_str("` depends on `");
                msg.push_str(&*dep.package_name());
                msg.push_str("`, with features: `");
                msg.push_str(features);
                msg.push_str("` but `");
                msg.push_str(&*dep.package_name());
                msg.push_str("` does not have these features.\n");
            }
            // p == parent so the full path is redundant.
        }

        let (required_dependency_as_features_errors, other_errors): (Vec<_>, Vec<_>) = other_errors
            .drain(..)
            .partition(|&(_, r)| r.is_required_dependency_as_features());

        for &(p, r) in required_dependency_as_features_errors.iter() {
            if let ConflictReason::RequiredDependencyAsFeatures(ref features) = *r {
                msg.push_str("\n\nthe package `");
                msg.push_str(&*p.name());
                msg.push_str("` depends on `");
                msg.push_str(&*dep.package_name());
                msg.push_str("`, with features: `");
                msg.push_str(features);
                msg.push_str("` but `");
                msg.push_str(&*dep.package_name());
                msg.push_str("` does not have these features.\n");
                msg.push_str(
                    " It has a required dependency with that name, \
                     but only optional dependencies can be used as features.\n",
                );
            }
            // p == parent so the full path is redundant.
        }

        if !other_errors.is_empty() {
            msg.push_str(
                "\n\nall possible versions conflict with \
                 previously selected packages.",
            );
        }

        for &(p, _) in other_errors.iter() {
            msg.push_str("\n\n  previously selected ");
            msg.push_str(&describe_path(&cx.parents.path_to_bottom(p)));
        }

        msg.push_str("\n\nfailed to select a version for `");
        msg.push_str(&*dep.package_name());
        msg.push_str("` which could resolve this conflict");

        return to_resolve_err(failure::format_err!("{}", msg));
    }

    // We didn't actually find any candidates, so we need to
    // give an error message that nothing was found.
    //
    // Maybe the user mistyped the ver_req? Like `dep="2"` when `dep="0.2"`
    // was meant. So we re-query the registry with `deb="*"` so we can
    // list a few versions that were actually found.
    let all_req = semver::VersionReq::parse("*").unwrap();
    let mut new_dep = dep.clone();
    new_dep.set_version_req(all_req);
    let mut candidates = match registry.query_vec(&new_dep, false) {
        Ok(candidates) => candidates,
        Err(e) => return to_resolve_err(e),
    };
    candidates.sort_unstable_by(|a, b| b.version().cmp(a.version()));

    let mut msg =
        if !candidates.is_empty() {
            let versions = {
                let mut versions = candidates
                    .iter()
                    .take(3)
                    .map(|cand| cand.version().to_string())
                    .collect::<Vec<_>>();

                if candidates.len() > 3 {
                    versions.push("...".into());
                }

                versions.join(", ")
            };

            let mut msg = format!(
                "failed to select a version for the requirement `{} = \"{}\"`\n  \
                 candidate versions found which didn't match: {}\n  \
                 location searched: {}\n",
                dep.package_name(),
                dep.version_req(),
                versions,
                registry.describe_source(dep.source_id()),
            );
            msg.push_str("required by ");
            msg.push_str(&describe_path(
                &cx.parents.path_to_bottom(&parent.package_id()),
            ));

            // If we have a path dependency with a locked version, then this may
            // indicate that we updated a sub-package and forgot to run `cargo
            // update`. In this case try to print a helpful error!
            if dep.source_id().is_path() && dep.version_req().to_string().starts_with('=') {
                msg.push_str(
                    "\nconsider running `cargo update` to update \
                     a path dependency's locked version",
                );
            }

            if registry.is_replaced(dep.source_id()) {
                msg.push_str("\nperhaps a crate was updated and forgotten to be re-vendored?");
            }

            msg
        } else {
            // Maybe the user mistyped the name? Like `dep-thing` when `Dep_Thing`
            // was meant. So we try asking the registry for a `fuzzy` search for suggestions.
            let mut candidates = Vec::new();
            if let Err(e) = registry.query(&new_dep, &mut |s| candidates.push(s.clone()), true) {
                return to_resolve_err(e);
            };
            candidates.sort_unstable_by(|a, b| a.name().cmp(&b.name()));
            candidates.dedup_by(|a, b| a.name() == b.name());
            let mut candidates: Vec<_> = candidates
                .iter()
                .map(|n| (lev_distance(&*new_dep.package_name(), &*n.name()), n))
                .filter(|&(d, _)| d < 4)
                .collect();
            candidates.sort_by_key(|o| o.0);
            let mut msg = format!(
                "no matching package named `{}` found\n\
                 location searched: {}\n",
                dep.package_name(),
                dep.source_id()
            );
            if !candidates.is_empty() {
                // If dependency package name is equal to the name of the candidate here
                // it may be a prerelease package which hasn't been speficied correctly
                if dep.package_name() == candidates[0].1.name()
                    && candidates[0].1.package_id().version().is_prerelease()
                {
                    msg.push_str("prerelease package needs to be specified explicitly\n");
                    msg.push_str(&format!(
                        "{name} = {{ version = \"{version}\" }}",
                        name = candidates[0].1.name(),
                        version = candidates[0].1.package_id().version()
                    ));
                } else {
                    let mut names = candidates
                        .iter()
                        .take(3)
                        .map(|c| c.1.name().as_str())
                        .collect::<Vec<_>>();

                    if candidates.len() > 3 {
                        names.push("...");
                    }

                    msg.push_str("perhaps you meant: ");
                    msg.push_str(&names.iter().enumerate().fold(
                        String::default(),
                        |acc, (i, el)| match i {
                            0 => acc + el,
                            i if names.len() - 1 == i && candidates.len() <= 3 => acc + " or " + el,
                            _ => acc + ", " + el,
                        },
                    ));
                }

                msg.push_str("\n");
            }
            msg.push_str("required by ");
            msg.push_str(&describe_path(
                &cx.parents.path_to_bottom(&parent.package_id()),
            ));

            msg
        };

    if let Some(config) = config {
        if config.offline() {
            msg.push_str(
                "\nAs a reminder, you're using offline mode (--offline) \
                 which can sometimes cause surprising resolution failures, \
                 if this error is too confusing you may wish to retry \
                 without the offline flag.",
            );
        }
    }

    to_resolve_err(failure::format_err!("{}", msg))
}

/// Returns String representation of dependency chain for a particular `pkgid`.
pub(super) fn describe_path(path: &[&PackageId]) -> String {
    use std::fmt::Write;
    let mut dep_path_desc = format!("package `{}`", path[0]);
    for dep in path[1..].iter() {
        write!(dep_path_desc, "\n    ... which is depended on by `{}`", dep).unwrap();
    }
    dep_path_desc
}
<|endoftext|>


<commit_before>extern crate libc;

use core::Workspaces;
use window_manager::WindowManager;
use window_system::WindowSystem;
use window_system::Window;
use config::{ GeneralConfig, Config };

pub type KeyHandler<'a> = Box<Fn<(WindowManager<'a>, &'a (WindowSystem + 'a), &'a GeneralConfig<'a>), WindowManager<'a>> + 'a>;
pub type MouseHandler<'a> = Box<Fn<(WindowManager<'a>, &'a (WindowSystem + 'a), &'a GeneralConfig<'a>, Window), WindowManager<'a>> + 'a>;
pub type ManageHook<'a> = Box<Fn<(Workspaces<'a>, &'a (WindowSystem + 'a), Window), Workspaces<'a>> + 'a>;
pub type StartupHook<'a> = Box<Fn<(WindowManager<'a>, &'a (WindowSystem + 'a), &'a Config<'a>), WindowManager<'a>> + 'a>;
pub type LogHook<'a> = Box<FnMut<(WindowManager<'a>, &'a (WindowSystem + 'a)), ()> + 'a>;

extern {
    pub fn waitpid(fd: libc::pid_t, status: *mut libc::c_int, options: libc::c_int) -> libc::pid_t;
}

/// Some default handlers for easier config scripts
pub mod default {
    use std::os;
    use std::ptr::null;
    use std::io::process::Command;
    use std::thread::Thread;
    use serialize::json;
    use core::Workspaces;
    use window_manager::WindowManager;
    use window_system::WindowSystem;
    use window_system::Window;
    use config::GeneralConfig;
    use handlers::libc::funcs::posix88::unistd::execvp;

    pub fn start_terminal<'a>(window_manager: WindowManager<'a>, _: &WindowSystem,
                          config: &GeneralConfig) -> WindowManager<'a> {
        let (terminal, args) = config.terminal.clone();
        let arguments : Vec<String> = if args.is_empty() {
            Vec::new()
        } else {
            args.split(' ').map(String::from_str).collect()
        };

        Thread::spawn(move || {
            debug!("spawning terminal");
            let command = if arguments.is_empty() {
                Command::new(terminal).detached().spawn()
            } else {
                Command::new(terminal).args(arguments.as_slice()).detached().spawn()
            };

            if let Err(_) = command {
                panic!("unable to start terminal")
            }
        }).detach();

        window_manager.clone()
    }

    pub fn start_launcher<'a>(window_manager: WindowManager<'a>, _: &WindowSystem,
                          config: &GeneralConfig) -> WindowManager<'a> {
        let launcher = config.launcher.clone();
        Thread::spawn(move || {
            debug!("spawning launcher");
            match Command::new(launcher).detached().spawn() {
                Ok(_) => (),
                _     => panic!("unable to start launcher")
            }
        }).detach();

        window_manager.clone()
    }

    pub fn switch_to_workspace<'a>(window_manager: WindowManager<'a>, window_system: &WindowSystem,
                               config: &GeneralConfig<'a>, index: uint) -> WindowManager<'a> {
        window_manager.view(window_system, index as u32, config)
    }

    pub fn move_window_to_workspace<'a>(window_manager: WindowManager<'a>, window_system: &WindowSystem,
                                    config: &GeneralConfig<'a>, index: uint) -> WindowManager<'a> {
        window_manager.move_window_to_workspace(window_system, config, index as u32)
    }

    /// Restart the window manager by calling execvp and replacing the current binary
    /// with the new one in memory.
    /// Pass a list of all windows to it via command line arguments
    /// so it may resume work as usual.
    pub fn restart<'a>(window_manager: WindowManager<'a>, _: &WindowSystem, c: &GeneralConfig<'a>) -> WindowManager<'a> {
        // Get absolute path to binary
        let filename = os::make_absolute(&Path::new(os::args()[0].clone())).unwrap().to_c_str();
        // Collect all managed windows
        let window_ids : String = json::encode(&window_manager.workspaces.all_windows_with_workspaces());

        // Create arguments
        let program_name = os::args()[0].clone().to_c_str();
        let resume = String::from_str("--resume").to_c_str();
        let windows = window_ids.to_c_str();

        for ref p in c.pipes.iter() {
            match p.deref().write().unwrap().deref_mut().wait() {
                _ => ()
            }
        }

        unsafe {
            let mut slice : &mut [*const i8, ..4] = &mut [
                program_name.as_ptr(),
                resume.as_ptr(),
                windows.as_ptr(),
                null()
            ];
            execvp(filename.as_ptr(), slice.as_mut_ptr());
        }

        window_manager.clone()
    }

    /// Stop the window manager
    pub fn exit<'a>(w: WindowManager<'a>, _: &WindowSystem, _: &GeneralConfig<'a>) -> WindowManager<'a> {
        WindowManager { running: false, dragging: None, workspaces: w.workspaces }
    }

    pub fn shift<'a>(index: u32, workspace: Workspaces<'a>, window: Window) -> Workspaces<'a> {
        workspace.shift_window(index, window)
    }
}
<commit_msg>fallout - adapt array size syntax<commit_after>extern crate libc;

use core::Workspaces;
use window_manager::WindowManager;
use window_system::WindowSystem;
use window_system::Window;
use config::{ GeneralConfig, Config };

pub type KeyHandler<'a> = Box<Fn<(WindowManager<'a>, &'a (WindowSystem + 'a), &'a GeneralConfig<'a>), WindowManager<'a>> + 'a>;
pub type MouseHandler<'a> = Box<Fn<(WindowManager<'a>, &'a (WindowSystem + 'a), &'a GeneralConfig<'a>, Window), WindowManager<'a>> + 'a>;
pub type ManageHook<'a> = Box<Fn<(Workspaces<'a>, &'a (WindowSystem + 'a), Window), Workspaces<'a>> + 'a>;
pub type StartupHook<'a> = Box<Fn<(WindowManager<'a>, &'a (WindowSystem + 'a), &'a Config<'a>), WindowManager<'a>> + 'a>;
pub type LogHook<'a> = Box<FnMut<(WindowManager<'a>, &'a (WindowSystem + 'a)), ()> + 'a>;

extern {
    pub fn waitpid(fd: libc::pid_t, status: *mut libc::c_int, options: libc::c_int) -> libc::pid_t;
}

/// Some default handlers for easier config scripts
pub mod default {
    use std::os;
    use std::ptr::null;
    use std::io::process::Command;
    use std::thread::Thread;
    use serialize::json;
    use core::Workspaces;
    use window_manager::WindowManager;
    use window_system::WindowSystem;
    use window_system::Window;
    use config::GeneralConfig;
    use handlers::libc::funcs::posix88::unistd::execvp;

    pub fn start_terminal<'a>(window_manager: WindowManager<'a>, _: &WindowSystem,
                          config: &GeneralConfig) -> WindowManager<'a> {
        let (terminal, args) = config.terminal.clone();
        let arguments : Vec<String> = if args.is_empty() {
            Vec::new()
        } else {
            args.split(' ').map(String::from_str).collect()
        };

        Thread::spawn(move || {
            debug!("spawning terminal");
            let command = if arguments.is_empty() {
                Command::new(terminal).detached().spawn()
            } else {
                Command::new(terminal).args(arguments.as_slice()).detached().spawn()
            };

            if let Err(_) = command {
                panic!("unable to start terminal")
            }
        }).detach();

        window_manager.clone()
    }

    pub fn start_launcher<'a>(window_manager: WindowManager<'a>, _: &WindowSystem,
                          config: &GeneralConfig) -> WindowManager<'a> {
        let launcher = config.launcher.clone();
        Thread::spawn(move || {
            debug!("spawning launcher");
            match Command::new(launcher).detached().spawn() {
                Ok(_) => (),
                _     => panic!("unable to start launcher")
            }
        }).detach();

        window_manager.clone()
    }

    pub fn switch_to_workspace<'a>(window_manager: WindowManager<'a>, window_system: &WindowSystem,
                               config: &GeneralConfig<'a>, index: uint) -> WindowManager<'a> {
        window_manager.view(window_system, index as u32, config)
    }

    pub fn move_window_to_workspace<'a>(window_manager: WindowManager<'a>, window_system: &WindowSystem,
                                    config: &GeneralConfig<'a>, index: uint) -> WindowManager<'a> {
        window_manager.move_window_to_workspace(window_system, config, index as u32)
    }

    /// Restart the window manager by calling execvp and replacing the current binary
    /// with the new one in memory.
    /// Pass a list of all windows to it via command line arguments
    /// so it may resume work as usual.
    pub fn restart<'a>(window_manager: WindowManager<'a>, _: &WindowSystem, c: &GeneralConfig<'a>) -> WindowManager<'a> {
        // Get absolute path to binary
        let filename = os::make_absolute(&Path::new(os::args()[0].clone())).unwrap().to_c_str();
        // Collect all managed windows
        let window_ids : String = json::encode(&window_manager.workspaces.all_windows_with_workspaces());

        // Create arguments
        let program_name = os::args()[0].clone().to_c_str();
        let resume = String::from_str("--resume").to_c_str();
        let windows = window_ids.to_c_str();

        for ref p in c.pipes.iter() {
            match p.deref().write().unwrap().deref_mut().wait() {
                _ => ()
            }
        }

        unsafe {
            let mut slice : &mut [*const i8; 4] = &mut [
                program_name.as_ptr(),
                resume.as_ptr(),
                windows.as_ptr(),
                null()
            ];
            execvp(filename.as_ptr(), slice.as_mut_ptr());
        }

        window_manager.clone()
    }

    /// Stop the window manager
    pub fn exit<'a>(w: WindowManager<'a>, _: &WindowSystem, _: &GeneralConfig<'a>) -> WindowManager<'a> {
        WindowManager { running: false, dragging: None, workspaces: w.workspaces }
    }

    pub fn shift<'a>(index: u32, workspace: Workspaces<'a>, window: Window) -> Workspaces<'a> {
        workspace.shift_window(index, window)
    }
}
<|endoftext|>


<commit_before>use std::os;
use std::io;
use std::io::{fs, File};

use util::{CargoResult, human, ChainError, process};
use core::shell::MultiShell;

macro_rules! git( ($($a:expr),*) => ({
    process("git") $(.arg($a))* .exec_with_output()
}) )

pub struct NewOptions<'a> {
    pub git: bool,
    pub bin: bool,
    pub path: &'a str,
}

pub fn new(opts: NewOptions, _shell: &mut MultiShell) -> CargoResult<()> {
    let path = os::getcwd().join(opts.path);
    if path.exists() {
        return Err(human(format!("Destination `{}` already exists",
                                 path.display())))
    }
    let name = path.filename_str().unwrap();
    mk(&path, name, &opts).chain_error(|| {
        human(format!("Failed to create project `{}` at `{}`",
                      name, path.display()))
    })
}

fn mk(path: &Path, name: &str, opts: &NewOptions) -> CargoResult<()> {

    if opts.git {
        try!(git!("init", path));
        try!(File::create(&path.join(".gitignore")).write(b"/target\n"));
    } else {
        try!(fs::mkdir(path, io::UserRWX));
    }

    let author = try!(discover_author());
    try!(File::create(&path.join("Cargo.toml")).write_str(format!(
r#"[package]

name = "{}"
version = "0.0.1"
authors = ["{}"]
"#, name, author).as_slice()));

    try!(fs::mkdir(&path.join("src"), io::UserRWX));

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

    Ok(())
}

fn discover_author() -> CargoResult<String> {
    let name = match git!("config", "user.name") {
        Ok(out) => String::from_utf8_lossy(out.output.as_slice()).into_string(),
        Err(..) => match os::getenv("USER") {
            Some(user) => user,
            None => return Err(human("could not determine the current user, \
                                      please set $USER"))
        }
    };

    let email = match git!("config", "user.email") {
        Ok(out) => Some(String::from_utf8_lossy(out.output.as_slice()).into_string()),
        Err(..) => None,
    };

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

    Ok(match (name, email) {
        (name, Some(email)) => format!("{} <{}>", name, email),
        (name, None) => name,
    })
}
<commit_msg>auto merge of #321 : alexcrichton/cargo/issue-304, r=wycats<commit_after>use std::os;
use std::io;
use std::io::{fs, File};

use util::{CargoResult, human, ChainError, process};
use core::shell::MultiShell;

macro_rules! git( ($($a:expr),*) => ({
    process("git") $(.arg($a))* .exec_with_output()
}) )

pub struct NewOptions<'a> {
    pub git: bool,
    pub bin: bool,
    pub path: &'a str,
}

pub fn new(opts: NewOptions, _shell: &mut MultiShell) -> CargoResult<()> {
    let path = os::getcwd().join(opts.path);
    if path.exists() {
        return Err(human(format!("Destination `{}` already exists",
                                 path.display())))
    }
    let name = path.filename_str().unwrap();
    mk(&path, name, &opts).chain_error(|| {
        human(format!("Failed to create project `{}` at `{}`",
                      name, path.display()))
    })
}

fn mk(path: &Path, name: &str, opts: &NewOptions) -> CargoResult<()> {

    if opts.git {
        try!(git!("init", path));
        let mut gitignore = "/target\n".to_string();
        if !opts.bin {
            gitignore.push_str("/Cargo.lock\n");
        }
        try!(File::create(&path.join(".gitignore")).write(gitignore.as_bytes()));
    } else {
        try!(fs::mkdir(path, io::UserRWX));
    }

    let author = try!(discover_author());
    try!(File::create(&path.join("Cargo.toml")).write_str(format!(
r#"[package]

name = "{}"
version = "0.0.1"
authors = ["{}"]
"#, name, author).as_slice()));

    try!(fs::mkdir(&path.join("src"), io::UserRWX));

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

    Ok(())
}

fn discover_author() -> CargoResult<String> {
    let name = match git!("config", "user.name") {
        Ok(out) => String::from_utf8_lossy(out.output.as_slice()).into_string(),
        Err(..) => match os::getenv("USER") {
            Some(user) => user,
            None => return Err(human("could not determine the current user, \
                                      please set $USER"))
        }
    };

    let email = match git!("config", "user.email") {
        Ok(out) => Some(String::from_utf8_lossy(out.output.as_slice()).into_string()),
        Err(..) => None,
    };

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

    Ok(match (name, email) {
        (name, Some(email)) => format!("{} <{}>", name, email),
        (name, None) => name,
    })
}
<|endoftext|>


<commit_before>//! Slog atomic switching drain
//!
//! `AtomicSwitch` allows swapping drain that it wraps atomically, race-free, in
//! runtime. This can be useful eg. for turning on debug logging
//! in production.
//!
//! See [`slog` `signal.rs`
//! example](https://github.com/dpc/slog-rs/blob/master/examples/signal.rs)
#![warn(missing_docs)]

#[macro_use]
extern crate slog;
extern crate crossbeam;

use slog::*;
use std::sync::Arc;
use crossbeam::sync::ArcCell;

/// Handle to `AtomicSwitch` that controls it.
pub struct AtomicSwitchCtrl<E>(Arc<ArcCell<Box<Drain<Error=E>>>>);

/// Drain wrapping another drain, allowing atomic substitution in runtime
pub struct AtomicSwitch<E>(Arc<ArcCell<Box<Drain<Error=E>>>>);

impl<E> AtomicSwitch<E> {
    /// Wrap `drain` in `AtomicSwitch` to allow swapping it later
    ///
    /// Use `AtomicSwitch::ctrl()` to get a handle to it
    pub fn new<D: Drain<Error=E> + 'static>(drain: D) -> Self {
        AtomicSwitch::new_from_arc(Arc::new(ArcCell::new(Arc::new(Box::new(drain) as Box<Drain<Error=E>>))))
    }

    /// Create new `AtomicSwitch` from an existing `Arc<...>`
    ///
    /// See `AtomicSwitch::new()`
    pub fn new_from_arc(d: Arc<ArcCell<Box<Drain<Error=E>>>>) -> Self {
        AtomicSwitch(d)
    }

    /// Get a `AtomicSwitchCtrl` handle to control this `AtomicSwitch` drain
    pub fn ctrl(&self) -> AtomicSwitchCtrl<E> {
        AtomicSwitchCtrl(self.0.clone())
    }
}

impl<E> AtomicSwitchCtrl<E> {
    /// Get the current drain reference
    pub fn get(&self) -> Arc<Box<Drain<Error=E>>> {
        self.0.get()
    }

    /// Set the drain
    pub fn set<D: Drain<Error=E>>(&self, drain: D) {
        let _ = self.0.set(Arc::new(Box::new(drain)));
    }

    /// Swap the existing drain with a new one
    pub fn swap(&self, drain: Arc<Box<Drain<Error=E>>>) -> Arc<Box<Drain<Error=E>>> {
        self.0.set(drain)
    }

    /// Get a drain controlled by this `AtomicSwitchCtrl`
    pub fn drain(&self) -> AtomicSwitch<E> {
        AtomicSwitch(self.0.clone())
    }
}

impl<E> Drain for AtomicSwitch<E> {
    type Error = E;
    fn log(&self, info: &Record, logger_values: &OwnedKeyValueList) -> std::result::Result<(), E> {
        self.0.get().log(info, logger_values)
    }
}
<commit_msg>doc(atomic): Improvements.<commit_after>//! Slog atomic switching drain
//!
//! `AtomicSwitch` allows swapping drain that it wraps atomically, race-free, in
//! runtime. This can be useful eg. for turning on debug logging
//! in production.
//!
//! See [`slog` `signal.rs`
//! example](https://github.com/dpc/slog-rs/blob/master/examples/signal.rs)
#![warn(missing_docs)]

#[macro_use]
extern crate slog;
extern crate crossbeam;

use slog::*;
use std::sync::Arc;
use crossbeam::sync::ArcCell;

/// Handle to `AtomicSwitch` that controls it.
pub struct AtomicSwitchCtrl<E>(Arc<ArcCell<Box<Drain<Error=E>>>>);

/// Drain wrapping another drain, allowing atomic substitution in runtime
pub struct AtomicSwitch<E>(Arc<ArcCell<Box<Drain<Error=E>>>>);

impl<E> AtomicSwitch<E> {
    /// Wrap `drain` in `AtomicSwitch` to allow swapping it later
    ///
    /// Use `AtomicSwitch::ctrl()` to get a handle to it
    pub fn new<D: Drain<Error=E> + 'static>(drain: D) -> Self {
        AtomicSwitch::new_from_arc(Arc::new(ArcCell::new(Arc::new(Box::new(drain) as Box<Drain<Error=E>>))))
    }

    /// Create new `AtomicSwitch` from an existing `Arc<...>`
    ///
    /// See `AtomicSwitch::new()`
    pub fn new_from_arc(d: Arc<ArcCell<Box<Drain<Error=E>>>>) -> Self {
        AtomicSwitch(d)
    }

    /// Get a `AtomicSwitchCtrl` handle to control this `AtomicSwitch` drain
    pub fn ctrl(&self) -> AtomicSwitchCtrl<E> {
        AtomicSwitchCtrl(self.0.clone())
    }
}

impl<E> AtomicSwitchCtrl<E> {
    /// Get Arc to the currently wrapped drain
    pub fn get(&self) -> Arc<Box<Drain<Error=E>>> {
        self.0.get()
    }

    /// Set the current wrapped drain
    pub fn set<D: Drain<Error=E>>(&self, drain: D) {
        let _ = self.0.set(Arc::new(Box::new(drain)));
    }

    /// Swap the existing drain with a new one
    pub fn swap(&self, drain: Arc<Box<Drain<Error=E>>>) -> Arc<Box<Drain<Error=E>>> {
        self.0.set(drain)
    }

    /// Get a `AtomicSwitch` drain controlled by this `AtomicSwitchCtrl`
    pub fn drain(&self) -> AtomicSwitch<E> {
        AtomicSwitch(self.0.clone())
    }
}

impl<E> Drain for AtomicSwitch<E> {
    type Error = E;
    fn log(&self, info: &Record, logger_values: &OwnedKeyValueList) -> std::result::Result<(), E> {
        self.0.get().log(info, logger_values)
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::iter::{once, repeat, FromIterator};

use memory::{MemoryLayout, CellIndex, MemSize};
use operations::{Operation, Operations};

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Instructions(Vec<Instruction>);

impl IntoIterator for Instructions {
    type Item = Instruction;
    type IntoIter = ::std::vec::IntoIter<Instruction>;

    fn into_iter(self) -> Self::IntoIter {
        self.0.into_iter()
    }
}

impl FromIterator<Instruction> for Instructions {
    fn from_iter<I: IntoIterator<Item=Instruction>>(iter: I) -> Self {
        Instructions(iter.into_iter().collect())
    }
}

impl FromIterator<Instruction> for String {
    fn from_iter<I: IntoIterator<Item=Instruction>>(iter: I) -> Self {
        iter.into_iter().map(|instr| instr.to_string()).collect()
    }
}

impl From<Instructions> for String {
    fn from(instrs: Instructions) -> String {
        instrs.into_iter().collect()
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Instruction {
    // ">" - increment the pointer (move it to the "right")
    Right,
    // "<" - decrement the pointer (move it to the "left")
    Left,
    // "+" - increment the byte at the pointer
    Increment,
    // "-" - decrement the byte at the pointer
    Decrement,
    // "." - output the byte at the pointer
    Write,
    // "," - input a byte and store it in the byte at the pointer
    Read,
    // "[" - jump forward past the matching ] if the byte at the pointer is zero
    JumpForwardIfZero,
    // "]" - jump backward to the matching [ unless the byte at the pointer is zero
    JumpBackwardUnlessZero,
}

impl fmt::Display for Instruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Instruction::*;
        f.write_str(match *self {
            Right => ">",
            Left => "<",
            Increment => "+",
            Decrement => "-",
            Write => ".",
            Read => ",",
            JumpForwardIfZero => "[",
            JumpBackwardUnlessZero => "]",
        })
    }
}

impl From<(Operations, MemoryLayout)> for Instructions {
    fn from((ops, layout): (Operations, MemoryLayout)) -> Instructions {
        let mut current_cell = 0;

        into_instructions_index(ops, &layout, &mut current_cell)
    }
}

fn into_instructions_index(
    ops: Operations,
    layout: &MemoryLayout,
    current_cell: &mut CellIndex,
) -> Instructions {
    use self::Operation::*;
    ops.into_iter().flat_map(|op| match op {
        Block {body} | TempAllocate {body, ..} => {
            into_instructions_index(body, layout, current_cell)
        },
        Increment {target, amount} => {
            move_to(current_cell, layout.position(&target)).into_iter()
                .chain(repeat(Instruction::Increment).take(amount as usize)).collect()
        },
        Decrement {target, amount} => {
            move_to(current_cell, layout.position(&target)).into_iter()
                .chain(repeat(Instruction::Decrement).take(amount as usize)).collect()
        },
        Read {target} => {
            move_to(current_cell, layout.position(&target.position())).into_iter()
                .chain(consecutive(vec![Instruction::Read], current_cell, target.size())).collect()
        },
        Write {target} => {
            move_to(current_cell, layout.position(&target.position())).into_iter()
                .chain(consecutive(vec![Instruction::Write], current_cell, target.size())).collect()
        },
        Zero {target} => {
            move_to(current_cell, layout.position(&target.position())).into_iter()
                .chain(consecutive(vec![
                    Instruction::JumpForwardIfZero,
                    Instruction::Decrement,
                    Instruction::JumpBackwardUnlessZero,
                ], current_cell, target.size())).collect()
        },
        Loop {cond, body} => {
            unimplemented!();
        },
        Copy {ref source, ref target, ..} => {
            unimplemented!();
        },
        Relocate {source, target} => {
            unimplemented!();
        },
    }).collect()
}

fn move_to(current_cell: &mut CellIndex, target: CellIndex) -> Vec<Instruction> {
    let current = *current_cell;
    *current_cell = target;

    if current > target {
        repeat(Instruction::Left).take(current - target).collect()
    }
    else if target > current {
        repeat(Instruction::Right).take(target - current).collect()
    }
    else {
        Vec::new()
    }
}

fn consecutive(instrs: Vec<Instruction>, current_cell: &mut CellIndex, size: MemSize) -> Vec<Instruction> {
    *current_cell += size;
    (0..size).flat_map(|_| instrs.clone().into_iter().chain(once(Instruction::Right))).collect()
}
<commit_msg>Implementing loop instruction generation<commit_after>use std::fmt;
use std::iter::{once, repeat, FromIterator};

use memory::{MemoryLayout, CellIndex, MemSize};
use operations::{Operation, Operations};

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Instructions(Vec<Instruction>);

impl IntoIterator for Instructions {
    type Item = Instruction;
    type IntoIter = ::std::vec::IntoIter<Instruction>;

    fn into_iter(self) -> Self::IntoIter {
        self.0.into_iter()
    }
}

impl FromIterator<Instruction> for Instructions {
    fn from_iter<I: IntoIterator<Item=Instruction>>(iter: I) -> Self {
        Instructions(iter.into_iter().collect())
    }
}

impl FromIterator<Instruction> for String {
    fn from_iter<I: IntoIterator<Item=Instruction>>(iter: I) -> Self {
        iter.into_iter().map(|instr| instr.to_string()).collect()
    }
}

impl From<Instructions> for String {
    fn from(instrs: Instructions) -> String {
        instrs.into_iter().collect()
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Instruction {
    // ">" - increment the pointer (move it to the "right")
    Right,
    // "<" - decrement the pointer (move it to the "left")
    Left,
    // "+" - increment the byte at the pointer
    Increment,
    // "-" - decrement the byte at the pointer
    Decrement,
    // "." - output the byte at the pointer
    Write,
    // "," - input a byte and store it in the byte at the pointer
    Read,
    // "[" - jump forward past the matching ] if the byte at the pointer is zero
    JumpForwardIfZero,
    // "]" - jump backward to the matching [ unless the byte at the pointer is zero
    JumpBackwardUnlessZero,
}

impl fmt::Display for Instruction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Instruction::*;
        f.write_str(match *self {
            Right => ">",
            Left => "<",
            Increment => "+",
            Decrement => "-",
            Write => ".",
            Read => ",",
            JumpForwardIfZero => "[",
            JumpBackwardUnlessZero => "]",
        })
    }
}

impl From<(Operations, MemoryLayout)> for Instructions {
    fn from((ops, layout): (Operations, MemoryLayout)) -> Instructions {
        let mut current_cell = 0;

        into_instructions_index(ops, &layout, &mut current_cell)
    }
}

fn into_instructions_index(
    ops: Operations,
    layout: &MemoryLayout,
    current_cell: &mut CellIndex,
) -> Instructions {
    use self::Operation::*;
    ops.into_iter().flat_map(|op| match op {
        Block {body} | TempAllocate {body, ..} => {
            into_instructions_index(body, layout, current_cell)
        },
        Increment {target, amount} => {
            move_to(current_cell, layout.position(&target)).into_iter()
                .chain(repeat(Instruction::Increment).take(amount as usize)).collect()
        },
        Decrement {target, amount} => {
            move_to(current_cell, layout.position(&target)).into_iter()
                .chain(repeat(Instruction::Decrement).take(amount as usize)).collect()
        },
        Read {target} => {
            move_to(current_cell, layout.position(&target.position())).into_iter()
                .chain(consecutive(vec![Instruction::Read], current_cell, target.size())).collect()
        },
        Write {target} => {
            move_to(current_cell, layout.position(&target.position())).into_iter()
                .chain(consecutive(vec![Instruction::Write], current_cell, target.size())).collect()
        },
        Zero {target} => {
            move_to(current_cell, layout.position(&target.position())).into_iter()
                .chain(consecutive(vec![
                    Instruction::JumpForwardIfZero,
                    Instruction::Decrement,
                    Instruction::JumpBackwardUnlessZero,
                ], current_cell, target.size())).collect()
        },
        Loop {cond, body} => {
            move_to(current_cell, layout.position(&cond)).into_iter()
                .chain(once(Instruction::JumpForwardIfZero))
                .chain(into_instructions_index(body, layout, current_cell))
                .chain(move_to(current_cell, layout.position(&cond)))
                .chain(once(Instruction::JumpBackwardUnlessZero))
                .collect()
        },
        Copy {source, target, size} => {
            unimplemented!();
        },
        Relocate {source, target} => {
            unimplemented!();
        },
    }).collect()
}

fn move_to(current_cell: &mut CellIndex, target: CellIndex) -> Vec<Instruction> {
    let current = *current_cell;
    *current_cell = target;

    if current > target {
        repeat(Instruction::Left).take(current - target).collect()
    }
    else if target > current {
        repeat(Instruction::Right).take(target - current).collect()
    }
    else {
        Vec::new()
    }
}

fn consecutive(instrs: Vec<Instruction>, current_cell: &mut CellIndex, size: MemSize) -> Vec<Instruction> {
    *current_cell += size;
    (0..size).flat_map(|_| instrs.clone().into_iter().chain(once(Instruction::Right))).collect()
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::net::url;
use std::net::url::Url;
use core::hashmap::HashMap;

/**
Create a URL object from a string. Does various helpful browsery things like

* If there's no current url and the path looks like a file then it will
  create a file url based of the current working directory
* If there's a current url and the new path is relative then the new url
  is based off the current url

*/
#[allow(non_implicitly_copyable_typarams)]
pub fn make_url(str_url: ~str, current_url: Option<Url>) -> Url {
    let schm = url::get_scheme(str_url);
    let str_url = if result::is_err(&schm) {
        if current_url.is_none() {
            // Assume we've been given a file path. If it's absolute just return
            // it, otherwise make it absolute with the cwd.
            if str_url.starts_with("/") {
                ~"file://" + str_url
            } else {
                ~"file://" + os::getcwd().push(str_url).to_str()
            }
        } else {
            let current_url = current_url.get();
            debug!("make_url: current_url: %?", current_url);
            if current_url.path.is_empty() || current_url.path.ends_with("/") {
                current_url.scheme + "://" + current_url.host + "/" + str_url
            } else if str_url.starts_with("//") {
                current_url.scheme + ":" + str_url
            } else {
                let mut path = ~[];
                for str::each_split_char(current_url.path, '/') |p| {
                    path.push(p.to_str());
                }
                let path = path; // FIXME: borrow checker workaround
                let path = path.init();
                let path = str::connect(path.map(|x| copy *x) + ~[str_url], "/");

                current_url.scheme + "://" + current_url.host + path
            }
        }
    } else {
        str_url
    };

    // FIXME: Need to handle errors
    url::from_str(str_url).get()
}

mod make_url_tests {

    #[test]
    fn should_create_absolute_file_url_if_current_url_is_none_and_str_url_looks_filey() {
        let file = ~"local.html";
        let url = make_url(file, None);
        debug!("url: %?", url);
        assert!(url.scheme == ~"file");
        assert!(url.path.contains(os::getcwd().to_str()));
    }

    #[test]
    fn should_create_url_based_on_old_url_1() {
        let old_str = ~"http://example.com";
        let old_url = make_url(old_str, None);
        let new_str = ~"index.html";
        let new_url = make_url(new_str, Some(old_url));
        assert!(new_url.scheme == ~"http");
        assert!(new_url.host == ~"example.com");
        assert!(new_url.path == ~"/index.html");
    }

    #[test]
    fn should_create_url_based_on_old_url_2() {
        let old_str = ~"http://example.com/";
        let old_url = make_url(old_str, None);
        let new_str = ~"index.html";
        let new_url = make_url(new_str, Some(old_url));
        assert!(new_url.scheme == ~"http");
        assert!(new_url.host == ~"example.com");
        assert!(new_url.path == ~"/index.html");
    }

    #[test]
    fn should_create_url_based_on_old_url_3() {
        let old_str = ~"http://example.com/index.html";
        let old_url = make_url(old_str, None);
        let new_str = ~"crumpet.html";
        let new_url = make_url(new_str, Some(old_url));
        assert!(new_url.scheme == ~"http");
        assert!(new_url.host == ~"example.com");
        assert!(new_url.path == ~"/crumpet.html");
    }

    #[test]
    fn should_create_url_based_on_old_url_4() {
        let old_str = ~"http://example.com/snarf/index.html";
        let old_url = make_url(old_str, None);
        let new_str = ~"crumpet.html";
        let new_url = make_url(new_str, Some(old_url));
        assert!(new_url.scheme == ~"http");
        assert!(new_url.host == ~"example.com");
        assert!(new_url.path == ~"/snarf/crumpet.html");
    }

}

pub type UrlMap<T> = @mut HashMap<Url, T>;

pub fn url_map<T: Copy>() -> UrlMap<T> {
    @mut HashMap::new()
}
<commit_msg>Fix URL relativization so that links on Wikipedia work<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::net::url;
use std::net::url::Url;
use core::hashmap::HashMap;

/**
Create a URL object from a string. Does various helpful browsery things like

* If there's no current url and the path looks like a file then it will
  create a file url based of the current working directory
* If there's a current url and the new path is relative then the new url
  is based off the current url

*/
#[allow(non_implicitly_copyable_typarams)]
pub fn make_url(str_url: ~str, current_url: Option<Url>) -> Url {
    let schm = url::get_scheme(str_url);
    let str_url = if result::is_err(&schm) {
        if current_url.is_none() {
            // Assume we've been given a file path. If it's absolute just return
            // it, otherwise make it absolute with the cwd.
            if str_url.starts_with("/") {
                ~"file://" + str_url
            } else {
                ~"file://" + os::getcwd().push(str_url).to_str()
            }
        } else {
            let current_url = current_url.get();
            debug!("make_url: current_url: %?", current_url);
            if str_url.starts_with("//") {
                current_url.scheme + ":" + str_url
            } else if current_url.path.is_empty() ||
                      str_url.starts_with("/") {
                current_url.scheme + "://" +
                current_url.host + "/" +
                str_url.trim_left_chars([ '/' ])
            } else {
                let mut path = ~[];
                for str::each_split_char(current_url.path, '/') |p| {
                    path.push(p.to_str());
                }
                let path = path; // FIXME: borrow checker workaround
                let path = path.init();
                let path = str::connect(path.map(|x| copy *x) + ~[str_url], "/");

                current_url.scheme + "://" + current_url.host + path
            }
        }
    } else {
        str_url
    };

    // FIXME: Need to handle errors
    url::from_str(str_url).get()
}

mod make_url_tests {

    #[test]
    fn should_create_absolute_file_url_if_current_url_is_none_and_str_url_looks_filey() {
        let file = ~"local.html";
        let url = make_url(file, None);
        debug!("url: %?", url);
        assert!(url.scheme == ~"file");
        assert!(url.path.contains(os::getcwd().to_str()));
    }

    #[test]
    fn should_create_url_based_on_old_url_1() {
        let old_str = ~"http://example.com";
        let old_url = make_url(old_str, None);
        let new_str = ~"index.html";
        let new_url = make_url(new_str, Some(old_url));
        assert!(new_url.scheme == ~"http");
        assert!(new_url.host == ~"example.com");
        assert!(new_url.path == ~"/index.html");
    }

    #[test]
    fn should_create_url_based_on_old_url_2() {
        let old_str = ~"http://example.com/";
        let old_url = make_url(old_str, None);
        let new_str = ~"index.html";
        let new_url = make_url(new_str, Some(old_url));
        assert!(new_url.scheme == ~"http");
        assert!(new_url.host == ~"example.com");
        assert!(new_url.path == ~"/index.html");
    }

    #[test]
    fn should_create_url_based_on_old_url_3() {
        let old_str = ~"http://example.com/index.html";
        let old_url = make_url(old_str, None);
        let new_str = ~"crumpet.html";
        let new_url = make_url(new_str, Some(old_url));
        assert!(new_url.scheme == ~"http");
        assert!(new_url.host == ~"example.com");
        assert!(new_url.path == ~"/crumpet.html");
    }

    #[test]
    fn should_create_url_based_on_old_url_4() {
        let old_str = ~"http://example.com/snarf/index.html";
        let old_url = make_url(old_str, None);
        let new_str = ~"crumpet.html";
        let new_url = make_url(new_str, Some(old_url));
        assert!(new_url.scheme == ~"http");
        assert!(new_url.host == ~"example.com");
        assert!(new_url.path == ~"/snarf/crumpet.html");
    }

}

pub type UrlMap<T> = @mut HashMap<Url, T>;

pub fn url_map<T: Copy>() -> UrlMap<T> {
    @mut HashMap::new()
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use extra::url;
use extra::url::Url;
use std::hashmap::HashMap;
use std::os;

/**
Create a URL object from a string. Does various helpful browsery things like

* If there's no current url and the path looks like a file then it will
  create a file url based of the current working directory
* If there's a current url and the new path is relative then the new url
  is based off the current url

*/
// TODO: about:failure->
pub fn make_url(str_url: ~str, current_url: Option<Url>) -> Url {
    let str_url = str_url.trim_chars(& &[' ', '\t', '\n', '\r', '\x0C']).to_owned();
    let schm = url::get_scheme(str_url);
    let str_url = match schm {
        Err(_) => {
            if current_url.is_none() {
                // Assume we've been given a file path. If it's absolute just return
                // it, otherwise make it absolute with the cwd.
                if str_url.starts_with("/") {
                    ~"file://" + str_url
                } else {
                    let mut path = os::getcwd();
                    path.push(str_url);
                    // FIXME (#1094): not the right way to transform a path
                    ~"file://" + path.display().to_str()
                }
            } else {
                let current_url = current_url.unwrap();
                debug!("make_url: current_url: {:?}", current_url);

                let mut new_url = current_url.clone();
                new_url.query = ~[];
                new_url.fragment = None;

                if str_url.starts_with("//") {
                    new_url.scheme + ":" + str_url
                } else if current_url.path.is_empty() || str_url.starts_with("/") {
                    new_url.path = ~"/";
                    new_url.to_str() + str_url.trim_left_chars(&'/')
                } else if str_url.starts_with("#") {
                    new_url.to_str() + str_url
                } else { // relative path
                    let base_path = current_url.path.trim_right_chars(&|c: char| c != '/');
                    new_url.path = base_path.to_owned();
                    new_url.to_str() + str_url
                }
            }
        },
        Ok((scheme, page)) => {
            match scheme {
                ~"about" => {
                    match page {
                        ~"failure" => {
                            let mut path = os::getcwd();
                            path.push("../src/test/html/failure.html");
                            // FIXME (#1094): not the right way to transform a path
                            ~"file://" + path.display().to_str()
                        }
                        // TODO: handle the rest of the about: pages
                        _ => str_url
                    }
                },
                ~"data" => {
                    // Drop whitespace within data: URLs, e.g. newlines within a base64
                    // src="..." block.  Whitespace intended as content should be
                    // %-encoded or base64'd.
                    str_url.chars().filter(|&c| !c.is_whitespace()).collect()
                },
                _ => str_url
            }
        }
    };

    // FIXME: Need to handle errors
    url::from_str(str_url).unwrap()
}

#[cfg(test)]
mod make_url_tests {
    use super::make_url;
    use std::os;

    #[test]
    fn should_create_absolute_file_url_if_current_url_is_none_and_str_url_looks_filey() {
        let file = ~"local.html";
        let url = make_url(file, None);
        debug!("url: {:?}", url);
        assert!(url.scheme == ~"file");
        let path = os::getcwd();
        // FIXME (#1094): not the right way to transform a path
        assert!(url.path.contains(path.display().to_str()));
    }

    #[test]
    fn should_create_url_based_on_old_url_1() {
        let old_str = ~"http://example.com";
        let old_url = make_url(old_str, None);
        let new_str = ~"index.html";
        let new_url = make_url(new_str, Some(old_url));
        assert!(new_url.scheme == ~"http");
        assert!(new_url.host == ~"example.com");
        assert!(new_url.path == ~"/index.html");
    }

    #[test]
    fn should_create_url_based_on_old_url_2() {
        let old_str = ~"http://example.com/";
        let old_url = make_url(old_str, None);
        let new_str = ~"index.html";
        let new_url = make_url(new_str, Some(old_url));
        assert!(new_url.scheme == ~"http");
        assert!(new_url.host == ~"example.com");
        assert!(new_url.path == ~"/index.html");
    }

    #[test]
    fn should_create_url_based_on_old_url_3() {
        let old_str = ~"http://example.com/index.html";
        let old_url = make_url(old_str, None);
        let new_str = ~"crumpet.html";
        let new_url = make_url(new_str, Some(old_url));
        assert!(new_url.scheme == ~"http");
        assert!(new_url.host == ~"example.com");
        assert!(new_url.path == ~"/crumpet.html");
    }

    #[test]
    fn should_create_url_based_on_old_url_4() {
        let old_str = ~"http://example.com/snarf/index.html";
        let old_url = make_url(old_str, None);
        let new_str = ~"crumpet.html";
        let new_url = make_url(new_str, Some(old_url));
        assert!(new_url.scheme == ~"http");
        assert!(new_url.host == ~"example.com");
        assert!(new_url.path == ~"/snarf/crumpet.html");
    }

    #[test]
    fn should_create_url_based_on_old_url_5() {
        let old_str = ~"http://example.com/index.html";
        let old_url = make_url(old_str, None);
        let new_str = ~"#top";
        let new_url = make_url(new_str, Some(old_url));

        assert!(new_url.scheme == ~"http");
        assert!(new_url.host == ~"example.com");
        assert!(new_url.path == ~"/index.html");
        assert!(new_url.fragment == Some(~"top"));
    }

    #[test]
    fn should_create_url_based_on_old_url_6() {
        use extra::url::UserInfo;

        let old_str = ~"http://foo:bar@example.com:8080/index.html";
        let old_url = make_url(old_str, None);
        let new_str = ~"#top";
        let new_url = make_url(new_str, Some(old_url));

        assert!(new_url.scheme == ~"http");
        assert!(new_url.user == Some(UserInfo { user: ~"foo", pass: Some(~"bar") }));
        assert!(new_url.host == ~"example.com");
        assert!(new_url.port == Some(~"8080"));
        assert!(new_url.path == ~"/index.html");
        assert!(new_url.fragment == Some(~"top"));
    }

    #[test]
    fn should_create_url_based_on_old_url_7() {
        let old_str = ~"https://example.com/snarf/index.html";
        let old_url = make_url(old_str, None);
        let new_str = ~"//example.com/crumpet.html";
        let new_url = make_url(new_str, Some(old_url));
        assert!(new_url.scheme == ~"https");
        assert!(new_url.host == ~"example.com");
        assert!(new_url.path == ~"/crumpet.html");
    }

}

pub type UrlMap<T> = HashMap<Url, T>;

pub fn url_map<T: Clone + 'static>() -> UrlMap<T> {
    HashMap::new()
}

<commit_msg>Use &str instead ~str in make_url<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use extra::url;
use extra::url::Url;
use std::hashmap::HashMap;
use std::os;

/**
Create a URL object from a string. Does various helpful browsery things like

* If there's no current url and the path looks like a file then it will
  create a file url based of the current working directory
* If there's a current url and the new path is relative then the new url
  is based off the current url

*/
// TODO: about:failure->
pub fn make_url(str_url: &str, current_url: Option<Url>) -> Url {
    let str_url = str_url.trim_chars(& &[' ', '\t', '\n', '\r', '\x0C']).to_owned();
    let schm = url::get_scheme(str_url);
    let str_url = match schm {
        Err(_) => {
            if current_url.is_none() {
                // Assume we've been given a file path. If it's absolute just return
                // it, otherwise make it absolute with the cwd.
                if str_url.starts_with("/") {
                    ~"file://" + str_url
                } else {
                    let mut path = os::getcwd();
                    path.push(str_url);
                    // FIXME (#1094): not the right way to transform a path
                    ~"file://" + path.display().to_str()
                }
            } else {
                let current_url = current_url.unwrap();
                debug!("make_url: current_url: {:?}", current_url);

                let mut new_url = current_url.clone();
                new_url.query = ~[];
                new_url.fragment = None;

                if str_url.starts_with("//") {
                    new_url.scheme + ":" + str_url
                } else if current_url.path.is_empty() || str_url.starts_with("/") {
                    new_url.path = ~"/";
                    new_url.to_str() + str_url.trim_left_chars(&'/')
                } else if str_url.starts_with("#") {
                    new_url.to_str() + str_url
                } else { // relative path
                    let base_path = current_url.path.trim_right_chars(&|c: char| c != '/');
                    new_url.path = base_path.to_owned();
                    new_url.to_str() + str_url
                }
            }
        },
        Ok((scheme, page)) => {
            match scheme {
                ~"about" => {
                    match page {
                        ~"failure" => {
                            let mut path = os::getcwd();
                            path.push("../src/test/html/failure.html");
                            // FIXME (#1094): not the right way to transform a path
                            ~"file://" + path.display().to_str()
                        }
                        // TODO: handle the rest of the about: pages
                        _ => str_url
                    }
                },
                ~"data" => {
                    // Drop whitespace within data: URLs, e.g. newlines within a base64
                    // src="..." block.  Whitespace intended as content should be
                    // %-encoded or base64'd.
                    str_url.chars().filter(|&c| !c.is_whitespace()).collect()
                },
                _ => str_url
            }
        }
    };

    // FIXME: Need to handle errors
    url::from_str(str_url).unwrap()
}

#[cfg(test)]
mod make_url_tests {
    use super::make_url;
    use std::os;

    #[test]
    fn should_create_absolute_file_url_if_current_url_is_none_and_str_url_looks_filey() {
        let file = ~"local.html";
        let url = make_url(file, None);
        debug!("url: {:?}", url);
        assert!(url.scheme == ~"file");
        let path = os::getcwd();
        // FIXME (#1094): not the right way to transform a path
        assert!(url.path.contains(path.display().to_str()));
    }

    #[test]
    fn should_create_url_based_on_old_url_1() {
        let old_str = ~"http://example.com";
        let old_url = make_url(old_str, None);
        let new_str = ~"index.html";
        let new_url = make_url(new_str, Some(old_url));
        assert!(new_url.scheme == ~"http");
        assert!(new_url.host == ~"example.com");
        assert!(new_url.path == ~"/index.html");
    }

    #[test]
    fn should_create_url_based_on_old_url_2() {
        let old_str = ~"http://example.com/";
        let old_url = make_url(old_str, None);
        let new_str = ~"index.html";
        let new_url = make_url(new_str, Some(old_url));
        assert!(new_url.scheme == ~"http");
        assert!(new_url.host == ~"example.com");
        assert!(new_url.path == ~"/index.html");
    }

    #[test]
    fn should_create_url_based_on_old_url_3() {
        let old_str = ~"http://example.com/index.html";
        let old_url = make_url(old_str, None);
        let new_str = ~"crumpet.html";
        let new_url = make_url(new_str, Some(old_url));
        assert!(new_url.scheme == ~"http");
        assert!(new_url.host == ~"example.com");
        assert!(new_url.path == ~"/crumpet.html");
    }

    #[test]
    fn should_create_url_based_on_old_url_4() {
        let old_str = ~"http://example.com/snarf/index.html";
        let old_url = make_url(old_str, None);
        let new_str = ~"crumpet.html";
        let new_url = make_url(new_str, Some(old_url));
        assert!(new_url.scheme == ~"http");
        assert!(new_url.host == ~"example.com");
        assert!(new_url.path == ~"/snarf/crumpet.html");
    }

    #[test]
    fn should_create_url_based_on_old_url_5() {
        let old_str = ~"http://example.com/index.html";
        let old_url = make_url(old_str, None);
        let new_str = ~"#top";
        let new_url = make_url(new_str, Some(old_url));

        assert!(new_url.scheme == ~"http");
        assert!(new_url.host == ~"example.com");
        assert!(new_url.path == ~"/index.html");
        assert!(new_url.fragment == Some(~"top"));
    }

    #[test]
    fn should_create_url_based_on_old_url_6() {
        use extra::url::UserInfo;

        let old_str = ~"http://foo:bar@example.com:8080/index.html";
        let old_url = make_url(old_str, None);
        let new_str = ~"#top";
        let new_url = make_url(new_str, Some(old_url));

        assert!(new_url.scheme == ~"http");
        assert!(new_url.user == Some(UserInfo { user: ~"foo", pass: Some(~"bar") }));
        assert!(new_url.host == ~"example.com");
        assert!(new_url.port == Some(~"8080"));
        assert!(new_url.path == ~"/index.html");
        assert!(new_url.fragment == Some(~"top"));
    }

    #[test]
    fn should_create_url_based_on_old_url_7() {
        let old_str = ~"https://example.com/snarf/index.html";
        let old_url = make_url(old_str, None);
        let new_str = ~"//example.com/crumpet.html";
        let new_url = make_url(new_str, Some(old_url));
        assert!(new_url.scheme == ~"https");
        assert!(new_url.host == ~"example.com");
        assert!(new_url.path == ~"/crumpet.html");
    }

}

pub type UrlMap<T> = HashMap<Url, T>;

pub fn url_map<T: Clone + 'static>() -> UrlMap<T> {
    HashMap::new()
}

<|endoftext|>