<commit_before>//! Coredump implementation of the Space API server.
//!
//! Start this via the commandline:
//!
//!     ./coredump_status [-p PORT] [-i IP]
extern crate env_logger;
extern crate docopt;
extern crate rustc_serialize;
extern crate spaceapi_server;

mod utils;

use std::sync::{Mutex,Arc};
use docopt::Docopt;
use spaceapi_server::SpaceapiServer;
use spaceapi_server::api;
use spaceapi_server::api::sensors::{TemperatureSensorTemplate, PeopleNowPresentSensorTemplate};
use spaceapi_server::datastore::{DataStore, RedisStore};
use utils::Ipv4;

static USAGE: &'static str = "
Usage: coredump_status [-p PORT] [-i IP]

Options:
    -p PORT  The port to listen on [default: 3000].
    -i IP    The ipv4 address to listen on [default: 127.0.0.1].
";

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_p: u16,
    flag_i: Ipv4,
}

#[cfg_attr(test, allow(dead_code))]
fn main() {
    env_logger::init().unwrap();

    // Parse arguments
    let args: Args = Docopt::new(USAGE).and_then(|d| d.decode())
                                       .unwrap_or_else(|e| e.exit());
    let host = args.flag_i.ip;
    let port = args.flag_p;

    // TODO: Create variables for all params
    let status = api::Status::new(
        "coredump".to_string(),
        "https://www.coredump.ch/logo.png".to_string(),
        "https://www.coredump.ch/".to_string(),
        api::Location {
            address: api::Optional::Value("Spinnereistrasse 2, 8640 Rapperswil, Switzerland".to_string()),
            lat: 47.22936,
            lon: 8.82949,
        },
        api::Contact {
            irc: api::Optional::Value("irc://freenode.net/#coredump".to_string()),
            twitter: api::Optional::Value("@coredump_ch".to_string()),
            foursquare: api::Optional::Value("525c20e5498e875d8231b1e5".to_string()),
            email: api::Optional::Value("danilo@coredump.ch".to_string()),
        },
        vec![
            "email".to_string(),
            "twitter".to_string(),
        ],
    );

    // Set up datastore
    let datastore = Arc::new(Mutex::new(Box::new(RedisStore::new().unwrap()) as Box<DataStore>));

    // Set up server
    let mut server = SpaceapiServer::new(host, port, status, datastore);

    // Register sensors
    server.register_sensor(Box::new(TemperatureSensorTemplate {
        unit: "°C".to_string(),
        location: "Hackerspace".to_string(),
        name: api::Optional::Value("Raspberry CPU".to_string()),
        description: api::Optional::Absent,
    }), "raspi_temperature".to_string());
    server.register_sensor(Box::new(PeopleNowPresentSensorTemplate {
        location: api::Optional::Value("Hackerspace".to_string()),
        name: api::Optional::Absent,
        description: api::Optional::Absent,
        names: api::Optional::Absent,
    }), "people_present".to_string());

    // Serve!
    server.serve();
}
<commit_msg>coredump_status: Added missing data<commit_after>//! Coredump implementation of the Space API server.
//!
//! Start this via the commandline:
//!
//!     ./coredump_status [-p PORT] [-i IP]
extern crate env_logger;
extern crate docopt;
extern crate rustc_serialize;
extern crate spaceapi_server;

mod utils;

use std::sync::{Mutex,Arc};
use docopt::Docopt;
use spaceapi_server::SpaceapiServer;
use spaceapi_server::api;
use spaceapi_server::api::sensors::{TemperatureSensorTemplate, PeopleNowPresentSensorTemplate};
use spaceapi_server::api::Optional::{Value, Absent};
use spaceapi_server::datastore::{DataStore, RedisStore};
use utils::Ipv4;

static USAGE: &'static str = "
Usage: coredump_status [-p PORT] [-i IP]

Options:
    -p PORT  The port to listen on [default: 3000].
    -i IP    The ipv4 address to listen on [default: 127.0.0.1].
";

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_p: u16,
    flag_i: Ipv4,
}

#[cfg_attr(test, allow(dead_code))]
fn main() {
    env_logger::init().unwrap();

    // Parse arguments
    let args: Args = Docopt::new(USAGE).and_then(|d| d.decode())
                                       .unwrap_or_else(|e| e.exit());
    let host = args.flag_i.ip;
    let port = args.flag_p;

    // Create new Status instance
    let mut status = api::Status::new(
        "coredump".to_string(),
        "https://www.coredump.ch/logo.png".to_string(),
        "https://www.coredump.ch/".to_string(),
        api::Location {
            address: Value("Spinnereistrasse 2, 8640 Rapperswil, Switzerland".to_string()),
            lat: 47.22936,
            lon: 8.82949,
        },
        api::Contact {
            irc: Value("irc://freenode.net/#coredump".to_string()),
            twitter: Value("@coredump_ch".to_string()),
            foursquare: Value("525c20e5498e875d8231b1e5".to_string()),
            email: Value("danilo@coredump.ch".to_string()),
        },
        vec![
            "email".to_string(),
            "twitter".to_string(),
        ],
    );

    // Add optional data
    status.spacefed = Value(api::Spacefed {
        spacenet: false,
        spacesaml: false,
        spacephone: false,
    });
    status.feeds = Value(api::Feeds {
        blog: Value(api::Feed {
            _type: Value("rss".to_string()),
            url: "https://www.coredump.ch/feed/".to_string(),
        }),
        wiki: Absent,
        calendar: Absent,
        flickr: Absent,
    });
    status.projects = Value(vec![
        "https://www.coredump.ch/projekte/".to_string(),
        "https://discourse.coredump.ch/c/projects".to_string(),
        "https://github.com/coredump-ch/".to_string(),
    ]);

    // Set up datastore
    let datastore = Arc::new(Mutex::new(Box::new(RedisStore::new().unwrap()) as Box<DataStore>));

    // Set up server
    let mut server = SpaceapiServer::new(host, port, status, datastore);

    // Register sensors
    server.register_sensor(Box::new(TemperatureSensorTemplate {
        unit: "°C".to_string(),
        location: "Hackerspace".to_string(),
        name: Value("Raspberry CPU".to_string()),
        description: Absent,
    }), "raspi_temperature".to_string());
    server.register_sensor(Box::new(PeopleNowPresentSensorTemplate {
        location: Value("Hackerspace".to_string()),
        name: Absent,
        description: Absent,
        names: Absent,
    }), "people_present".to_string());

    // Serve!
    server.serve();
}
<|endoftext|>


<commit_before>
extern crate crypto;
extern crate iron;
extern crate router;
extern crate params;
extern crate hyper;
extern crate logger;

use iron::prelude::*;
use iron::{BeforeMiddleware, AfterMiddleware, typemap};
use iron::middleware::Handler;
use router::{Router};
use iron::status;
use params::Params;
use logger::Logger;

/// generate the md5sum of a given file
pub fn md5sum<T : std::io::Read> (f: &mut T) -> String  {
    use crypto::digest::Digest;

     let mut digest = crypto::md5::Md5::new();
     let mut data: Vec<u8> = Vec::new();

     f.read_to_end(&mut data);
     digest.input(&data);
     digest.result_str()
}

fn submit_form_file(req: &mut Request) -> IronResult<Response> {
    println!("cazzo");
    println!("{:?}", req.get_ref::<Params>());
    Ok(Response::with(status::Ok))
}

fn start_server() {
   let (logger_before, logger_after) = Logger::new(None);
   let mut router = Router::new();
   let mut chain_form_file = Chain::new(submit_form_file);
   chain_form_file.link_before(logger_before);
   chain_form_file.link_after(logger_after);
   router.post("/openact", chain_form_file);
   println!("started server at http://localhost:3000/");
   Iron::new(router).http("localhost:3000").unwrap();
}

#[cfg(test)]
mod tests {

    use std::fs::File;
    use super::md5sum;

    #[test]
    fn md5sum_of_file() {
        static FP : &'static str = "/home/costa/pkg/lav/regione/attiweb/attività/20150107/definizione procedura di riavvio/Procedure_Riavvio_omnia.odt";

        let mut odt = match File::open(FP) {
            Err(why) => panic!("Cannot open the test file: {}", why),
            Ok(file) => file,
        };

        assert_eq!(md5sum(&mut odt), "a381cbe043c38a94af0983ffa934f338");
    }

    #[test]
    fn simple_get() {
        use hyper::Client;
        use hyper::header::Connection;
        use std::io::Read;
        use super::start_server;

        // start_server();

        // Create a client.
        let client = Client::new();
        //
        // Creating an outgoing request.
        let mut res = client.get("http://localhost:3000/openact")
            // set a header
            .header(Connection::close())
            // let 'er go!
            .send().unwrap();

        // Read the Response.
        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        println!("Response: {}", body);
        assert_eq!(body, "Hello World");
    }

}

fn main() {
    println!("Hello, world!");
    start_server();
}
<commit_msg>handled the file as filename parameter of the request<commit_after>
extern crate crypto;
extern crate iron;
extern crate router;
extern crate params;
extern crate hyper;
extern crate logger;

use iron::prelude::*;
use iron::{BeforeMiddleware, AfterMiddleware, typemap};
use iron::middleware::Handler;
use router::{Router};
use iron::status;
use params::Params;
use logger::Logger;
use std::error::Error;

/// generate the md5sum of a given file (io::Read)
pub fn md5sum<T : std::io::Read> (f: &mut T) -> String  {
  use crypto::digest::Digest;

  let mut digest = crypto::md5::Md5::new();
  let mut data: Vec<u8> = Vec::new();

  f.read_to_end(&mut data);
  digest.input(&data);
  digest.result_str()
}

// fn getFile(params: &params::Map) -> Option<&std::io::Read>
// {
//   use std::fs::File;
//   use std::path::Path;
//
// //   #[cfg(debug)]
// //   {
// //     for (key, value) in params.iter() {
// //       println!("{}: {:?}", key, value);
// //     }
// //   }
//
//
//   match params.find(&["filename"]) {
//     Some(ref f) => println!("{:?}", f),
//
//                       { // Open the path in read-only mode, returns `io::Result<File>`
//       let path = Path::new(path);
//       match File::open(path) {
//           // The `description` method of `io::Error` returns a string that
//           // describes the error
//           Err(why) => panic!("couldn't open {}: {}", path.display(),
//                                                     Error::description(&why)),
//           Ok(file) => &file,
//       }
//     },
//     Nome => //None
//             println!("peccato"),
//   }
// }

