<commit_before>// (c) 2016 Joost Yervante Damad <joost@productize.be>

use std::fmt;
use std::path::PathBuf;

// from parent
use ERes;
use err;
use read_file;
use footprint;

extern crate rustysexp;
use self::rustysexp::Sexp;

pub struct Layout {
    pub version:i64,
    pub elements:Vec<Element>,
}

#[derive(Clone)]
pub enum Element {
    Module(footprint::Module),
    Net(Net),
    NetClass(NetClass),
    Other(Sexp),
}

#[derive(Clone)]
pub struct Net {
    pub num:i64,
    pub name:String,
}

#[derive(Clone)]
pub struct NetClass {
    pub name:String,
    pub desc:String,
    pub clearance:f64,
    pub trace_width:f64,
    pub via_dia:f64,
    pub via_drill:f64,
    pub uvia_dia:f64,
    pub uvia_drill:f64,
    pub nets:Vec<String>,
}

impl Layout {
    fn new() -> Layout {
        Layout {
            version:0,
            elements:vec![],
        }
    }

    pub fn modify_module<F>(&mut self, reference:&String, fun:F) -> ERes<()>
        where F:Fn(&mut footprint::Module) -> ()
    {
        for ref mut x in &mut self.elements[..] {
            match **x {
                Element::Module(ref mut m) => {
                    if m.is_reference(reference) {
                        return Ok(fun(m))
                    }
                },
                Element::Net(_) => (),
                Element::NetClass(_) => (),
                Element::Other(_) => (),
            }
        }
        Err(format!("did not find module with reference {}", reference))
    }
}

impl fmt::Display for Layout {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(writeln!(f, "(kicad_pcb (version {})", self.version));
        for element in &self.elements[..] {
            try!(writeln!(f, "  {}", element));
            try!(writeln!(f, ""));
        }
        writeln!(f, ")")
    }
}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Element::Other(ref s) => write!(f, "{}", s),
            Element::Module(ref s) => write!(f, "{}", s),
            Element::Net(ref s) => write!(f, "{}", s),
            Element::NetClass(ref s) => write!(f, "{}", s),
        }
    }
}

impl fmt::Display for Net {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.name.contains("(") || self.name.contains(")") {
            write!(f, "(net {} \"{}\")", self.num, self.name)
        } else {
            write!(f, "(net {} {})", self.num, self.name)
        }
    }
}
impl fmt::Display for NetClass {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "(net_class {} \"{}\" ", self.name, self.desc));
        try!(write!(f, "(clearance {}) ", self.clearance));
        try!(write!(f, "(trace_width {}) ", self.trace_width));
        try!(write!(f, "(via_dia {}) ", self.via_dia));
        try!(write!(f, "(via_drill {}) ", self.via_drill));
        try!(write!(f, "(uvia_dia {}) ", self.uvia_dia));
        try!(write!(f, "(uvia_drill {}) ", self.uvia_drill));
        for net in &self.nets {
            if net.contains("(") || net.contains(")") {
                try!(write!(f, "(add_net \"{}\")", net))
            } else {
                try!(write!(f, "(add_net {})", net))
            }
        }
        write!(f, ")")

    }
}

fn parse_version(e:&Sexp) -> ERes<i64> {
    let l = try!(e.slice_atom("version"));
    try!(l[0].atom()).i()
}

fn parse_other(e:&Sexp) -> Element {
    let e2 = e.clone();
    Element::Other(e2)
}

fn parse_module(e:&Sexp) -> ERes<Element> {
    let e2 = e.clone();
    let m = try!(footprint::parse_module(e2));
    Ok(Element::Module(m))
}

fn parse_net(e:&Sexp) -> ERes<Element> {
    let l = try!(e.slice_atom("net"));
    let num = try!(l[0].i());
    let name = try!(l[1].string());
    Ok(Element::Net(Net { name:name, num:num }))
}

fn parse_net_class(e:&Sexp) -> ERes<Element> {
    fn parse(e:&Sexp, name:&str) -> ERes<f64> {
        let l = try!(e.slice_atom(name));
        l[0].f()
    }
    let l = try!(e.slice_atom("net_class"));
    let name = try!(l[0].string());
    let desc = try!(l[1].string());
    let mut clearance = 0.1524;
    let mut trace_width = 0.2032;
    let mut via_dia = 0.675;
    let mut via_drill = 0.25;
    let mut uvia_dia = 0.508;
    let mut uvia_drill = 0.127;
    let mut nets = vec![];
    for x in &l[2..] {
        let list_name = try!(x.list_name());
        let xn = &list_name[..];
        match xn {
            "add_net" => {
                let l1 = try!(x.slice_atom("add_net"));
                nets.push(try!(l1[0].string()))
            },
            "clearance" => clearance = try!(parse(x, xn)),
            "trace_width" => trace_width = try!(parse(x, xn)),
            "via_dia" => via_dia = try!(parse(x, xn)),
            "via_drill" => via_drill = try!(parse(x, xn)),
            "uvia_dia" => uvia_dia = try!(parse(x, xn)),
            "uvia_drill" => uvia_drill = try!(parse(x, xn)),
            _ => return Err(format!("unknown net_class field {}", list_name))
        }
    }
    let net_class = NetClass {
        name:name, desc:desc, clearance:clearance, via_dia:via_dia,
        via_drill:via_drill, uvia_dia:uvia_dia, uvia_drill:uvia_drill,
        nets:nets, trace_width:trace_width,
    };
    Ok(Element::NetClass(net_class))
}

fn parse(s: &str) -> ERes<Layout> {
    let exp = match rustysexp::parse_str(s) {
        Ok(s) => s,
        Err(x) => return Err(format!("ParseError: {}", x)),
    };
    let l1 = try!(exp.slice_atom("kicad_pcb"));
    let mut layout = Layout::new();

    for ref e in l1 {
        match &try!(e.list_name())[..] {
            "version" => layout.version = try!(parse_version(e)),
            "module" => layout.elements.push(try!(parse_module(e))),
            "net" => layout.elements.push(try!(parse_net(e))),
            "net_class" => layout.elements.push(try!(parse_net_class(e))),
            _ => layout.elements.push(parse_other(e)),
        }
    }
    Ok(layout)
}

pub fn parse_str(s: &str) -> ERes<Layout> {
    parse(s)
}

pub fn parse_file(filename: &PathBuf) -> ERes<Layout> {
    let name = filename.to_str().unwrap();
    let s = try!(match read_file(name) {
        Ok(s) => Ok(s),
        Err(x) => Err(format!("io error: {}", x))
    });
    parse(&s[..])
}
<commit_msg>partialeq for Net and NetClass<commit_after>// (c) 2016 Joost Yervante Damad <joost@productize.be>

use std::fmt;
use std::path::PathBuf;

// from parent
use ERes;
use err;
use read_file;
use footprint;

extern crate rustysexp;
use self::rustysexp::Sexp;

pub struct Layout {
    pub version:i64,
    pub elements:Vec<Element>,
}

#[derive(Clone)]
pub enum Element {
    Module(footprint::Module),
    Net(Net),
    NetClass(NetClass),
    Other(Sexp),
}

#[derive(Clone,PartialEq)]
pub struct Net {
    pub num:i64,
    pub name:String,
}

#[derive(Clone,PartialEq)]
pub struct NetClass {
    pub name:String,
    pub desc:String,
    pub clearance:f64,
    pub trace_width:f64,
    pub via_dia:f64,
    pub via_drill:f64,
    pub uvia_dia:f64,
    pub uvia_drill:f64,
    pub nets:Vec<String>,
}

impl Layout {
    fn new() -> Layout {
        Layout {
            version:0,
            elements:vec![],
        }
    }

    pub fn modify_module<F>(&mut self, reference:&String, fun:F) -> ERes<()>
        where F:Fn(&mut footprint::Module) -> ()
    {
        for ref mut x in &mut self.elements[..] {
            match **x {
                Element::Module(ref mut m) => {
                    if m.is_reference(reference) {
                        return Ok(fun(m))
                    }
                },
                Element::Net(_) => (),
                Element::NetClass(_) => (),
                Element::Other(_) => (),
            }
        }
        Err(format!("did not find module with reference {}", reference))
    }
}

impl fmt::Display for Layout {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(writeln!(f, "(kicad_pcb (version {})", self.version));
        for element in &self.elements[..] {
            try!(writeln!(f, "  {}", element));
            try!(writeln!(f, ""));
        }
        writeln!(f, ")")
    }
}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Element::Other(ref s) => write!(f, "{}", s),
            Element::Module(ref s) => write!(f, "{}", s),
            Element::Net(ref s) => write!(f, "{}", s),
            Element::NetClass(ref s) => write!(f, "{}", s),
        }
    }
}

impl fmt::Display for Net {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.name.contains("(") || self.name.contains(")") {
            write!(f, "(net {} \"{}\")", self.num, self.name)
        } else {
            write!(f, "(net {} {})", self.num, self.name)
        }
    }
}
impl fmt::Display for NetClass {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "(net_class {} \"{}\" ", self.name, self.desc));
        try!(write!(f, "(clearance {}) ", self.clearance));
        try!(write!(f, "(trace_width {}) ", self.trace_width));
        try!(write!(f, "(via_dia {}) ", self.via_dia));
        try!(write!(f, "(via_drill {}) ", self.via_drill));
        try!(write!(f, "(uvia_dia {}) ", self.uvia_dia));
        try!(write!(f, "(uvia_drill {}) ", self.uvia_drill));
        for net in &self.nets {
            if net.contains("(") || net.contains(")") {
                try!(write!(f, "(add_net \"{}\")", net))
            } else {
                try!(write!(f, "(add_net {})", net))
            }
        }
        write!(f, ")")

    }
}

fn parse_version(e:&Sexp) -> ERes<i64> {
    let l = try!(e.slice_atom("version"));
    try!(l[0].atom()).i()
}

fn parse_other(e:&Sexp) -> Element {
    let e2 = e.clone();
    Element::Other(e2)
}

fn parse_module(e:&Sexp) -> ERes<Element> {
    let e2 = e.clone();
    let m = try!(footprint::parse_module(e2));
    Ok(Element::Module(m))
}

fn parse_net(e:&Sexp) -> ERes<Element> {
    let l = try!(e.slice_atom("net"));
    let num = try!(l[0].i());
    let name = try!(l[1].string());
    Ok(Element::Net(Net { name:name, num:num }))
}

fn parse_net_class(e:&Sexp) -> ERes<Element> {
    fn parse(e:&Sexp, name:&str) -> ERes<f64> {
        let l = try!(e.slice_atom(name));
        l[0].f()
    }
    let l = try!(e.slice_atom("net_class"));
    let name = try!(l[0].string());
    let desc = try!(l[1].string());
    let mut clearance = 0.1524;
    let mut trace_width = 0.2032;
    let mut via_dia = 0.675;
    let mut via_drill = 0.25;
    let mut uvia_dia = 0.508;
    let mut uvia_drill = 0.127;
    let mut nets = vec![];
    for x in &l[2..] {
        let list_name = try!(x.list_name());
        let xn = &list_name[..];
        match xn {
            "add_net" => {
                let l1 = try!(x.slice_atom("add_net"));
                nets.push(try!(l1[0].string()))
            },
            "clearance" => clearance = try!(parse(x, xn)),
            "trace_width" => trace_width = try!(parse(x, xn)),
            "via_dia" => via_dia = try!(parse(x, xn)),
            "via_drill" => via_drill = try!(parse(x, xn)),
            "uvia_dia" => uvia_dia = try!(parse(x, xn)),
            "uvia_drill" => uvia_drill = try!(parse(x, xn)),
            _ => return Err(format!("unknown net_class field {}", list_name))
        }
    }
    let net_class = NetClass {
        name:name, desc:desc, clearance:clearance, via_dia:via_dia,
        via_drill:via_drill, uvia_dia:uvia_dia, uvia_drill:uvia_drill,
        nets:nets, trace_width:trace_width,
    };
    Ok(Element::NetClass(net_class))
}

fn parse(s: &str) -> ERes<Layout> {
    let exp = match rustysexp::parse_str(s) {
        Ok(s) => s,
        Err(x) => return Err(format!("ParseError: {}", x)),
    };
    let l1 = try!(exp.slice_atom("kicad_pcb"));
    let mut layout = Layout::new();

    for ref e in l1 {
        match &try!(e.list_name())[..] {
            "version" => layout.version = try!(parse_version(e)),
            "module" => layout.elements.push(try!(parse_module(e))),
            "net" => layout.elements.push(try!(parse_net(e))),
            "net_class" => layout.elements.push(try!(parse_net_class(e))),
            _ => layout.elements.push(parse_other(e)),
        }
    }
    Ok(layout)
}

