use core::{SimpleError, Result};
use client::{GitSqlClient};
use std::fmt::{Write};
use git2::{self, Repository, Reference, Oid};
use postgres::stmt::{Statement};
pub struct RepositoryUpdater<'a> {
client: &'a GitSqlClient,
hashes: Vec<String>,
counter: i64,
handle: (Statement<'a>)
}
impl<'a> RepositoryUpdater<'a> {
pub fn new(client: &GitSqlClient) -> Result<RepositoryUpdater> {
let handle = client.start_object_list()?;
Ok(RepositoryUpdater {
client,
hashes: Vec::new(),
counter: 0,
handle: handle
})
}
fn callback(&mut self, oid: &Oid) -> bool {
self.counter += 1;
let mut hash = String::new();
write!(&mut hash, "{}", oid).unwrap();
self.hashes.push(hash);
if self.counter % 2000 == 0 {
self.client.add_hashes_to_object_list(
&self.handle,
&self.hashes
).unwrap();
println!("Loaded {} objects for comparison...", self.counter);
self.hashes.clear();
}
true
}
pub fn process_objects(&mut self, repo: &Repository) -> Result<()> {
let odb = repo.odb().map_err(|x| SimpleError::from(x))?;
odb.foreach(|x: &Oid| {
return self.callback(x);
}).map_err(|x: git2::Error| SimpleError::new(x.message()))?;
if !self.hashes.is_empty() {
self.client.add_hashes_to_object_list(
&self.handle,
&self.hashes
)?;
println!("Loaded {} objects for comparison...", self.counter);
self.hashes.clear();
}
Ok(())
}
pub fn update_objects(&mut self, repo: &Repository) -> Result<()> {
let odb = repo.odb().map_err(|x| SimpleError::from(x))?;
self.client.diff_object_list(|hash: String| {
println!("Insert {}", hash);
let oid = Oid::from_str(&hash).unwrap();
let obj = odb.read(oid).unwrap();
let kind = obj.kind();
let size = obj.len();
let data = obj.data();
self.client.insert_object(&hash, &kind, size, data).unwrap();
})
}
fn process_ref(&mut self, rf: &Reference, name: String) -> Result<()> {
let target : String;
if !rf.symbolic_target().is_none() {
target = rf.symbolic_target().unwrap().to_string();
} else {
target = rf.target().unwrap().to_string();
}
let peeled = rf.target_peel();
if peeled.is_some() {
let mut peeled_name = name.clone();
peeled_name.push_str("^{}");
self.client.set_ref(
&peeled_name,
&peeled.unwrap().to_string()
)?;
}
let did_update = self.client.set_ref(
&name,
&target
)?;
if did_update {
println!("{} updated to {}", name, target);
}
Ok(())
}
pub fn update_refs(&mut self, repo: &Repository) -> Result<()> {
let refs = repo.references().map_err(|x| SimpleError::from(x))?;
for r in refs {
let rf = r.unwrap();
let name = rf.name().unwrap().to_string();
self.process_ref(&rf, name)?;
}
if let Ok(rf) = repo.head() {
self.process_ref(&rf, "HEAD".into())?;
}
Ok(())
}
}