Skip to content

Commit f560bc5

Browse files
committed
prepare writing of time as part of signature
1 parent e66c9ed commit f560bc5

File tree

8 files changed

+87
-13
lines changed

8 files changed

+87
-13
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ The CLI uses various crates, please see _'Development Status'_ for details.
6969
* **git-ref**
7070
* Handle symbolic references and packed references
7171
* discover them in typical folder structures
72-
* [ ] name validation
72+
* [x] name validation
7373
* [ ] API documentation with examples
7474
* **git-index**
7575
* read and write a git-index file

git-object/src/borrowed/object.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ pub use error::Error;
44
use crate::BStr;
55
use crate::{
66
borrowed,
7-
borrowed::{Blob, Commit, Tag, Tree},
7+
borrowed::{parse, Blob, Commit, Tag, Tree},
88
Time,
99
};
1010

@@ -17,6 +17,12 @@ pub struct Signature<'a> {
1717
pub time: Time,
1818
}
1919

20+
impl<'a> Signature<'a> {
21+
pub fn from_bytes(d: &'a [u8]) -> Result<Signature<'a>, Error> {
22+
parse::signature(d).map(|(_, t)| t).map_err(Error::from)
23+
}
24+
}
25+
2026
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
2127
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
2228
pub enum Object<'a> {

git-object/src/owned/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
//! Owned objects for use with serialization.
22
3+
pub(crate) const NL: &[u8; 1] = b"\n";
4+
pub(crate) const SPACE: &[u8; 1] = b" ";
5+
36
mod convert;
47
mod object;
58
mod ser;

git-object/src/owned/object.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,48 @@
11
use crate::Time;
22
use bstr::BString;
33

4+
pub mod signature {
5+
use super::Signature;
6+
use crate::owned::SPACE;
7+
use bstr::{BStr, ByteSlice};
8+
use quick_error::quick_error;
9+
use std::io;
10+
11+
quick_error! {
12+
#[derive(Debug)]
13+
pub enum Error {
14+
IllegalCharacter {
15+
description("Signature name or email must not contain '<', '>' or \\n")
16+
}
17+
}
18+
}
19+
20+
impl From<Error> for io::Error {
21+
fn from(err: Error) -> Self {
22+
io::Error::new(io::ErrorKind::Other, err)
23+
}
24+
}
25+
26+
impl Signature {
27+
pub fn write_to(&self, mut out: impl io::Write) -> io::Result<()> {
28+
out.write_all(validated_token(self.name.as_bstr())?)?;
29+
out.write_all(SPACE)?;
30+
out.write_all(&b"<"[..])?;
31+
out.write_all(validated_token(self.email.as_bstr())?)?;
32+
out.write_all(&b">"[..])?;
33+
self.time.write_to(out)?;
34+
Ok(())
35+
}
36+
}
37+
38+
fn validated_token(name: &BStr) -> Result<&BStr, Error> {
39+
if name.find_byteset(b"<>\n").is_some() {
40+
return Err(Error::IllegalCharacter);
41+
}
42+
Ok(name)
43+
}
44+
}
45+
446
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
547
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
648
pub struct Signature {

git-object/src/owned/ser.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::owned::{NL, SPACE};
12
use bstr::{BString, ByteSlice};
23
use quick_error::quick_error;
34
use std::io;
@@ -20,9 +21,6 @@ impl Into<io::Error> for Error {
2021
}
2122
}
2223

23-
const NL: &[u8; 1] = b"\n";
24-
const SPACE: &[u8; 1] = b" ";
25-
2624
pub fn trusted_header_field(name: &[u8], value: &[u8], mut out: impl io::Write) -> io::Result<()> {
2725
out.write_all(name)?;
2826
out.write_all(&SPACE[..])?;

git-object/src/owned/tag.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,15 @@ pub struct Tag {
3737
}
3838

3939
impl Tag {
40-
pub fn to_write(&self, mut out: impl io::Write) -> io::Result<()> {
40+
pub fn write_to(&self, mut out: impl io::Write) -> io::Result<()> {
4141
let mut hex_buf: [u8; 40] = [0; 40];
4242
self.target
4343
.encode_to_40_bytes_slice(&mut hex_buf[..])
4444
.expect("20 to 40 bytes hex encoding to always work");
4545

4646
ser::trusted_header_field(b"object", &hex_buf, &mut out)?;
4747
ser::trusted_header_field(b"type", self.target_kind.to_bytes(), &mut out)?;
48-
ser::header_field(b"type", validated_name(self.name.as_ref())?, &mut out)?;
48+
ser::header_field(b"tag", validated_name(self.name.as_ref())?, &mut out)?;
4949
unimplemented!("tag to_write")
5050
}
5151
}

git-object/src/types.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::ByteSlice;
2-
use nom::{lib::std::fmt::Formatter, lib::std::ops::Deref};
32
use quick_error::quick_error;
3+
use std::ops::Deref;
4+
use std::{fmt, io};
45

56
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
67
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
@@ -20,6 +21,12 @@ pub struct Time {
2021
pub sign: Sign,
2122
}
2223

24+
impl Time {
25+
pub fn write_to(&self, out: impl io::Write) -> io::Result<()> {
26+
unimplemented!("time write to")
27+
}
28+
}
29+
2330
pub const SHA1_SIZE: usize = 20;
2431

2532
/// A SHA1 identifying objects
@@ -60,8 +67,8 @@ impl Deref for Id {
6067
}
6168
}
6269

63-
impl std::fmt::Display for Id {
64-
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
70+
impl fmt::Display for Id {
71+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
6572
let mut buf = [0u8; 40];
6673
self.encode_to_40_bytes_slice(&mut buf).unwrap();
6774
write!(f, "{}", &buf.as_bstr())
@@ -106,8 +113,8 @@ impl Kind {
106113
}
107114
}
108115

109-
impl std::fmt::Display for Kind {
110-
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
116+
impl fmt::Display for Kind {
117+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111118
f.write_str(std::str::from_utf8(self.to_bytes()).expect("valid utf8 in kind name"))
112119
}
113120
}

git-object/tests/owned/mod.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
mod object {
2+
mod signature {
3+
mod to_write {
4+
use bstr::ByteSlice;
5+
use git_object::{borrowed, owned};
6+
7+
#[test]
8+
fn round_trip() {
9+
let input = b"Sebastian Thiel <byronimo@gmail.com> 1528473343 +0230";
10+
let signature: owned::Signature = borrowed::Signature::from_bytes(input).unwrap().into();
11+
let mut output = Vec::new();
12+
signature.write_to(&mut output).unwrap();
13+
assert_eq!(input.as_bstr(), output.as_bstr());
14+
}
15+
}
16+
}
17+
}
18+
119
mod tag {
220
use crate::fixture_bytes;
321
use bstr::ByteSlice;
@@ -8,7 +26,7 @@ mod tag {
826
let input = fixture_bytes("tag/empty.txt");
927
let tag: owned::Tag = borrowed::Tag::from_bytes(&input).unwrap().into();
1028
let mut output = Vec::new();
11-
tag.to_write(&mut output).unwrap();
29+
tag.write_to(&mut output).unwrap();
1230
assert_eq!(input.as_bstr(), output.as_bstr());
1331
}
1432
}

0 commit comments

Comments
 (0)