|
| 1 | +/* |
| 2 | + * Copyright (c) Facebook, Inc. and its affiliates. |
| 3 | + * |
| 4 | + * This software may be used and distributed according to the terms of the |
| 5 | + * GNU General Public License version 2. |
| 6 | + */ |
| 7 | + |
| 8 | +use anyhow::{format_err, Error}; |
| 9 | +use bookmarks::BookmarkName; |
| 10 | +use clap::{App, Arg, ArgMatches, SubCommand}; |
| 11 | +use cmdlib::args; |
| 12 | +use futures_ext::{try_boxfuture, BoxFuture, FutureExt}; |
| 13 | +use futures_old::future::{err, ok}; |
| 14 | +use megarepolib::common::ChangesetArgs; |
| 15 | +use mononoke_types::DateTime; |
| 16 | + |
| 17 | +pub const COMMIT_HASH: &'static str = "commit-hash"; |
| 18 | +pub const MOVE: &'static str = "move"; |
| 19 | +pub const MERGE: &'static str = "merge"; |
| 20 | +pub const MARK_PUBLIC: &'static str = "mark-public"; |
| 21 | +pub const ORIGIN_REPO: &'static str = "origin-repo"; |
| 22 | +pub const CHANGESET: &'static str = "commit"; |
| 23 | +pub const FIRST_PARENT: &'static str = "first-parent"; |
| 24 | +pub const SECOND_PARENT: &'static str = "second-parent"; |
| 25 | +pub const COMMIT_MESSAGE: &'static str = "commit-message"; |
| 26 | +pub const COMMIT_AUTHOR: &'static str = "commit-author"; |
| 27 | +pub const COMMIT_DATE_RFC3339: &'static str = "commit-date-rfc3339"; |
| 28 | +pub const COMMIT_BOOKMARK: &'static str = "bookmark"; |
| 29 | +pub const SYNC_DIAMOND_MERGE: &'static str = "sync-diamond-merge"; |
| 30 | +pub const MAX_NUM_OF_MOVES_IN_COMMIT: &'static str = "max-num-of-moves-in-commit"; |
| 31 | + |
| 32 | +pub fn cs_args_from_matches<'a>(sub_m: &ArgMatches<'a>) -> BoxFuture<ChangesetArgs, Error> { |
| 33 | + let message = try_boxfuture!(sub_m |
| 34 | + .value_of(COMMIT_MESSAGE) |
| 35 | + .ok_or_else(|| format_err!("missing argument {}", COMMIT_MESSAGE))) |
| 36 | + .to_string(); |
| 37 | + let author = try_boxfuture!(sub_m |
| 38 | + .value_of(COMMIT_AUTHOR) |
| 39 | + .ok_or_else(|| format_err!("missing argument {}", COMMIT_AUTHOR))) |
| 40 | + .to_string(); |
| 41 | + let datetime = try_boxfuture!(sub_m |
| 42 | + .value_of(COMMIT_DATE_RFC3339) |
| 43 | + .map(|datetime_str| DateTime::from_rfc3339(datetime_str)) |
| 44 | + .unwrap_or_else(|| Ok(DateTime::now()))); |
| 45 | + let bookmark = try_boxfuture!(sub_m |
| 46 | + .value_of(COMMIT_BOOKMARK) |
| 47 | + .map(|bookmark_str| BookmarkName::new(bookmark_str)) |
| 48 | + .transpose()); |
| 49 | + let mark_public = sub_m.is_present(MARK_PUBLIC); |
| 50 | + if !mark_public && bookmark.is_some() { |
| 51 | + return err(format_err!( |
| 52 | + "--mark-public is required if --bookmark is provided" |
| 53 | + )) |
| 54 | + .boxify(); |
| 55 | + } |
| 56 | + |
| 57 | + ok(ChangesetArgs { |
| 58 | + author, |
| 59 | + message, |
| 60 | + datetime, |
| 61 | + bookmark, |
| 62 | + mark_public, |
| 63 | + }) |
| 64 | + .boxify() |
| 65 | +} |
| 66 | + |
| 67 | +fn add_resulting_commit_args<'a, 'b>(subcommand: App<'a, 'b>) -> App<'a, 'b> { |
| 68 | + subcommand |
| 69 | + .arg( |
| 70 | + Arg::with_name(COMMIT_AUTHOR) |
| 71 | + .help("commit author to use") |
| 72 | + .takes_value(true) |
| 73 | + .required(true), |
| 74 | + ) |
| 75 | + .arg( |
| 76 | + Arg::with_name(COMMIT_MESSAGE) |
| 77 | + .help("commit message to use") |
| 78 | + .takes_value(true) |
| 79 | + .required(true), |
| 80 | + ) |
| 81 | + .arg( |
| 82 | + Arg::with_name(MARK_PUBLIC) |
| 83 | + .help("add the resulting commit to the public phase") |
| 84 | + .long(MARK_PUBLIC), |
| 85 | + ) |
| 86 | + .arg( |
| 87 | + Arg::with_name(COMMIT_DATE_RFC3339) |
| 88 | + .help("commit date to use (default is now)") |
| 89 | + .long(COMMIT_DATE_RFC3339) |
| 90 | + .takes_value(true), |
| 91 | + ) |
| 92 | + .arg( |
| 93 | + Arg::with_name(COMMIT_BOOKMARK) |
| 94 | + .help("bookmark to point to resulting commits (no sanity checks, will move existing bookmark, be careful)") |
| 95 | + .long(COMMIT_BOOKMARK) |
| 96 | + .takes_value(true) |
| 97 | + ) |
| 98 | +} |
| 99 | + |
| 100 | +pub fn setup_app<'a, 'b>() -> App<'a, 'b> { |
| 101 | + let move_subcommand = SubCommand::with_name(MOVE) |
| 102 | + .about("create a move commit, using a provided spec") |
| 103 | + .arg( |
| 104 | + Arg::with_name(MAX_NUM_OF_MOVES_IN_COMMIT) |
| 105 | + .long(MAX_NUM_OF_MOVES_IN_COMMIT) |
| 106 | + .help("how many files a single commit moves (note - that might create a stack of move commits instead of just one)") |
| 107 | + .takes_value(true) |
| 108 | + .required(false), |
| 109 | + ) |
| 110 | + .arg( |
| 111 | + Arg::with_name(ORIGIN_REPO) |
| 112 | + .help("use predefined mover for part of megarepo, coming from this repo") |
| 113 | + .takes_value(true) |
| 114 | + .required(true), |
| 115 | + ) |
| 116 | + .arg( |
| 117 | + Arg::with_name(CHANGESET) |
| 118 | + .help("a changeset hash or bookmark of move commit's parent") |
| 119 | + .takes_value(true) |
| 120 | + .required(true), |
| 121 | + ); |
| 122 | + |
| 123 | + let merge_subcommand = SubCommand::with_name(MERGE) |
| 124 | + .about("create a merge commit with given parents") |
| 125 | + .arg( |
| 126 | + Arg::with_name(FIRST_PARENT) |
| 127 | + .help("first parent of a produced merge commit") |
| 128 | + .takes_value(true) |
| 129 | + .required(true), |
| 130 | + ) |
| 131 | + .arg( |
| 132 | + Arg::with_name(SECOND_PARENT) |
| 133 | + .help("second parent of a produced merge commit") |
| 134 | + .takes_value(true) |
| 135 | + .required(true), |
| 136 | + ); |
| 137 | + |
| 138 | + let sync_diamond_subcommand = SubCommand::with_name(SYNC_DIAMOND_MERGE) |
| 139 | + .about("sync a diamond merge commit from a small repo into large repo") |
| 140 | + .arg( |
| 141 | + Arg::with_name(COMMIT_HASH) |
| 142 | + .help("diamond merge commit from small repo to sync") |
| 143 | + .takes_value(true) |
| 144 | + .required(true), |
| 145 | + ) |
| 146 | + .arg( |
| 147 | + Arg::with_name(COMMIT_BOOKMARK) |
| 148 | + .help("bookmark to point to resulting commits (no sanity checks, will move existing bookmark, be careful)") |
| 149 | + .long(COMMIT_BOOKMARK) |
| 150 | + .takes_value(true) |
| 151 | + ); |
| 152 | + |
| 153 | + args::MononokeApp::new("megarepo preparation tool") |
| 154 | + .with_advanced_args_hidden() |
| 155 | + .with_source_and_target_repos() |
| 156 | + .build() |
| 157 | + .subcommand(add_resulting_commit_args(move_subcommand)) |
| 158 | + .subcommand(add_resulting_commit_args(merge_subcommand)) |
| 159 | + .subcommand(sync_diamond_subcommand) |
| 160 | +} |
0 commit comments