// curl -i "http://localhost:3000/openact"  -F "filename=@/home/costa/test.csv" -F "name=jason" -F
// "age=2"
fn submit_form_file(req: &mut Request) -> IronResult<Response> {
  let param_res = req.get_ref::<Params>(); // Result<&params::Map, params::ParamsError>
    println!("{:?}", &param_res);

    let md5sum_check = match param_res {
        Ok(ref params) => match params.find(&["md5sum"]) {
          Some(ref passed_md5sum) => {
            match params.find(&["filename"]) {
              None => {
                println!("missing 'filename' field: {:?}", params);
                false
              },
              Some(f) => {
                match *f {
                  params::Value::File(ref file) => println!("the path is: {:?}", file.path() ),
                  _ => println!("non si tratta di un file!!!!")
                }
                true
              }
//               match *f as params::Value {
//                 params::Value::File => {
//                   let file = f as &params::Value::File;
//                   md5sum(file.open()) == passed_md5sum
//                 }
//               }
            }
          },
            _ => false
        },
        Err(why) => {println!("{:?}", why); false},
    };
    Ok(Response::with(status::Ok))
}

fn start_server() {
   let (logger_before, logger_after) = Logger::new(None);
   let mut router = Router::new();
   let mut chain_form_file = Chain::new(submit_form_file);
   chain_form_file.link_before(logger_before);
   chain_form_file.link_after(logger_after);
   router.post("/openact", chain_form_file);
   println!("started server at http://localhost:3000/");
   Iron::new(router).http("localhost:3000").unwrap();
}

#[cfg(test)]
mod tests {

    use std::fs::File;
    use super::md5sum;

#[test]
    fn md5sum_of_file() {
        static FP : &'static str = "/home/costa/pkg/lav/regione/attiweb/attività/20150107/definizione procedura di riavvio/Procedure_Riavvio_omnia.odt";

        let mut odt = match File::open(FP) {
            Err(why) => panic!("Cannot open the test file: {}", why),
            Ok(file) => file,
        };

        assert_eq!(md5sum(&mut odt), "a381cbe043c38a94af0983ffa934f338");
    }

    #[test]
    fn simple_get() {
        use hyper::Client;
        use hyper::header::Connection;
        use std::io::Read;
        use super::start_server;

        // start_server();

        // Create a client.
        let client = Client::new();
        //
        // Creating an outgoing request.
        let mut res = client.get("http://localhost:3000/openact")
            // set a header
            .header(Connection::close())
            // let 'er go!
            .send().unwrap();

        // Read the Response.
        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        println!("Response: {}", body);
        assert_eq!(body, "Hello World");
    }

}

fn main() {
    println!("Hello, world!");
    start_server();
}
<|endoftext|>


<commit_before>extern crate euclid;
#[macro_use]
extern crate glium;
extern crate image;
extern crate vitral;
extern crate serde;
extern crate calx_color;

mod backend;
#[macro_use]
mod resource;

use std::hash;
use image::GenericImage;
use std::collections::HashMap;
use calx_color::color::*;
pub use euclid::{Point2D, Rect, Size2D};
pub use glium::{DisplayBuild, glutin};
pub use backend::Backend;
pub use resource::{Loadable, Resource, ResourceCache, ResourceStore};

type Color = [f32; 4];

type ImageRef = usize;

#[derive(Copy, Clone, Debug)]
struct Frame {
    pub image: ImageRef,
    pub offset: Point2D<f32>,
    pub color: Color,
}

type Splat = Vec<Frame>;

type Brush = Vec<Splat>;

// Brush implements Loadable so we can have a cache for it, but there's no actual implicit load
// method, brushes must be inserted manually in code.
//
// (We *could* make a load method later and have it read configuration files or something that
// specify te brush.)
impl Loadable for Brush {}

impl_store!(BRUSH, String, Brush);

type FrameImage = image::ImageBuffer<image::Rgba<u8>, Vec<u8>>;

impl_store!(DYNAMIC_IMAGE, String, image::DynamicImage);

#[derive(Clone, PartialEq, Eq, Debug)]
struct SubImageSpec {
    image: Resource<image::DynamicImage>,
    bounds: euclid::Rect<u32>,
}

impl SubImageSpec {
    pub fn new(path: String, bounds: euclid::Rect<u32>) -> Option<SubImageSpec> {
        if let Some(image) = Resource::new(path) {
            Some(SubImageSpec {
                image: image,
                bounds: bounds,
            })
        } else {
            None
        }
    }
}

impl Loadable<SubImageSpec> for FrameImage {
    fn load(spec: &SubImageSpec) -> Option<Self>
        where Self: Sized
    {
        // XXX: Using sub_image on spec.image would be neater, but can't use it here
        // because current image::SubImage must get a mutable access to the parent image and the
        // resource handle is immutable.
        Some(image::ImageBuffer::from_fn(spec.bounds.size.width, spec.bounds.size.height, |x, y| {
            spec.image.get_pixel(spec.bounds.origin.x + x, spec.bounds.origin.y + y)
        }))
    }
}

impl hash::Hash for SubImageSpec {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        self.image.hash(state);
        self.bounds.origin.hash(state);
        self.bounds.size.hash(state);
    }
}

impl_store!(FRAME_IMAGE, SubImageSpec, FrameImage);

struct BrushBuilder<'a, V: 'a> {
    builder: &'a mut vitral::Builder<V>,
    image_file: Option<String>,
    brush: Brush,
    frame_images: HashMap<SubImageSpec, usize>,
}

impl<'a, V: Copy + Eq + 'a> BrushBuilder<'a, V> {
    pub fn new(builder: &'a mut vitral::Builder<V>) -> BrushBuilder<'a, V> {
        BrushBuilder {
            builder: builder,
            image_file: None,
            brush: Vec::new(),
            frame_images: HashMap::new(),
        }
    }

    pub fn file(mut self, name: &str) -> Self {
        self.image_file = Some(name.to_string());
        self
    }

    fn get_frame(&mut self, key: &SubImageSpec) -> usize {
        // XXX: Crashy-crash unwrapping if you feed it bad data.
        if let Some(ret) = self.frame_images.get(key) {
            return *ret;
        }

        let image: Resource<FrameImage, SubImageSpec> = Resource::new(key.clone()).unwrap();
        let ret = self.builder.add_image(&*image);

        self.frame_images.insert(key.clone(), ret);

        ret
    }

    /// Add a new frame with the given bounding rectangle to the current splat.
    pub fn frame(mut self, x: u32, y: u32, w: u32, h: u32) -> Self {
        if self.brush.is_empty() {
            self.brush.push(Vec::new());
        }
        let filename = self.image_file.clone().expect("Image file not set");
        let spec = SubImageSpec::new(filename,
            Rect::new(Point2D::new(x, y), Size2D::new(w, h))).unwrap();

        let image = self.get_frame(&spec);

        let idx = self.brush.len() - 1;
        self.brush[idx].push(Frame { image: image, offset: Point2D::new(0.0, 0.0), color: [1.0, 1.0, 1.0, 1.0] });

        self
    }

    /// Set the color of the last frame.
    pub fn color<C: Into<calx_color::Rgba>>(mut self, c: C) -> Self {
        assert!(!self.brush.is_empty());
        let i = self.brush.len() - 1;
        assert!(!self.brush[i].is_empty());
        let j = self.brush[i].len() - 1;

        let c: calx_color::Rgba = c.into();

        self.brush[i][j].color = [c.r, c.g, c.b, c.a];

        self
    }

    /// Set the offset of the last frame.
    pub fn offset(mut self, x: i32, y: i32) -> Self {
        // Internally offset is floats because everything is, but on the data spec level we're
        // pretty much operating on per-pixel level.

        let i = self.brush.len() - 1;
        assert!(i >= 0);
        let j = self.brush[i].len() - 1;
        assert!(j >= 0);

        self.brush[i][j].offset = Point2D::new(x as f32, y as f32);

        self
    }

    /// Start a new splat in the current brush.
    pub fn splat(mut self) -> Self {
        self.brush.push(Vec::new());
        self
    }

    /// Finish and name the current brush and start a new one.
    pub fn brush(mut self, name: &str) -> Self {
        use std::mem;

        let name = name.to_string();
        // Must be an original name.
        assert!(Brush::get_resource(&name).is_none());

        // Zero cached brush and copy the old value here so we can insert it.
        let mut brush = Vec::new();
        mem::swap(&mut brush, &mut self.brush);
        assert!(!brush.is_empty());

        Brush::insert_resource(name, brush);

        self
    }
}

fn init_brushes<V: Copy + Eq>(builder: &mut vitral::Builder<V>) {
    BrushBuilder::new(builder)
        .file("content/assets/props.png")
        .frame(32, 0, 32, 32).color(RED)
        .brush("cursor")
        ;
}

fn draw_splat(context: &mut backend::Context, offset: Point2D<f32>, splat: &Splat) {
    for frame in splat.iter() {
        context.draw_image(frame.image, offset + frame.offset, frame.color);
    }
}

pub fn main() {
    let display = glutin::WindowBuilder::new()
                      .build_glium()
                      .unwrap();

    let mut backend = Backend::new(&display);

    // Construct Vitral context.
    let mut context: backend::Context;
    let mut builder = vitral::Builder::new();

    init_brushes(&mut builder);

    context = builder.build(|img| backend.make_texture(&display, img));

    let font = context.default_font();

    loop {
        context.begin_frame();

        context.draw_text(font,
                          Point2D::new(4.0, 20.0),
                          [1.0, 1.0, 1.0, 1.0],
                          "Hello, world!");

        let image = Brush::get_resource(&"cursor".to_string()).unwrap()[0][0].image;

        draw_splat(&mut context, Point2D::new(50.0, 50.0), &Brush::get_resource(&"cursor".to_string()).unwrap()[0]);

        if !backend.update(&display, &mut context) {
            return;
        }
    }
}
<commit_msg>Tweaking<commit_after>extern crate euclid;
#[macro_use]
extern crate glium;
extern crate image;
extern crate vitral;
extern crate serde;
extern crate calx_color;

mod backend;
#[macro_use]
mod resource;

use std::hash;
use image::GenericImage;
use std::collections::HashMap;
use calx_color::color::*;
pub use euclid::{Point2D, Rect, Size2D};
pub use glium::{DisplayBuild, glutin};
pub use backend::Backend;
pub use resource::{Loadable, Resource, ResourceCache, ResourceStore};

type Color = [f32; 4];

type ImageRef = usize;

#[derive(Copy, Clone, Debug)]
struct Frame {
    pub image: ImageRef,
    pub offset: Point2D<f32>,
    pub color: Color,
}

type Splat = Vec<Frame>;

type Brush = Vec<Splat>;

// Brush implements Loadable so we can have a cache for it, but there's no actual implicit load
// method, brushes must be inserted manually in code.
//
// (We *could* make a load method later and have it read configuration files or something that
// specify te brush.)
impl Loadable for Brush {}

impl_store!(BRUSH, String, Brush);

