Repositories

grarr

(mirrored on github)

Wim Looman <wim@nemo157.com>
51f441 Start parsing upload pack requests
Wim Looman committed at 2016-03-14 17:22:20

Modified src/handler/git_smart_http/mod.rs

@@ -1,4 +1,6 @@
mod refs;
mod utils;
mod upload_pack;
pub use self::refs::Refs;
pub use self::upload_pack::UploadPack;

Added src/handler/git_smart_http/upload_pack.rs

@@ -0,0 +1,51 @@
use handler::base::*;
use super::utils::*;
use git2::Oid;
#[derive(Clone)]
pub struct UploadPack;
#[derive(Debug)]
struct Details {
wants: Vec<Oid>,
haves: Vec<Oid>,
}
fn parse_requst(req: &mut Request) -> Result<Details, Error> {
let mut details = Details { wants: Vec::new(), haves: Vec::new() };
for line in req.body.pkt_lines() {
let line = try!(line);
if line.len() < 4 { continue }
match &line[0..4] {
"want" => {
details.wants.push(try!(line[5..].parse()));
},
"have" => {
details.haves.push(try!(line[5..].parse()));
},
"done" => break,
_ => return Err(Error::from(format!("Unexpected pkt-line {}", line))),
}
}
Ok(details)
}
impl Handler for UploadPack {
fn handle(&self, req: &mut Request) -> IronResult<Response> {
let details = parse_requst(req);
// let context = itry!(req.extensions.get::<RepositoryContext>().ok_or(Error::from("missing extension")), status::InternalServerError);
println!("{:?}", details);
Err(IronError::new(Error::from("TODO"), status::InternalServerError))
}
}
impl Route for UploadPack {
fn method() -> Method {
Method::Post
}
fn route() -> Cow<'static, str> {
"/git-upload-pack".into()
}
}

Modified src/handler/git_smart_http/utils.rs

@@ -1,4 +1,5 @@
use std::io::{ self, Write };
use std::str;
pub trait WritePktLine {
fn write_pkt_line<S: AsRef<str>>(&mut self, buf: S) -> io::Result<()>;
@@ -40,3 +41,58 @@ impl WritePktLine for Vec<u8> {
self.write_all(b"0000")
}
}
pub struct PktLines<'a> {
source: &'a mut io::Read,
}
pub trait ReadPktLine {
fn read_pkt_line(&mut self, buf: &mut [u8]) -> io::Result<usize>;
fn pkt_lines(&mut self) -> PktLines;
}
impl<T: io::Read> ReadPktLine for T {
fn read_pkt_line(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let mut size_buf = [0; 4];
try!(self.read_exact(&mut size_buf));
let size_str = try!(str::from_utf8(&size_buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)));
let size = try!(usize::from_str_radix(size_str, 16).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)));
if size == 0 {
return Ok(0);
}
if size < 4 {
return Err(io::Error::new(io::ErrorKind::InvalidData, "Size less than 4 and not equal to 0"));
}
let size = size - 4;
if size > buf.len() {
return Err(io::Error::new(io::ErrorKind::InvalidInput, "Buffer was not large enough"));
}
try!(self.read_exact(&mut buf[..size]));
if size > 0 && buf[size - 1] == b'\n' {
Ok(size - 1)
} else {
Ok(size)
}
}
fn pkt_lines(&mut self) -> PktLines {
PktLines { source: self }
}
}
impl<'a> Iterator for PktLines<'a> {
type Item = Result<String, io::Error>;
fn next(&mut self) -> Option<Result<String, io::Error>> {
let mut buf = vec![0; 65520];
match self.source.read_pkt_line(&mut buf) {
Ok(len) => {
buf.truncate(len);
Some(String::from_utf8(buf).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)))
},
Err(e) => match e.kind() {
io::ErrorKind::UnexpectedEof => None,
_ => Some(Err(e)),
},
}
}
}

Modified src/main.rs

@@ -91,6 +91,7 @@ fn main() {
.register(inject_repository_context(&config.repos.root, handler::Pages))
.register(inject_repository_context(&config.repos.root, handler::Compare))
.register(inject_repository_context(&config.repos.root, handler::git_smart_http::Refs))
.register(inject_repository_context(&config.repos.root, handler::git_smart_http::UploadPack))
.register(statics![
prefix: "./static/";
"./static/js/highlight.js",