Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 33 additions & 2 deletions crates/sqlbuild-cli/src/argv/_helpers/normalization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use crate::argv::constants::{
COMMAND_DEST, CONCURRENCY_COMMANDS, CONCURRENCY_ENV_VAR, CURSOR_COMMANDS, DBT_COMMAND,
DBT_DEBUG_COMMAND, DBT_PASSTHROUGH_COMMANDS, DBT_PASSTHROUGH_SEPARATOR, DBT_VERBOSE_OPTION,
DBT_VERBOSE_OPTIONS, DEBUG_OPTION, INT_CONVERTER, JANITOR_COMMAND, NO_COLOR_OPTION,
POSITIONAL_SELECT_COMMANDS, SCOPE_COMMAND, SCOPE_DEFAULT_PAGE_SIZE, SCOPE_GLOBAL_SUMMARY,
SCOPE_KIND_DEST, TEST_COMMAND,
POSITIONAL_SELECT_COMMANDS, RENAME_COMMAND, SCOPE_COMMAND, SCOPE_DEFAULT_PAGE_SIZE,
SCOPE_GLOBAL_SUMMARY, SCOPE_KIND_DEST, TEST_COMMAND,
};
use crate::argv::models::{Namespace, ParserSpec, Value};

Expand Down Expand Up @@ -96,6 +96,12 @@ impl Run<'_> {
));
}
}
if command == RENAME_COMMAND
&& let Some(message) = rename_error(&namespace)
{
let rename: &ParserSpec = subcommand_parser(parser, RENAME_COMMAND).unwrap_or(parser);
return Err(self.error(rename, &message));
}
if command == SCOPE_COMMAND
&& let Some(message) = scope_error(parser, &namespace)
{
Expand Down Expand Up @@ -263,3 +269,28 @@ fn integer(value: &Value) -> i128 {
i128::MAX
})
}

/// The usage error of a `sqb rename` without `--from-file` and without one full pair.
fn rename_error(namespace: &Namespace) -> Option<String> {
if namespace.value("refactor_from_file") != Value::None
|| namespace.value("refactor_new_name") != Value::None
{
return None;
}
let missing: &str = if namespace.value("refactor_target") == Value::None {
"TARGET, NEW_NAME"
} else {
"NEW_NAME"
};
Some(format!("the following arguments are required: {missing}"))
}

/// The parser of sub-command `name` below `parser`.
fn subcommand_parser<'a>(parser: &'a ParserSpec, name: &str) -> Option<&'a ParserSpec> {
parser
.actions
.iter()
.flat_map(|action| &action.parsers)
.find(|(command, _)| command == name)
.map(|(_, spec)| spec)
}
23 changes: 21 additions & 2 deletions crates/sqlbuild-cli/src/argv/command_table.json
Original file line number Diff line number Diff line change
Expand Up @@ -4891,18 +4891,37 @@
{
"kind": "store",
"dest": "refactor_target",
"required": true,
"nargs": "?",
"help": "<model> or <model>.<column>; the model: and column: prefixes are optional",
"metavar": "TARGET",
"group": 0
},
{
"kind": "store",
"dest": "refactor_new_name",
"required": true,
"nargs": "?",
"metavar": "NEW_NAME",
"group": 0
},
{
"kind": "store",
"dest": "refactor_more_moves",
"nargs": "*",
"default": [],
"help": "further model TARGET NEW_NAME pairs, renamed together with the first",
"metavar": "MORE",
"group": 0
},
{
"kind": "store",
"options": [
"--from-file"
],
"dest": "refactor_from_file",
"help": "read model TARGET NEW_NAME pairs from FILE, one per line; # starts a comment",
"metavar": "FILE",
"group": 1
},
{
"kind": "store_true",
"options": [
Expand Down
1 change: 1 addition & 0 deletions crates/sqlbuild-cli/src/argv/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ pub(crate) const POSITIONAL_SELECT_COMMANDS: [&str; 8] = [
];
pub(crate) const CONCURRENCY_COMMANDS: [&str; 5] = ["audit", "build", "load", "seed", "test"];
pub(crate) const CURSOR_COMMANDS: [&str; 3] = ["build", "load", "plan"];
pub(crate) const RENAME_COMMAND: &str = "rename";
pub(crate) const SCOPE_COMMAND: &str = "scope";
pub(crate) const TEST_COMMAND: &str = "test";
pub(crate) const JANITOR_COMMAND: &str = "janitor";
Expand Down
12 changes: 12 additions & 0 deletions crates/sqlbuild-cli/src/argv/tests/test_parse_cli_arguments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,18 @@ fn given_help_version_or_rejected_arguments_when_parsing_then_exits_after_writin
expected_exit: 2,
expected_last_write: "sqb rules: error[C900]: the following arguments are required: rules_command\n\n",
},
ExitTestCase {
description: "a rename target without a new name stays a usage error",
argv: &["rename", "stg_orders"],
expected_exit: 2,
expected_last_write: "sqb rename: error[C900]: the following arguments are required: NEW_NAME\n\n",
},
ExitTestCase {
description: "a rename without a target or a file stays a usage error",
argv: &["rename"],
expected_exit: 2,
expected_last_write: "sqb rename: error[C900]: the following arguments are required: TARGET, NEW_NAME\n\n",
},
];