type FrameImage = image::ImageBuffer<image::Rgba<u8>, Vec<u8>>;

impl_store!(DYNAMIC_IMAGE, String, image::DynamicImage);

#[derive(Clone, PartialEq, Eq, Debug)]
struct SubImageSpec {
    image: Resource<image::DynamicImage>,
    bounds: euclid::Rect<u32>,
}

impl SubImageSpec {
    pub fn new(path: String, bounds: euclid::Rect<u32>) -> Option<SubImageSpec> {
        if let Some(image) = Resource::new(path) {
            Some(SubImageSpec {
                image: image,
                bounds: bounds,
            })
        } else {
            None
        }
    }
}

impl Loadable<SubImageSpec> for FrameImage {
    fn load(spec: &SubImageSpec) -> Option<Self>
        where Self: Sized
    {
        // XXX: Using sub_image on spec.image would be neater, but can't use it here
        // because current image::SubImage must get a mutable access to the parent image and the
        // resource handle is immutable.
        Some(image::ImageBuffer::from_fn(spec.bounds.size.width, spec.bounds.size.height, |x, y| {
            spec.image.get_pixel(spec.bounds.origin.x + x, spec.bounds.origin.y + y)
        }))
    }
}

impl hash::Hash for SubImageSpec {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        self.image.hash(state);
        self.bounds.origin.hash(state);
        self.bounds.size.hash(state);
    }
}

impl_store!(FRAME_IMAGE, SubImageSpec, FrameImage);

struct BrushBuilder<'a, V: 'a> {
    builder: &'a mut vitral::Builder<V>,
    image_file: Option<String>,
    brush: Brush,
    frame_images: HashMap<SubImageSpec, usize>,
}

impl<'a, V: Copy + Eq + 'a> BrushBuilder<'a, V> {
    pub fn new(builder: &'a mut vitral::Builder<V>) -> BrushBuilder<'a, V> {
        BrushBuilder {
            builder: builder,
            image_file: None,
            brush: Vec::new(),
            frame_images: HashMap::new(),
        }
    }

    pub fn file(mut self, name: &str) -> Self {
        self.image_file = Some(name.to_string());
        self
    }

    fn get_frame(&mut self, key: &SubImageSpec) -> usize {
        // XXX: Crashy-crash unwrapping if you feed it bad data.
        if let Some(ret) = self.frame_images.get(key) {
            return *ret;
        }

        let image: Resource<FrameImage, SubImageSpec> = Resource::new(key.clone()).unwrap();
        let ret = self.builder.add_image(&*image);

        self.frame_images.insert(key.clone(), ret);

        ret
    }

    /// Add a new frame with the given bounding rectangle to the current splat.
    pub fn frame(mut self, x: u32, y: u32, w: u32, h: u32) -> Self {
        if self.brush.is_empty() {
            self.brush.push(Vec::new());
        }
        let filename = self.image_file.clone().expect("Image file not set");
        let spec = SubImageSpec::new(filename,
            Rect::new(Point2D::new(x, y), Size2D::new(w, h))).unwrap();

        let image = self.get_frame(&spec);

        let idx = self.brush.len() - 1;
        self.brush[idx].push(Frame { image: image, offset: Point2D::new(0.0, 0.0), color: [1.0, 1.0, 1.0, 1.0] });

        self
    }

    /// Set the color of the last frame.
    pub fn color<C: Into<calx_color::Rgba>>(mut self, c: C) -> Self {
        assert!(!self.brush.is_empty());
        let i = self.brush.len() - 1;
        assert!(!self.brush[i].is_empty());
        let j = self.brush[i].len() - 1;

        let c: calx_color::Rgba = c.into();

        self.brush[i][j].color = [c.r, c.g, c.b, c.a];

        self
    }

    /// Set the offset of the last frame.
    pub fn offset(mut self, x: i32, y: i32) -> Self {
        assert!(!self.brush.is_empty());
        let i = self.brush.len() - 1;
        assert!(!self.brush[i].is_empty());
        let j = self.brush[i].len() - 1;

        // Internally offset is floats because all screen geometry stuff is, but on the data spec
        // level we're pretty much operating on per-pixel level.
        self.brush[i][j].offset = Point2D::new(x as f32, y as f32);

        self
    }

    /// Start a new splat in the current brush.
    pub fn splat(mut self) -> Self {
        self.brush.push(Vec::new());
        self
    }

    /// Finish and name the current brush and start a new one.
    pub fn brush(mut self, name: &str) -> Self {
        use std::mem;

        let name = name.to_string();
        // Must be an original name.
        assert!(Brush::get_resource(&name).is_none());

        // Zero cached brush and copy the old value here so we can insert it.
        let mut brush = Vec::new();
        mem::swap(&mut brush, &mut self.brush);
        assert!(!brush.is_empty());

        Brush::insert_resource(name, brush);

        self
    }
}

fn init_brushes<V: Copy + Eq>(builder: &mut vitral::Builder<V>) {
    BrushBuilder::new(builder)
        .file("content/assets/props.png")
        .frame(32, 0, 32, 32).color(RED)
        .brush("cursor")
        ;
}

fn draw_splat(context: &mut backend::Context, offset: Point2D<f32>, splat: &Splat) {
    for frame in splat.iter() {
        context.draw_image(frame.image, offset + frame.offset, frame.color);
    }
}

pub fn main() {
    let display = glutin::WindowBuilder::new()
                      .build_glium()
                      .unwrap();

    let mut backend = Backend::new(&display);

    // Construct Vitral context.
    let mut context: backend::Context;
    let mut builder = vitral::Builder::new();

    init_brushes(&mut builder);

    context = builder.build(|img| backend.make_texture(&display, img));

    let font = context.default_font();

    loop {
        context.begin_frame();

        context.draw_text(font,
                          Point2D::new(4.0, 20.0),
                          [1.0, 1.0, 1.0, 1.0],
                          "Hello, world!");

        draw_splat(&mut context, Point2D::new(50.0, 50.0), &Brush::get_resource(&"cursor".to_string()).unwrap()[0]);

        if !backend.update(&display, &mut context) {
            return;
        }
    }
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate git2;

use git2::{Repository, Commit, Oid, Revwalk, Index};
use std::collections::HashMap;

#[macro_use]
mod macros;

const E_SUCCESS: i32 = 0;
const E_NO_GIT_REPO: i32 = 1;

fn main() {
    let exit_code = real_main();
    std::process::exit(exit_code);
}

fn real_main() -> i32 {
    let submodule_dir = parse_cli_arguments();
    println!("Merging {}...", submodule_dir);

    let repo = match Repository::open(".") {
        Ok(repo) => repo,
        Err(e) => {
            eprintln!("Couldn't find Git repo in the current directory: {}",
                      e.message());
            return E_NO_GIT_REPO;
        }
    };

    let mut submodule_revwalk = get_submodule_revwalk(&repo, &submodule_dir);

    let mut old_id_to_new = HashMap::new();

    rewrite_submodule_history(&repo,
                              &mut submodule_revwalk,
                              &mut old_id_to_new,
                              &submodule_dir);

    let mut repo_revwalk = get_repo_revwalk(&repo);
    rewrite_repo_history(&repo, &mut repo_revwalk, &mut old_id_to_new, &submodule_dir);

    checkout_rewritten_history(&repo, &old_id_to_new);

    E_SUCCESS
}

fn parse_cli_arguments() -> String {
    let options = clap::App::new("git-submerge")
                          .version("0.1")
                          .author("Alexander Batischev <eual.jp@gmail.com>")
                          .about("Merge Git submodule into the main repo \
                                  as if they've never been separate at all")
                          .arg(clap::Arg::with_name("SUBMODULE_DIR")
                               .help("The submodule to merge")
                               .required(true)
                               .index(1))
                          .get_matches();

    // We can safely use unwrap() here because the argument is marked as "required" and Clap checks
    // its presence for us.
    String::from( options.value_of("SUBMODULE_DIR").unwrap() )
}

fn get_submodule_revwalk<'repo>(repo: &'repo Repository, submodule_dir: &str) -> Revwalk<'repo> {
    let submodule_url = String::from("./") + submodule_dir;
    let mut remote = repo.remote_anonymous(&submodule_url).expect("Couldn't create an anonymous remote");
    remote.fetch(&[], None, None).expect("Couldn't fetch submodule's history");
    let submodule = repo.find_submodule(submodule_dir)
        .expect("Couldn't find the submodule with expected path");
    let submodule_head = submodule.head_id()
        .expect("Couldn't obtain submodule's HEAD");

    let mut revwalk = repo.revwalk().expect("Couldn't obtain RevWalk object for the repo");
    // "Topological" and reverse means "parents are always visited before their children".
    // We need that in order to be sure that our old-to-new-ids map always contains everything we
    // need it to contain.
    revwalk.set_sorting(git2::SORT_REVERSE | git2::SORT_TOPOLOGICAL);
    // TODO (#6): push all branches and tags, not just HEAD
    revwalk.push(submodule_head).expect("Couldn't add submodule's HEAD to RevWalk list");

    revwalk
}

fn rewrite_submodule_history(repo: &Repository,
                             revwalk: &mut Revwalk,
                             old_id_to_new: &mut HashMap<Oid, Oid>,
                             submodule_dir: &str) {
    for maybe_oid in revwalk {
        match maybe_oid {
            Ok(oid) => {
                let commit = repo.find_commit(oid)
                    .expect(&format!("Couldn't get a commit with ID {}", oid));
                let tree = commit.tree()
                    .expect(&format!("Couldn't obtain the tree of a commit with ID {}", oid));
                let mut old_index = Index::new()
                    .expect("Couldn't create an in-memory index for commit");
                let mut new_index = Index::new().expect("Couldn't create an in-memory index");
                old_index.read_tree(&tree)
                    .expect(&format!("Couldn't read the commit {} into index", oid));

                // Obtain the new tree, where everything from the old one is moved under
                // a directory named after the submodule
                for entry in old_index.iter() {
                    let mut new_entry = entry;

                    let mut new_path = String::from(submodule_dir);
                    new_path += "/";
                    new_path += &String::from_utf8(new_entry.path)
                        .expect("Failed to convert a path to str");

                    new_entry.path = new_path.into_bytes();
                    new_index.add(&new_entry).expect("Couldn't add an entry to the index");
                }
                let tree_id = new_index.write_tree_to(&repo)
                    .expect("Couldn't write the index into a tree");
                old_id_to_new.insert(tree.id(), tree_id);
                let tree = repo.find_tree(tree_id)
                    .expect("Couldn't retrieve the tree we just created");

                let parents = {
                    let mut p: Vec<Commit> = Vec::new();
                    for parent_id in commit.parent_ids() {
                        let new_parent_id = old_id_to_new[&parent_id];
                        let parent = repo.find_commit(new_parent_id)
                            .expect("Couldn't find parent commit by its id");
                        p.push(parent);
                    }
                    p
                };

                let mut parents_refs: Vec<&Commit> = Vec::new();
                for i in 0..parents.len() {
                    parents_refs.push(&parents[i]);
                }
                let new_commit_id = repo.commit(None,
                            &commit.author(),
                            &commit.committer(),
                            &commit.message().expect("Couldn't retrieve commit's message"),
                            &tree,
                            &parents_refs[..])
                    .expect("Failed to commit");

                old_id_to_new.insert(oid, new_commit_id);
            }
            Err(e) => eprintln!("Error walking the submodule's history: {:?}", e),
        }
    }
}

