@@ -22,15 +22,24 @@ pub async fn run(mut args: Vec<String>) -> Result<()> {
2222 "_import" => return setup:: cmd_import ( ) . await ,
2323 "version" | "--version" | "-V" => { print_version ( ) ; return Ok ( ( ) ) ; }
2424 "features" => { build_mode:: Features :: current ( ) . print ( ) ; return Ok ( ( ) ) ; }
25+ "oci" => return run_oci ( & rest) . await ,
2526 "help" | "--help" | "-h" | "" => { print_help ( ) ; return Ok ( ( ) ) ; }
2627 _ => { }
2728 }
2829
2930 // ── Live system guard ──────────────────────────────────────
30- let live_safe = matches ! ( cmd,
31- "immutable" | "doctor" | "version" | "features" | "log" | "logs"
32- ) ;
33- if !live_safe { livecheck:: assert_not_live ( ) ; }
31+ // Only the atomic build actually requires a real installed root
32+ // (generations, immutable /usr, GRUB entries, etc — none of which
33+ // exist or make sense on a live ISO / container overlay root).
34+ // --features normal-mode is explicitly designed to work anywhere,
35+ // including containers and live-booted systems (see the "Live-boot
36+ // note" in internal/build_mode.rs) — it must never hit this guard.
37+ if !build_mode:: NORMAL_MODE {
38+ let live_safe = matches ! ( cmd,
39+ "immutable" | "doctor" | "version" | "features" | "log" | "logs"
40+ ) ;
41+ if !live_safe { livecheck:: assert_not_live ( ) ; }
42+ }
3443
3544 if flags. user_mode {
3645 return pkg:: run_user ( cmd, & rest, & flags) . await ;
@@ -105,13 +114,16 @@ pub async fn run(mut args: Vec<String>) -> Result<()> {
105114 sys:: cmd_rollback ( & rest)
106115 }
107116 "diff" => sys:: cmd_diff ( & rest) ,
108- "pending" => sys:: cmd_pending ( & rest) ,
117+ "pending" => {
118+ build_mode:: require_atomic ( "hammer pending" ) ?;
119+ sys:: cmd_pending ( & rest)
120+ }
109121
110122 // ── Query v0.5 ────────────────────────────────────────
111123 "what" => crate :: file_index:: cmd_what ( & rest) ,
112124 "what-rebuild" => crate :: file_index:: cmd_what_rebuild ( ) ,
113125 "size" => crate :: size:: cmd_size ( & rest) ,
114- "undo" => crate :: undo:: cmd_undo ( & rest) ,
126+ "undo" => { build_mode :: require_atomic ( "hammer undo" ) ? ; crate :: undo:: cmd_undo ( & rest) }
115127 "show-deps" => crate :: query:: cmd_show_deps ( & rest) ,
116128 "owns" => crate :: query:: cmd_owns ( & rest) ,
117129 "stats" => crate :: query:: cmd_stats ( ) ,
@@ -186,6 +198,25 @@ pub async fn run(mut args: Vec<String>) -> Result<()> {
186198 }
187199}
188200
201+ // ─────────────────────────────────────────────────────────────
202+ // OCI mode (--features oci-mode only; graceful message otherwise)
203+ // ─────────────────────────────────────────────────────────────
204+
205+ #[ cfg( feature = "oci-mode" ) ]
206+ async fn run_oci ( rest : & [ String ] ) -> Result < ( ) > {
207+ crate :: oci:: cmd:: run ( rest) . await
208+ }
209+
210+ #[ cfg( not( feature = "oci-mode" ) ) ]
211+ async fn run_oci ( _rest : & [ String ] ) -> Result < ( ) > {
212+ eprintln ! ( ) ;
213+ eprintln ! ( " {} 'hammer oci' is only available in builds compiled with" , "!" . yellow( ) . bold( ) ) ;
214+ eprintln ! ( " {}." , "--features oci-mode" . cyan( ) ) ;
215+ eprintln ! ( " This binary was built without it (run 'hammer features' to check)." ) ;
216+ eprintln ! ( ) ;
217+ process:: exit ( 1 ) ;
218+ }
219+
189220// ─────────────────────────────────────────────────────────────
190221// Version
191222// ─────────────────────────────────────────────────────────────
0 commit comments