Skip to content

Commit 558d67e

Browse files
committed
cargo-rail: fixed the crate name validation, dry-run, and other command/config issues
1 parent d29fbb1 commit 558d67e

File tree

5 files changed

+84
-43
lines changed

5 files changed

+84
-43
lines changed

src/commands/release.rs

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,26 @@ pub fn run_release_plan(
1717
bump: String,
1818
json: bool,
1919
) -> RailResult<()> {
20-
println!("🔍 Planning release...\n");
20+
if !json {
21+
eprintln!("🔍 Planning release...\n");
22+
}
2123

2224
// Parse bump type
2325
let bump_type = bump.parse::<BumpType>()?;
2426

27+
// Validate crate names exist before planning
28+
if let Some(ref names) = crate_names {
29+
let workspace_members = ctx.graph.workspace_members();
30+
for name in names {
31+
if !workspace_members.contains(name) {
32+
return Err(RailError::with_help(
33+
format!("Crate '{}' not found in workspace", name),
34+
format!("Available crates: {}", workspace_members.join(", ")),
35+
));
36+
}
37+
}
38+
}
39+
2540
// Get release config
2641
let config = ctx.config.as_ref().map(|c| &c.release);
2742
let release_config = config.ok_or_else(|| {
@@ -43,13 +58,13 @@ pub fn run_release_plan(
4358
} else {
4459
println!("{}", plan.format_summary());
4560

46-
println!("📝 This is a dry-run. To execute this release, run:");
61+
eprintln!("\n📝 This is a dry-run. To execute this release, run:");
4762
if let Some(names) = crate_names {
4863
for name in names {
49-
println!(" cargo rail release {} --execute", name);
64+
eprintln!(" cargo rail release {}", name);
5065
}
5166
} else {
52-
println!(" cargo rail release --all --execute");
67+
eprintln!(" cargo rail release --all");
5368
}
5469
}
5570

@@ -64,7 +79,6 @@ pub fn run_release_publish(
6479
crate_names: Option<Vec<String>>,
6580
all: bool,
6681
bump: String,
67-
execute: bool,
6882
skip_publish: bool,
6983
skip_tag: bool,
7084
) -> RailResult<()> {
@@ -98,25 +112,12 @@ pub fn run_release_publish(
98112
validator.validate(&target_crates, release_config.require_clean)?;
99113

100114
// Build release plan
101-
println!("🔍 Building release plan...\n");
115+
eprintln!("🔍 Building release plan...\n");
102116
let planner = ReleasePlanner::new(ctx, release_config);
103117
let plan = planner.plan(targets, &bump_type)?;
104118

105-
// Display plan
106-
println!("{}", plan.format_summary());
107-
108-
// Dry-run check
109-
if !execute {
110-
println!("\n🔍 DRY-RUN MODE - No changes will be made\n");
111-
println!("To execute this release, add --execute flag:");
112-
let target_str = if all {
113-
"--all".to_string()
114-
} else {
115-
target_crates.join(" ")
116-
};
117-
println!(" cargo rail release {} --execute", target_str);
118-
return Ok(());
119-
}
119+
// Display plan with skip flags reflected
120+
println!("{}", plan.format_summary_with_flags(skip_publish, skip_tag));
120121

121122
// Interactive confirmation (if terminal)
122123
if io::stdin().is_terminal() {

src/commands/split.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ pub fn run_split(
2020
dry_run: bool,
2121
json: bool,
2222
) -> RailResult<()> {
23-
println!("📦 Loaded configuration");
23+
if !json {
24+
eprintln!("📦 Loaded configuration");
25+
}
2426

2527
// Build configurations using the centralized builder
2628
let builder = SplitSyncConfigBuilder::new(ctx)?
@@ -31,12 +33,12 @@ pub fn run_split(
3133
let all_local = builder.all_local();
3234
let config_count = builder.count();
3335

34-
if all_local && !dry_run {
35-
println!(" Local testing mode\n");
36+
if all_local && !dry_run && !json {
37+
eprintln!(" Local testing mode\n");
3638
}
3739

38-
if all {
39-
println!(" Splitting all {} configured crates", config_count);
40+
if all && !json {
41+
eprintln!(" Splitting all {} configured crates", config_count);
4042
}
4143

4244
let configs = builder.build_split_configs()?;

src/commands/sync.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ pub fn run_sync(
2828
// Parse conflict strategy
2929
let conflict_strategy = ConflictStrategy::from_str(&strategy_str)?;
3030

31-
println!("📦 Loaded configuration");
31+
if !json {
32+
eprintln!("📦 Loaded configuration");
33+
}
3234

3335
// Build configurations using the centralized builder
3436
let builder = SplitSyncConfigBuilder::new(ctx)?
@@ -40,8 +42,8 @@ pub fn run_sync(
4042
let all_local = builder.all_local();
4143
let config_count = builder.count();
4244

43-
if all_local && !dry_run {
44-
println!(" Local testing mode\n");
45+
if all_local && !dry_run && !json {
46+
eprintln!(" Local testing mode\n");
4547
}
4648

4749
// Determine sync direction
@@ -53,21 +55,27 @@ pub fn run_sync(
5355
));
5456
}
5557
(true, false) => {
56-
println!(" Direction: remote → monorepo");
58+
if !json {
59+
eprintln!(" Direction: remote → monorepo");
60+
}
5761
SyncDirection::RemoteToMono
5862
}
5963
(false, true) => {
60-
println!(" Direction: monorepo → remote");
64+
if !json {
65+
eprintln!(" Direction: monorepo → remote");
66+
}
6167
SyncDirection::MonoToRemote
6268
}
6369
(false, false) => {
64-
println!(" Direction: bidirectional");
70+
if !json {
71+
eprintln!(" Direction: bidirectional");
72+
}
6573
SyncDirection::Both
6674
}
6775
};
6876

69-
if all {
70-
println!(" Syncing all {} configured crates", config_count);
77+
if all && !json {
78+
eprintln!(" Syncing all {} configured crates", config_count);
7179
}
7280

7381
let configs = builder.build_sync_configs()?;

src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ enum Commands {
112112
/// Split a crate from monorepo to separate repo with history
113113
///
114114
/// Usage:
115-
/// cargo rail split init <crate> - Initialize split config for crate(s)
115+
/// cargo rail split init - Initialize split config for all workspace crates
116116
/// cargo rail split <crate> - Execute split for a crate
117117
/// cargo rail split --all - Execute split for all configured crates
118118
/// cargo rail split --dry-run - Preview split operations
@@ -425,7 +425,7 @@ fn main() {
425425
commands::run_release_plan(&ctx, names, bump, json)
426426
} else {
427427
// Execute mode: perform the release
428-
commands::run_release_publish(&ctx, names, all, bump, true, skip_publish, skip_tag)
428+
commands::run_release_publish(&ctx, names, all, bump, skip_publish, skip_tag)
429429
}
430430
}
431431
}

src/release/planner.rs

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,11 @@ impl<'a> ReleasePlanner<'a> {
184184

185185
impl ReleasePlan {
186186
/// Format summary for display
187-
pub fn format_summary(&self) -> String {
187+
///
188+
/// # Arguments
189+
/// * `skip_publish` - If true, show publishing as skipped for all crates
190+
/// * `skip_tag` - If true, show tagging as skipped for all crates
191+
pub fn format_summary_with_flags(&self, skip_publish: bool, skip_tag: bool) -> String {
188192
let mut output = String::new();
189193

190194
output.push_str("📦 Release Plan\n\n");
@@ -195,23 +199,49 @@ impl ReleasePlan {
195199
" Version: {} → {}\n",
196200
crate_plan.current_version, crate_plan.new_version
197201
));
198-
output.push_str(&format!(" Tag: {}\n", crate_plan.tag_name));
199-
output.push_str(&format!(
200-
" Publish: {}\n",
201-
if crate_plan.publish { "✓" } else { "✗ (skipped)" }
202-
));
202+
203+
// Show tag status
204+
let tag_status = if skip_tag {
205+
"✗ (--skip-tag)"
206+
} else {
207+
&crate_plan.tag_name
208+
};
209+
output.push_str(&format!(" Tag: {}\n", tag_status));
210+
211+
// Show publish status
212+
let publish_status = if skip_publish {
213+
"✗ (--skip-publish)".to_string()
214+
} else if crate_plan.publish {
215+
"✓".to_string()
216+
} else {
217+
"✗ (publish = false)".to_string()
218+
};
219+
output.push_str(&format!(" Publish: {}\n", publish_status));
203220

204221
if !crate_plan.affected_dependents.is_empty() {
205222
output.push_str(&format!(" Affects: {}\n", crate_plan.affected_dependents.join(", ")));
206223
}
207224
output.push('\n');
208225
}
209226

227+
// Adjust summary counts based on flags
228+
let effective_publish_count = if skip_publish {
229+
0
230+
} else {
231+
self.summary.crates_to_publish
232+
};
233+
let effective_tag_count = if skip_tag { 0 } else { self.summary.crates_to_tag };
234+
210235
output.push_str(&format!(
211236
"Summary: {} crate(s), {} to publish, {} tag(s)\n",
212-
self.summary.total_crates, self.summary.crates_to_publish, self.summary.crates_to_tag
237+
self.summary.total_crates, effective_publish_count, effective_tag_count
213238
));
214239

215240
output
216241
}
242+
243+
/// Format summary for display (default: no skip flags)
244+
pub fn format_summary(&self) -> String {
245+
self.format_summary_with_flags(false, false)
246+
}
217247
}

0 commit comments

Comments
 (0)