pub fn parse_str(s: &str) -> ERes<Layout> {
    parse(s)
}

pub fn parse_file(filename: &PathBuf) -> ERes<Layout> {
    let name = filename.to_str().unwrap();
    let s = try!(match read_file(name) {
        Ok(s) => Ok(s),
        Err(x) => Err(format!("io error: {}", x))
    });
    parse(&s[..])
}
<|endoftext|>


<commit_before>mod scheduler {

  extern crate libc;
  use native;

  // The type of Scheduler Driver implementations.
  trait SchedulerDriver {

    fn launch_tasks(
      offerId: *mut native::ProtobufObj,
      tasks: *mut native::ProtobufObj,
      filters: *mut native::ProtobufObj) -> libc::c_int;

    fn start() -> libc::c_int;

    fn stop(failover: libc::c_int) -> libc::c_int;

    fn abort() -> libc::c_int;

    fn join() -> libc::c_int;

    fn run() -> libc::c_int;

    fn request_resources(requestsData: *mut native::ProtobufObj) -> libc::c_int;

    fn decline_offer(
      offerId: *mut native::ProtobufObj,
      filters: *mut native::ProtobufObj) -> libc::c_int;

    fn kill_task(taskId: *mut native::ProtobufObj) -> libc::c_int;

    fn revive_offers() -> libc::c_int;

    fn send_framework_message(
      executor: *mut native::ProtobufObj,
      slaveId: *mut native::ProtobufObj,
      data: *const libc::c_char) -> libc::c_int;

    fn init(
      callbacks: *mut native::SchedulerCallbacks,
      payload: *mut libc::c_void,
      framework: *mut native::ProtobufObj,
      master: *const libc::c_char) -> native::SchedulerPtrPair;

    fn destroy(scheduler: *mut libc::c_void);
  }

  // Scheduler Driver implemented by calling out to native library.
/*
  impl MesosSchedulerDriver for SchedulerDriver {

    fn launchTasks(
      offerId: *mut ProtobufObj,
      tasks: *mut ProtobufObj,
      filters: *mut ProtobufObj) -> libc::c_int;

    fn start() -> libc::c_int;

    fn stop(failover: libc::c_int) -> libc::c_int;

    fn abort() -> libc::c_int;

    fn join() -> libc::c_int;

    fn run() -> libc::c_int;

    fn requestResources(requestsData: *mut ProtobufObj) -> libc::c_int;

    fn declineOffer(
      offerId: *mut ProtobufObj,
      filters: *mut ProtobufObj) -> libc::c_int;

    fn killTask(taskId: *mut ProtobufObj) -> libc::c_int;

    fn reviveOffers() -> libc::c_int;

    fn sendFrameworkMessage(
      executor: *mut ProtobufObj,
      slaveId: *mut ProtobufObj,
      data: *const libc::c_char) -> libc::c_int;

    fn init(
      callbacks: *mut SchedulerCallbacks,
      payload: *mut libc::c_void,
      framework: *mut ProtobufObj,
      master: *const libc::c_char) -> SchedulerPtrPair;

    fn destroy(scheduler: *mut libc::c_void);

  }
*/

}

<commit_msg>Formatting.<commit_after>mod scheduler {

  extern crate libc;
  use native;

  // The type of Scheduler Driver implementations.
  trait SchedulerDriver {

    fn launch_tasks(
      offerId: *mut native::ProtobufObj,
      tasks: *mut native::ProtobufObj,
      filters: *mut native::ProtobufObj) -> libc::c_int;

    fn start() -> libc::c_int;

    fn stop(failover: libc::c_int) -> libc::c_int;

    fn abort() -> libc::c_int;

    fn join() -> libc::c_int;

    fn run() -> libc::c_int;

    fn request_resources(
      requestsData: *mut native::ProtobufObj) -> libc::c_int;

    fn decline_offer(
      offerId: *mut native::ProtobufObj,
      filters: *mut native::ProtobufObj) -> libc::c_int;

    fn kill_task(taskId: *mut native::ProtobufObj) -> libc::c_int;

    fn revive_offers() -> libc::c_int;

    fn send_framework_message(
      executor: *mut native::ProtobufObj,
      slaveId: *mut native::ProtobufObj,
      data: *const libc::c_char) -> libc::c_int;

    fn init(
      callbacks: *mut native::SchedulerCallbacks,
      payload: *mut libc::c_void,
      framework: *mut native::ProtobufObj,
      master: *const libc::c_char) -> native::SchedulerPtrPair;

    fn destroy(scheduler: *mut libc::c_void);
  }

  // Scheduler Driver implemented by calling out to native library.
/*
  impl MesosSchedulerDriver for SchedulerDriver {
    // TODO(CD)
  }
*/

}

<|endoftext|>


<commit_before>use std::ffi::CString;
use std::marker;
use std::mem;
use std::str;
use std::fmt;
use libc;

use {raw, Error, Time};
use util::Binding;

/// A Signature is used to indicate authorship of various actions throughout the
/// library.
///
/// Signatures contain a name, email, and timestamp. All fields can be specified
/// with `new`, the `now` constructor omits the timestamp, and the `default`
/// constructor reads configuration from the given repository.
pub struct Signature<'a> {
    raw: *mut raw::git_signature,
    _marker: marker::PhantomData<&'a str>,
    owned: bool,
}

impl<'a> Signature<'a> {
    /// Create a new action signature with a timestamp of 'now'.
    ///
    /// See `new` for more information
    pub fn now(name: &str, email: &str) -> Result<Signature<'static>, Error> {
        ::init();
        let mut ret = 0 as *mut raw::git_signature;
        let name = try!(CString::new(name));
        let email = try!(CString::new(email));
        unsafe {
            try_call!(raw::git_signature_now(&mut ret, name, email));
            Ok(Binding::from_raw(ret))
        }
    }

    /// Create a new action signature.
    ///
    /// The `time` specified is in seconds since the epoch, and the `offset` is
    /// the time zone offset in minutes.
    ///
    /// Returns error if either `name` or `email` contain angle brackets.
    pub fn new(name: &str, email: &str, time: &Time)
               -> Result<Signature<'static>, Error> {
        ::init();
        let mut ret = 0 as *mut raw::git_signature;
        let name = try!(CString::new(name));
        let email = try!(CString::new(email));
        unsafe {
            try_call!(raw::git_signature_new(&mut ret, name, email,
                                             time.seconds() as raw::git_time_t,
                                             time.offset_minutes() as libc::c_int));
            Ok(Binding::from_raw(ret))
        }
    }

    /// Gets the name on the signature.
    ///
    /// Returns `None` if the name is not valid utf-8
    pub fn name(&self) -> Option<&str> {
        str::from_utf8(self.name_bytes()).ok()
    }

    /// Gets the name on the signature as a byte slice.
    pub fn name_bytes(&self) -> &[u8] {
        unsafe { ::opt_bytes(self, (*self.raw).name).unwrap() }
    }

    /// Gets the email on the signature.
    ///
    /// Returns `None` if the email is not valid utf-8
    pub fn email(&self) -> Option<&str> {
        str::from_utf8(self.email_bytes()).ok()
    }

    /// Gets the email on the signature as a byte slice.
    pub fn email_bytes(&self) -> &[u8] {
        unsafe { ::opt_bytes(self, (*self.raw).email).unwrap() }
    }

    /// Get the `when` of this signature.
    pub fn when(&self) -> Time {
        unsafe { Binding::from_raw((*self.raw).when) }
    }

    /// Convert a signature of any lifetime into an owned signature with a
    /// static lifetime.
    pub fn to_owned(&self) -> Signature<'static> {
        unsafe {
            let me = mem::transmute::<&Signature<'a>, &Signature<'static>>(self);
            me.clone()
        }
    }
}

impl<'a> Binding for Signature<'a> {
    type Raw = *mut raw::git_signature;
    unsafe fn from_raw(raw: *mut raw::git_signature) -> Signature<'a> {
        Signature {
            raw: raw,
            _marker: marker::PhantomData,
            owned: true,
        }
    }
    fn raw(&self) -> *mut raw::git_signature { self.raw }
}

/// Creates a new signature from the give raw pointer, tied to the lifetime
/// of the given object.
///
/// This function is unsafe as there is no guarantee that `raw` is valid for
/// `'a` nor if it's a valid pointer.
pub unsafe fn from_raw_const<'b, T>(_lt: &'b T,
                                    raw: *const raw::git_signature)
                                    -> Signature<'b> {
    Signature {
        raw: raw as *mut raw::git_signature,
        _marker: marker::PhantomData,
        owned: false,
    }
}

impl Clone for Signature<'static> {
    fn clone(&self) -> Signature<'static> {
        // TODO: can this be defined for 'a and just do a plain old copy if the
        //       lifetime isn't static?
        let mut raw = 0 as *mut raw::git_signature;
        let rc = unsafe { raw::git_signature_dup(&mut raw, &*self.raw) };
        assert_eq!(rc, 0);
        unsafe { Binding::from_raw(raw) }
    }
}

impl<'a> Drop for Signature<'a> {
    fn drop(&mut self) {
        if self.owned {
            unsafe { raw::git_signature_free(self.raw) }
        }
    }
}

impl<'a> fmt::Display for Signature<'a> {

    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} <{}>",
               String::from_utf8_lossy(self.name_bytes()),
               String::from_utf8_lossy(self.email_bytes()))
    }

}

#[cfg(test)]
mod tests {
    use {Signature, Time};

    #[test]
    fn smoke() {
        Signature::new("foo", "bar", &Time::new(89, 0)).unwrap();
        Signature::now("foo", "bar").unwrap();
        assert!(Signature::new("<foo>", "bar", &Time::new(89, 0)).is_err());
        assert!(Signature::now("<foo>", "bar").is_err());

        let s = Signature::now("foo", "bar").unwrap();
        assert_eq!(s.name(), Some("foo"));
        assert_eq!(s.email(), Some("bar"));

        drop(s.clone());
        drop(s.to_owned());
    }
}
<commit_msg>Update outdated `Signature` docs<commit_after>use std::ffi::CString;
use std::marker;
use std::mem;
use std::str;
use std::fmt;
use libc;

use {raw, Error, Time};
use util::Binding;

/// A Signature is used to indicate authorship of various actions throughout the
/// library.
///
/// Signatures contain a name, email, and timestamp. All fields can be specified
/// with `new` while the `now` constructor omits the timestamp. The
/// [`Repository::signature`] method can be used to create a default signature
/// with name and email values read from the configuration.
///
/// [`Repository::signature`]: struct.Repository.html#method.signature
pub struct Signature<'a> {
    raw: *mut raw::git_signature,
    _marker: marker::PhantomData<&'a str>,
    owned: bool,
}

impl<'a> Signature<'a> {
    /// Create a new action signature with a timestamp of 'now'.
    ///
    /// See `new` for more information
    pub fn now(name: &str, email: &str) -> Result<Signature<'static>, Error> {
        ::init();
        let mut ret = 0 as *mut raw::git_signature;
        let name = try!(CString::new(name));
        let email = try!(CString::new(email));
        unsafe {
            try_call!(raw::git_signature_now(&mut ret, name, email));
            Ok(Binding::from_raw(ret))
        }
    }

    /// Create a new action signature.
    ///
    /// The `time` specified is in seconds since the epoch, and the `offset` is
    /// the time zone offset in minutes.
    ///
    /// Returns error if either `name` or `email` contain angle brackets.
    pub fn new(name: &str, email: &str, time: &Time)
               -> Result<Signature<'static>, Error> {
        ::init();
        let mut ret = 0 as *mut raw::git_signature;
        let name = try!(CString::new(name));
        let email = try!(CString::new(email));
        unsafe {
            try_call!(raw::git_signature_new(&mut ret, name, email,
                                             time.seconds() as raw::git_time_t,
                                             time.offset_minutes() as libc::c_int));
            Ok(Binding::from_raw(ret))
        }
    }

    /// Gets the name on the signature.
    ///
    /// Returns `None` if the name is not valid utf-8
    pub fn name(&self) -> Option<&str> {
        str::from_utf8(self.name_bytes()).ok()
    }

    /// Gets the name on the signature as a byte slice.
    pub fn name_bytes(&self) -> &[u8] {
        unsafe { ::opt_bytes(self, (*self.raw).name).unwrap() }
    }

    /// Gets the email on the signature.
    ///
    /// Returns `None` if the email is not valid utf-8
    pub fn email(&self) -> Option<&str> {
        str::from_utf8(self.email_bytes()).ok()
    }

    /// Gets the email on the signature as a byte slice.
    pub fn email_bytes(&self) -> &[u8] {
        unsafe { ::opt_bytes(self, (*self.raw).email).unwrap() }
    }

    /// Get the `when` of this signature.
    pub fn when(&self) -> Time {
        unsafe { Binding::from_raw((*self.raw).when) }
    }

    /// Convert a signature of any lifetime into an owned signature with a
    /// static lifetime.
    pub fn to_owned(&self) -> Signature<'static> {
        unsafe {
            let me = mem::transmute::<&Signature<'a>, &Signature<'static>>(self);
            me.clone()
        }
    }
}

