use std::io;
use std::fs;
use std::collections::HashMap;
use git2::{Oid, Repository};
#[derive(Debug)]
pub struct OidMap {
map: HashMap<Oid, Option<Oid>>,
}
impl OidMap {
pub fn new() -> OidMap {
OidMap { map: HashMap::new() }
}
pub fn from_repo(repo: &Repository, name: &str) -> io::Result<OidMap> {
let mut path = repo.path().join("subset");
path.push(name);
if let Ok(f) = fs::File::open(&path) {
Self::from_reader(io::BufReader::new(f))
}
else {
Ok(Self::new())
}
}
pub fn write_repo(&self, repo: &Repository, name: &str) -> io::Result<()> {
let mut path = repo.path().join("subset");
fs::create_dir_all(&path)?;
path.push(name);
let mut f = io::BufWriter::new(fs::File::create(&path)?);
self.write(&mut f)
}
pub fn from_reader<R: io::BufRead>(reader: R) -> io::Result<OidMap> {
let mut map = HashMap::new();
for line in reader.lines() {
let line = line?;
let line = line.trim();
if line.is_empty() || line.starts_with("#") {
continue;
}
let mut s = line.split(' ');
let a = s.next().map(Oid::from_str);
let b = s.next().map(Oid::from_str);
match (a, b) {
(Some(Ok(a)), Some(Ok(b))) => {
map.insert(a, Some(b));
},
(Some(Ok(a)), None) => {
map.insert(a, None);
},
_ => continue, };
}
Ok(OidMap { map: map })
}
pub fn write<W: io::Write>(&self, f: &mut W) -> io::Result<()> {
for (k, v) in &self.map {
write!(f, "{}", k)?;
if let Some(v) = *v {
write!(f, " {}\n", v)?;
}
}
Ok(())
}
pub fn get(&self, k: &Oid) -> Option<&Option<Oid>> {
self.map.get(k)
}
pub fn resolve(&self, k: &Oid) -> Option<&Option<Oid>> {
match self.map.get(k) {
Some(value) => {
match *value {
Some(oid) => {
if k == &oid {
Some(value)
} else if self.map.contains_key(&oid) {
self.resolve(&oid)
}
else {
Some(value)
}
},
None => Some(value),
}
},
None => None,
}
}
pub fn insert(&mut self, k: Oid, v: Option<Oid>) -> Option<Option<Oid>> {
self.map.insert(k, v)
}
}
#[cfg(test)]
mod tests {
use super::*;
use git2::Oid;
#[test]
fn test_resolve() {
let mut map = OidMap::new();
let a = Oid::from_str("0000000000000000000000000000000000000000").unwrap();
let b = Oid::from_str("0000000000000000000000000000000000000001").unwrap();
let c = Oid::from_str("0000000000000000000000000000000000000002").unwrap();
map.insert(a, Some(b));
assert_eq!(map.resolve(&a), Some(&Some(b)));
assert_eq!(map.resolve(&b), None);
map.insert(b, Some(c));
assert_eq!(map.resolve(&a), Some(&Some(c)));
assert_eq!(map.resolve(&b), Some(&Some(c)));
map.insert(c, None);
assert_eq!(map.resolve(&a), Some(&None));
assert_eq!(map.resolve(&b), Some(&None));
assert_eq!(map.resolve(&c), Some(&None));
}
}