Skip to content
This repository has been archived by the owner on May 28, 2022. It is now read-only.

Commit

Permalink
Invert ordering of layers in most contexts (in both CLI and API) to b…
Browse files Browse the repository at this point in the history
…e more consistent with Docker's own tools. (Breaks behavioral and option compatibility.)
  • Loading branch information
posita committed May 20, 2015
1 parent fce1f24 commit 7b6445b
Show file tree
Hide file tree
Showing 8 changed files with 367 additions and 376 deletions.
28 changes: 13 additions & 15 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -86,32 +86,30 @@ Examples
::

% dimgx nifty-box # show layers for "nifty-box[:latest]"
IMAGE TAG IMAGE ID PARENT ID CREATED LAYER SIZE VIRTUAL SIZE
- 3cb35ae859e7 - 16 days ago 125.1 MB 125.1 MB
debian:jessie 41b730702607 3cb35ae859e7 16 days ago 0 Bytes 125.1 MB
- 60aa72e3db11 41b730702607 7 days ago 0 Bytes 125.1 MB
- 390ac3ff1e87 60aa72e3db11 6 days ago 1.7 kB 125.1 MB
- fec4e64b2b57 390ac3ff1e87 6 days ago 9.4 MB 134.5 MB
- 51a39b466ad7 fec4e64b2b57 6 days ago 0 Bytes 134.5 MB
nifty-box 0bb92bb75744 51a39b466ad7 4 days ago 1.7 kB 134.5 MB
REPO TAG IMAGE ID PARENT ID CREATED LAYER SIZE VIRTUAL SIZE
nifty-box 6667bbd4093c 82e5dcafc08c 18 hours ago 18.8 MB 144.0 MB
- 82e5dcafc08c cd5e80677a53 18 hours ago 1.8 kB 125.2 MB
- cd5e80677a53 df2a0347c9d0 18 hours ago 0 Bytes 125.2 MB
debian:jessie df2a0347c9d0 39bb80489af7 21 hours ago 0 Bytes 125.2 MB
- 39bb80489af7 - 21 hours ago 125.2 MB 125.2 MB

..
::

% dimgx -l 2:4 nifty-box # show only the second through fourth layers
% dimgx -l df2a:82ef nifty-box # show only the second through fourth layers
IMAGE TAG IMAGE ID PARENT ID CREATED LAYER SIZE VIRTUAL SIZE
debian:jessie 60aa72e3db11 41b730702607 7 days ago 0 Bytes 0 Bytes
- 390ac3ff1e87 60aa72e3db11 6 days ago 1.7 kB 1.7 kB
- fec4e64b2b57 390ac3ff1e87 6 days ago 9.4 MB 9.4 MB
- 82e5dcafc08c cd5e80677a53 18 hours ago 1.8 kB 125.2 MB
- cd5e80677a53 df2a0347c9d0 18 hours ago 0 Bytes 125.2 MB
debian:jessie df2a0347c9d0 39bb80489af7 21 hours ago 0 Bytes 125.2 MB

..
::

% dimgx -l 2:4 -t nifty.tar nifty-box # extract them
% du -h nifty.tar
9.0M nifty.tar
% dimgx -l cd5e:6667 -t nifty.tar nifty-box # extract the third through fifth layers
% du -hs nifty.tar
18M nifty.tar

Issues
------
Expand Down
67 changes: 26 additions & 41 deletions _dimgx/cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
__all__ = ()