fn get_repo_revwalk<'repo>(repo: &'repo Repository) -> Revwalk<'repo> {
    let mut revwalk = repo.revwalk().expect("Couldn't obtain RevWalk object for the repo");
    revwalk.set_sorting(git2::SORT_REVERSE | git2::SORT_TOPOLOGICAL);
    let head = repo.head().expect("Couldn't obtain repo's HEAD");
    let head_id = head.target().expect("Couldn't resolve repo's HEAD to a commit ID");
    // TODO (#6): push all branches and tags, not just HEAD
    revwalk.push(head_id).expect("Couldn't add repo's HEAD to RevWalk list");

    revwalk
}

fn rewrite_repo_history(repo: &Repository,
                        revwalk: &mut Revwalk,
                        old_id_to_new: &mut HashMap<Oid, Oid>,
                        submodule_dir: &str) {
    let submodule_path = std::path::Path::new(submodule_dir);

    for maybe_oid in revwalk {
        match maybe_oid {
            Ok(oid) => {
                let commit = repo.find_commit(oid)
                    .expect(&format!("Couldn't get a commit with ID {}", oid));
                let tree = commit.tree()
                    .expect(&format!("Couldn't obtain the tree of a commit with ID {}", oid));

                let submodule_subdir = match tree.get_path(submodule_path) {
                    Ok(tree) => tree,
                    Err(e) => {
                        if e.code() == git2::ErrorCode::NotFound &&
                           e.class() == git2::ErrorClass::Tree {
                            // It's okay. The tree lacks the subtree corresponding to the
                            // submodule. In other words, the commit doesn't include the submodule.
                            // That's totally fine. Let's map it into itself and move on.
                            old_id_to_new.insert(oid, oid);
                            continue;
                        } else {
                            // Unexpected error; let's report it and abort the program
                            panic!("Error getting submodule's subdir from the tree: {:?}", e);
                        };
                    }
                };

                // **INVARIANT**: if we got this far, current commit contains a submodule and
                // should be rewritten

                let submodule_commit_id = submodule_subdir.id();
                let new_submodule_commit_id = old_id_to_new[&submodule_commit_id];
                let submodule_commit = repo.find_commit(new_submodule_commit_id)
                    .expect("Couldn't obtain submodule's commit");
                let subtree_id = submodule_commit.tree()
                    .and_then(|t| t.get_path(submodule_path))
                    .and_then(|te| Ok(te.id()))
                    .expect("Couldn't obtain submodule's subtree ID");

                let mut treebuilder = repo.treebuilder(Some(&tree))
                    .expect("Couldn't create TreeBuilder");
                treebuilder.remove(submodule_path)
                    .expect("Couldn't remove submodule path from TreeBuilder");
                treebuilder.insert(submodule_path, subtree_id, 0o040000)
                    .expect("Couldn't add submodule as a subdir to TreeBuilder");
                let new_tree_id = treebuilder.write()
                    .expect("Couldn't write TreeBuilder into a Tree");
                let new_tree = repo.find_tree(new_tree_id)
                    .expect("Couldn't read back the Tree we just wrote");

                // In commits that used to update the submodule, add a parent pointing to
                // appropriate commit in new submodule history
                let mut parent_subtree_ids = std::collections::HashSet::new();
                for parent in commit.parents() {
                    let parent_tree = parent.tree().expect("Couldn't obtain parent's tree");
                    let parent_subdir_tree_id = parent_tree.get_path(submodule_path)
                        .and_then(|x| Ok(x.id()));

                    match parent_subdir_tree_id {
                        Ok(id) => {
                            parent_subtree_ids.insert(id);
                            ()
                        }
                        Err(e) => {
                            if e.code() == git2::ErrorCode::NotFound &&
                               e.class() == git2::ErrorClass::Tree
                            {
                                continue;
                            } else {
                                panic!("Error getting submodule's subdir from the tree: {:?}", e);
                            };
                        }
                    }
                }

                // Here's a few pictures to help you understand how we figure out if current commit
                // updated the submodule. If we draw a DAG and name submodule states, the following
                // situations will mean that the submodule wasn't updated:
                //
                //     o--o--o--A--
                //                 `,-A
                //      o--o--o--B-
                //
                // or
                //
                //     o--o--o--A--
                //                 `,-B
                //      o--o--o--B-
                //
                // And in the following graphs the submodule was updated:
                //
                //     o--o--o--A--
                //                 `,-C
                //      o--o--o--B-
                //
                // or
                //
                //     o--o--o--o--A--B
                //
                // Put into words, the rule will be "the submodule state in current commit is
                // different from states in all its parents". Or, more formally, the current state
                // doesn't belong to the set of states in parents.
                let submodule_updated: bool = !parent_subtree_ids.contains(&submodule_commit_id);

                // Rewrite the parents if the submodule was updated
                let parents = {
                    let mut p: Vec<Commit> = Vec::new();
                    for parent_id in commit.parent_ids() {
                        let actual_parent_id = old_id_to_new[&parent_id];
                        let parent = repo.find_commit(actual_parent_id)
                            .expect("Couldn't find parent commit by its id");
                        p.push(parent);
                    }

                    if submodule_updated {
                        p.push(submodule_commit);
                    }

                    p
                };

                let mut parents_refs: Vec<&Commit> = Vec::new();
                for i in 0..parents.len() {
                    parents_refs.push(&parents[i]);
                }
                let new_commit_id = repo.commit(None,
                            &commit.author(),
                            &commit.committer(),
                            &commit.message().expect("Couldn't retrieve commit's message"),
                            &new_tree,
                            &parents_refs[..])
                    .expect("Failed to commit");

                old_id_to_new.insert(oid, new_commit_id);
            }
            Err(e) => eprintln!("Error walking the submodule's history: {:?}", e),
        }
    }
}

fn checkout_rewritten_history(repo: &Repository, old_id_to_new: &HashMap<Oid, Oid>) {
    let mut checkoutbuilder = git2::build::CheckoutBuilder::new();
    checkoutbuilder.force();

    let head = repo.head().expect("Couldn't obtain repo's HEAD");
    let head_id = head.target().expect("Couldn't resolve repo's HEAD to a commit ID");
    let updated_id = old_id_to_new[&head_id];
    let object = repo.find_object(updated_id, None)
        .expect("Couldn't look up an object at which HEAD points");
    repo.reset(&object, git2::ResetType::Hard, Some(&mut checkoutbuilder))
        .expect("Couldn't run force-reset");
}
<commit_msg>Run rustfmt<commit_after>extern crate clap;
extern crate git2;

use git2::{Repository, Commit, Oid, Revwalk, Index};
use std::collections::HashMap;

#[macro_use]
mod macros;

const E_SUCCESS: i32 = 0;
const E_NO_GIT_REPO: i32 = 1;

fn main() {
    let exit_code = real_main();
    std::process::exit(exit_code);
}

fn real_main() -> i32 {
    let submodule_dir = parse_cli_arguments();
    println!("Merging {}...", submodule_dir);

    let repo = match Repository::open(".") {
        Ok(repo) => repo,
        Err(e) => {
            eprintln!("Couldn't find Git repo in the current directory: {}",
                      e.message());
            return E_NO_GIT_REPO;
        }
    };

    let mut submodule_revwalk = get_submodule_revwalk(&repo, &submodule_dir);

    let mut old_id_to_new = HashMap::new();

    rewrite_submodule_history(&repo,
                              &mut submodule_revwalk,
                              &mut old_id_to_new,
                              &submodule_dir);

    let mut repo_revwalk = get_repo_revwalk(&repo);
    rewrite_repo_history(&repo, &mut repo_revwalk, &mut old_id_to_new, &submodule_dir);

    checkout_rewritten_history(&repo, &old_id_to_new);

    E_SUCCESS
}

fn parse_cli_arguments() -> String {
    let options = clap::App::new("git-submerge")
        .version("0.1")
        .author("Alexander Batischev <eual.jp@gmail.com>")
        .about("Merge Git submodule into the main repo as if they've never been separate at all")
        .arg(clap::Arg::with_name("SUBMODULE_DIR")
            .help("The submodule to merge")
            .required(true)
            .index(1))
        .get_matches();

    // We can safely use unwrap() here because the argument is marked as "required" and Clap checks
    // its presence for us.
    String::from(options.value_of("SUBMODULE_DIR").unwrap())
}

fn get_submodule_revwalk<'repo>(repo: &'repo Repository, submodule_dir: &str) -> Revwalk<'repo> {
    let submodule_url = String::from("./") + submodule_dir;
    let mut remote = repo.remote_anonymous(&submodule_url)
        .expect("Couldn't create an anonymous remote");
    remote.fetch(&[], None, None).expect("Couldn't fetch submodule's history");
    let submodule = repo.find_submodule(submodule_dir)
        .expect("Couldn't find the submodule with expected path");
    let submodule_head = submodule.head_id()
        .expect("Couldn't obtain submodule's HEAD");

    let mut revwalk = repo.revwalk().expect("Couldn't obtain RevWalk object for the repo");
    // "Topological" and reverse means "parents are always visited before their children".
    // We need that in order to be sure that our old-to-new-ids map always contains everything we
    // need it to contain.
    revwalk.set_sorting(git2::SORT_REVERSE | git2::SORT_TOPOLOGICAL);
    // TODO (#6): push all branches and tags, not just HEAD
    revwalk.push(submodule_head).expect("Couldn't add submodule's HEAD to RevWalk list");

    revwalk
}