for test_case in test_cases {
Expand Down
7 changes: 1 addition & 6 deletions crates/sqlbuild-cli/src/dispatch/main/command_dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use crate::dispatch::constants::{
LINEAGE_ROUTE, LOAD_ROUTE, PLAN_ROUTE, PLAYGROUND_ROUTE, QUERY_ROUTE, RECALL_COMMAND_NAME,
RECALL_ROUTE, REFACTOR_ROUTE, RULES_ROUTE, SCOPE_ROUTE, SEED_ROUTE, SKILLS_ROUTE, TEST_ROUTE,
};
use crate::dispatch::main::unavailable_handler::unavailable_handler;
use crate::dispatch::models::{CommandFacts, Dispatch, DispatchFailure, Route};

/// The route `facts` select, checked in the order the Python dispatcher checked them.
Expand All @@ -21,11 +20,7 @@ pub fn command_dispatch(facts: &CommandFacts) -> Dispatch {
let checked =
|route: &'static Route, failure: Option<DispatchFailure>| Dispatch::Run(route, failure);
match command {
"rename" => checked(
&REFACTOR_ROUTE,
(!facts.refactor_target).then(|| unavailable_handler(command, "C950")),
),
"mv" => run(&REFACTOR_ROUTE),
"rename" | "mv" => run(&REFACTOR_ROUTE),
"contract" => checked(
&CONTRACT_ROUTE,
(!facts.contract_ready).then(|| {
Expand Down
1 change: 0 additions & 1 deletion crates/sqlbuild-cli/src/dispatch/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ pub struct CommandFacts {
pub command: Option<String>,
pub subcommand: Option<String>,
pub json: bool,
pub refactor_target: bool,
pub from_target: bool,
pub contract_ready: bool,
pub format_diff: bool,
Expand Down
1 change: 0 additions & 1 deletion crates/sqlbuild-cli/src/dispatch/tests/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ pub(super) fn facts(command: &str, subcommand: Option<&str>) -> CommandFacts {
CommandFacts {
command: Some(command.to_owned()),
subcommand: subcommand.map(str::to_owned),
refactor_target: true,
from_target: true,
contract_ready: true,
..CommandFacts::default()
Expand Down
19 changes: 5 additions & 14 deletions crates/sqlbuild-cli/src/dispatch/tests/test_command_dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,22 +89,13 @@ fn given_parsed_command_when_dispatching_then_selects_python_dispatcher_route()
expected_dispatch: runs(&SCENARIO_CAPTURE_ROUTE),
},
CommandDispatchTestCase {
description: "rename without a target fails",
facts: CommandFacts {
refactor_target: false,
..facts("rename", None)
},
expected_dispatch: Dispatch::Run(
&REFACTOR_ROUTE,
Some(failure("rename command handler is unavailable", "C950")),
),
description: "rename reads its pairs itself, so they may come only from a file",
facts: facts("rename", None),
expected_dispatch: runs(&REFACTOR_ROUTE),
},
CommandDispatchTestCase {
description: "mv reads its pairs itself, so it may come only from a file",
facts: CommandFacts {
refactor_target: false,
..facts("mv", None)
},
description: "mv reads its pairs itself, so they may come only from a file",
facts: facts("mv", None),
expected_dispatch: runs(&REFACTOR_ROUTE),
},
CommandDispatchTestCase {
Expand Down
Loading
Loading