impl<'a> Binding for Signature<'a> {
    type Raw = *mut raw::git_signature;
    unsafe fn from_raw(raw: *mut raw::git_signature) -> Signature<'a> {
        Signature {
            raw: raw,
            _marker: marker::PhantomData,
            owned: true,
        }
    }
    fn raw(&self) -> *mut raw::git_signature { self.raw }
}

/// Creates a new signature from the give raw pointer, tied to the lifetime
/// of the given object.
///
/// This function is unsafe as there is no guarantee that `raw` is valid for
/// `'a` nor if it's a valid pointer.
pub unsafe fn from_raw_const<'b, T>(_lt: &'b T,
                                    raw: *const raw::git_signature)
                                    -> Signature<'b> {
    Signature {
        raw: raw as *mut raw::git_signature,
        _marker: marker::PhantomData,
        owned: false,
    }
}

impl Clone for Signature<'static> {
    fn clone(&self) -> Signature<'static> {
        // TODO: can this be defined for 'a and just do a plain old copy if the
        //       lifetime isn't static?
        let mut raw = 0 as *mut raw::git_signature;
        let rc = unsafe { raw::git_signature_dup(&mut raw, &*self.raw) };
        assert_eq!(rc, 0);
        unsafe { Binding::from_raw(raw) }
    }
}

impl<'a> Drop for Signature<'a> {
    fn drop(&mut self) {
        if self.owned {
            unsafe { raw::git_signature_free(self.raw) }
        }
    }
}

impl<'a> fmt::Display for Signature<'a> {

    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} <{}>",
               String::from_utf8_lossy(self.name_bytes()),
               String::from_utf8_lossy(self.email_bytes()))
    }

}

#[cfg(test)]
mod tests {
    use {Signature, Time};

    #[test]
    fn smoke() {
        Signature::new("foo", "bar", &Time::new(89, 0)).unwrap();
        Signature::now("foo", "bar").unwrap();
        assert!(Signature::new("<foo>", "bar", &Time::new(89, 0)).is_err());
        assert!(Signature::now("<foo>", "bar").is_err());

        let s = Signature::now("foo", "bar").unwrap();
        assert_eq!(s.name(), Some("foo"));
        assert_eq!(s.email(), Some("bar"));

        drop(s.clone());
        drop(s.to_owned());
    }
}
<|endoftext|>


<commit_before>extern crate iron;
extern crate time;

use iron::prelude::*;
use iron::{BeforeMiddleware, AfterMiddleware, typemap};
use time::precise_time_ns;

pub struct RequestLogger;

impl typemap::Key for RequestLogger { type Value = u64; }

impl BeforeMiddleware for RequestLogger {
    fn before(&self, request: &mut Request) -> IronResult<()> {
        request.extensions.insert::<RequestLogger>(precise_time_ns());
        println!(
            "Started {} \"{}\" for {} at {}",
            request.method,
            format!("/{}", request.url.path().join("/")),
            request.remote_addr,
            time::now().strftime("%+").unwrap()
        );

        Ok(())
    }
}

impl AfterMiddleware for RequestLogger {
    fn after(&self, request: &mut Request, response: Response) -> IronResult<Response> {
        let delta = precise_time_ns() - *request.extensions.get::<RequestLogger>().unwrap();
        println!("Request took {} ms", (delta as f64) / 1000000.0);

        Ok(response)
    }
}
<commit_msg>Log error, elapsed time and http status code<commit_after>extern crate iron;
extern crate time;

use iron::prelude::*;
use iron::{BeforeMiddleware, AfterMiddleware, typemap};
use time::precise_time_ns;

pub struct RequestLogger;

impl RequestLogger {
    fn start(&self, request: &mut Request) {
        request.extensions.insert::<RequestLogger>(precise_time_ns());
    }

    fn elapsed_time(&self, request: &mut Request) -> Result<u64, IronError> {
        let start_time = *request.extensions.get::<RequestLogger>().unwrap();
        let delta = (precise_time_ns() - start_time) as i64;

        if delta <= 0 {
            Ok(0)
        } else {
            Ok(((delta as f64) / 1000000.0).round() as u64)
        }
    }
}

impl typemap::Key for RequestLogger { type Value = u64; }

impl BeforeMiddleware for RequestLogger {
    fn before(&self, request: &mut Request) -> IronResult<()> {
        self.start(request);

        println!(
            "Started {} \"{}\" for {} at {}",
            request.method,
            format!("/{}", request.url.path().join("/")),
            request.remote_addr,
            time::now().strftime("%+").unwrap()
        );

        Ok(())
    }
}

impl AfterMiddleware for RequestLogger {
    fn after(&self, request: &mut Request, response: Response) -> IronResult<Response> {
        println!("{} ({} ms)", response.status.unwrap(), self.elapsed_time(request)?);

        Ok(response)
    }

    fn catch(&self, request: &mut Request, err: IronError) -> IronResult<Response> {
        println!(
            "{}: {} ({} ms)",
            err.response.status.unwrap(),
            err.error,
            self.elapsed_time(request)?
        );

        Err(err)
    }
}
<|endoftext|>


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

/// Connect events to sending a message.
///
/// ## Rules
/// 1. Send `$msg` to `$other_component` when the GTK+ `$event` is emitted on `$widget`.
///
/// 2. Optionally send `$msg.0` when the GTK+ `$event` is emitted on `$widget`.
/// Return `$msg.1` in the GTK+ callback.
/// This variant gives more control to the caller since it expects a `$msg` returning `(Option<MSG>,
/// ReturnValue)` where the `ReturnValue` is the value to return in the GTK+ callback.
/// Option<MSG> can be None if no message needs to be emitted.
///
/// 3. Send `$msg` when the GTK+ `$event` is emitted on `$widget`.
///
/// 4. Send `$msg` to `$widget` when the `$message` is received on `$stream`.
#[macro_export]
macro_rules! connect {
    // Connect to a GTK+ widget event, sending a message to another widget.
    ($widget:expr, $event:ident($($args:pat),*), $other_component:expr, $msg:expr) => {
        connect_stream!($widget, $event($($args),*), $other_component.stream(), $msg);
    };

    // Connect to a GTK+ widget event.
    // This variant gives more control to the caller since it expects a `$msg` returning (Option<MSG>,
    // ReturnValue) where the ReturnValue is the value to return in the GTK+ callback.
    // Option<MSG> can be None if no message needs to be emitted.
    ($relm:expr, $widget:expr, $event:ident($($args:pat),*), return $msg:expr) => {{
        connect_stream!(return $relm.stream(), $widget, $event($($args),*), $msg);
    }};

    // Connect to a GTK+ widget event.
    ($relm:expr, $widget:expr, $event:ident($($args:pat),*), $msg:expr) => {{
        let stream = $relm.stream().clone();
        let _ = $widget.$event(move |$($args),*| {
            let msg: Option<_> = $crate::IntoOption::into_option($msg);
            if let Some(msg) = msg {
                stream.emit(msg);
            }
        });
    }};

    // Connect to a message reception.
    // TODO: create another macro rule accepting multiple patterns.
    ($src_component:ident @ $message:pat, $dst_component:expr, $msg:expr) => {
        let stream = $src_component.stream().clone();
        connect_stream!(stream@$message, $dst_component.stream(), $msg);
    };
}

/// Connect events to sending a message.
/// Similar to `connect!` but wants a stream instead of a component.
///
/// ## Rules
/// 1. Send `$msg` to `$other_stream` when the GTK+ `$event` is emitted on `$widget`.
///
/// 2. Send `$msg` to `$widget` when the `$message` is received on `$stream`.
#[macro_export]
macro_rules! connect_stream {
    // Connect to a GTK+ widget event.
    // This variant gives more control to the caller since it expects a `$msg` returning (Option<MSG>,
    // ReturnValue) where the ReturnValue is the value to return in the GTK+ callback.
    // Option<MSG> can be None if no message needs to be emitted.
    (return $stream:expr, $widget:expr, $event:ident($($args:pat),*), $msg:expr) => {{
        let stream = $stream.clone();
        let _ = $widget.$event(move |$($args),*| {
            let (msg, return_value) = $crate::IntoPair::into_pair($msg);
            let msg: Option<_> = $crate::IntoOption::into_option(msg);
            if let Some(msg) = msg {
                stream.emit(msg);
            }
            return_value
        });
    }};

    // Connect to a GTK+ widget event, sending a message to another widget.
    ($widget:expr, $event:ident($($args:pat),*), $other_stream:expr, $msg:expr) => {
        let stream = $other_stream.clone();
        let _ = $widget.$event(move |$($args),*| {
            let msg: Option<_> = $crate::IntoOption::into_option($msg);
            if let Some(msg) = msg {
                stream.emit(msg);
            }
        });
    };

    // Connect to a message reception.
    // TODO: create another macro rule accepting multiple patterns.
    ($src_stream:ident @ $message:pat, $dst_stream:expr, $msg:expr) => {
        let stream = $dst_stream.clone();
        $src_stream.observe(move |msg| {
            #[allow(unreachable_patterns)]
            match msg {
                &$message =>  {
                    let msg: Option<_> = $crate::IntoOption::into_option($msg);
                    if let Some(msg) = msg {
                        stream.emit(msg);
                    }
                },
                _ => (),
            }
        });
    };
}

/// Connect an asynchronous method call to send a message.
/// The variants with `$fail_msg` will send this message when there's an error.
/// Those without this argument will ignore the error.
#[macro_export]
macro_rules! connect_async {
    ($object:expr, $async_method:ident, $relm:expr, $msg:ident) => {
        connect_async!($object, $async_method(), $relm, $msg)
    };
    ($object:expr, $async_method:ident ( $($args:expr),* ), $relm:expr, $msg:ident) => {{
        use ::futures::Sink;
        let (tx, rx) = ::futures::sync::mpsc::unbounded();
        let tx = ::std::sync::Mutex::new(tx);
        $object.$async_method($($args,)* None, move |result| {
            if let Ok(result) = result {
                let mut tx = tx.lock().unwrap();
                if let Ok(::futures::AsyncSink::Ready) = tx.start_send(result) {
                    tx.poll_complete().unwrap();
                } else {
                    eprintln!("Unable to send message to sender");
                }
            }
        });
        $relm.connect_exec_ignore_err(rx, $msg);
    }};
    ($object:expr, $async_method:ident, $relm:expr, $msg:ident, $fail_msg:ident) => {
        connect_async!($object, $async_method(), $relm, $msg, $fail_msg)
    };
    ($object:expr, $async_method:ident ( $($args:expr),* ), $relm:expr, $msg:ident, $fail_msg:ident) => {{
        use ::futures::{Sink, Stream};
        let (tx, rx) = ::futures::sync::mpsc::unbounded();
        let tx = ::std::sync::Mutex::new(tx);
        $object.$async_method($($args,)* None, move |result| {
            let mut tx = tx.lock().unwrap();
            if let Ok(::futures::AsyncSink::Ready) = tx.start_send(result) {
                tx.poll_complete().unwrap();
            } else {
                eprintln!("Unable to send message to sender");
            }
        });

        let event_stream = $relm.stream().clone();
        let fail_event_stream = $relm.stream().clone();
        let future =
            rx.for_each(move |result| {
                match result {
                    Ok(value) => event_stream.emit($msg(value)),
                    Err(error) => fail_event_stream.emit($fail_msg(error)),
                }
                Ok(())
            });
        $relm.exec(future);
    }};
}