fn rewrite_submodule_history(repo: &Repository,
                             revwalk: &mut Revwalk,
                             old_id_to_new: &mut HashMap<Oid, Oid>,
                             submodule_dir: &str) {
    for maybe_oid in revwalk {
        match maybe_oid {
            Ok(oid) => {
                let commit = repo.find_commit(oid)
                    .expect(&format!("Couldn't get a commit with ID {}", oid));
                let tree = commit.tree()
                    .expect(&format!("Couldn't obtain the tree of a commit with ID {}", oid));
                let mut old_index = Index::new()
                    .expect("Couldn't create an in-memory index for commit");
                let mut new_index = Index::new().expect("Couldn't create an in-memory index");
                old_index.read_tree(&tree)
                    .expect(&format!("Couldn't read the commit {} into index", oid));

                // Obtain the new tree, where everything from the old one is moved under
                // a directory named after the submodule
                for entry in old_index.iter() {
                    let mut new_entry = entry;

                    let mut new_path = String::from(submodule_dir);
                    new_path += "/";
                    new_path += &String::from_utf8(new_entry.path)
                        .expect("Failed to convert a path to str");

                    new_entry.path = new_path.into_bytes();
                    new_index.add(&new_entry).expect("Couldn't add an entry to the index");
                }
                let tree_id = new_index.write_tree_to(&repo)
                    .expect("Couldn't write the index into a tree");
                old_id_to_new.insert(tree.id(), tree_id);
                let tree = repo.find_tree(tree_id)
                    .expect("Couldn't retrieve the tree we just created");

                let parents = {
                    let mut p: Vec<Commit> = Vec::new();
                    for parent_id in commit.parent_ids() {
                        let new_parent_id = old_id_to_new[&parent_id];
                        let parent = repo.find_commit(new_parent_id)
                            .expect("Couldn't find parent commit by its id");
                        p.push(parent);
                    }
                    p
                };

                let mut parents_refs: Vec<&Commit> = Vec::new();
                for i in 0..parents.len() {
                    parents_refs.push(&parents[i]);
                }
                let new_commit_id = repo.commit(None,
                            &commit.author(),
                            &commit.committer(),
                            &commit.message().expect("Couldn't retrieve commit's message"),
                            &tree,
                            &parents_refs[..])
                    .expect("Failed to commit");

                old_id_to_new.insert(oid, new_commit_id);
            }
            Err(e) => eprintln!("Error walking the submodule's history: {:?}", e),
        }
    }
}

fn get_repo_revwalk<'repo>(repo: &'repo Repository) -> Revwalk<'repo> {
    let mut revwalk = repo.revwalk().expect("Couldn't obtain RevWalk object for the repo");
    revwalk.set_sorting(git2::SORT_REVERSE | git2::SORT_TOPOLOGICAL);
    let head = repo.head().expect("Couldn't obtain repo's HEAD");
    let head_id = head.target().expect("Couldn't resolve repo's HEAD to a commit ID");
    // TODO (#6): push all branches and tags, not just HEAD
    revwalk.push(head_id).expect("Couldn't add repo's HEAD to RevWalk list");

    revwalk
}

fn rewrite_repo_history(repo: &Repository,
                        revwalk: &mut Revwalk,
                        old_id_to_new: &mut HashMap<Oid, Oid>,
                        submodule_dir: &str) {
    let submodule_path = std::path::Path::new(submodule_dir);

    for maybe_oid in revwalk {
        match maybe_oid {
            Ok(oid) => {
                let commit = repo.find_commit(oid)
                    .expect(&format!("Couldn't get a commit with ID {}", oid));
                let tree = commit.tree()
                    .expect(&format!("Couldn't obtain the tree of a commit with ID {}", oid));

                let submodule_subdir = match tree.get_path(submodule_path) {
                    Ok(tree) => tree,
                    Err(e) => {
                        if e.code() == git2::ErrorCode::NotFound &&
                           e.class() == git2::ErrorClass::Tree {
                            // It's okay. The tree lacks the subtree corresponding to the
                            // submodule. In other words, the commit doesn't include the submodule.
                            // That's totally fine. Let's map it into itself and move on.
                            old_id_to_new.insert(oid, oid);
                            continue;
                        } else {
                            // Unexpected error; let's report it and abort the program
                            panic!("Error getting submodule's subdir from the tree: {:?}", e);
                        };
                    }
                };

                // **INVARIANT**: if we got this far, current commit contains a submodule and
                // should be rewritten

                let submodule_commit_id = submodule_subdir.id();
                let new_submodule_commit_id = old_id_to_new[&submodule_commit_id];
                let submodule_commit = repo.find_commit(new_submodule_commit_id)
                    .expect("Couldn't obtain submodule's commit");
                let subtree_id = submodule_commit.tree()
                    .and_then(|t| t.get_path(submodule_path))
                    .and_then(|te| Ok(te.id()))
                    .expect("Couldn't obtain submodule's subtree ID");

                let mut treebuilder = repo.treebuilder(Some(&tree))
                    .expect("Couldn't create TreeBuilder");
                treebuilder.remove(submodule_path)
                    .expect("Couldn't remove submodule path from TreeBuilder");
                treebuilder.insert(submodule_path, subtree_id, 0o040000)
                    .expect("Couldn't add submodule as a subdir to TreeBuilder");
                let new_tree_id = treebuilder.write()
                    .expect("Couldn't write TreeBuilder into a Tree");
                let new_tree = repo.find_tree(new_tree_id)
                    .expect("Couldn't read back the Tree we just wrote");

                // In commits that used to update the submodule, add a parent pointing to
                // appropriate commit in new submodule history
                let mut parent_subtree_ids = std::collections::HashSet::new();
                for parent in commit.parents() {
                    let parent_tree = parent.tree().expect("Couldn't obtain parent's tree");
                    let parent_subdir_tree_id = parent_tree.get_path(submodule_path)
                        .and_then(|x| Ok(x.id()));

                    match parent_subdir_tree_id {
                        Ok(id) => {
                            parent_subtree_ids.insert(id);
                            ()
                        }
                        Err(e) => {
                            if e.code() == git2::ErrorCode::NotFound &&
                               e.class() == git2::ErrorClass::Tree {
                                continue;
                            } else {
                                panic!("Error getting submodule's subdir from the tree: {:?}", e);
                            };
                        }
                    }
                }

                // Here's a few pictures to help you understand how we figure out if current commit
                // updated the submodule. If we draw a DAG and name submodule states, the following
                // situations will mean that the submodule wasn't updated:
                //
                //     o--o--o--A--
                //                 `,-A
                //      o--o--o--B-
                //
                // or
                //
                //     o--o--o--A--
                //                 `,-B
                //      o--o--o--B-
                //
                // And in the following graphs the submodule was updated:
                //
                //     o--o--o--A--
                //                 `,-C
                //      o--o--o--B-
                //
                // or
                //
                //     o--o--o--o--A--B
                //
                // Put into words, the rule will be "the submodule state in current commit is
                // different from states in all its parents". Or, more formally, the current state
                // doesn't belong to the set of states in parents.
                let submodule_updated: bool = !parent_subtree_ids.contains(&submodule_commit_id);

                // Rewrite the parents if the submodule was updated
                let parents = {
                    let mut p: Vec<Commit> = Vec::new();
                    for parent_id in commit.parent_ids() {
                        let actual_parent_id = old_id_to_new[&parent_id];
                        let parent = repo.find_commit(actual_parent_id)
                            .expect("Couldn't find parent commit by its id");
                        p.push(parent);
                    }

                    if submodule_updated {
                        p.push(submodule_commit);
                    }

                    p
                };

                let mut parents_refs: Vec<&Commit> = Vec::new();
                for i in 0..parents.len() {
                    parents_refs.push(&parents[i]);
                }
                let new_commit_id = repo.commit(None,
                            &commit.author(),
                            &commit.committer(),
                            &commit.message().expect("Couldn't retrieve commit's message"),
                            &new_tree,
                            &parents_refs[..])
                    .expect("Failed to commit");

                old_id_to_new.insert(oid, new_commit_id);
            }
            Err(e) => eprintln!("Error walking the repo's history: {:?}", e),
        }
    }
}

fn checkout_rewritten_history(repo: &Repository, old_id_to_new: &HashMap<Oid, Oid>) {
    let mut checkoutbuilder = git2::build::CheckoutBuilder::new();
    checkoutbuilder.force();

    let head = repo.head().expect("Couldn't obtain repo's HEAD");
    let head_id = head.target().expect("Couldn't resolve repo's HEAD to a commit ID");
    let updated_id = old_id_to_new[&head_id];
    let object = repo.find_object(updated_id, None)
        .expect("Couldn't look up an object at which HEAD points");
    repo.reset(&object, git2::ResetType::Hard, Some(&mut checkoutbuilder))
        .expect("Couldn't run force-reset");
}
<|endoftext|>


<commit_before>#![feature(box_syntax)]
#![feature(core)]
#![feature(io)]
#![feature(collections)]
#![feature(path)]
#![feature(os)]

extern crate rdb;
extern crate getopts;
extern crate regex;
use std::os;
use std::old_io::{BufferedReader, File};
use getopts::Options;
use regex::Regex;

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options] dump.rdb", program);
    print!("{}", opts.usage(brief.as_slice()));

}

pub fn main() {
    let args = os::args();
    let program = args[0].clone();
    let mut opts = Options::new();

    opts.optopt("f", "format", "Format to output. Valid: json, plain, nil, protocol", "FORMAT");
    opts.optopt("k", "keys", "Keys to show. Can be a regular expression", "KEYS");
    opts.optmulti("d", "databases", "Database to show. Can be specified multiple times", "DB");
    opts.optmulti("t", "type", "Type to show. Can be specified multiple times", "TYPE");
    opts.optflag("h", "help", "print this help menu");

    let matches = match opts.parse(args.tail()) {
        Ok(m) => { m  }
        Err(e) => {
            println!("{}\n", e);
            print_usage(program.as_slice(), opts);
            return;
        }
    };

    if matches.opt_present("h") {
         print_usage(program.as_slice(), opts);
         return;
    }

    let mut filter = rdb::filter::Simple::new();

    for db in matches.opt_strs("d").iter() {
        filter.add_database(db.parse().unwrap());
    }

    for t in matches.opt_strs("t").iter() {
        let typ = match t.as_slice() {
            "string" => rdb::Type::String,
            "list" => rdb::Type::List,
            "set" => rdb::Type::Set,
            "sortedset" | "sorted-set" | "sorted_set" => rdb::Type::SortedSet,
            "hash" => rdb::Type::Hash,
            _ => {
                println!("Unknown type: {}\n", t);
                print_usage(program.as_slice(), opts);
                return;
            }
        };
        filter.add_type(typ);
    }

    if let Some(k) = matches.opt_str("k") {
        let re = match Regex::new(k.as_slice()) {
            Ok(re) => re,
            Err(err) => {
                println!("Incorrect regexp: {:?}\n", err);
                print_usage(program.as_slice(), opts);
                return;
            }
        };
        filter.add_keys(re);
    }

    if matches.free.is_empty() {
        print_usage(program.as_slice(), opts);
        return;
    }

    let path = matches.free[0].clone();
    let file = File::open(&Path::new(path));
    let reader = BufferedReader::new(file);

    let mut res = Ok(());

    if let Some(f) = matches.opt_str("f") {
        match f.as_slice() {
            "json" => {
                res = rdb::parse(reader, rdb::formatter::JSON::new(), filter);
            },
            "plain" => {
                res = rdb::parse(reader, rdb::formatter::Plain::new(), filter);
            },
            "nil" => {
                res = rdb::parse(reader, rdb::formatter::Nil::new(), filter);
            },
            "protocol" => {
                res = rdb::parse(reader, rdb::formatter::Protocol::new(), filter);

            },
            _ => {
                println!("Unknown format: {}\n", f);
                print_usage(program.as_slice(), opts);
            }
        }
    } else {
        res = rdb::parse(reader, rdb::formatter::JSON::new(), filter);
    }

    match res {
        Ok(()) => {},
        Err(e) => {
            println!("");
            let mut stderr = std::old_io::stderr();

            stderr.write_str(format!("Parsing failed: {}\n", e.desc).as_slice()).unwrap();

            if let Some(detail) = e.detail {
                stderr.write_str(format!("Details: {}\n", detail).as_slice()).unwrap();
            }
        }
    }
}
<commit_msg>Use new env::args<commit_after>#![feature(box_syntax)]
#![feature(core)]
#![feature(io)]
#![feature(collections)]
#![feature(path)]
#![feature(env)]

