@@ -798,18 +798,19 @@ def __exit__(self, unused_type, unused_value, unused_traceback):
798798 pass
799799
800800
801- def _in_whiteout_dir (fs , name ):
801+ def _in_whiteout_dir (fs , opaque_whiteouts , name ):
802802 while name :
803803 dirname = os .path .dirname (name )
804804 if name == dirname :
805805 break
806- if fs .get (dirname ):
806+ if fs .get (dirname ) or dirname in opaque_whiteouts :
807807 return True
808808 name = dirname
809809 return False
810810
811811
812812_WHITEOUT_PREFIX = '.wh.'
813+ _OPAQUE_WHITEOUT_FILENAME = '.wh..wh..opq'
813814
814815
815816def extract (image , tar ):
@@ -823,17 +824,24 @@ def extract(image, tar):
823824 # to whether they are a tombstone or not.
824825 fs = {}
825826
827+ opaque_whiteouts_in_higher_layers = set ()
828+
826829 # Walk the layers, topmost first and add files. If we've seen them in a
827830 # higher layer then we skip them
828831 for layer in image .diff_ids ():
829832 buf = io .BytesIO (image .uncompressed_layer (layer ))
830833 with tarfile .open (mode = 'r:' , fileobj = buf ) as layer_tar :
834+ opaque_whiteouts_in_this_layer = []
831835 for tarinfo in layer_tar :
832836 # If we see a whiteout file, then don't add anything to the tarball
833837 # but ensure that any lower layers don't add a file with the whited
834838 # out name.
835839 basename = os .path .basename (tarinfo .name )
836840 dirname = os .path .dirname (tarinfo .name )
841+
842+ if basename == _OPAQUE_WHITEOUT_FILENAME :
843+ opaque_whiteouts_in_this_layer .append (dirname )
844+
837845 tombstone = basename .startswith (_WHITEOUT_PREFIX )
838846 if tombstone :
839847 basename = basename [len (_WHITEOUT_PREFIX ):]
@@ -845,7 +853,7 @@ def extract(image, tar):
845853 continue
846854
847855 # Check for a whited out parent directory
848- if _in_whiteout_dir (fs , name ):
856+ if _in_whiteout_dir (fs , opaque_whiteouts_in_higher_layers , name ):
849857 continue
850858
851859 # Mark this file as handled by adding its name.
@@ -857,3 +865,4 @@ def extract(image, tar):
857865 tar .addfile (tarinfo , fileobj = layer_tar .extractfile (tarinfo ))
858866 else :
859867 tar .addfile (tarinfo , fileobj = None )
868+ opaque_whiteouts_in_higher_layers .update (opaque_whiteouts_in_this_layer )
0 commit comments