/// Connect an asynchronous function call to send a message.
/// The variants with `$fail_msg` will send this message when there's an error.
/// Those without this argument will ignore the error.
#[macro_export]
macro_rules! connect_async_func {
    ($class:ident :: $async_function:ident, $relm:expr, $msg:ident) => {
        connect_async!($async_func(), $relm, $msg)
    };
    ($class:ident :: $async_func:ident ( $($args:expr),* ), $relm:expr, $msg:ident) => {{
        use ::futures::Sink;
        let (tx, rx) = ::futures::sync::mpsc::unbounded();
        let tx = ::std::sync::Mutex::new(tx);
        $class::$async_func($($args,)* None, move |result| {
            if let Ok(result) = result {
                let mut tx = tx.lock().unwrap();
                if let Ok(::futures::AsyncSink::Ready) = tx.start_send(result) {
                    tx.poll_complete().unwrap();
                } else {
                    eprintln!("Unable to send message to sender");
                }
            }
        });
        $relm.connect_exec_ignore_err(rx, $msg);
    }};
    ($class:ident :: $async_func:ident, $relm:expr, $msg:ident, $fail_msg:ident) => {
        connect_async!($async_func(), $relm, $msg, $fail_msg)
    };
    ($class:ident :: $async_func:ident ( $($args:expr),* ), $relm:expr, $msg:ident, $fail_msg:ident) => {{
        use ::futures::{Sink, Stream};
        let (tx, rx) = ::futures::sync::mpsc::unbounded();
        let tx = ::std::sync::Mutex::new(tx);
        $class::$async_func($($args,)* None, move |result| {
            let mut tx = tx.lock().unwrap();
            if let Ok(::futures::AsyncSink::Ready) = tx.start_send(result) {
                tx.poll_complete().unwrap();
            } else {
                eprintln!("Unable to send message to sender");
            }
        });

        let event_stream = $relm.stream().clone();
        let fail_event_stream = $relm.stream().clone();
        let future =
            rx.for_each(move |result| {
                match result {
                    Ok(value) => event_stream.emit($msg(value)),
                    Err(error) => fail_event_stream.emit($fail_msg(error)),
                }
                Ok(())
            });
        $relm.exec(future);
    }};
}

/// Like `connect_async!`, but also return a `Cancellable` to control the asynchronous request.
#[macro_export]
macro_rules! connect_async_full {
    ($object:expr, $async_method:ident, $relm:expr, $msg:ident) => {
        connect_async_full!($object, $async_method(), $relm, $msg)
    };
    ($object:expr, $async_method:ident ( $($args:expr),* ), $relm:expr, $msg:ident) => {{
        let cancellable = ::gio::Cancellable::new();
        use ::futures::Sink;
        let (tx, rx) = ::futures::sync::mpsc::unbounded();
        let tx = ::std::sync::Mutex::new(tx);
        $object.$async_method($($args,)* Some(&cancellable), move |result| {
            if let Ok(result) = result {
                let mut tx = tx.lock().unwrap();
                if let Ok(::futures::AsyncSink::Ready) = tx.start_send(result) {
                    tx.poll_complete().unwrap();
                } else {
                    eprintln!("Unable to send message to sender");
                }
            }
        });
        $relm.connect_exec_ignore_err(rx, $msg);
        cancellable
    }};
    ($object:expr, $async_method:ident, $relm:expr, $msg:ident, $fail_msg:ident) => {
        connect_async_full!($object, $async_method(), $relm, $msg, $fail_msg)
    };
    ($object:expr, $async_method:ident ( $($args:expr),* ), $relm:expr, $msg:ident, $fail_msg:ident) => {{
        let cancellable = ::gio::Cancellable::new();
        use ::futures::{Sink, Stream};
        let (tx, rx) = ::futures::sync::mpsc::unbounded();
        let tx = ::std::sync::Mutex::new(tx);
        $object.$async_method($($args,)* Some(&cancellable), move |result| {
            let mut tx = tx.lock().unwrap();
            if let Ok(::futures::AsyncSink::Ready) = tx.start_send(result) {
                tx.poll_complete().unwrap();
            } else {
                eprintln!("Unable to send message to sender");
            }
        });

        let event_stream = $relm.stream().clone();
        let fail_event_stream = $relm.stream().clone();
        let future =
            rx.for_each(move |result| {
                match result {
                    Ok(value) => event_stream.emit($msg(value)),
                    Err(error) => fail_event_stream.emit($fail_msg(error)),
                }
                Ok(())
            });
        $relm.exec(future);
        cancellable
    }};
}

