mirror of
https://github.com/facebook/sapling.git
synced 2024-10-10 08:47:12 +03:00
apiserver: implement SourceControlService repo_resolve_bookmark
Summary: Implement the `repo_resolve_bookmark` call, which resolves a bookmark in a repo to the commits that the bookmark points to. Reviewed By: krallin Differential Revision: D17157498 fbshipit-source-id: e7e53df2cb9e3efaddcd22a8d0db344a8d279f08
This commit is contained in:
parent
121a66da8b
commit
879c6d9900
@ -4,10 +4,11 @@
|
||||
// This software may be used and distributed according to the terms of the
|
||||
// GNU General Public License version 2 or any later version.
|
||||
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use mononoke_api::{CoreContext, Mononoke};
|
||||
use mononoke_api::{ChangesetContext, CoreContext, Mononoke, MononokeError};
|
||||
use scuba_ext::ScubaSampleBuilder;
|
||||
use slog::Logger;
|
||||
use source_control::server::SourceControlService;
|
||||
@ -29,6 +30,12 @@ trait ScubaInfoProvider {
|
||||
}
|
||||
}
|
||||
|
||||
impl ScubaInfoProvider for thrift::RepoSpecifier {
|
||||
fn scuba_reponame(&self) -> Option<String> {
|
||||
Some(self.name.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SourceControlServiceImpl {
|
||||
mononoke: Arc<Mononoke>,
|
||||
@ -74,6 +81,39 @@ impl SourceControlServiceImpl {
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate a mapping for a commit's identity into the requested identity
|
||||
/// schemes.
|
||||
async fn map_commit_identity(
|
||||
changeset_ctx: &ChangesetContext,
|
||||
schemes: &BTreeSet<thrift::CommitIdentityScheme>,
|
||||
) -> Result<BTreeMap<thrift::CommitIdentityScheme, thrift::CommitId>, MononokeError> {
|
||||
let mut ids = BTreeMap::new();
|
||||
ids.insert(
|
||||
thrift::CommitIdentityScheme::BONSAI,
|
||||
thrift::CommitId::bonsai(changeset_ctx.id().as_ref().into()),
|
||||
);
|
||||
if schemes.contains(&thrift::CommitIdentityScheme::HG) {
|
||||
if let Some(hg_cs_id) = changeset_ctx.hg_id().await? {
|
||||
ids.insert(
|
||||
thrift::CommitIdentityScheme::HG,
|
||||
thrift::CommitId::hg(hg_cs_id.as_ref().into()),
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(ids)
|
||||
}
|
||||
|
||||
mod errors {
|
||||
use super::thrift;
|
||||
|
||||
pub(super) fn repo_not_found(reponame: impl AsRef<str>) -> thrift::RequestError {
|
||||
thrift::RequestError {
|
||||
kind: thrift::RequestErrorKind::REPO_NOT_FOUND,
|
||||
reason: format!("repo not found ({})", reponame.as_ref()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl SourceControlService for SourceControlServiceImpl {
|
||||
async fn list_repos(
|
||||
@ -90,4 +130,33 @@ impl SourceControlService for SourceControlServiceImpl {
|
||||
.collect();
|
||||
Ok(rsp)
|
||||
}
|
||||
|
||||
/// Resolve a bookmark to a changeset.
|
||||
///
|
||||
/// Returns whether the bookmark exists, and the IDs of the changeset in
|
||||
/// the requested indentity schemes.
|
||||
async fn repo_resolve_bookmark(
|
||||
&self,
|
||||
repo: thrift::RepoSpecifier,
|
||||
params: thrift::RepoResolveBookmarkParams,
|
||||
) -> Result<thrift::RepoResolveBookmarkResponse, service::RepoResolveBookmarkExn> {
|
||||
let ctx = self.create_ctx(Some(&repo));
|
||||
let repo = self
|
||||
.mononoke
|
||||
.repo(ctx, &repo.name)?
|
||||
.ok_or_else(|| errors::repo_not_found(&repo.name))?;
|
||||
match repo.resolve_bookmark(params.bookmark_name).await? {
|
||||
Some(cs) => {
|
||||
let ids = map_commit_identity(&cs, ¶ms.identity_schemes).await?;
|
||||
Ok(thrift::RepoResolveBookmarkResponse {
|
||||
exists: true,
|
||||
ids: Some(ids),
|
||||
})
|
||||
}
|
||||
None => Ok(thrift::RepoResolveBookmarkResponse {
|
||||
exists: false,
|
||||
ids: None,
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ use std::sync::Arc;
|
||||
use blobrepo::BlobRepo;
|
||||
use blobrepo_factory::{open_blobrepo, Caching};
|
||||
use blobstore::Blobstore;
|
||||
use bookmarks::BookmarkName;
|
||||
use context::CoreContext;
|
||||
use derive_unode_manifest::derived_data_unodes::RootUnodeManifestMapping;
|
||||
use failure::Error;
|
||||
@ -131,6 +132,21 @@ impl RepoContext {
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
/// Resolve a bookmark to a changeset.
|
||||
pub async fn resolve_bookmark(
|
||||
&self,
|
||||
bookmark: impl ToString,
|
||||
) -> Result<Option<ChangesetContext>, MononokeError> {
|
||||
let bookmark = BookmarkName::new(bookmark.to_string())?;
|
||||
let cs_id = self
|
||||
.repo
|
||||
.blob_repo
|
||||
.get_bonsai_bookmark(self.ctx.clone(), &bookmark)
|
||||
.compat()
|
||||
.await?;
|
||||
Ok(cs_id.map(|cs_id| ChangesetContext::new(self.clone(), cs_id)))
|
||||
}
|
||||
|
||||
/// Look up a changeset by specifier.
|
||||
pub async fn changeset(
|
||||
&self,
|
||||
|
@ -58,3 +58,27 @@ async fn commit_info_by_hg_hash() -> Result<(), Error> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn commit_info_by_bookmark() -> Result<(), Error> {
|
||||
let mononoke = Mononoke::new_test(vec![("test".to_string(), linear::getrepo())]);
|
||||
let ctx = CoreContext::test_mock();
|
||||
let repo = mononoke.repo(ctx, "test")?.expect("repo exists");
|
||||
let cs = repo
|
||||
.resolve_bookmark("master")
|
||||
.await?
|
||||
.expect("bookmark exists");
|
||||
|
||||
let hash = "7785606eb1f26ff5722c831de402350cf97052dc44bc175da6ac0d715a3dbbf6";
|
||||
assert_eq!(cs.id(), ChangesetId::from_str(hash)?);
|
||||
let hg_hash = "79a13814c5ce7330173ec04d279bf95ab3f652fb";
|
||||
assert_eq!(cs.hg_id().await?, Some(HgChangesetId::from_str(hg_hash)?));
|
||||
assert_eq!(cs.message().await?, "modified 10");
|
||||
assert_eq!(cs.author().await?, "Jeremy Fitzhardinge <jsgf@fb.com>");
|
||||
assert_eq!(
|
||||
cs.author_date().await?,
|
||||
FixedOffset::west(7 * 3600).timestamp(1504041761, 0)
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user