sapling/eden/mononoke/cmds/admin/pushrebase.rs
Thomas Orozco 2f47e9263e mononoke: allow pushes in globalrev repos to ancestors of globalrev bookmark
Summary:
Like it says in the title, this updates our implementation of Globalrevs to
be a little more relaxed, and allows you to create and move bookmarks as long as
they are ancestors of the "main" Globalrevs bookmark (but NOT to pushrebase to
them later, because we only want to allow ONE globalrevs-publishing bookmark
per repo).

While in there, I also deduplicated how we instantiate pushrebase hooks a
little bit. If anything, this could be better in the pushrebase crate, but
that'd be a circular dependency between pushrebase & bookmarks movement.
Eventually, the callsites should probably be using bookmarks movement anyway,
so leaving pushrebase as the low-level crate and bookmarks movement as the high
level one seems reasonable.

Reviewed By: StanislavGlebik

Differential Revision: D26020274

fbshipit-source-id: 5ff6c1a852800b491a16d16f632462ce9453c89a
2021-02-01 05:30:57 -08:00

100 lines
2.8 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.
*/
use anyhow::{anyhow, Error};
use blobstore::Loadable;
use bookmarks::BookmarkName;
use clap::{App, Arg, ArgMatches, SubCommand};
use fbinit::FacebookInit;
use futures::{compat::Future01CompatExt, TryFutureExt};
use cmdlib::{
args::{self, MononokeMatches},
helpers,
};
use context::CoreContext;
use maplit::hashset;
use pushrebase::do_pushrebase_bonsai;
use slog::Logger;
use crate::error::SubcommandError;
pub const ARG_BOOKMARK: &str = "bookmark";
pub const ARG_CSID: &str = "csid";
pub const PUSHREBASE: &str = "pushrebase";
pub fn build_subcommand<'a, 'b>() -> App<'a, 'b> {
SubCommand::with_name(PUSHREBASE)
.about("pushrebases a commit to a bookmark")
.arg(
Arg::with_name(ARG_CSID)
.long(ARG_CSID)
.takes_value(true)
.required(true)
.help("{hg|bonsai} changeset id or bookmark name"),
)
.arg(
Arg::with_name(ARG_BOOKMARK)
.long(ARG_BOOKMARK)
.takes_value(true)
.required(true)
.help("name of the bookmark to pushrebase to"),
)
}
pub async fn subcommand_pushrebase<'a>(
fb: FacebookInit,
logger: Logger,
matches: &'a MononokeMatches<'_>,
sub_matches: &'a ArgMatches<'_>,
) -> Result<(), SubcommandError> {
args::init_cachelib(fb, &matches);
let ctx = CoreContext::new_with_logger(fb, logger.clone());
let repo = args::open_repo(fb, &logger, &matches).await?;
let cs_id = sub_matches
.value_of(ARG_CSID)
.ok_or_else(|| anyhow!("{} arg is not specified", ARG_CSID))?;
let cs_id = helpers::csid_resolve(ctx.clone(), repo.clone(), cs_id)
.compat()
.await?;
let bookmark = sub_matches
.value_of(ARG_BOOKMARK)
.ok_or_else(|| anyhow!("{} arg is not specified", ARG_BOOKMARK))?;
let config_store = args::init_config_store(fb, &logger, matches)?;
let (_, repo_config) = args::get_config(config_store, matches)?;
let bookmark = BookmarkName::new(bookmark)?;
let pushrebase_flags = repo_config.pushrebase.flags;
let pushrebase_hooks =
bookmarks_movement::get_pushrebase_hooks(&ctx, &repo, &bookmark, &repo_config.pushrebase)
.map_err(Error::from)?;
let bcs = cs_id
.load(&ctx, &repo.get_blobstore())
.map_err(Error::from)
.await?;
let pushrebase_res = do_pushrebase_bonsai(
&ctx,
&repo,
&pushrebase_flags,
&bookmark,
&hashset![bcs],
None,
&pushrebase_hooks,
)
.map_err(Error::from)
.await?;
println!("{}", pushrebase_res.head);
Ok(())
}