/// Like `connect_async_func!`, but also return a `Cancellable` to control the asynchronous request.
#[macro_export]
macro_rules! connect_async_func_full {
    ($class:ident :: $async_function:ident, $relm:expr, $msg:ident) => {
        connect_async!($async_func(), $relm, $msg)
    };
    ($class:ident :: $async_func:ident ( $($args:expr),* ), $relm:expr, $msg:ident) => {{
        let cancellable = ::gio::Cancellable::new();
        use ::futures::Sink;
        let (tx, rx) = ::futures::sync::mpsc::unbounded();
        let tx = ::std::sync::Mutex::new(tx);
        $class::$async_func($($args,)* Some(&cancellable), move |result| {
            if let Ok(result) = result {
                let mut tx = tx.lock().unwrap();
                if let Ok(::futures::AsyncSink::Ready) = tx.start_send(result) {
                    tx.poll_complete().unwrap();
                } else {
                    eprintln!("Unable to send message to sender");
                }
            }
        });
        $relm.connect_exec_ignore_err(rx, $msg);
        cancellable
    }};
    ($class:ident :: $async_func:ident, $relm:expr, $msg:ident, $fail_msg:ident) => {
        connect_async!($async_func(), $relm, $msg, $fail_msg)
    };
    ($class:ident :: $async_func:ident ( $($args:expr),* ), $relm:expr, $msg:ident, $fail_msg:ident) => {{
        let cancellable = ::gio::Cancellable::new();
        use ::futures::{Sink, Stream};
        let (tx, rx) = ::futures::sync::mpsc::unbounded();
        let tx = ::std::sync::Mutex::new(tx);
        $class::$async_func($($args,)* Some(&cancellable), move |result| {
            let mut tx = tx.lock().unwrap();
            if let Ok(::futures::AsyncSink::Ready) = tx.start_send(result) {
                tx.poll_complete().unwrap();
            } else {
                eprintln!("Unable to send message to sender");
            }
        });

        let event_stream = $relm.stream().clone();
        let fail_event_stream = $relm.stream().clone();
        let future =
            rx.for_each(move |result| {
                match result {
                    Ok(value) => event_stream.emit($msg(value)),
                    Err(error) => fail_event_stream.emit($fail_msg(error)),
                }
                Ok(())
            });
        $relm.exec(future);
        cancellable
    }};
}
<commit_msg>Revert temporary fix<commit_after>/*
 * Copyright (c) 2017 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

include!("../relm-state/src/macros.rs");
<|endoftext|>


<commit_before>macro_rules! ensure {
    ($expr:expr, $err:expr) => (
        if !($expr) {
            return Err(From::from($err));
        }
    )
}

macro_rules! h5lock_s {
    ($expr:expr) => ({
        use sync::h5sync;
        h5sync(|| { $expr })
    })
}

macro_rules! h5lock {
    ($expr:expr) => (h5lock_s!(unsafe { $expr }))
}

macro_rules! h5call_s {
    ($expr:expr) => ({
        use error::h5check;
        h5lock_s!(h5check($expr))
    })
}

macro_rules! h5call {
    ($expr:expr) => (h5call_s!(unsafe { $expr }))
}

macro_rules! h5try_s {
    ($expr:expr) => (match h5call_s!($expr) {
        Ok(value) => value,
        Err(err)  => {
            return Err(From::from(err))
        },
    })
}

macro_rules! h5try {
    ($expr:expr) => (h5try_s!(unsafe { $expr }))
}

macro_rules! register_hid {
    ($rust_name:ident, $c_name:ident) => {
        #[link(name = "hdf5")]
        extern {
            static $c_name: hid_t;
        }
        lazy_static! {
            pub static ref $rust_name: hid_t = {
                use ffi::h5;
                h5lock!(h5::H5open());
                $c_name
            };
        }
    }
}
<commit_msg>Added fail! macro to macros module<commit_after>macro_rules! fail {
    ($err:expr) => (
        return Err(From::from($err));
    )
}

macro_rules! ensure {
    ($expr:expr, $err:expr) => (
        if !($expr) {
            fail!($err);
        }
    )
}

macro_rules! h5lock_s {
    ($expr:expr) => ({
        use sync::h5sync;
        h5sync(|| { $expr })
    })
}

macro_rules! h5lock {
    ($expr:expr) => (h5lock_s!(unsafe { $expr }))
}

macro_rules! h5call_s {
    ($expr:expr) => ({
        use error::h5check;
        h5lock_s!(h5check($expr))
    })
}

macro_rules! h5call {
    ($expr:expr) => (h5call_s!(unsafe { $expr }))
}

macro_rules! h5try_s {
    ($expr:expr) => (match h5call_s!($expr) {
        Ok(value) => value,
        Err(err)  => {
            return Err(From::from(err))
        },
    })
}

macro_rules! h5try {
    ($expr:expr) => (h5try_s!(unsafe { $expr }))
}

macro_rules! register_hid {
    ($rust_name:ident, $c_name:ident) => {
        #[link(name = "hdf5")]
        extern {
            static $c_name: hid_t;
        }
        lazy_static! {
            pub static ref $rust_name: hid_t = {
                use ffi::h5;
                h5lock!(h5::H5open());
                $c_name
            };
        }
    }
}
<|endoftext|>


<commit_before>macro_rules! compile_prim(
    ($ty:ty, $type_name:ident, $make_constant:ident) => (
impl Compile for $ty {
    #[inline(always)]
    fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a> {
        unsafe {
            NativeRef::from_ptr($make_constant(func.as_ptr(), $type_name, *self) )
        }
    }
    #[inline(always)]
    fn jit_type(_:Option<$ty>) -> Type {
        unsafe {
            NativeRef::from_ptr($type_name)
        }
    }
});
    ($ty:ty, $type_name:ident, $make_constant:ident, $cast:ty) => (
impl Compile for $ty {
    #[inline(always)]
    fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a> {
        unsafe {
            NativeRef::from_ptr($make_constant(func.as_ptr(), $type_name, *self as $cast) )
        }
    }
    #[inline(always)]
    fn jit_type(_:Option<$ty>) -> Type {
        unsafe {
            NativeRef::from_ptr($type_name)
        }
    }
});
);

macro_rules! compile_func(
    (fn($($arg:ident),*) -> $ret:ty, $sig:ty, $ext_sig:ty) => (
        impl<$($arg:Compile,)* R:Compile> Compile for $sig {
            #[inline(always)]
            fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a> {
                let ptr = (self as *const $sig).to_uint().compile(func);
                func.insn_convert(&ptr, get::<$sig>(), false)
            }
            #[inline(always)]
            fn jit_type(_:Option<$sig>) -> Type {
                Type::create_signature(CDECL, get::<R>(), [$(get::<$arg>()),*][mut])
            }
        }
        impl<$($arg:Compile,)* R:Compile> Compile for $ext_sig {
            #[inline(always)]
            fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a> {
                let ptr = (self as *const $ext_sig).to_uint().compile(func);
                func.insn_convert(&ptr, get::<$ext_sig>(), false)
            }
            #[inline(always)]
            fn jit_type(_:Option<$ext_sig>) -> Type {
                get::<$sig>()
            }
        }
    )
);
macro_rules! compile_tuple(
    ($($ty:ident),+ => $($name:ident),+) => (
        impl<$($ty),+> Compile for ($($ty),+) where $($ty:Compile),+ {
            #[inline(always)]
            fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a> {
                let ($(ref $name),+) = *self;
                let ty = get::<($($ty),+)>();
                let tuple = Value::new(func, ty.clone());
                let ($(ref $name),+) = ($(func.insn_of($name)),+);
                let mut fields = ty.fields();
                $(func.insn_store_relative(&tuple, fields.next().unwrap().get_offset() as int, $name);)+
                tuple
            }
            #[inline(always)]
            fn jit_type(_:Option<($($ty),+)>) -> Type {
                Type::create_struct([$(get::<$ty>()),+][mut])
            }
        }
    )
);

macro_rules! compile_prims(
    ($(($ty:ty, $cast: ty) => ($type_name:ident, $make_constant:ident)),+) => (
        $(compile_prim!($ty, $type_name, $make_constant, $cast);)+
    );
);

macro_rules! native_ref(
    ($name:ident, $field:ident, $pointer_ty:ty) => (
        impl NativeRef for $name {
            #[inline(always)]
            /// Convert to a native pointer
            unsafe fn as_ptr(&self) -> $pointer_ty {
                self.$field
            }
            #[inline(always)]
            /// Convert from a native pointer
            unsafe fn from_ptr(ptr:$pointer_ty) -> $name {
                $name {
                    $field: ptr
                }
            }
        }
    );
    ($name:ident, $field:ident, $pointer_ty:ty, $lifetime:ident) => (
        impl<'a> NativeRef for $name<'a> {
            #[inline]
            /// Convert to a native pointer
            unsafe fn as_ptr(&self) -> $pointer_ty {
                self.$field
            }
            #[inline]
            /// Convert from a native pointer
            unsafe fn from_ptr(ptr:$pointer_ty) -> $name<'a> {
                $name {
                    $field: ptr,
                    marker: $lifetime::<'a>
                }
            }
        }
    )
);
#[macro_export]
macro_rules! jit(
    (struct {
        $($name:expr: $ty:ty),*
    }) => ({
        let structure = Type::create_struct([
            $(get::<$ty>()),*
        ].as_mut_slice());
        structure.set_names(&[$($name),*]);
        structure
    });
    (union {
        $($name:expr: $ty:ty),+
    }) => ({
        let structure = Type::create_union([
            $(get::<$ty>()),+
        ].as_mut_slice());
        structure.set_names(&[$($name),+]);
        structure
    });
    ($func:ident, return) => (
        $func.insn_default_return()
    );
    ($func:ident, return $($t:tt)+) => (
        $func.insn_return(jit!($($t)+))
    );
    ($func:ident, $var:ident += $num:expr) => (
        $func.insn_store($var, &$func.insn_add($var, $num));
    );
    ($func:ident, $var:ident -= $num:expr) => (
        $func.insn_store($var, &$func.insn_sub($var, $num));
    );
    ($func:ident, $var:ident *= $num:expr) => (
        $func.insn_store($var, &$func.insn_mul($var, $num));
    );
    ($func:ident, $var:ident /= $num:expr) => (
        $func.insn_store($var, &$func.insn_div($var, $num));
    );
    ($func:ident, $a:expr + $b:expr) => (
        $func.insn_add($a, $b)
    );
    ($func:ident, $a:expr - $b:expr) => (
        $func.insn_sub($a, $b)
    );
    ($func:ident, $a:expr * $b:expr) => (
        $func.insn_mul($a, $b)
    );
    ($func:ident, $a:expr / $b:expr) => (
        $func.insn_div($a, $b)
    );
    ($func:ident, $a:expr % $b:expr) => (
        $func.insn_rem($a, $b)
    );
    ($func:ident, $var:ident = $val:expr) => (
        $func.insn_store($var, $val);
    );
    ($func:ident, *$var:ident) => (
        $func.insn_load($var)
    );
    ($func:ident, call($call:expr,
        $($arg:expr),+
    )) => (
        $func.insn_call(None::<String>, $call, None, [$($arg),+].as_mut_slice())
    );
    ($func:ident, jump_table($value:expr,
        $($label:ident),+
    )) => (
    let ($($label),+) = {
        $(let $label:Label = Label::new($func);)+
        $func.insn_jump_table($value, [
            $($label),+
        ].as_mut_slice());
        ($($label),+)
    });
    ($func:expr, $value:expr) => (
        $func.insn_of(&$value)
    );
);
#[macro_export]
macro_rules! jit_func(
    ($ctx:expr, $func:ident, fn $name:ident($($arg:ident:$ty:ty),*) -> $ret:ty $value:expr) => ({
        use std::default::Default;
        let sig = Type::create_signature(Default::default(), get::<$ret>(), [$(get::<$ty>()),*].as_mut_slice());
        $ctx.build_func(sig, |$func| {
            let mut i = 0u;
            $(let ref $arg = $func[{i += 1; i - 1}];)+
            $value
        })
    });
    ($ctx:expr, $func:ident, fn $name:ident($($arg:ident:$arg_ty:ty),*) -> $ret:ty $value:expr, |$comp_func:ident| $comp:expr) => ({
        use std::default::Default;
        let sig = Type::create_signature(Default::default(), get::<$ret>(), [$(get::<$arg_ty>()),*].as_mut_slice());
        $ctx.build_func(sig, |$func| {
            let mut i = 0u;
            $(let ref $arg = $func[{i += 1; i - 1}];)*
            $value
        }).with::<($($arg_ty),*), $ret, _>(|$comp_func|
            $comp)
    });
);<commit_msg>Suppress warning in macr<commit_after>macro_rules! compile_prim(
    ($ty:ty, $type_name:ident, $make_constant:ident) => (
impl Compile for $ty {
    #[inline(always)]
    fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a> {
        unsafe {
            NativeRef::from_ptr($make_constant(func.as_ptr(), $type_name, *self) )
        }
    }
    #[inline(always)]
    fn jit_type(_:Option<$ty>) -> Type {
        unsafe {
            NativeRef::from_ptr($type_name)
        }
    }
});
    ($ty:ty, $type_name:ident, $make_constant:ident, $cast:ty) => (
impl Compile for $ty {
    #[inline(always)]
    fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a> {
        unsafe {
            NativeRef::from_ptr($make_constant(func.as_ptr(), $type_name, *self as $cast) )
        }
    }
    #[inline(always)]
    fn jit_type(_:Option<$ty>) -> Type {
        unsafe {
            NativeRef::from_ptr($type_name)
        }
    }
});
);

macro_rules! compile_func(
    (fn($($arg:ident),*) -> $ret:ty, $sig:ty, $ext_sig:ty) => (
        impl<$($arg:Compile,)* R:Compile> Compile for $sig {
            #[inline(always)]
            fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a> {
                let ptr = (self as *const $sig).to_uint().compile(func);
                func.insn_convert(&ptr, get::<$sig>(), false)
            }
            #[inline(always)]
            fn jit_type(_:Option<$sig>) -> Type {
                Type::create_signature(CDECL, get::<R>(), [$(get::<$arg>()),*][mut])
            }
        }
        impl<$($arg:Compile,)* R:Compile> Compile for $ext_sig {
            #[inline(always)]
            fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a> {
                let ptr = (self as *const $ext_sig).to_uint().compile(func);
                func.insn_convert(&ptr, get::<$ext_sig>(), false)
            }
            #[inline(always)]
            fn jit_type(_:Option<$ext_sig>) -> Type {
                get::<$sig>()
            }
        }
    )
);
macro_rules! compile_tuple(
    ($($ty:ident),+ => $($name:ident),+) => (
        impl<$($ty),+> Compile for ($($ty),+) where $($ty:Compile),+ {
            #[inline(always)]
            fn compile<'a>(&self, func:&UncompiledFunction<'a>) -> Value<'a> {
                let ($(ref $name),+) = *self;
                let ty = get::<($($ty),+)>();
                let tuple = Value::new(func, ty.clone());
                let ($(ref $name),+) = ($(func.insn_of($name)),+);
                let mut fields = ty.fields();
                $(func.insn_store_relative(&tuple, fields.next().unwrap().get_offset() as int, $name);)+
                tuple
            }
            #[inline(always)]
            fn jit_type(_:Option<($($ty),+)>) -> Type {
                Type::create_struct([$(get::<$ty>()),+][mut])
            }
        }
    )
);

macro_rules! compile_prims(
    ($(($ty:ty, $cast: ty) => ($type_name:ident, $make_constant:ident)),+) => (
        $(compile_prim!($ty, $type_name, $make_constant, $cast);)+
    );
);

macro_rules! native_ref(
    ($name:ident, $field:ident, $pointer_ty:ty) => (
        impl NativeRef for $name {
            #[inline(always)]
            /// Convert to a native pointer
            unsafe fn as_ptr(&self) -> $pointer_ty {
                self.$field
            }
            #[inline(always)]
            /// Convert from a native pointer
            unsafe fn from_ptr(ptr:$pointer_ty) -> $name {
                $name {
                    $field: ptr
                }
            }
        }
    );
    ($name:ident, $field:ident, $pointer_ty:ty, $lifetime:ident) => (
        impl<'a> NativeRef for $name<'a> {
            #[inline]
            /// Convert to a native pointer
            unsafe fn as_ptr(&self) -> $pointer_ty {
                self.$field
            }
            #[inline]
            /// Convert from a native pointer
            unsafe fn from_ptr(ptr:$pointer_ty) -> $name<'a> {
                $name {
                    $field: ptr,
                    marker: $lifetime::<'a>
                }
            }
        }
    )
);
#[macro_export]
macro_rules! jit(
    (struct {
        $($name:expr: $ty:ty),*
    }) => ({
        let structure = Type::create_struct([
            $(get::<$ty>()),*
        ].as_mut_slice());
        structure.set_names(&[$($name),*]);
        structure
    });
    (union {
        $($name:expr: $ty:ty),+
    }) => ({
        let structure = Type::create_union([
            $(get::<$ty>()),+
        ].as_mut_slice());
        structure.set_names(&[$($name),+]);
        structure
    });
    ($func:ident, return) => (
        $func.insn_default_return()
    );
    ($func:ident, return $($t:tt)+) => (
        $func.insn_return(jit!($($t)+))
    );
    ($func:ident, $var:ident += $num:expr) => (
        $func.insn_store($var, &$func.insn_add($var, $num));
    );
    ($func:ident, $var:ident -= $num:expr) => (
        $func.insn_store($var, &$func.insn_sub($var, $num));
    );
    ($func:ident, $var:ident *= $num:expr) => (
        $func.insn_store($var, &$func.insn_mul($var, $num));
    );
    ($func:ident, $var:ident /= $num:expr) => (
        $func.insn_store($var, &$func.insn_div($var, $num));
    );
    ($func:ident, $a:expr + $b:expr) => (
        $func.insn_add($a, $b)
    );
    ($func:ident, $a:expr - $b:expr) => (
        $func.insn_sub($a, $b)
    );
    ($func:ident, $a:expr * $b:expr) => (
        $func.insn_mul($a, $b)
    );
    ($func:ident, $a:expr / $b:expr) => (
        $func.insn_div($a, $b)
    );
    ($func:ident, $a:expr % $b:expr) => (
        $func.insn_rem($a, $b)
    );
    ($func:ident, $var:ident = $val:expr) => (
        $func.insn_store($var, $val);
    );
    ($func:ident, *$var:ident) => (
        $func.insn_load($var)
    );
    ($func:ident, call($call:expr,
        $($arg:expr),+
    )) => (
        $func.insn_call(None::<String>, $call, None, [$($arg),+].as_mut_slice())
    );
    ($func:ident, jump_table($value:expr,
        $($label:ident),+
    )) => (
    let ($($label),+) = {
        $(let $label:Label = Label::new($func);)+
        $func.insn_jump_table($value, [
            $($label),+
        ].as_mut_slice());
        ($($label),+)
    });
    ($func:expr, $value:expr) => (
        $func.insn_of(&$value)
    );
);
#[macro_export]
macro_rules! jit_func(
    ($ctx:expr, $func:ident, fn $name:ident($($arg:ident:$ty:ty),*) -> $ret:ty $value:expr) => ({
        #[allow(unused_mut)]
        use std::default::Default;
        let sig = Type::create_signature(Default::default(), get::<$ret>(), [$(get::<$ty>()),*].as_mut_slice());
        $ctx.build_func(sig, |$func| {
            let mut i = 0u;
            $(let ref $arg = $func[{i += 1; i - 1}];)+
            $value
        })
    });
    ($ctx:expr, $func:ident, fn $name:ident($($arg:ident:$arg_ty:ty),*) -> $ret:ty $value:expr, |$comp_func:ident| $comp:expr) => ({
        #[allow(unused_mut)]
        use std::default::Default;
        let sig = Type::create_signature(Default::default(), get::<$ret>(), [$(get::<$arg_ty>()),*].as_mut_slice());
        $ctx.build_func(sig, |$func| {
            let mut i = 0u;
            $(let ref $arg = $func[{i += 1; i - 1}];)*
            $value
        }).with::<($($arg_ty),*), $ret, _>(|$comp_func|
            $comp)
    });
);<|endoftext|>


<commit_before>macro_rules! define_uuid_macro {
    {$(#[$doc:meta])*} => {
        $(#[$doc])*
        #[cfg(feature = "macro-diagnostics")]
        #[macro_export]
        macro_rules! uuid {
            ($uuid:literal) => {{
                $crate::Uuid::from_bytes($crate::uuid_macro_internal::parse_lit!($uuid))
            }};
        }

        $(#[$doc])*
        #[cfg(not(feature = "macro-diagnostics"))]
        #[macro_export]
        macro_rules! uuid {
            ($uuid:literal) => {{
                const OUTPUT: $crate::Uuid = match $crate::Uuid::try_parse($uuid) {
                    Ok(u) => u,
                    Err(_) => {
                        // here triggers const_err
                        // const_panic requires 1.57
                        #[allow(unconditional_panic)]
                        let _ = ["invalid uuid representation"][1];

                        loop {} // -> never type
                    }
                };
                OUTPUT
            }};
        }
    }
}

define_uuid_macro! {
/// Parse [`Uuid`][uuid::Uuid]s from string literals at compile time.
///
/// ## Usage
///
/// This macro transforms the string literal representation of a
/// [`Uuid`][uuid::Uuid] into the bytes representation, raising a compilation
/// error if it cannot properly be parsed.
///
/// ## Examples
///
/// Setting a global constant:
///
/// ```
/// # use uuid::{uuid, Uuid};
/// pub const SCHEMA_ATTR_CLASS: Uuid = uuid!("00000000-0000-0000-0000-ffff00000000");
/// pub const SCHEMA_ATTR_UUID: Uuid = uuid!("00000000-0000-0000-0000-ffff00000001");
/// pub const SCHEMA_ATTR_NAME: Uuid = uuid!("00000000-0000-0000-0000-ffff00000002");
/// ```
///
/// Defining a local variable:
///
/// ```
/// # use uuid::{uuid, Uuid};
/// let uuid: Uuid = uuid!("urn:uuid:F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4");
/// ```
///
/// ## Compilation Failures
///
/// Invalid UUIDs are rejected:
///
/// ```compile_fail
/// # use uuid::{uuid, Uuid};
/// let uuid: Uuid = uuid!("F9168C5E-ZEB2-4FAA-B6BF-329BF39FA1E4");
/// ```
///
/// Enable the feature `macro-diagnostics` to see the error messages below.
///
/// Provides the following compilation error:
///
/// ```txt
/// error: invalid character: expected an optional prefix of `urn:uuid:` followed by 0123456789abcdefABCDEF-, found Z at 9
///     |
///     |     let id: Uuid = uuid!("F9168C5E-ZEB2-4FAA-B6BF-329BF39FA1E4");
///     |                                    ^
/// ```
///
/// Tokens that aren't string literals are also rejected:
///
/// ```compile_fail
/// # use uuid::{uuid, Uuid};
/// let uuid_str: &str = "550e8400e29b41d4a716446655440000";
/// let uuid: Uuid = uuid!(uuid_str);
/// ```
///
/// Provides the following compilation error:
///
/// ```txt
/// error: expected string literal
///   |
///   |     let uuid: Uuid = uuid!(uuid_str);
///   |                            ^^^^^^^^
/// ```
///
/// [uuid::Uuid]: https://docs.rs/uuid/*/uuid/struct.Uuid.html
}
<commit_msg>simplify macro examples a bit<commit_after>macro_rules! define_uuid_macro {
    {$(#[$doc:meta])*} => {
        $(#[$doc])*
        #[cfg(feature = "macro-diagnostics")]
        #[macro_export]
        macro_rules! uuid {
            ($uuid:literal) => {{
                $crate::Uuid::from_bytes($crate::uuid_macro_internal::parse_lit!($uuid))
            }};
        }

        $(#[$doc])*
        #[cfg(not(feature = "macro-diagnostics"))]
        #[macro_export]
        macro_rules! uuid {
            ($uuid:literal) => {{
                const OUTPUT: $crate::Uuid = match $crate::Uuid::try_parse($uuid) {
                    Ok(u) => u,
                    Err(_) => {
                        // here triggers const_err
                        // const_panic requires 1.57
                        #[allow(unconditional_panic)]
                        let _ = ["invalid uuid representation"][1];

                        loop {} // -> never type
                    }
                };
                OUTPUT
            }};
        }
    }
}

define_uuid_macro! {
/// Parse [`Uuid`][uuid::Uuid]s from string literals at compile time.
///
/// ## Usage
///
/// This macro transforms the string literal representation of a
/// [`Uuid`][uuid::Uuid] into the bytes representation, raising a compilation
/// error if it cannot properly be parsed.
///
/// ## Examples
///
/// Setting a global constant:
///
/// ```
/// # use uuid::{uuid, Uuid};
/// pub const SCHEMA_ATTR_CLASS: Uuid = uuid!("00000000-0000-0000-0000-ffff00000000");
/// pub const SCHEMA_ATTR_UUID: Uuid = uuid!("00000000-0000-0000-0000-ffff00000001");
/// pub const SCHEMA_ATTR_NAME: Uuid = uuid!("00000000-0000-0000-0000-ffff00000002");
/// ```
///
/// Defining a local variable:
///
/// ```
/// # use uuid::uuid;
/// let uuid = uuid!("urn:uuid:F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4");
/// ```
///
/// ## Compilation Failures
///
/// Invalid UUIDs are rejected:
///
/// ```compile_fail
/// # use uuid::uuid;
/// let uuid = uuid!("F9168C5E-ZEB2-4FAA-B6BF-329BF39FA1E4");
/// ```
///
/// Enable the feature `macro-diagnostics` to see the error messages below.
///
/// Provides the following compilation error:
///
/// ```txt
/// error: invalid character: expected an optional prefix of `urn:uuid:` followed by 0123456789abcdefABCDEF-, found Z at 9
///     |
///     |     let id = uuid!("F9168C5E-ZEB2-4FAA-B6BF-329BF39FA1E4");
///     |                              ^
/// ```
///
/// Tokens that aren't string literals are also rejected:
///
/// ```compile_fail
/// # use uuid::uuid;
/// let uuid_str: &str = "550e8400e29b41d4a716446655440000";
/// let uuid = uuid!(uuid_str);
/// ```
///
/// Provides the following compilation error:
///
/// ```txt
/// error: expected string literal
///   |
///   |     let uuid = uuid!(uuid_str);
///   |                      ^^^^^^^^
/// ```
///
/// [uuid::Uuid]: https://docs.rs/uuid/*/uuid/struct.Uuid.html
}
<|endoftext|>


<commit_before>#![warn(clippy::all, rust_2018_idioms)]

#[macro_use]
extern crate claim;
#[macro_use]
extern crate diesel;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate serde;
#[macro_use]
extern crate serde_json;
#[macro_use]
extern crate tracing;

use crate::util::{RequestHelper, TestApp};
use cargo_registry::{
    models::{Crate, CrateOwner, Dependency, NewCategory, NewTeam, NewUser, Team, User, Version},
    schema::crate_owners,
    util::AppResponse,
    views::{
        EncodableCategory, EncodableCategoryWithSubcategories, EncodableCrate, EncodableKeyword,
        EncodableOwner, EncodableVersion, GoodCrate,
    },
    App, Config, Env, Replica, Uploader,
};
use std::{
    borrow::Cow,
    sync::{
        atomic::{AtomicUsize, Ordering},
        Arc,
    },
};

use conduit::Body;
use diesel::prelude::*;
use reqwest::{blocking::Client, Proxy};

mod account_lock;
mod authentication;
mod badge;
mod builders;
mod categories;
mod category;
mod dump_db;
mod git;
mod keyword;
mod krate;
mod owners;
mod read_only_mode;
mod record;
mod schema_details;
mod server;
mod team;
mod token;
mod user;
mod util;
mod version;

#[derive(Deserialize)]
pub struct CrateList {
    crates: Vec<EncodableCrate>,
    meta: CrateMeta,
}
#[derive(Deserialize)]
struct CrateMeta {
    total: i32,
    next_page: Option<String>,
    prev_page: Option<String>,
}
#[derive(Deserialize)]
pub struct CrateResponse {
    #[serde(rename = "crate")]
    krate: EncodableCrate,
    versions: Vec<EncodableVersion>,
    keywords: Vec<EncodableKeyword>,
}
#[derive(Deserialize)]
pub struct VersionResponse {
    version: EncodableVersion,
}
#[derive(Deserialize)]
pub struct OwnerTeamsResponse {
    teams: Vec<EncodableOwner>,
}
#[derive(Deserialize)]
pub struct OwnersResponse {
    users: Vec<EncodableOwner>,
}
#[derive(Deserialize)]
pub struct CategoryResponse {
    category: EncodableCategoryWithSubcategories,
}
#[derive(Deserialize)]
pub struct CategoryListResponse {
    categories: Vec<EncodableCategory>,
    meta: CategoryMeta,
}
#[derive(Deserialize)]
pub struct CategoryMeta {
    total: i32,
}
#[derive(Deserialize)]
pub struct OkBool {
    ok: bool,
}

fn app() -> (Arc<App>, conduit_middleware::MiddlewareBuilder) {
    build_app(simple_config(), None)
}

fn simple_config() -> Config {
    let uploader = Uploader::S3 {
        bucket: s3::Bucket::new(
            String::from("alexcrichton-test"),
            None,
            dotenv::var("S3_ACCESS_KEY").unwrap_or_default(),
            dotenv::var("S3_SECRET_KEY").unwrap_or_default(),
            // When testing we route all API traffic over HTTP so we can
            // sniff/record it, but everywhere else we use https
            "http",
        ),
        cdn: None,
    };

    Config {
        uploader,
        session_key: "test this has to be over 32 bytes long".to_string(),
        gh_client_id: dotenv::var("GH_CLIENT_ID").unwrap_or_default(),
        gh_client_secret: dotenv::var("GH_CLIENT_SECRET").unwrap_or_default(),
        gh_base_url: "http://api.github.com".to_string(),
        db_url: env("TEST_DATABASE_URL"),
        replica_db_url: None,
        env: Env::Test,
        max_upload_size: 3000,
        max_unpack_size: 2000,
        mirror: Replica::Primary,
        // When testing we route all API traffic over HTTP so we can
        // sniff/record it, but everywhere else we use https
        api_protocol: String::from("http"),
        publish_rate_limit: Default::default(),
        blocked_traffic: Default::default(),
        domain_name: "crates.io".into(),
        allowed_origins: Vec::new(),
    }
}

fn build_app(
    config: Config,
    proxy: Option<String>,
) -> (Arc<App>, conduit_middleware::MiddlewareBuilder) {
    let client = if let Some(proxy) = proxy {
        let mut builder = Client::builder();
        builder = builder
            .proxy(Proxy::all(&proxy).expect("Unable to configure proxy with the provided URL"));
        Some(builder.build().expect("TLS backend cannot be initialized"))
    } else {
        None
    };

    let app = App::new(config, client);
    assert_ok!(assert_ok!(app.primary_database.get()).begin_test_transaction());
    let app = Arc::new(app);
    let handler = cargo_registry::build_handler(Arc::clone(&app));
    (app, handler)
}

// Return the environment variable only if it has been defined
#[track_caller]
fn env(var: &str) -> String {
    match dotenv::var(var) {
        Ok(ref s) if s.is_empty() => panic!("environment variable `{}` must not be empty", var),
        Ok(s) => s,
        _ => panic!(
            "environment variable `{}` must be defined and valid unicode",
            var
        ),
    }
}

fn json<T>(r: &mut AppResponse) -> T
where
    for<'de> T: serde::Deserialize<'de>,
{
    use conduit::Body::*;

    let mut body = Body::empty();
    std::mem::swap(r.body_mut(), &mut body);
    let body: std::borrow::Cow<'static, [u8]> = match body {
        Static(slice) => slice.into(),
        Owned(vec) => vec.into(),
        File(_) => unimplemented!(),
    };

    let s = std::str::from_utf8(&body).unwrap();
    match serde_json::from_str(s) {
        Ok(t) => t,
        Err(e) => panic!("failed to decode: {:?}\n{}", e, s),
    }
}

static NEXT_GH_ID: AtomicUsize = AtomicUsize::new(0);

fn new_user(login: &str) -> NewUser<'_> {
    NewUser {
        gh_id: NEXT_GH_ID.fetch_add(1, Ordering::SeqCst) as i32,
        gh_login: login,
        name: None,
        gh_avatar: None,
        gh_access_token: Cow::Borrowed("some random token"),
    }
}

fn new_team(login: &str) -> NewTeam<'_> {
    NewTeam {
        org_id: NEXT_GH_ID.fetch_add(1, Ordering::SeqCst) as i32,
        github_id: NEXT_GH_ID.fetch_add(1, Ordering::SeqCst) as i32,
        login,
        name: None,
        avatar: None,
    }
}

