Currently this will only work if the working copy contains no extra changes. Further work will, of course, fix this limitation, and present the information to the user
LSSPVZONPCHHLOWSJWORILOV6ZP55Q4DFIX47J7YG3VCHQCA6SBAC
}
pub struct InlineCreditBuffer {
changes: Vec<(ChangeId, usize)>,
}
impl InlineCreditBuffer {
pub fn new() -> Result<Self, anyhow::Error> {
Ok(Self {
changes: Vec::new(),
})
}
}
impl VertexBuffer for InlineCreditBuffer {
fn output_line<E, F>(
&mut self,
key: libpijul::Vertex<libpijul::ChangeId>,
contents_writer: F,
) -> Result<(), E>
where
E: From<std::io::Error>,
F: FnOnce(&mut [u8]) -> Result<(), E>,
{
// Do not render the root change
if key.change.is_root() {
return Ok(());
}
let mut buf = vec![0; key.end - key.start];
contents_writer(&mut buf)?;
// TODO: this will not work with alternative encodings
for _line in String::from_utf8(buf).expect("Non-utf8 change").lines() {
if let Some((last_change, lines)) = self.changes.last_mut() {
if last_change.to_owned() == key.change {
*lines += 1;
continue;
}
}
// Fell through to end, so must be a new change for this line
self.changes.push((key.change, 1));
}
Ok(())
}
fn output_conflict_marker<C: libpijul::changestore::ChangeStore>(
&mut self,
_s: &str,
_id: usize,
_sides: Option<(&C, &[&Hash])>,
) -> Result<(), std::io::Error> {
unimplemented!();
}
}
// TODO: Refactor repository setup into separate module to prevent code duplication
pub fn file_credits(path: PathBuf) -> Result<Vec<(Hash, usize)>, anyhow::Error> {
let repo = Repository::find_root(Some(path.to_owned())).expect("Could not find root");
let txn = repo.pristine.arc_txn_begin()?;
let channel_name = txn
.read()
.current_channel()
.unwrap_or(libpijul::DEFAULT_CHANNEL)
.to_string();
let channel = txn.write().open_or_create_channel(&channel_name)?;
let prefix = path.strip_prefix(&repo.path)?.to_string_lossy().to_string();
let write_txn = txn.write();
let (oldest_change, _ambiguous) =
write_txn.follow_oldest_path(&repo.changes, &channel, prefix.as_str())?;
// Drop writeable access to prevent ownership deadlock from calling txn.read()
std::mem::drop(write_txn);
let mut credit_buffer = InlineCreditBuffer::new()?;
libpijul::output::output_file(
&repo.changes,
&txn,
&channel,
oldest_change,
&mut credit_buffer,
)?;
let mut hashes = Vec::new();
for (change_id, lines) in credit_buffer.changes {
let hash = txn.read().get_external(&change_id)?.unwrap().to_owned();
hashes.push((Hash::from(hash), lines));
}
Ok(hashes)