sapling/eden/mononoke/derived_data/blame/lib.rs
Mark Juggurnauth-Thomas c8b33fd580 blame: enable batch derivation of blame_v2
Summary:
Implement batch derivation of blame V2.

Blame derivations are independent so long as the two commits do not change or
delete any of the same files.  We can re-use the existing batching code so long
as we change it to split the stacks on *any* change (not just a
change-vs-delete conflict).

Reviewed By: StanislavGlebik

Differential Revision: D29776514

fbshipit-source-id: b06289467c9ec502170c2f851b07569214b6ff0a
2021-07-26 07:09:35 -07:00

111 lines
3.2 KiB
Rust

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This software may be used and distributed according to the terms of the
* GNU General Public License version 2.
*/
#![deny(warnings)]
#![type_length_limit = "1441792"]
mod batch_v2;
mod compat;
mod derive_v1;
mod derive_v2;
mod fetch;
mod mapping_v1;
mod mapping_v2;
#[cfg(test)]
mod tests;
use anyhow::Error;
use blobrepo::BlobRepo;
use blobstore::{Loadable, LoadableError};
use context::CoreContext;
use derived_data::{BonsaiDerived, DeriveError};
use manifest::ManifestOps;
use metaconfig_types::BlameVersion;
use mononoke_types::blame::{BlameId, BlameRejected};
use mononoke_types::blame_v2::BlameV2Id;
use mononoke_types::{ChangesetId, FileUnodeId, MPath};
use thiserror::Error;
use unodes::RootUnodeManifestId;
pub use compat::CompatBlame;
pub use fetch::{fetch_content_for_blame, FetchOutcome};
pub use mapping_v1::{BlameRoot, BlameRootMapping};
pub use mapping_v2::{RootBlameV2, RootBlameV2Mapping};
pub const DEFAULT_BLAME_FILESIZE_LIMIT: u64 = 10 * 1024 * 1024;
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub struct BlameDeriveOptions {
filesize_limit: u64,
blame_version: BlameVersion,
}
impl Default for BlameDeriveOptions {
fn default() -> Self {
BlameDeriveOptions {
filesize_limit: DEFAULT_BLAME_FILESIZE_LIMIT,
blame_version: BlameVersion::default(),
}
}
}
#[derive(Debug, Error)]
pub enum BlameError {
#[error("No such path: {0}")]
NoSuchPath(MPath),
#[error("Blame is not available for directories: {0}")]
IsDirectory(MPath),
#[error(transparent)]
Rejected(#[from] BlameRejected),
#[error(transparent)]
DeriveError(#[from] DeriveError),
#[error(transparent)]
LoadableError(#[from] LoadableError),
#[error(transparent)]
Error(#[from] Error),
}
/// Fetch the blame for a file. Blame will be derived if necessary.
pub async fn fetch_blame_compat(
ctx: &CoreContext,
repo: &BlobRepo,
csid: ChangesetId,
path: MPath,
) -> Result<(CompatBlame, FileUnodeId), BlameError> {
let blame_version = repo.get_derived_data_config().enabled.blame_version;
let root_unode = match blame_version {
BlameVersion::V1 => {
BlameRoot::derive(ctx, repo, csid).await?;
RootUnodeManifestId::derive(&ctx, &repo, csid).await?
}
BlameVersion::V2 => {
let root_blame = RootBlameV2::derive(ctx, repo, csid).await?;
root_blame.root_manifest()
}
};
let blobstore = repo.get_blobstore();
let file_unode_id = root_unode
.manifest_unode_id()
.clone()
.find_entry(ctx.clone(), blobstore.clone(), Some(path.clone()))
.await?
.ok_or_else(|| BlameError::NoSuchPath(path.clone()))?
.into_leaf()
.ok_or_else(|| BlameError::IsDirectory(path))?;
match blame_version {
BlameVersion::V1 => {
let blame = BlameId::from(file_unode_id).load(ctx, &blobstore).await?;
Ok((CompatBlame::V1(blame), file_unode_id))
}
BlameVersion::V2 => {
let blame = BlameV2Id::from(file_unode_id).load(ctx, &blobstore).await?;
Ok((CompatBlame::V2(blame), file_unode_id))
}
}
}