Skip to content

Commit 98f7d3c

Browse files
committed
cargo-rail: cleaning up dead_code blocks; fixing CI for Windows ARM64 runner (wrong label) and Windows escaping in TOML parsing.
1 parent 3603f5f commit 98f7d3c

File tree

16 files changed

+621
-296
lines changed

16 files changed

+621
-296
lines changed

.github/workflows/commit.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,16 @@ jobs:
4747
runner: windows-latest
4848
cache-key: commit-windows-x64
4949

50-
# Windows ARM64 (GitHub Teams/Enterprise)
50+
# Windows ARM64 (GitHub Free in public repos)
5151
- name: aarch64-pc-windows-msvc
52-
runner: windows-11-arm64
52+
runner: windows-11-arm
5353
cache-key: commit-windows-arm64
5454

5555
# macOS tested locally (not in CI)
5656

5757
steps:
5858
- name: Checkout
59-
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
59+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
6060

6161
- name: Setup
6262
uses: ./.github/actions/setup
@@ -74,7 +74,7 @@ jobs:
7474

7575
- name: Upload Test Results (on failure)
7676
if: failure()
77-
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
77+
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
7878
with:
7979
name: test-results-${{ matrix.target.name }}
8080
path: target/nextest/

TODO.md

Lines changed: 28 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -55,58 +55,53 @@ Build status: ✅ 115 tests passing, zero warnings, cargo deny/audit passing
5555

5656
#### Minor Optimizations (MEDIUM - 20-50ms)
5757

58-
- [ ] Use HashSet for resolved_files membership test (sync.rs:305) - *10 min*
59-
- Currently Vec for `.any()` = O(n), should be HashSet = O(1)
60-
61-
- [ ] Batch path deduplication in walk_filtered_history (split.rs:76-101) - *30 min*
62-
- Currently: `get_commits_touching_path()` per crate_path separately
63-
- Use single git command for all paths
64-
65-
- [ ] Share metadata/transform in parallel split (split.rs:237-261) - *30 min*
66-
- Wrap in Arc instead of creating per thread
67-
68-
- [ ] Simplify git status check (split.rs:420-425) - *10 min*
69-
- Remove redundant `status --porcelain`, just run `add -A`
58+
- [x] Use HashSet for resolved_files membership test - O(1) lookups
59+
- [x] Batch path deduplication in walk_filtered_history - single git command
60+
- [x] Remove unused metadata field in SyncEngine - eliminated unnecessary clone
61+
- [x] Simplify git status check - cleaner logic with diff --cached
7062

7163
### Critical: Code Cleanup (2 hours)
7264

7365
#### DRY Violations (CRITICAL)
7466

75-
- [ ] Extract path normalization helper - *15 min*
76-
- Pattern: `strip_prefix().unwrap_or()` appears 5+ times
77-
- system_git_ops.rs:53-57, 105-109, 136-140; transform.rs:35-39
78-
- Create `SystemGit::normalize_path()`
79-
80-
- [ ] Extract Cargo.toml transformation helper - *30 min*
81-
- Identical 11-line block in split.rs:611-622 and 654-664
82-
- Create `apply_manifest_transform()`
67+
- [x] Extract path normalization helper - SystemGit::normalize_path()
68+
- [x] Extract Cargo.toml transformation helper - Splitter::apply_manifest_transform()
8369

8470
#### Dead Code Suppressions (CRITICAL)
8571

86-
- [ ] Replace module-level `#![allow(dead_code)]` with item-level - *30 min*
87-
- Files: sync.rs, config.rs, transform.rs, files.rs, metadata.rs
88-
- Currently masks accidental dead code
89-
- Keep: plan.rs (documented for future CI/automation)
90-
- Keep: All function-level annotations (legitimate convenience APIs)
72+
- [x] Replace module-level `#![allow(dead_code)]` with item-level
73+
- Removed from: sync.rs, config.rs, transform.rs, files.rs, metadata.rs
74+
- Added item-level annotations with documentation for legitimate API methods
75+
- Kept: plan.rs (documented for future CI/automation)
9176

9277
#### TODO Comments Cleanup (CRITICAL)
9378

94-
- [ ] Resolve sync.rs:139 combined mode TODO - *30 min*
95-
- Either implement or remove combined mode support
96-
- Currently blocks entire file with dead_code suppression
79+
- [x] Resolve sync.rs:139 combined mode TODO - now uses get_commits_touching_paths()
80+
- [x] Address release.rs:66 skip_sync TODO - documented deferral to post-v1
9781

98-
- [ ] Address release.rs:66 skip_sync TODO - *15 min*
99-
- Implement or document deferral
82+
**Week 1 Complete**: All performance optimizations and code cleanup done
10083

