@@ -683,28 +683,37 @@ public struct VBDiskResizer {
683683 }
684684
685685 let cleanDeviceNode = sanitizeDeviceIdentifier ( deviceNode)
686- var candidates : [ ( info: APFSContainerInfo , size: UInt64 , isLikelyISC : Bool ) ] = [ ]
686+ var candidates : [ ( info: APFSContainerInfo , size: UInt64 , isMainContainer : Bool ) ] = [ ]
687687
688688 for container in containers {
689689 guard let containerRef = container [ " ContainerReference " ] as? String else { continue }
690690 let volumes = container [ " Volumes " ] as? [ [ String : Any ] ] ?? [ ]
691691 let roles = volumes. compactMap { $0 [ " Roles " ] as? [ String ] } . flatMap { $0 }
692- let hasSystemOrData = roles. contains ( where: { $0 == " System " } ) || roles. contains ( where: { $0 == " Data " } )
693692 let hasLockedVolumes = volumes. contains { ( $0 [ " Locked " ] as? Bool ) == true }
694693
694+ // Detect MAIN container: has "System" or "Data" role (the boot/data container)
695+ let hasSystemOrData = roles. contains ( where: { $0 == " System " } ) || roles. contains ( where: { $0 == " Data " } )
696+
697+ // Detect ISC container: has "xART" or "Hardware" roles (unique to Internal Shared Cache)
698+ let hasISCRoles = roles. contains ( where: { $0 == " xART " } ) || roles. contains ( where: { $0 == " Hardware " } )
699+
700+ // The main container is the one with System/Data and NOT ISC
701+ let isMainContainer = hasSystemOrData && !hasISCRoles
702+
695703 let physicalStores = container [ " PhysicalStores " ] as? [ [ String : Any ] ] ?? [ ]
696704 for store in physicalStores {
697705 guard let storeIdentifier = store [ " DeviceIdentifier " ] as? String else { continue }
698706 guard storeIdentifier. hasPrefix ( cleanDeviceNode) || containerRef == cleanDeviceNode else { continue }
699707 let size = store [ " Size " ] as? UInt64 ?? 0
700708 let info = APFSContainerInfo ( container: containerRef, physicalStore: storeIdentifier, hasLockedVolumes: hasLockedVolumes)
701- candidates. append ( ( info: info, size: size, isLikelyISC: !hasSystemOrData) )
709+ candidates. append ( ( info: info, size: size, isMainContainer: isMainContainer) )
710+ NSLog ( " APFS candidate: container= \( containerRef) , store= \( storeIdentifier) , size= \( size) , isMain= \( isMainContainer) , hasSystemOrData= \( hasSystemOrData) , hasISCRoles= \( hasISCRoles) , roles= \( roles) " )
702711 }
703712
704713 if containerRef == cleanDeviceNode {
705714 let size = ( physicalStores. first ? [ " Size " ] as? UInt64 ) ?? 0
706715 let info = APFSContainerInfo ( container: containerRef, physicalStore: nil , hasLockedVolumes: hasLockedVolumes)
707- candidates. append ( ( info: info, size: size, isLikelyISC : !hasSystemOrData ) )
716+ candidates. append ( ( info: info, size: size, isMainContainer : isMainContainer ) )
708717 }
709718 }
710719
@@ -713,17 +722,39 @@ public struct VBDiskResizer {
713722 return nil
714723 }
715724
716- let preferred = candidates. sorted { lhs, rhs in
717- if lhs. info. hasLockedVolumes != rhs. info. hasLockedVolumes {
718- return lhs. info. hasLockedVolumes == false
719- }
720- if lhs. isLikelyISC != rhs. isLikelyISC {
721- return lhs. isLikelyISC == false
722- }
723- return lhs. size > rhs. size
724- } . first
725+ // Selection priority:
726+ // 1. Find the MAIN container (has System/Data, not ISC) that is unlocked
727+ // 2. Fall back to largest unlocked container
728+ // 3. Fall back to any container
729+
730+ let selected : ( info: APFSContainerInfo , size: UInt64 , isMainContainer: Bool ) ?
731+
732+ // First priority: unlocked main container
733+ if let mainUnlocked = candidates. first ( where: { $0. isMainContainer && !$0. info. hasLockedVolumes } ) {
734+ selected = mainUnlocked
735+ NSLog ( " Selected unlocked main APFS container: \( mainUnlocked. info. container) " )
736+ }
737+ // Second priority: any main container (even if locked)
738+ else if let mainAny = candidates. first ( where: { $0. isMainContainer } ) {
739+ selected = mainAny
740+ NSLog ( " Selected main APFS container (locked): \( mainAny. info. container) " )
741+ }
742+ // Third priority: largest unlocked non-main container
743+ else if let largestUnlocked = candidates. filter ( { !$0. info. hasLockedVolumes } ) . max ( by: { $0. size < $1. size } ) {
744+ selected = largestUnlocked
745+ NSLog ( " Selected largest unlocked APFS container: \( largestUnlocked. info. container) " )
746+ }
747+ // Last resort: any container
748+ else {
749+ selected = candidates. first
750+ NSLog ( " Selected fallback APFS container: \( selected? . info. container ?? " none " ) " )
751+ }
752+
753+ if let selected = selected {
754+ NSLog ( " Final APFS container selection: \( selected. info. container) (store: \( selected. info. physicalStore ?? " none " ) , size: \( selected. size) , isMain: \( selected. isMainContainer) ) " )
755+ }
725756
726- return preferred ? . info
757+ return selected ? . info
727758 }
728759
729760 private static func findAPFSContainer( in diskutilOutput: String , deviceNode: String ) -> APFSContainerInfo ? {
0 commit comments