fn add_team_to_crate(t: &Team, krate: &Crate, u: &User, conn: &PgConnection) -> QueryResult<()> {
    let crate_owner = CrateOwner {
        crate_id: krate.id,
        owner_id: t.id,
        created_by: u.id,
        owner_kind: 1, // Team owner kind is 1 according to owner.rs
        email_notifications: true,
    };

    diesel::insert_into(crate_owners::table)
        .values(&crate_owner)
        .on_conflict(crate_owners::table.primary_key())
        .do_update()
        .set(crate_owners::deleted.eq(false))
        .execute(conn)?;

    Ok(())
}

fn new_dependency(conn: &PgConnection, version: &Version, krate: &Crate) -> Dependency {
    use cargo_registry::schema::dependencies::dsl::*;
    use diesel::insert_into;

    insert_into(dependencies)
        .values((
            version_id.eq(version.id),
            crate_id.eq(krate.id),
            req.eq(">= 0"),
            optional.eq(false),
            default_features.eq(false),
            features.eq(Vec::<String>::new()),
        ))
        .get_result(conn)
        .unwrap()
}

fn new_category<'a>(category: &'a str, slug: &'a str, description: &'a str) -> NewCategory<'a> {
    NewCategory {
        category,
        slug,
        description,
    }
}

#[test]
fn multiple_live_references_to_the_same_connection_can_be_checked_out() {
    use std::ptr;

    let (app, _) = app();
    let conn1 = app.primary_database.get().unwrap();
    let conn2 = app.primary_database.get().unwrap();
    let conn1_ref: &PgConnection = &conn1;
    let conn2_ref: &PgConnection = &conn2;

    assert!(ptr::eq(conn1_ref, conn2_ref));
}
<commit_msg>Update an additional test to helper utils<commit_after>#![warn(clippy::all, rust_2018_idioms)]