_LOGGER = getLogger(__name__)
_LAYER_RE_STR = r'(?:0|-?[1-9]\d{0,10}|-?0[Bb][01]+|-?0[Oo][0-7]+|-?0[Xx][0-9A-Fa-f]+|[0-9A-Fa-f]{12,64})'
_LAYER_RE_STR = r'(?:[0-9A-Fa-f]{1,64})'
_LAYER_SPEC_RE = re_compile(r'^(?P<l>{layer_re})(?::(?P<r>{layer_re}))?$'.format(layer_re=_LAYER_RE_STR), IGNORECASE)
_TARGET_STDOUT = '-'
_CMP_BZIP2 = 'bz2'
Expand All @@ -113,13 +113,12 @@
""".format(_EXIT_EXEC, _EXIT_LAYER_SPEC)

_LAYER_GROUP_DESCRIPTION = """
Layers can be specified as indexes [-n..n) (where "n" is the total number of layers present in the image), or Docker image IDs.
Negative indexes count from the end (i.e., "-i" is equivalent to "n - i").
Layers are specified as (partial) Docker image IDs.
Layers may also be specified as ranges in the form "i:j" (where "i" and "j" are indexes or image IDs).
The range "j:i" is equivalent to the reverse of the range "i:j".
Ranges are inclusive, meaning "i:i" is equivalent to "i".
If no layers are specified, all layers are inferred, starting with the root (i.e., primogenitor), and ending with the specified image (i.e., "0:-1").
Layers are extracted in order, which means that files from layers specified later in the command line will overwrite (or block) those from earlier ones where there is a conflict.
If no layers are specified, all layers are inferred, starting with the root (i.e., primogenitor), and ending with IMAGE_SPEC.
Layers are extracted in order, which means that files from layers specified later in the command line will overwrite (or block) those from earlier specifications where there is a conflict.
Ordering is resolved before retrieval so that each distinct layer is only extracted once.
"""

Expand Down Expand Up @@ -233,29 +232,10 @@ def layerspec2index(args, layers, layer_spec_part):
if layer_spec_part is None:
return None

num_layers = len(layers[':layers'])

if len(layer_spec_part) < 12:
try:
li = int(layer_spec_part, 0)

if not args.strict:
new_li = min(max(li, -num_layers), num_layers - 1)

if new_li != li:
li = new_li
_LOGGER.warning('"%s" is out of range (truncating) to "%d")', layer_spec_part, li)

if li >= -num_layers \
and li < num_layers:
return li if li >= 0 else num_layers + li
except ValueError:
pass
else:
try:
return layers[layer_spec_part]
except KeyError:
pass
try:
return layers[layer_spec_part]
except KeyError:
pass

no_layer_msg = '"%s" does not resolve to any layer associated with image "%s"'

Expand Down Expand Up @@ -305,32 +285,37 @@ def printlayerinfo(args, layers, outfile=stdout):

total_size = 0
fields_fmt = '\t'.join([ '{:<23}' ] + [ '{:<15}' ] * 5)
print(fields_fmt.format('IMAGE TAG', 'IMAGE ID', 'PARENT ID', 'CREATED', 'LAYER SIZE', 'VIRTUAL SIZE'), file=outfile)
print(fields_fmt.format('REPO TAG', 'IMAGE ID', 'PARENT ID', 'CREATED', 'LAYER SIZE', 'VIRTUAL SIZE'), file=outfile)

for l in layers:
total_size = sum(( l['Size'] for l in layers ))

for layer in layers:
try:
image_tag = l[':repo_tags'][0]
image_tag = layer[':repo_tags'][0]
except IndexError:
image_tag = '-'

image_id = l[':short_id']
parent_id = l[':parent_id'][:12].lower()
image_id = layer[':short_id']
parent_id = layer[':parent_id'][:12].lower()

if not parent_id:
parent_id = '-'

created = naturaltime(l[':created_dt'])
layer_size = naturalsize(l['Size'])
total_size += l['Size']
created = naturaltime(layer[':created_dt'])
layer_size = naturalsize(layer['Size'])
virt_size = naturalsize(total_size)
print(fields_fmt.format(image_tag, image_id, parent_id, created, layer_size, virt_size), file=outfile)
total_size -= layer['Size']

#=========================================================================
def selectlayers(args, layers):
layer_specs = args.layers

if layer_specs is None:
selected_indexes = list(range(len(layers[':layers'])))

if args.reverse:
selected_indexes.reverse()
else:
selected_indexes = []
last_num_selected_indexes = num_selected_indexes = len(selected_indexes)
Expand Down Expand Up @@ -363,18 +348,18 @@ def selectlayers(args, layers):
else:
_LOGGER.warning(empty_layer_range_msg, v)

if args.reverse:
selected_indexes.reverse()
if not args.reverse:
selected_indexes.reverse()

# Take the last of each index specified (so we don't have to look at
# each distinct layer more than once)
seen = OrderedDict()

for i in selected_indexes[::-1]:
for i in selected_indexes:
if i not in seen:
seen[i] = None # use OrderedDict as an ordered set

top_most_layer_id = None if not seen else layers[':layers'][max(seen)][':id']
selected_layers = [ layers[':layers'][i] for i in seen ][::-1]
top_most_layer_id = None if not seen else layers[':layers'][min(seen)][':id']
selected_layers = [ layers[':layers'][i] for i in seen ]

return top_most_layer_id, selected_layers

0 comments on commit 7b6445b

Please sign in to comment.