101-
**Week 1 Performance Complete**: All critical performance optimizations done
84+
Performance improvements:
10285

10386
- Reverse mapping index: O(1) lookups (100-500ms saved per sync)
10487
- Conflict detection cache: Single git call vs N calls (100ms-1s saved)
10588
- get_changed_files() cache: Eliminated duplicate parsing (10-50ms saved)
10689
- Arc<SecurityConfig>: Cheap clones in parallel (eliminates N deep clones)
10790
- Mapping load cache: Eliminated redundant subprocess calls (50ms saved)
108-
- Type complexity warning: Fixed with ConflictResolutionResult type alias
109-
- Dead code warning: Fixed with proper documentation + #[allow(dead_code)]
91+
- HashSet for resolved_files: O(1) vs O(n) membership testing
92+
- Batched path operations: Single git command for multiple paths
93+
- Removed unused metadata field: Eliminated unnecessary WorkspaceMetadata clone
94+
95+
Code quality improvements:
96+
97+
- Extracted SystemGit::normalize_path() helper (5 duplicates removed)
98+
- Extracted Splitter::apply_manifest_transform() helper (3 duplicates removed)
99+
- Replaced all module-level #![allow(dead_code)] with item-level annotations
100+
- Resolved sync.rs combined mode TODO (now handles both single and combined modes)
101+
- Documented skip_sync deferral in release.rs
102+
- Simplified git status check logic
103+
- Zero compiler warnings
104+
- All 115 tests passing
110105

111106
---
112107

src/cargo/files.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#![allow(dead_code)]
2-
31
use crate::core::error::{RailResult, ResultExt};
42
use crate::ui::progress::FileProgress;
53
use std::fs;

src/cargo/metadata.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#![allow(dead_code)]
2-
31
use crate::core::error::RailResult;
42
use cargo_metadata::{MetadataCommand, Package};
53
use std::path::Path;
@@ -22,6 +20,8 @@ impl WorkspaceMetadata {
2220
self.metadata.workspace_packages()
2321
}
2422