extern crate rdb;
extern crate getopts;
extern crate regex;
use std::env;
use std::old_io::{BufferedReader, File};
use getopts::Options;
use regex::Regex;

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options] dump.rdb", program);
    print!("{}", opts.usage(brief.as_slice()));

}

pub fn main() {
    let mut args = env::args();
    let program = args.next().unwrap();
    let mut opts = Options::new();

    opts.optopt("f", "format", "Format to output. Valid: json, plain, nil, protocol", "FORMAT");
    opts.optopt("k", "keys", "Keys to show. Can be a regular expression", "KEYS");
    opts.optmulti("d", "databases", "Database to show. Can be specified multiple times", "DB");
    opts.optmulti("t", "type", "Type to show. Can be specified multiple times", "TYPE");
    opts.optflag("h", "help", "print this help menu");

    let matches = match opts.parse(args) {
        Ok(m) => { m  }
        Err(e) => {
            println!("{}\n", e);
            print_usage(program.as_slice(), opts);
            return;
        }
    };

    if matches.opt_present("h") {
         print_usage(program.as_slice(), opts);
         return;
    }

    let mut filter = rdb::filter::Simple::new();

    for db in matches.opt_strs("d").iter() {
        filter.add_database(db.parse().unwrap());
    }

    for t in matches.opt_strs("t").iter() {
        let typ = match t.as_slice() {
            "string" => rdb::Type::String,
            "list" => rdb::Type::List,
            "set" => rdb::Type::Set,
            "sortedset" | "sorted-set" | "sorted_set" => rdb::Type::SortedSet,
            "hash" => rdb::Type::Hash,
            _ => {
                println!("Unknown type: {}\n", t);
                print_usage(program.as_slice(), opts);
                return;
            }
        };
        filter.add_type(typ);
    }

    if let Some(k) = matches.opt_str("k") {
        let re = match Regex::new(k.as_slice()) {
            Ok(re) => re,
            Err(err) => {
                println!("Incorrect regexp: {:?}\n", err);
                print_usage(program.as_slice(), opts);
                return;
            }
        };
        filter.add_keys(re);
    }

    if matches.free.is_empty() {
        print_usage(program.as_slice(), opts);
        return;
    }

    let path = matches.free[0].clone();
    let file = File::open(&Path::new(path));
    let reader = BufferedReader::new(file);

    let mut res = Ok(());

    if let Some(f) = matches.opt_str("f") {
        match f.as_slice() {
            "json" => {
                res = rdb::parse(reader, rdb::formatter::JSON::new(), filter);
            },
            "plain" => {
                res = rdb::parse(reader, rdb::formatter::Plain::new(), filter);
            },
            "nil" => {
                res = rdb::parse(reader, rdb::formatter::Nil::new(), filter);
            },
            "protocol" => {
                res = rdb::parse(reader, rdb::formatter::Protocol::new(), filter);

            },
            _ => {
                println!("Unknown format: {}\n", f);
                print_usage(program.as_slice(), opts);
            }
        }
    } else {
        res = rdb::parse(reader, rdb::formatter::JSON::new(), filter);
    }

    match res {
        Ok(()) => {},
        Err(e) => {
            println!("");
            let mut stderr = std::old_io::stderr();

            stderr.write_str(format!("Parsing failed: {}\n", e.desc).as_slice()).unwrap();

            if let Some(detail) = e.detail {
                stderr.write_str(format!("Details: {}\n", detail).as_slice()).unwrap();
            }
        }
    }
}
<|endoftext|>


<commit_before>struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let mut origin = Point { x: 0, y: 0 };

    println!("X is {} and Y is {})", origin.x + 1, origin.y + 90);

    let mut v = vec![1, 2, 3, 4, 5];

    for i in &v {
        println!("A reference to {}", i);
    }

    for i in &mut v {
        println!("A mutable reference to {}", i);
    }

    for i in v {
        println!("Take ownership of the vector and its element {}", i);
    }
}
<commit_msg>more imagination<commit_after>struct Coordinates {
    x: i32,
    y: i32,
}

fn main() {
    let mut origin = Coordinates { x: 0, y: 0 };

    println!("X is {} and Y is {})", origin.x + 1, origin.y + 90);

    let mut v = vec![1, 2, 3, 4, 5];

    for i in &v {
        println!("A reference to {}", i);
    }

    for i in &mut v {
        println!("A mutable reference to {}", i);
    }

    for i in v {
        println!("Take ownership of the vector and its element {}", i);
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::fs;
use std::io;
use std::path::Path;

use handlebars::{no_escape, Handlebars};

const SITE_TITLE: &str = "Grauwoelfchen's Workroom";
const DST_DIR: &str = "./dst";

const LINKS: [(&str, &str); 4] = [
    ("Home", "/"),
    ("About", "/about.html"),
    ("Software", "/software.html"),
    ("Link", "/link.html"),
];

#[derive(Debug)]
enum Error {
    Io(io::Error),
    Parse(handlebars::TemplateError),
    Render(handlebars::RenderError),
}

impl From<io::Error> for Error {
    fn from(error: io::Error) -> Self {
        Self::Io(error)
    }
}

impl From<handlebars::TemplateError> for Error {
    fn from(error: handlebars::TemplateError) -> Self {
        Self::Parse(error)
    }
}

impl From<handlebars::RenderError> for Error {
    fn from(error: handlebars::RenderError) -> Self {
        Self::Render(error)
    }
}

fn main() -> Result<(), Error> {
    let mut reg = Handlebars::new();

    let layout = include_str!("./layout.hbs");
    reg.register_template_string("layout", layout)?;
    reg.register_escape_fn(no_escape);

    let dst = Path::new(&DST_DIR);

    // error
    let dat = include_str!("./error.hbs");
    fs::write(dst.join("error.html"), &dat.as_bytes())?;

    // index
    let data = load("Home", include_str!("./index.hbs"));
    let result = reg.render("layout", &data)?;
    fs::write(dst.join("index.html"), result)?;

    // about
    let data = load("About", include_str!("./about.hbs"));
    let result = reg.render("layout", &data).unwrap();
    fs::write(dst.join("about.html"), result)?;

    // software
    let data = load("Software", include_str!("./software.hbs"));
    let result = reg.render("layout", &data).unwrap();
    fs::write(dst.join("software.html"), result)?;

    // link
    let data = load("Link", include_str!("./link.hbs"));
    let result = reg.render("layout", &data).unwrap();
    fs::write(dst.join("link.html"), result)?;

    reg.unregister_escape_fn();

    Ok(())
}

/// Returns built an entry for navigations list.
fn build_nav(heading: &str, link: (&str, &str)) -> String {
    let title = link.0;
    let href = link.1;

    let class = if title == heading {
        " class=\"active\""
    } else {
        ""
    };
    format!(
        r#"

  {}

"#,
        class, href, title,
    )
}

fn load(heading: &str, content: &str) -> BTreeMap<String, String> {
    let mut data = BTreeMap::new();

    let mut nav = "".to_string();
    for link in LINKS {
        nav.push_str(&build_nav(heading, link));
    }
    data.insert("navi".to_string(), nav);
    data.insert("content".to_string(), content.to_string());

    // meta
    if heading != "Home" {
        data.insert("page_title".to_string(), heading.to_string());
    }
    data.insert("site_title".to_string(), SITE_TITLE.to_string());
    data
}

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

    #[test]
    fn test_build_nav() {
        let active = build_nav("Foo", ("Foo", "/foo.html"));
        assert_eq!(
            active,
            r#"

  Foo

"#
        );

        let inactive = build_nav("Bar", ("Foo", "/foo.html"));
        assert_eq!(
            inactive,
            r#"

  Foo

"#
        );
    }
}
<commit_msg>Use Link structs instead of tuples<commit_after>use std::collections::BTreeMap;
use std::fs;
use std::io;
use std::path::Path;

use handlebars::{no_escape, Handlebars};

const SITE_TITLE: &str = "Grauwoelfchen's Workroom";
const DST_DIR: &str = "./dst";

const LINKS: [Link; 4] = [
    Link {
        title: "Home",
        href: "/",
    },
    Link {
        title: "About",
        href: "/about.html",
    },
    Link {
        title: "Software",
        href: "/software.html",
    },
    Link {
        title: "Link",
        href: "/link.html",
    },
];

#[derive(Debug)]
enum Error {
    Io(io::Error),
    Parse(handlebars::TemplateError),
    Render(handlebars::RenderError),
}

impl From<io::Error> for Error {
    fn from(error: io::Error) -> Self {
        Self::Io(error)
    }
}

impl From<handlebars::TemplateError> for Error {
    fn from(error: handlebars::TemplateError) -> Self {
        Self::Parse(error)
    }
}

impl From<handlebars::RenderError> for Error {
    fn from(error: handlebars::RenderError) -> Self {
        Self::Render(error)
    }
}

struct Link {
    pub title: &'static str,
    pub href: &'static str,
}

fn main() -> Result<(), Error> {
    let mut reg = Handlebars::new();

    let layout = include_str!("./layout.hbs");
    reg.register_template_string("layout", layout)?;
    reg.register_escape_fn(no_escape);

    let dst = Path::new(&DST_DIR);

    // error
    let dat = include_str!("./error.hbs");
    fs::write(dst.join("error.html"), &dat.as_bytes())?;

    // index
    let data = load("Home", include_str!("./index.hbs"));
    let result = reg.render("layout", &data)?;
    fs::write(dst.join("index.html"), result)?;

    // about
    let data = load("About", include_str!("./about.hbs"));
    let result = reg.render("layout", &data).unwrap();
    fs::write(dst.join("about.html"), result)?;

    // software
    let data = load("Software", include_str!("./software.hbs"));
    let result = reg.render("layout", &data).unwrap();
    fs::write(dst.join("software.html"), result)?;

    // link
    let data = load("Link", include_str!("./link.hbs"));
    let result = reg.render("layout", &data).unwrap();
    fs::write(dst.join("link.html"), result)?;

    reg.unregister_escape_fn();

    Ok(())
}

/// Returns built an entry for navigations list.
fn build_nav(heading: &str, link: &Link) -> String {
    let class = if link.title == heading {
        " class=\"active\""
    } else {
        ""
    };
    format!(
        r#"

  {}

"#,
        class, link.href, link.title,
    )
}

fn load(heading: &str, content: &str) -> BTreeMap<String, String> {
    let mut data = BTreeMap::new();

    let mut nav = "".to_string();
    for link in LINKS {
        nav.push_str(&build_nav(heading, &link));
    }
    data.insert("navi".to_string(), nav);
    data.insert("content".to_string(), content.to_string());

    // meta
    if heading != "Home" {
        data.insert("page_title".to_string(), heading.to_string());
    }
    data.insert("site_title".to_string(), SITE_TITLE.to_string());
    data
}

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

    #[test]
    fn test_build_nav() {
        let link = Link {
            title: "Foo",
            href: "/foo.html",
        };
        let nav = build_nav("Foo", &link);
        assert_eq!(
            nav,
            r#"

  Foo

"#
        );

        let link = Link {
            title: "Bar",
            href: "/foo.html",
        };
        let nav = build_nav("Bar", &link);
        assert_eq!(
            nav,
            r#"

  Foo

"#
        );
    }
}
<|endoftext|>


