mirror of
https://github.com/facebook/sapling.git
synced 2024-10-09 16:31:02 +03:00
c8b33fd580
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
111 lines
3.2 KiB
Rust
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))
|
|
}
|
|
}
|
|
}
|