23+
/// Get package by name - public API for external use
24+
#[allow(dead_code)]
2525
pub fn get_package(&self, name: &str) -> Option<&Package> {
2626
self
2727
.metadata
@@ -34,7 +34,8 @@ impl WorkspaceMetadata {
3434
self.metadata.workspace_root.as_std_path()
3535
}
3636

37-
/// Get raw JSON string for external tools
37+
/// Get raw JSON string for external tools - public API for debugging/logging
38+
#[allow(dead_code)]
3839
pub fn to_json_string(&self) -> RailResult<String> {
3940
serde_json::to_string(&self.metadata)
4041
.map_err(|e| crate::core::error::RailError::message(format!("Failed to serialize metadata: {}", e)))

src/cargo/transform.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
#![allow(dead_code)]
2-
31
use crate::cargo::metadata::WorkspaceMetadata;
42
use crate::core::error::{RailError, RailResult, ResultExt};
53
use std::collections::HashMap;
64
use std::path::PathBuf;
75
use toml_edit::{DocumentMut, Item, Value};
86

9-
/// Context for transforming Cargo.toml
7+
/// Context for transformation operations
108
pub struct TransformContext {
9+
/// Crate name being transformed - public API field for future use
10+
#[allow(dead_code)]
1111
pub crate_name: String,
12+
/// Workspace root path - public API field for future use
13+
#[allow(dead_code)]
1214
pub workspace_root: PathBuf,
1315
}
1416

src/commands/release.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ pub fn run_release_plan(name: Option<String>, all: bool, json: bool) -> RailResu
6363
pub fn run_release_apply(
6464
name: String,
6565
dry_run: bool,
66-
_skip_sync: bool, // TODO: Implement split sync
66+
// Skip syncing to split repos - deferred to post-v1 (see TODO.md Post-v1: Auto-sync to split repos)
67+
#[allow(unused_variables)] skip_sync: bool,
6768
) -> RailResult<()> {
6869
let workspace_root = env::current_dir()?;
6970

src/commands/split.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,13 @@ fn prompt_for_confirmation(message: &str) -> RailResult<bool> {
2222
}
2323

2424
/// Run the split command
25-
pub fn run_split(crate_name: Option<String>, all: bool, apply: bool, json: bool) -> RailResult<()> {
25+
pub fn run_split(
26+
crate_name: Option<String>,
27+
all: bool,
28+
remote: Option<String>,
29+
apply: bool,
30+
json: bool,
31+
) -> RailResult<()> {
2632
let current_dir = env::current_dir()?;
2733

2834
// Load configuration
@@ -35,8 +41,8 @@ pub fn run_split(crate_name: Option<String>, all: bool, apply: bool, json: bool)
3541
let config = RailConfig::load(&current_dir)?;
3642
println!("📦 Loaded configuration from .rail/config.toml");
3743

38-
// Determine which crates to split (need this to check if they're all local)
39-
let crates_to_split_check: Vec<_> = if all {
44+
// Determine which crates to split
45+
let mut crates_to_split_check: Vec<_> = if all {
4046
config.splits.clone()
4147
} else if let Some(ref name) = crate_name {
4248
let split_config = config
@@ -52,6 +58,13 @@ pub fn run_split(crate_name: Option<String>, all: bool, apply: bool, json: bool)
5258
));
5359
};
5460

61+
// Apply remote override if provided (before all_local check)
62+
if let Some(ref remote_override) = remote {
63+
for split_config in &mut crates_to_split_check {
64+
split_config.remote = remote_override.clone();
65+
}
66+
}
67+
5568
// Check if all remotes are local paths (skip SSH checks for local testing)
5669
let all_local = crates_to_split_check
5770
.iter()

src/commands/sync.rs

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,60 @@ use crate::core::sync::{SyncConfig, SyncDirection, SyncEngine, SyncResult};
99
use crate::ui::progress::{FileProgress, MultiProgress};
1010
use rayon::prelude::*;
1111

12+
/// Sync command parameters
13+
pub struct SyncParams {
14+
pub crate_name: Option<String>,
15+
pub all: bool,
16+
pub remote: Option<String>,
17+
pub from_remote: bool,
18+
pub to_remote: bool,
19+
pub strategy_str: String,
20+
pub no_protected_branches: bool,
21+
pub apply: bool,
22+
pub json: bool,
23+
}
24+
1225
/// Run the sync command
26+
#[allow(clippy::too_many_arguments)]
1327
pub fn run_sync(
1428
crate_name: Option<String>,
1529
all: bool,
30+
remote: Option<String>,
1631
from_remote: bool,
1732
to_remote: bool,
1833
strategy_str: String,
34+
no_protected_branches: bool,
1935
apply: bool,
2036
json: bool,
2137
) -> RailResult<()> {
38+
// Convert to struct for internal use
39+
let params = SyncParams {
40+
crate_name,
41+
all,
42+
remote,
43+
from_remote,
44+
to_remote,
45+
strategy_str,
46+
no_protected_branches,
47+
apply,
48+
json,
49+
};
50+
run_sync_impl(params)
51+
}
52+
53+
/// Internal implementation of sync command
54+
fn run_sync_impl(params: SyncParams) -> RailResult<()> {
55+
let SyncParams {
56+
crate_name,
57+
all,
58+
remote,
59+
from_remote,
60+
to_remote,
61+
strategy_str,
62+
no_protected_branches,
63+
apply,
64+
json,
65+
} = params;
2266
// Parse conflict strategy
2367
let strategy = ConflictStrategy::from_str(&strategy_str)?;
2468
let current_dir = env::current_dir()?;
@@ -30,11 +74,17 @@ pub fn run_sync(
3074
}));
3175
}
3276

33-
let config = RailConfig::load(&current_dir)?;
77+
let mut config = RailConfig::load(&current_dir)?;
78+
79+
// Apply CLI overrides to security config if provided
80+
if no_protected_branches {
81+
config.security.protected_branches.clear();
82+
}
83+
3484
println!("📦 Loaded configuration from .rail/config.toml");
3585

36-
// Determine which crates to sync (need this to check if they're all local)
37-
let crates_to_sync_check: Vec<_> = if all {
86+
// Determine which crates to sync
87+
let mut crates_to_sync_check: Vec<_> = if all {
3888
config.splits.clone()
3989
} else if let Some(ref name) = crate_name {
4090
let split_config = config
@@ -50,6 +100,13 @@ pub fn run_sync(
50100
));
51101
};
52102

103+
// Apply remote override if provided (before all_local check)
104+
if let Some(ref remote_override) = remote {
105+
for split_config in &mut crates_to_sync_check {
106+
split_config.remote = remote_override.clone();
107+
}
108+
}
109+
53110
// Check if all remotes are local paths (skip SSH checks for local testing)
54111
let all_local = crates_to_sync_check
55112
.iter()

src/core/config.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#![allow(dead_code)]
2-
31
use crate::core::error::{ConfigError, RailError, RailResult, ResultExt};
42
use serde::{Deserialize, Serialize};
53
use std::fs;
@@ -147,7 +145,8 @@ impl PolicyConfig {
147145
Ok(())
148146
}
149147

150-
/// Check if policy is enabled (any field is set)
148+
/// Check if policy is enabled (any field is set) - public API for conditional logic
149+
#[allow(dead_code)]
151150
pub fn is_enabled(&self) -> bool {
152151
self.resolver.is_some()
153152
|| self.msrv.is_some()

0 commit comments

Comments
 (0)