<commit_before>#![crate_id = "risp"]
#![crate_type = "bin"]

//! A Lisp interpreter.

extern crate libc;

use libc::c_char;
use std::c_str::CString;

//pub mod read;

#[link(name = "linenoise")]
extern {
    fn linenoise(p: *c_char) -> *c_char;
    fn linenoiseHistoryAdd(l: *c_char);
}

/// Attempts to read input from a user using linenoise. Returns an option,
/// Some(StrBuf) for success, or None if EOF (^D) is entered.
pub fn rust_linenoise(prompt: &str) -> Option<StrBuf> {
    if prompt.len() == 0 {
        return None
    }

    let c_prompt = prompt.to_c_str();

    c_prompt.with_ref(|c_buf| {
        unsafe {
            let ret_str = CString::new(linenoise(c_buf), true);
            if ret_str.is_not_null() {
                ret_str.as_str().map(|ret_str| ret_str.to_strbuf())
            } else {
                None
            }
        }
    })
}

/// Adds a string to a history buffer.
pub fn rust_add_history(line: &str) {
    if line.len() == 0 {
        return
    }

    let c_line = line.to_c_str();
    c_line.with_ref(|c_line| {
        unsafe {
            linenoiseHistoryAdd(c_line);
        }
    });
}

/// Make sure there are equal amounts of parens and prevent malformed
/// expressions such as ``(+ 2 2)(+ 2 2)"
pub fn count_parens(expr: &str) -> (uint, uint, bool) {
    let (mut lparens, mut rparens) = (0, 0);
    for c in expr.chars() {
        if c == '(' {
            if lparens == rparens && lparens != 0 {
                return (lparens, rparens, false)
            } else {
                lparens += 1
            }
        } else if c == ')' {
            if rparens >= lparens && rparens != 0 {
                return (lparens, rparens, false)
            } else {
                rparens += 1
            }
        }
    }

    (lparens, rparens, true)
}

fn main() {
    loop {
        let mut expr = match rust_linenoise(">>> ") {
            Some(val)   => { val.to_str() },
            None    => { continue }
        };

        let (mut lparens, mut rparens): (uint, uint);
        //A valid expression can have no parens if and only if it is a
        //constant or variable, eg 2, x, 'd' or "hello, world!"
        let mut okay_expr = true;

        if expr.trim().starts_with("(") {
            loop {
                let (lparenstmp, rparenstmp, okay_exprtmp) = count_parens(expr.as_slice());
                lparens = lparenstmp;
                rparens = rparenstmp;
                okay_expr = okay_exprtmp;
                if okay_expr == false {
                    break
                }

                if lparens == rparens {
                    okay_expr = true;
                    break
                }

                 let expr_part = match rust_linenoise(" ") {
                    Some(val)   => { val.to_str() },
                    None    => { continue }
                };

                expr = expr + "\n" + expr_part;
            }
        }

        if okay_expr == false {
            println!("Bad expression");
            continue
        }

        rust_add_history(expr);

        match expr.trim() {
            "(exit)" | "exit" | ",q"    => { break },
            _   => { println!("{}", expr); }
        }
    }
}
<commit_msg>changed count_parens from fn to closure<commit_after>#![crate_id = "risp"]
#![crate_type = "bin"]

//! A Lisp interpreter.

extern crate libc;

use libc::c_char;
use std::c_str::CString;

//pub mod read;

#[link(name = "linenoise")]
extern {
    fn linenoise(p: *c_char) -> *c_char;
    fn linenoiseHistoryAdd(l: *c_char);
}

/// Attempts to read input from a user using linenoise. Returns an option,
/// Some(StrBuf) for success, or None if EOF (^D) is entered.
pub fn rust_linenoise(prompt: &str) -> Option<StrBuf> {
    if prompt.len() == 0 {
        return None
    }

    let c_prompt = prompt.to_c_str();

    c_prompt.with_ref(|c_buf| {
        unsafe {
            let ret_str = CString::new(linenoise(c_buf), true);
            if ret_str.is_not_null() {
                ret_str.as_str().map(|ret_str| ret_str.to_strbuf())
            } else {
                None
            }
        }
    })
}

/// Adds a string to a history buffer.
pub fn rust_add_history(line: &str) {
    if line.len() == 0 {
        return
    }

    let c_line = line.to_c_str();
    c_line.with_ref(|c_line| {
        unsafe {
            linenoiseHistoryAdd(c_line);
        }
    });
}

fn main() {
    loop {
        let mut expr = match rust_linenoise(">>> ") {
            Some(val)   => { val.to_str() },
            None    => { "".to_str() } //I hate ~str
        };

        let mut okay_expr = true;

        if expr.trim().starts_with("(") || expr.len() == 0 {
            let count_parens = |expr: &str| -> (uint, uint, bool) {
                let (mut lparens, mut rparens) = (0, 0);
                for c in expr.chars() {
                    if c == '(' {
                        if lparens == rparens && lparens != 0 {
                            return (lparens, rparens, false)
                        } else {
                            lparens += 1
                        }
                    } else if c == ')' {
                        if rparens >= lparens && rparens != 0 {
                            return (lparens, rparens, false)
                        } else {
                            rparens += 1
                        }
                    }
                }

                (lparens, rparens, true)
            };

            loop {
                let (lparens, rparens, okay_expr_tmp) = count_parens(expr.as_slice());

                if okay_expr_tmp == false {
                    okay_expr = false;
                    break
                }
                if lparens == rparens && lparens != 0 {
                    break
                }

                let expr_part = match rust_linenoise(" ") {
                    Some(val)   => { val.to_str() },
                    None    => { continue }
                };
                expr = expr + "\n" + expr_part;
            }
        }

        if okay_expr == false {
            println!("Bad expression");
            continue
        }
        rust_add_history(expr);

        match expr.trim() {
            "(exit)" | "exit" | ",q"    => { break },
            _   => { println!("{}", expr); }
        }
    }
}
<|endoftext|>


<commit_before>//! Main module of way-cooler

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate bitflags;

extern crate rustwlc;

#[macro_use]
extern crate log;
extern crate env_logger;

#[macro_use]
extern crate hlua;

use std::env;

use rustwlc::types::LogType;

#[macro_use] // As it happens, it's important to declare the macros first.
mod macros;

mod callbacks;
mod keys;

mod lua;
mod registry;
mod convert;

mod layout;
mod compositor;

/// Callback to route wlc logs into env_logger
fn log_handler(level: LogType, message: &str) {
    match level {
        LogType::Info => info!("wlc: {}", message),
        LogType::Warn => warn!("wlc: {}", message),
        LogType::Error => error!("wlc: {}", message),
        LogType::Wayland => info!("wayland: {}", message)
    }
}

/// Formats the log strings properly
fn log_format(record: &log::LogRecord) -> String {
    format!("{} [{}] {}", record.level(), record.location().module_path(),
            record.args())
}

fn main() {
    debug!("Launching way-cooler...");

    // Initialize callbacks
    callbacks::init();

    // Prepare log builder
    let mut builder = env_logger::LogBuilder::new();
    builder.format(log_format);
    builder.filter(None, log::LogLevelFilter::Trace);
    if env::var("WAY_COOLER_LOG").is_ok() {
        builder.parse(&env::var("WAY_COOLER_LOG").unwrap());
    }
    builder.init().unwrap();
    info!("Logger initialized, setting wlc handler.");

    // Handle wlc logs
    rustwlc::log_set_rust_handler(log_handler);

    // Prepare to launch wlc
    let run_wlc = rustwlc::init2().expect("Unable to initialize wlc!");

    // Hand control over to wlc's event loop
    run_wlc();
}
<commit_msg>Remove the last unwrap() from main<commit_after>//! Main module of way-cooler

#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate bitflags;

extern crate rustwlc;

#[macro_use]
extern crate log;
extern crate env_logger;

#[macro_use]
extern crate hlua;

use std::env;

use rustwlc::types::LogType;

#[macro_use] // As it happens, it's important to declare the macros first.
mod macros;

mod callbacks;
mod keys;

mod lua;
mod registry;
mod convert;

mod layout;
mod compositor;

/// Callback to route wlc logs into env_logger
fn log_handler(level: LogType, message: &str) {
    match level {
        LogType::Info => info!("wlc: {}", message),
        LogType::Warn => warn!("wlc: {}", message),
        LogType::Error => error!("wlc: {}", message),
        LogType::Wayland => info!("wayland: {}", message)
    }
}

/// Formats the log strings properly
fn log_format(record: &log::LogRecord) -> String {
    format!("{} [{}] {}", record.level(), record.location().module_path(),
            record.args())
}