#[macro_use]
extern crate claim;
#[macro_use]
extern crate diesel;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate serde;
#[macro_use]
extern crate serde_json;
#[macro_use]
extern crate tracing;

use crate::util::{RequestHelper, TestApp};
use cargo_registry::{
    models::{Crate, CrateOwner, Dependency, NewCategory, NewTeam, NewUser, Team, User, Version},
    schema::crate_owners,
    util::AppResponse,
    views::{
        EncodableCategory, EncodableCategoryWithSubcategories, EncodableCrate, EncodableKeyword,
        EncodableOwner, EncodableVersion, GoodCrate,
    },
    App, Config, Env, Replica, Uploader,
};
use std::{
    borrow::Cow,
    sync::{
        atomic::{AtomicUsize, Ordering},
        Arc,
    },
};

use conduit::Body;
use diesel::prelude::*;
use reqwest::{blocking::Client, Proxy};

mod account_lock;
mod authentication;
mod badge;
mod builders;
mod categories;
mod category;
mod dump_db;
mod git;
mod keyword;
mod krate;
mod owners;
mod read_only_mode;
mod record;
mod schema_details;
mod server;
mod team;
mod token;
mod user;
mod util;
mod version;

#[derive(Deserialize)]
pub struct CrateList {
    crates: Vec<EncodableCrate>,
    meta: CrateMeta,
}
#[derive(Deserialize)]
struct CrateMeta {
    total: i32,
    next_page: Option<String>,
    prev_page: Option<String>,
}
#[derive(Deserialize)]
pub struct CrateResponse {
    #[serde(rename = "crate")]
    krate: EncodableCrate,
    versions: Vec<EncodableVersion>,
    keywords: Vec<EncodableKeyword>,
}
#[derive(Deserialize)]
pub struct VersionResponse {
    version: EncodableVersion,
}
#[derive(Deserialize)]
pub struct OwnerTeamsResponse {
    teams: Vec<EncodableOwner>,
}
#[derive(Deserialize)]
pub struct OwnersResponse {
    users: Vec<EncodableOwner>,
}
#[derive(Deserialize)]
pub struct CategoryResponse {
    category: EncodableCategoryWithSubcategories,
}
#[derive(Deserialize)]
pub struct CategoryListResponse {
    categories: Vec<EncodableCategory>,
    meta: CategoryMeta,
}
#[derive(Deserialize)]
pub struct CategoryMeta {
    total: i32,
}
#[derive(Deserialize)]
pub struct OkBool {
    ok: bool,
}

fn simple_config() -> Config {
    let uploader = Uploader::S3 {
        bucket: s3::Bucket::new(
            String::from("alexcrichton-test"),
            None,
            dotenv::var("S3_ACCESS_KEY").unwrap_or_default(),
            dotenv::var("S3_SECRET_KEY").unwrap_or_default(),
            // When testing we route all API traffic over HTTP so we can
            // sniff/record it, but everywhere else we use https
            "http",
        ),
        cdn: None,
    };

    Config {
        uploader,
        session_key: "test this has to be over 32 bytes long".to_string(),
        gh_client_id: dotenv::var("GH_CLIENT_ID").unwrap_or_default(),
        gh_client_secret: dotenv::var("GH_CLIENT_SECRET").unwrap_or_default(),
        gh_base_url: "http://api.github.com".to_string(),
        db_url: env("TEST_DATABASE_URL"),
        replica_db_url: None,
        env: Env::Test,
        max_upload_size: 3000,
        max_unpack_size: 2000,
        mirror: Replica::Primary,
        // When testing we route all API traffic over HTTP so we can
        // sniff/record it, but everywhere else we use https
        api_protocol: String::from("http"),
        publish_rate_limit: Default::default(),
        blocked_traffic: Default::default(),
        domain_name: "crates.io".into(),
        allowed_origins: Vec::new(),
    }
}

fn build_app(
    config: Config,
    proxy: Option<String>,
) -> (Arc<App>, conduit_middleware::MiddlewareBuilder) {
    let client = if let Some(proxy) = proxy {
        let mut builder = Client::builder();
        builder = builder
            .proxy(Proxy::all(&proxy).expect("Unable to configure proxy with the provided URL"));
        Some(builder.build().expect("TLS backend cannot be initialized"))
    } else {
        None
    };

    let app = App::new(config, client);
    assert_ok!(assert_ok!(app.primary_database.get()).begin_test_transaction());
    let app = Arc::new(app);
    let handler = cargo_registry::build_handler(Arc::clone(&app));
    (app, handler)
}

// Return the environment variable only if it has been defined
#[track_caller]
fn env(var: &str) -> String {
    match dotenv::var(var) {
        Ok(ref s) if s.is_empty() => panic!("environment variable `{}` must not be empty", var),
        Ok(s) => s,
        _ => panic!(
            "environment variable `{}` must be defined and valid unicode",
            var
        ),
    }
}

fn json<T>(r: &mut AppResponse) -> T
where
    for<'de> T: serde::Deserialize<'de>,
{
    use conduit::Body::*;

    let mut body = Body::empty();
    std::mem::swap(r.body_mut(), &mut body);
    let body: std::borrow::Cow<'static, [u8]> = match body {
        Static(slice) => slice.into(),
        Owned(vec) => vec.into(),
        File(_) => unimplemented!(),
    };

    let s = std::str::from_utf8(&body).unwrap();
    match serde_json::from_str(s) {
        Ok(t) => t,
        Err(e) => panic!("failed to decode: {:?}\n{}", e, s),
    }
}

static NEXT_GH_ID: AtomicUsize = AtomicUsize::new(0);

fn new_user(login: &str) -> NewUser<'_> {
    NewUser {
        gh_id: NEXT_GH_ID.fetch_add(1, Ordering::SeqCst) as i32,
        gh_login: login,
        name: None,
        gh_avatar: None,
        gh_access_token: Cow::Borrowed("some random token"),
    }
}

fn new_team(login: &str) -> NewTeam<'_> {
    NewTeam {
        org_id: NEXT_GH_ID.fetch_add(1, Ordering::SeqCst) as i32,
        github_id: NEXT_GH_ID.fetch_add(1, Ordering::SeqCst) as i32,
        login,
        name: None,
        avatar: None,
    }
}

fn add_team_to_crate(t: &Team, krate: &Crate, u: &User, conn: &PgConnection) -> QueryResult<()> {
    let crate_owner = CrateOwner {
        crate_id: krate.id,
        owner_id: t.id,
        created_by: u.id,
        owner_kind: 1, // Team owner kind is 1 according to owner.rs
        email_notifications: true,
    };

    diesel::insert_into(crate_owners::table)
        .values(&crate_owner)
        .on_conflict(crate_owners::table.primary_key())
        .do_update()
        .set(crate_owners::deleted.eq(false))
        .execute(conn)?;

    Ok(())
}

fn new_dependency(conn: &PgConnection, version: &Version, krate: &Crate) -> Dependency {
    use cargo_registry::schema::dependencies::dsl::*;
    use diesel::insert_into;

    insert_into(dependencies)
        .values((
            version_id.eq(version.id),
            crate_id.eq(krate.id),
            req.eq(">= 0"),
            optional.eq(false),
            default_features.eq(false),
            features.eq(Vec::<String>::new()),
        ))
        .get_result(conn)
        .unwrap()
}

fn new_category<'a>(category: &'a str, slug: &'a str, description: &'a str) -> NewCategory<'a> {
    NewCategory {
        category,
        slug,
        description,
    }
}

// This reflects the configuration of our test environment. In the production application, this
// does not hold true.
#[test]
fn multiple_live_references_to_the_same_connection_can_be_checked_out() {
    use std::ptr;

    let (app, _) = TestApp::init().empty();
    let app = app.as_inner();

    let conn1 = app.primary_database.get().unwrap();
    let conn2 = app.primary_database.get().unwrap();
    let conn1_ref: &PgConnection = &conn1;
    let conn2_ref: &PgConnection = &conn2;

    assert!(ptr::eq(conn1_ref, conn2_ref));
}
<|endoftext|>


<commit_before>#![deny(warnings, clippy::all, rust_2018_idioms)]

#[macro_use]
extern crate diesel;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate serde;
#[macro_use]
extern crate serde_json;

use crate::util::{Bad, RequestHelper, TestApp};
use cargo_registry::{
    middleware::current_user::AuthenticationSource,
    models::{Crate, CrateOwner, Dependency, NewCategory, NewTeam, NewUser, Team, User, Version},
    schema::crate_owners,
    util::CargoResult,
    views::{EncodableCrate, EncodableKeyword, EncodableOwner, EncodableVersion, GoodCrate},
    App, Config, Env, Replica, Uploader,
};
use std::{
    borrow::Cow,
    sync::{
        atomic::{AtomicUsize, Ordering},
        Arc,
    },
};

use conduit::Request;
use conduit_test::MockRequest;
use diesel::prelude::*;
use reqwest::{Client, Proxy};
use url::Url;

macro_rules! t {
    ($e:expr) => {
        match $e {
            Ok(e) => e,
            Err(m) => panic!("{} failed with: {}", stringify!($e), m),
        }
    };
}

macro_rules! ok_resp {
    ($e:expr) => {{
        let resp = t!($e);
        if !crate::ok_resp(&resp) {
            panic!("bad response: {:?}", resp.status);
        }
        resp
    }};
}

macro_rules! bad_resp {
    ($e:expr) => {{
        let mut resp = t!($e);
        match crate::bad_resp(&mut resp) {
            None => panic!("ok response: {:?}", resp.status),
            Some(b) => b,
        }
    }};
}

mod badge;
mod builders;
mod categories;
mod category;
mod git;
mod keyword;
mod krate;
mod owners;
mod read_only_mode;
mod record;
mod schema_details;
mod server;
mod team;
mod token;
mod user;
mod util;
mod version;

#[derive(Deserialize)]
pub struct CrateList {
    crates: Vec<EncodableCrate>,
    meta: CrateMeta,
}
#[derive(Deserialize)]
struct CrateMeta {
    total: i32,
}
#[derive(Deserialize)]
pub struct CrateResponse {
    #[serde(rename = "crate")]
    krate: EncodableCrate,
    versions: Vec<EncodableVersion>,
    keywords: Vec<EncodableKeyword>,
}
#[derive(Deserialize)]
pub struct VersionResponse {
    version: EncodableVersion,
}
#[derive(Deserialize)]
pub struct OwnerTeamsResponse {
    teams: Vec<EncodableOwner>,
}
#[derive(Deserialize)]
pub struct OkBool {
    ok: bool,
}

fn app() -> (
    record::Bomb,
    Arc<App>,
    conduit_middleware::MiddlewareBuilder,
) {
    let (proxy, bomb) = record::proxy();
    let (app, handler) = simple_app(Some(proxy));
    (bomb, app, handler)
}

fn simple_app(proxy: Option<String>) -> (Arc<App>, conduit_middleware::MiddlewareBuilder) {
    git::init();

    let uploader = Uploader::S3 {
        bucket: s3::Bucket::new(
            String::from("alexcrichton-test"),
            None,
            dotenv::var("S3_ACCESS_KEY").unwrap_or_default(),
            dotenv::var("S3_SECRET_KEY").unwrap_or_default(),
            // When testing we route all API traffic over HTTP so we can
            // sniff/record it, but everywhere else we use https
            "http",
        ),
        cdn: None,
    };

    let config = Config {
        uploader,
        session_key: "test this has to be over 32 bytes long".to_string(),
        git_repo_checkout: git::checkout(),
        index_location: Url::from_file_path(&git::bare()).unwrap(),
        gh_client_id: dotenv::var("GH_CLIENT_ID").unwrap_or_default(),
        gh_client_secret: dotenv::var("GH_CLIENT_SECRET").unwrap_or_default(),
        db_url: env("TEST_DATABASE_URL"),
        env: Env::Test,
        max_upload_size: 3000,
        max_unpack_size: 2000,
        mirror: Replica::Primary,
        // When testing we route all API traffic over HTTP so we can
        // sniff/record it, but everywhere else we use https
        api_protocol: String::from("http"),
    };

    let client = if let Some(proxy) = proxy {
        let mut builder = Client::builder();
        builder = builder
            .proxy(Proxy::all(&proxy).expect("Unable to configure proxy with the provided URL"));
        Some(builder.build().expect("TLS backend cannot be initialized"))
    } else {
        None
    };

    let app = App::new(&config, client);
    t!(t!(app.diesel_database.get()).begin_test_transaction());
    let app = Arc::new(app);
    let handler = cargo_registry::build_handler(Arc::clone(&app));
    (app, handler)
}

