More download/unpack CLI progress

This commit is contained in:
Disassembler 2020-02-17 23:50:20 +01:00
parent 4497e1e793
commit 67f994f190
No known key found for this signature in database
GPG Key ID: 524BD33A0EE29499
2 changed files with 40 additions and 21 deletions

View File

@ -6,9 +6,10 @@ import argparse
from spoc import repo_local from spoc import repo_local
from spoc import repo_online from spoc import repo_online
from spoc import repo_publish from spoc import repo_publish
from spoc.exceptions import ImageNotFoundError
from spoc.image import Image from spoc.image import Image
from spoc.imagebuilder import ImageBuilder from spoc.imagebuilder import ImageBuilder
from spoc.cli import ActionQueue, ActionItem, readable_size from spoc.cli import ActionQueue, readable_size
ACTION_LIST = 1 ACTION_LIST = 1
ACTION_DOWNLOAD = 2 ACTION_DOWNLOAD = 2
@ -36,17 +37,24 @@ def listing(repo_type):
print(image) print(image)
def download(image_name): def download(image_name):
actionqueue = ActionQueue() queue = ActionQueue()
local_images = repo_local.get_images() local_images = repo_local.get_images()
for layer in repo_online.get_image(image_name)['layers']: for layer in repo_online.get_image(image_name)['layers']:
if layer not in local_images: if layer not in local_images:
image = Image(layer, False) queue.download_image(Image(layer, False))
actionqueue.append(ActionItem(f'Downloading {image_name}', image.download)) queue.process()
actionqueue.append(ActionItem(f'Unpacking {image_name}', image.unpack_downloaded))
actionqueue.process()
def delete(image_name): def delete(image_name):
Image(image_name, False).delete() # TODO: Check if any container or image doesn't depend
# TODO: Some kind of autoremove routine for images unused in containers
try:
image = Image(image_name)
except ImageNotFoundError:
return
queue = ActionQueue()
for layer in reversed(image.layers):
queue.delete_image(Image(layer, False))
queue.process()
def build(filename, force, do_publish): def build(filename, force, do_publish):
# Check if a build is needed and attempt to build the image from image file # Check if a build is needed and attempt to build the image from image file
@ -68,8 +76,8 @@ def publish(image_name, force):
# Check if publishing is needed and attempt to publish the image # Check if publishing is needed and attempt to publish the image
if force or image_name not in repo_publish.get_images(): if force or image_name not in repo_publish.get_images():
image = Image(image_name) image = Image(image_name)
image.unpublish()
print(f'Publishing image {image_name}') print(f'Publishing image {image_name}')
image.unpublish()
image.publish() image.publish()
print(f'Image {image_name} compressed from {readable_size(image.size)} to {readable_size(image.dlsize)} and published successfully') print(f'Image {image_name} compressed from {readable_size(image.size)} to {readable_size(image.dlsize)} and published successfully')
else: else:

View File

@ -10,8 +10,12 @@ class ActionQueue:
def __init__(self): def __init__(self):
self.queue = [] self.queue = []
def append(self, actionitem): def download_image(self, image):
self.queue.append(actionitem) self.queue.append(ActionItem(f'Downloading image {image.name}', image.download))
self.queue.append(ActionItem(f'Unpacking image {image.name}', image.unpack_downloaded))
def delete_image(self, image):
self.queue.append(ActionItem(f'Deleting image {image.name}', image.delete, False))
def process(self): def process(self):
index = 0 index = 0
@ -22,23 +26,30 @@ class ActionQueue:
item.run() item.run()
class ActionItem: class ActionItem:
def __init__(self, text, action): def __init__(self, text, action, has_progress=True):
self.text = text self.text = text
self.action = action self.action = action
self.units_total = 0 self.has_progress = has_progress
self.units_total = 1
self.units_done = 0 self.units_done = 0
def run(self): def run(self):
if self.has_progress:
with ThreadPoolExecutor() as executor: with ThreadPoolExecutor() as executor:
future = executor.submit(self.action, self) future = executor.submit(self.action, self)
while not future.done(): while not future.done():
time.sleep(0.2) time.sleep(0.2)
self.print_status() self.print_progress()
# Get the result of the future and let it raise exception, if there was any # Get the result of the future and let it raise exception, if there was any
data = future.result() data = future.result()
self.print_status('\n') self.print_progress('\n')
else:
self.print_progress()
self.action()
self.units_done = 1
self.print_progress('\n')
def print_status(self, end='\r'): def print_progress(self, end='\r'):
print(f'\x1b[K{self.text} ({self.units_done}/{self.units_total}) [{self.units_done/self.units_total*100:.2f} %]', end=end) print(f'\x1b[K{self.text} ({self.units_done}/{self.units_total}) [{self.units_done/self.units_total*100:.2f} %]', end=end)
def readable_size(bytes): def readable_size(bytes):