fn main() {
    debug!("Launching way-cooler...");

    // Initialize callbacks
    callbacks::init();

    // Prepare log builder
    let mut builder = env_logger::LogBuilder::new();
    builder.format(log_format);
    builder.filter(None, log::LogLevelFilter::Trace);
    if env::var("WAY_COOLER_LOG").is_ok() {
        builder.parse(&env::var("WAY_COOLER_LOG").unwrap());
    }
    builder.init().expect("Unable to initialize logging!");
    info!("Logger initialized, setting wlc handler.");

    // Handle wlc logs
    rustwlc::log_set_rust_handler(log_handler);

    // Prepare to launch wlc
    let run_wlc = rustwlc::init2().expect("Unable to initialize wlc!");

    // Hand control over to wlc's event loop
    run_wlc();
}
<|endoftext|>


<commit_before>extern crate websocket;

use std::sync::{Arc, Mutex};
use std::sync::mpsc;
use std::thread;
use std::str;

use websocket::{Server, Message, Sender, Receiver};
use websocket::header::WebSocketProtocol;
use websocket::message::Type;

fn main() {
	let server = Server::bind("0.0.0.0:2794").unwrap();

	let (dispatcher_tx, dispatcher_rx) = mpsc::channel::<String>();
	let client_senders: Arc<Mutex<Vec<mpsc::Sender<String>>>> = Arc::new(Mutex::new(vec![]));

	// Dispatcher thread
	{
		let client_senders = client_senders.clone();
		let _ = thread::Builder::new().name("dispatcher".to_string()).spawn(move || {
			while let Ok(msg) = dispatcher_rx.recv() {
				let mut removed_clients = Vec::new();
				for (i, sender) in client_senders.lock().unwrap().iter().enumerate() {
					match sender.send(msg.clone()) {
						Ok(_) => {},
						Err(_) => {
							// Could not send message because client thread closed
							removed_clients.push(i);
						}
					}
				}

				// Remove all clients that don't exist anymore
				let mut removed_nbr = 0;
				for i in removed_clients {
					client_senders.lock().unwrap().swap_remove(i - removed_nbr);
					removed_nbr += 1;
				}
			}
		});
	}

	// client threads
	for connection in server {
		let dispatcher = dispatcher_tx.clone();
		let (client_tx, client_rx) = mpsc::channel();
		client_senders.lock().unwrap().push(client_tx);   // THIS MIGHT CAUSE THE POISONERROR!!!

		// Spawn a new thread for each connection.
		let _ = thread::Builder::new().name("client".to_string()).spawn(move || {
			let request = connection.unwrap().read_request().unwrap(); // Get the request
			let headers = request.headers.clone(); // Keep the headers so we can check them

			request.validate().unwrap(); // Validate the request

			let mut response = request.accept(); // Form a response

			if let Some(&WebSocketProtocol(ref protocols)) = headers.get() {
				if protocols.contains(&("rust-websocket".to_string())) {
					// We have a protocol we want to use
					response.headers.set(WebSocketProtocol(vec!["rust-websocket".to_string()]));
				}
			}

			let mut client = response.send().unwrap(); // Send the response

			let ip = client.get_mut_sender()
				.get_mut()
				.peer_addr()
				.unwrap();

			println!("Connection from {}", ip);

			let message: Message = Message::text("SERVER: Connected.".to_string());
			client.send_message(&message).unwrap();

			let (mut sender, mut receiver) = client.split();

			let mut username = String::new();

			let(tx, rx) = mpsc::channel::<Message>();
			let _ = thread::Builder::new().name("receiver".to_string()).spawn(move || {
				for message in receiver.incoming_messages() {
					if let Ok(message) = message {
						let message: Message = message;
						match message.opcode {
							Type::Close => {
								tx.send(message).unwrap();
								break;
							},
							_ => {
								tx.send(message).unwrap();
							}
						}
					}
					else {
						let message = Message::close();
						tx.send(message).unwrap();
						break;
					}
				}
			});

			loop {
				if let Ok(message) = rx.try_recv() {
					match message.opcode {
						Type::Close => {
							// Closes connection on both sides, doesn't check if client is still connected
							let message = Message::close();
							let _ = sender.send_message(&message);
							println!("Client {} disconnected", ip);
							return;
						},
						Type::Ping => {
							// This could be an issue if ping is sent and client dies, the server will panic!
							let message = Message::pong(message.payload);
							sender.send_message(&message).unwrap();
						},
						_ => {
							if username.is_empty() {
								let payload_bytes = &message.payload;
								let mut payload_string = match str::from_utf8(payload_bytes) {
									Ok(v) => v,
									Err(e) => panic!("Invalid UTF-8 sequence: {}", e),
								};
								if payload_string.len() > 7 {
									match &payload_string[..7] {
										"/login " => {
											// Confirms login, if client dies the server doesnt give a fuck
											payload_string = &payload_string[7..].trim();
											username = String::from(payload_string);
											if !username.is_empty() {
												let msg_end = "'.".to_string();
												let msg_string = "SERVER: Logged in as '".to_string() + &username + &msg_end;
												let message: Message = Message::text(&msg_string[..	]);
												let _ = sender.send_message(&message);
											}
										},
										_ => { }
									}
								}
							}
							else {
								let payload_bytes = &message.payload;
								let payload_string = match str::from_utf8(payload_bytes) {
									Ok(v) => v,
									Err(e) => panic!("Invalid UTF-8 sequence: {}", e),
								};
								let payload_string = payload_string.trim();
								if payload_string.len() > 0 {
									let msg_string = format!("MESSAGE: {}: {}", username, payload_string);
									dispatcher.send(msg_string).unwrap();
								}
							}
						}
					}
				}
				if let Ok(message) = client_rx.try_recv() {
					// Send message from dispatcher to sender, the server doesnt give a fuck when client is dead
					let message: Message = Message::text(message);
					let _ = sender.send_message(&message);
				}
			}
		});
	}
}
<commit_msg>Testing spacemacs git integration<commit_after>extern crate websocket;

use std::sync::{Arc, Mutex};
use std::sync::mpsc;
use std::thread;
use std::str;

use websocket::{Server, Message, Sender, Receiver};
use websocket::header::WebSocketProtocol;
use websocket::message::Type;

fn main() {
	let server = Server::bind("0.0.0.0:2794").unwrap();

	let (dispatcher_tx, dispatcher_rx) = mpsc::channel::<String>();
	let client_senders: Arc<Mutex<Vec<mpsc::Sender<String>>>> = Arc::new(Mutex::new(vec![]));

	// Dispatcher thread
	{
		let client_senders = client_senders.clone();
		let _ = thread::Builder::new().name("dispatcher".to_string()).spawn(move || {
			while let Ok(msg) = dispatcher_rx.recv() {
				let mut removed_clients = Vec::new();
				for (i, sender) in client_senders.lock().unwrap().iter().enumerate() {
					match sender.send(msg.clone()) {
						Ok(_) => {},
						Err(_) => {
							// Couldn't send message because client thread closed
							removed_clients.push(i);
						}
					}
				}

				// Remove all clients that don't exist anymore
				let mut removed_nbr = 0;
				for i in removed_clients {
					client_senders.lock().unwrap().swap_remove(i - removed_nbr);
					removed_nbr += 1;
				}
			}
		});
	}

	// client threads
	for connection in server {
		let dispatcher = dispatcher_tx.clone();
		let (client_tx, client_rx) = mpsc::channel();
		client_senders.lock().unwrap().push(client_tx);   // THIS MIGHT CAUSE THE POISONERROR!!!

		// Spawn a new thread for each connection.
		let _ = thread::Builder::new().name("client".to_string()).spawn(move || {
			let request = connection.unwrap().read_request().unwrap(); // Get the request
			let headers = request.headers.clone(); // Keep the headers so we can check them

			request.validate().unwrap(); // Validate the request

			let mut response = request.accept(); // Form a response

			if let Some(&WebSocketProtocol(ref protocols)) = headers.get() {
				if protocols.contains(&("rust-websocket".to_string())) {
					// We have a protocol we want to use
					response.headers.set(WebSocketProtocol(vec!["rust-websocket".to_string()]));
				}
			}

			let mut client = response.send().unwrap(); // Send the response

			let ip = client.get_mut_sender()
				.get_mut()
				.peer_addr()
				.unwrap();

			println!("Connection from {}", ip);

			let message: Message = Message::text("SERVER: Connected.".to_string());
			client.send_message(&message).unwrap();

			let (mut sender, mut receiver) = client.split();

			let mut username = String::new();

			let(tx, rx) = mpsc::channel::<Message>();
			let _ = thread::Builder::new().name("receiver".to_string()).spawn(move || {
				for message in receiver.incoming_messages() {
					if let Ok(message) = message {
						let message: Message = message;
						match message.opcode {
							Type::Close => {
								tx.send(message).unwrap();
								break;
							},
							_ => {
								tx.send(message).unwrap();
							}
						}
					}
					else {
						let message = Message::close();
						tx.send(message).unwrap();
						break;
					}
				}
			});

			loop {
				if let Ok(message) = rx.try_recv() {
					match message.opcode {
						Type::Close => {
							// Closes connection on both sides, doesn't check if client is still connected
							let message = Message::close();
							let _ = sender.send_message(&message);
							println!("Client {} disconnected", ip);
							return;
						},
						Type::Ping => {
							// This could be an issue if ping is sent and client dies, the server will panic!
							let message = Message::pong(message.payload);
							sender.send_message(&message).unwrap();
						},
						_ => {
							if username.is_empty() {
								let payload_bytes = &message.payload;
								let mut payload_string = match str::from_utf8(payload_bytes) {
									Ok(v) => v,
									Err(e) => panic!("Invalid UTF-8 sequence: {}", e),
								};
								if payload_string.len() > 7 {
									match &payload_string[..7] {
										"/login " => {
											// Confirms login, if client dies the server doesnt give a fuck
											payload_string = &payload_string[7..].trim();
											username = String::from(payload_string);
											if !username.is_empty() {
												let msg_end = "'.".to_string();
												let msg_string = "SERVER: Logged in as '".to_string() + &username + &msg_end;
												let message: Message = Message::text(&msg_string[..	]);
												let _ = sender.send_message(&message);
											}
										},
										_ => { }
									}
								}
							}
							else {
								let payload_bytes = &message.payload;
								let payload_string = match str::from_utf8(payload_bytes) {
									Ok(v) => v,
									Err(e) => panic!("Invalid UTF-8 sequence: {}", e),
								};
								let payload_string = payload_string.trim();
								if payload_string.len() > 0 {
									let msg_string = format!("MESSAGE: {}: {}", username, payload_string);
									dispatcher.send(msg_string).unwrap();
								}
							}
						}
					}
				}
				if let Ok(message) = client_rx.try_recv() {
					// Send message from dispatcher to sender, the server doesnt give a fuck when client is dead
					let message: Message = Message::text(message);
					let _ = sender.send_message(&message);
				}
			}
		});
	}
}
<|endoftext|>