// Return the environment variable only if it has been defined
fn env(var: &str) -> String {
    match dotenv::var(var) {
        Ok(ref s) if s == "" => panic!("environment variable `{}` must not be empty", var),
        Ok(s) => s,
        _ => panic!(
            "environment variable `{}` must be defined and valid unicode",
            var
        ),
    }
}

fn req(method: conduit::Method, path: &str) -> MockRequest {
    let mut request = MockRequest::new(method, path);
    request.header("User-Agent", "conduit-test");
    request
}

fn ok_resp(r: &conduit::Response) -> bool {
    r.status.0 == 200
}

fn bad_resp(r: &mut conduit::Response) -> Option<Bad> {
    let bad = json::<Bad>(r);
    if bad.errors.is_empty() {
        return None;
    }
    Some(bad)
}

fn json<T>(r: &mut conduit::Response) -> T
where
    for<'de> T: serde::Deserialize<'de>,
{
    let mut data = Vec::new();
    r.body.write_body(&mut data).unwrap();
    let s = std::str::from_utf8(&data).unwrap();
    match serde_json::from_str(s) {
        Ok(t) => t,
        Err(e) => panic!("failed to decode: {:?}\n{}", e, s),
    }
}

static NEXT_GH_ID: AtomicUsize = AtomicUsize::new(0);

fn new_user(login: &str) -> NewUser<'_> {
    NewUser {
        gh_id: NEXT_GH_ID.fetch_add(1, Ordering::SeqCst) as i32,
        gh_login: login,
        email: None,
        name: None,
        gh_avatar: None,
        gh_access_token: Cow::Borrowed("some random token"),
    }
}

fn new_team(login: &str) -> NewTeam<'_> {
    NewTeam {
        github_id: NEXT_GH_ID.fetch_add(1, Ordering::SeqCst) as i32,
        login,
        name: None,
        avatar: None,
    }
}

fn add_team_to_crate(t: &Team, krate: &Crate, u: &User, conn: &PgConnection) -> CargoResult<()> {
    let crate_owner = CrateOwner {
        crate_id: krate.id,
        owner_id: t.id,
        created_by: u.id,
        owner_kind: 1, // Team owner kind is 1 according to owner.rs
    };

    diesel::insert_into(crate_owners::table)
        .values(&crate_owner)
        .on_conflict(crate_owners::table.primary_key())
        .do_update()
        .set(crate_owners::deleted.eq(false))
        .execute(conn)?;

    Ok(())
}

fn sign_in_as(req: &mut dyn Request, user: &User) {
    req.mut_extensions().insert(user.clone());
    req.mut_extensions()
        .insert(AuthenticationSource::SessionCookie);
}

fn new_dependency(conn: &PgConnection, version: &Version, krate: &Crate) -> Dependency {
    use cargo_registry::schema::dependencies::dsl::*;
    use diesel::insert_into;

    insert_into(dependencies)
        .values((
            version_id.eq(version.id),
            crate_id.eq(krate.id),
            req.eq(">= 0"),
            optional.eq(false),
            default_features.eq(false),
            features.eq(Vec::<String>::new()),
        ))
        .get_result(conn)
        .unwrap()
}

fn new_category<'a>(category: &'a str, slug: &'a str, description: &'a str) -> NewCategory<'a> {
    NewCategory {
        category,
        slug,
        description,
    }
}

fn logout(req: &mut dyn Request) {
    req.mut_extensions().pop::<User>();
}

#[test]
fn multiple_live_references_to_the_same_connection_can_be_checked_out() {
    use std::ptr;

    let (_bomb, app, _) = app();
    let conn1 = app.diesel_database.get().unwrap();
    let conn2 = app.diesel_database.get().unwrap();
    let conn1_ref: &PgConnection = &conn1;
    let conn2_ref: &PgConnection = &conn2;

    assert!(ptr::eq(conn1_ref, conn2_ref));
}
<commit_msg>Support old lint name until the next stable release<commit_after>#![deny(warnings, clippy::all, rust_2018_idioms)]
// TODO: Remove after we can bump to Rust 1.35 stable in `RustConfig`
#![allow(
    renamed_and_removed_lints,
    clippy::cyclomatic_complexity,
    clippy::unknown_clippy_lints
)]

#[macro_use]
extern crate diesel;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate serde;
#[macro_use]
extern crate serde_json;

use crate::util::{Bad, RequestHelper, TestApp};
use cargo_registry::{
    middleware::current_user::AuthenticationSource,
    models::{Crate, CrateOwner, Dependency, NewCategory, NewTeam, NewUser, Team, User, Version},
    schema::crate_owners,
    util::CargoResult,
    views::{EncodableCrate, EncodableKeyword, EncodableOwner, EncodableVersion, GoodCrate},
    App, Config, Env, Replica, Uploader,
};
use std::{
    borrow::Cow,
    sync::{
        atomic::{AtomicUsize, Ordering},
        Arc,
    },
};

use conduit::Request;
use conduit_test::MockRequest;
use diesel::prelude::*;
use reqwest::{Client, Proxy};
use url::Url;

macro_rules! t {
    ($e:expr) => {
        match $e {
            Ok(e) => e,
            Err(m) => panic!("{} failed with: {}", stringify!($e), m),
        }
    };
}

macro_rules! ok_resp {
    ($e:expr) => {{
        let resp = t!($e);
        if !crate::ok_resp(&resp) {
            panic!("bad response: {:?}", resp.status);
        }
        resp
    }};
}

macro_rules! bad_resp {
    ($e:expr) => {{
        let mut resp = t!($e);
        match crate::bad_resp(&mut resp) {
            None => panic!("ok response: {:?}", resp.status),
            Some(b) => b,
        }
    }};
}

mod badge;
mod builders;
mod categories;
mod category;
mod git;
mod keyword;
mod krate;
mod owners;
mod read_only_mode;
mod record;
mod schema_details;
mod server;
mod team;
mod token;
mod user;
mod util;
mod version;

#[derive(Deserialize)]
pub struct CrateList {
    crates: Vec<EncodableCrate>,
    meta: CrateMeta,
}
#[derive(Deserialize)]
struct CrateMeta {
    total: i32,
}
#[derive(Deserialize)]
pub struct CrateResponse {
    #[serde(rename = "crate")]
    krate: EncodableCrate,
    versions: Vec<EncodableVersion>,
    keywords: Vec<EncodableKeyword>,
}
#[derive(Deserialize)]
pub struct VersionResponse {
    version: EncodableVersion,
}
#[derive(Deserialize)]
pub struct OwnerTeamsResponse {
    teams: Vec<EncodableOwner>,
}
#[derive(Deserialize)]
pub struct OkBool {
    ok: bool,
}

fn app() -> (
    record::Bomb,
    Arc<App>,
    conduit_middleware::MiddlewareBuilder,
) {
    let (proxy, bomb) = record::proxy();
    let (app, handler) = simple_app(Some(proxy));
    (bomb, app, handler)
}

fn simple_app(proxy: Option<String>) -> (Arc<App>, conduit_middleware::MiddlewareBuilder) {
    git::init();

    let uploader = Uploader::S3 {
        bucket: s3::Bucket::new(
            String::from("alexcrichton-test"),
            None,
            dotenv::var("S3_ACCESS_KEY").unwrap_or_default(),
            dotenv::var("S3_SECRET_KEY").unwrap_or_default(),
            // When testing we route all API traffic over HTTP so we can
            // sniff/record it, but everywhere else we use https
            "http",
        ),
        cdn: None,
    };

    let config = Config {
        uploader,
        session_key: "test this has to be over 32 bytes long".to_string(),
        git_repo_checkout: git::checkout(),
        index_location: Url::from_file_path(&git::bare()).unwrap(),
        gh_client_id: dotenv::var("GH_CLIENT_ID").unwrap_or_default(),
        gh_client_secret: dotenv::var("GH_CLIENT_SECRET").unwrap_or_default(),
        db_url: env("TEST_DATABASE_URL"),
        env: Env::Test,
        max_upload_size: 3000,
        max_unpack_size: 2000,
        mirror: Replica::Primary,
        // When testing we route all API traffic over HTTP so we can
        // sniff/record it, but everywhere else we use https
        api_protocol: String::from("http"),
    };

    let client = if let Some(proxy) = proxy {
        let mut builder = Client::builder();
        builder = builder
            .proxy(Proxy::all(&proxy).expect("Unable to configure proxy with the provided URL"));
        Some(builder.build().expect("TLS backend cannot be initialized"))
    } else {
        None
    };

    let app = App::new(&config, client);
    t!(t!(app.diesel_database.get()).begin_test_transaction());
    let app = Arc::new(app);
    let handler = cargo_registry::build_handler(Arc::clone(&app));
    (app, handler)
}

// Return the environment variable only if it has been defined
fn env(var: &str) -> String {
    match dotenv::var(var) {
        Ok(ref s) if s == "" => panic!("environment variable `{}` must not be empty", var),
        Ok(s) => s,
        _ => panic!(
            "environment variable `{}` must be defined and valid unicode",
            var
        ),
    }
}

fn req(method: conduit::Method, path: &str) -> MockRequest {
    let mut request = MockRequest::new(method, path);
    request.header("User-Agent", "conduit-test");
    request
}

fn ok_resp(r: &conduit::Response) -> bool {
    r.status.0 == 200
}

fn bad_resp(r: &mut conduit::Response) -> Option<Bad> {
    let bad = json::<Bad>(r);
    if bad.errors.is_empty() {
        return None;
    }
    Some(bad)
}

fn json<T>(r: &mut conduit::Response) -> T
where
    for<'de> T: serde::Deserialize<'de>,
{
    let mut data = Vec::new();
    r.body.write_body(&mut data).unwrap();
    let s = std::str::from_utf8(&data).unwrap();
    match serde_json::from_str(s) {
        Ok(t) => t,
        Err(e) => panic!("failed to decode: {:?}\n{}", e, s),
    }
}

static NEXT_GH_ID: AtomicUsize = AtomicUsize::new(0);

fn new_user(login: &str) -> NewUser<'_> {
    NewUser {
        gh_id: NEXT_GH_ID.fetch_add(1, Ordering::SeqCst) as i32,
        gh_login: login,
        email: None,
        name: None,
        gh_avatar: None,
        gh_access_token: Cow::Borrowed("some random token"),
    }
}

fn new_team(login: &str) -> NewTeam<'_> {
    NewTeam {
        github_id: NEXT_GH_ID.fetch_add(1, Ordering::SeqCst) as i32,
        login,
        name: None,
        avatar: None,
    }
}

fn add_team_to_crate(t: &Team, krate: &Crate, u: &User, conn: &PgConnection) -> CargoResult<()> {
    let crate_owner = CrateOwner {
        crate_id: krate.id,
        owner_id: t.id,
        created_by: u.id,
        owner_kind: 1, // Team owner kind is 1 according to owner.rs
    };

    diesel::insert_into(crate_owners::table)
        .values(&crate_owner)
        .on_conflict(crate_owners::table.primary_key())
        .do_update()
        .set(crate_owners::deleted.eq(false))
        .execute(conn)?;

    Ok(())
}

fn sign_in_as(req: &mut dyn Request, user: &User) {
    req.mut_extensions().insert(user.clone());
    req.mut_extensions()
        .insert(AuthenticationSource::SessionCookie);
}

fn new_dependency(conn: &PgConnection, version: &Version, krate: &Crate) -> Dependency {
    use cargo_registry::schema::dependencies::dsl::*;
    use diesel::insert_into;

    insert_into(dependencies)
        .values((
            version_id.eq(version.id),
            crate_id.eq(krate.id),
            req.eq(">= 0"),
            optional.eq(false),
            default_features.eq(false),
            features.eq(Vec::<String>::new()),
        ))
        .get_result(conn)
        .unwrap()
}

fn new_category<'a>(category: &'a str, slug: &'a str, description: &'a str) -> NewCategory<'a> {
    NewCategory {
        category,
        slug,
        description,
    }
}

fn logout(req: &mut dyn Request) {
    req.mut_extensions().pop::<User>();
}

#[test]
fn multiple_live_references_to_the_same_connection_can_be_checked_out() {
    use std::ptr;

    let (_bomb, app, _) = app();
    let conn1 = app.diesel_database.get().unwrap();
    let conn2 = app.diesel_database.get().unwrap();
    let conn1_ref: &PgConnection = &conn1;
    let conn2_ref: &PgConnection = &conn2;

    assert!(ptr::eq(conn1_ref, conn2_ref));
}
<|endoftext|>