@@ -380,6 +380,112 @@ pub(crate) async fn prepare_for_pull(
380380    Ok ( PreparedPullResult :: Ready ( Box :: new ( prepared_image) ) ) 
381381} 
382382
383+ /// Unified approach: Use bootc's CStorage to pull the image, then prepare from containers-storage. 
384+ /// This reuses the same infrastructure as LBIs. 
385+ pub ( crate )  async  fn  prepare_for_pull_unified ( 
386+     repo :  & ostree:: Repo , 
387+     imgref :  & ImageReference , 
388+     target_imgref :  Option < & OstreeImageReference > , 
389+     store :  & Storage , 
390+ )  -> Result < PreparedPullResult >  { 
391+     // Get or initialize the bootc container storage (same as used for LBIs) 
392+     let  imgstore = store. get_ensure_imgstore ( ) ?; 
393+ 
394+     let  image_ref_str = format ! ( "{imgref:#}" ) ; 
395+ 
396+     // Log the original transport being used for the pull 
397+     tracing:: info!( 
398+         "Unified pull: pulling from transport '{}' to bootc storage" , 
399+         & imgref. transport
400+     ) ; 
401+ 
402+     // Pull the image to bootc storage using the same method as LBIs 
403+     imgstore
404+         . pull ( & image_ref_str,  crate :: podstorage:: PullMode :: Always ) 
405+         . await ?; 
406+ 
407+     // Now create a containers-storage reference to read from bootc storage 
408+     tracing:: info!( "Unified pull: now importing from containers-storage transport" ) ; 
409+     let  containers_storage_imgref = ImageReference  { 
410+         transport :  "containers-storage" . to_string ( ) , 
411+         image :  imgref. image . clone ( ) , 
412+         signature :  imgref. signature . clone ( ) , 
413+     } ; 
414+     let  ostree_imgref = OstreeImageReference :: from ( containers_storage_imgref) ; 
415+ 
416+     // Use the standard preparation flow but reading from containers-storage 
417+     let  mut  imp = new_importer ( repo,  & ostree_imgref) . await ?; 
418+     if  let  Some ( target)  = target_imgref { 
419+         imp. set_target ( target) ; 
420+     } 
421+     let  prep = match  imp. prepare ( ) . await ? { 
422+         PrepareResult :: AlreadyPresent ( c)  => { 
423+             println ! ( "No changes in {imgref:#} => {}" ,  c. manifest_digest) ; 
424+             return  Ok ( PreparedPullResult :: AlreadyPresent ( Box :: new ( ( * c) . into ( ) ) ) ) ; 
425+         } 
426+         PrepareResult :: Ready ( p)  => p, 
427+     } ; 
428+     check_bootc_label ( & prep. config ) ; 
429+     if  let  Some ( warning)  = prep. deprecated_warning ( )  { 
430+         ostree_ext:: cli:: print_deprecated_warning ( warning) . await ; 
431+     } 
432+     ostree_ext:: cli:: print_layer_status ( & prep) ; 
433+     let  layers_to_fetch = prep. layers_to_fetch ( ) . collect :: < Result < Vec < _ > > > ( ) ?; 
434+ 
435+     // Log that we're importing a new image from containers-storage 
436+     const  PULLING_NEW_IMAGE_ID :  & str  = "6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0" ; 
437+     tracing:: info!( 
438+         message_id = PULLING_NEW_IMAGE_ID , 
439+         bootc. image. reference = & imgref. image, 
440+         bootc. image. transport = "containers-storage" , 
441+         bootc. original_transport = & imgref. transport, 
442+         bootc. status = "importing_from_storage" , 
443+         "Importing image from bootc storage: {}" , 
444+         ostree_imgref
445+     ) ; 
446+ 
447+     let  prepared_image = PreparedImportMeta  { 
448+         imp, 
449+         n_layers_to_fetch :  layers_to_fetch. len ( ) , 
450+         layers_total :  prep. all_layers ( ) . count ( ) , 
451+         bytes_to_fetch :  layers_to_fetch. iter ( ) . map ( |( l,  _) | l. layer . size ( ) ) . sum ( ) , 
452+         bytes_total :  prep. all_layers ( ) . map ( |l| l. layer . size ( ) ) . sum ( ) , 
453+         digest :  prep. manifest_digest . clone ( ) , 
454+         prep, 
455+     } ; 
456+ 
457+     Ok ( PreparedPullResult :: Ready ( Box :: new ( prepared_image) ) ) 
458+ } 
459+ 
460+ /// Unified pull: Use podman to pull to containers-storage, then read from there 
461+ pub ( crate )  async  fn  pull_unified ( 
462+     repo :  & ostree:: Repo , 
463+     imgref :  & ImageReference , 
464+     target_imgref :  Option < & OstreeImageReference > , 
465+     quiet :  bool , 
466+     prog :  ProgressWriter , 
467+     store :  & Storage , 
468+ )  -> Result < Box < ImageState > >  { 
469+     match  prepare_for_pull_unified ( repo,  imgref,  target_imgref,  store) . await ? { 
470+         PreparedPullResult :: AlreadyPresent ( existing)  => { 
471+             // Log that the image was already present (Debug level since it's not actionable) 
472+             const  IMAGE_ALREADY_PRESENT_ID :  & str  = "5c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f9" ; 
473+             tracing:: debug!( 
474+                 message_id = IMAGE_ALREADY_PRESENT_ID , 
475+                 bootc. image. reference = & imgref. image, 
476+                 bootc. image. transport = & imgref. transport, 
477+                 bootc. status = "already_present" , 
478+                 "Image already present: {}" , 
479+                 imgref
480+             ) ; 
481+             Ok ( existing) 
482+         } 
483+         PreparedPullResult :: Ready ( prepared_image_meta)  => { 
484+             pull_from_prepared ( imgref,  quiet,  prog,  * prepared_image_meta) . await 
485+         } 
486+     } 
487+ } 
488+ 
383489#[ context( "Pulling" ) ]  
384490pub ( crate )  async  fn  pull_from_prepared ( 
385491    imgref :  & ImageReference , 
@@ -429,18 +535,21 @@ pub(crate) async fn pull_from_prepared(
429535    let  imgref_canonicalized = imgref. clone ( ) . canonicalize ( ) ?; 
430536    tracing:: debug!( "Canonicalized image reference: {imgref_canonicalized:#}" ) ; 
431537
432-     // Log successful import completion 
433-     const  IMPORT_COMPLETE_JOURNAL_ID :  & str  = "4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f9a8" ; 
434- 
435-     tracing:: info!( 
436-         message_id = IMPORT_COMPLETE_JOURNAL_ID , 
437-         bootc. image. reference = & imgref. image, 
438-         bootc. image. transport = & imgref. transport, 
439-         bootc. manifest_digest = import. manifest_digest. as_ref( ) , 
440-         bootc. ostree_commit = & import. merge_commit, 
441-         "Successfully imported image: {}" , 
442-         imgref
443-     ) ; 
538+     // Log successful import completion (skip if using unified storage to avoid double logging) 
539+     let  is_unified_path = imgref. transport  == "containers-storage" ; 
540+     if  !is_unified_path { 
541+         const  IMPORT_COMPLETE_JOURNAL_ID :  & str  = "4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f9a8" ; 
542+ 
543+         tracing:: info!( 
544+             message_id = IMPORT_COMPLETE_JOURNAL_ID , 
545+             bootc. image. reference = & imgref. image, 
546+             bootc. image. transport = & imgref. transport, 
547+             bootc. manifest_digest = import. manifest_digest. as_ref( ) , 
548+             bootc. ostree_commit = & import. merge_commit, 
549+             "Successfully imported image: {}" , 
550+             imgref
551+         ) ; 
552+     } 
444553
445554    if  let  Some ( msg)  =
446555        ostree_container:: store:: image_filtered_content_warning ( & import. filtered_files ) 
0 commit comments