Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only upload file to device if remote is different #107

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 86 additions & 5 deletions scripts/microupload.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
-X --exclude=PATH Path to exclude, may be repeated.
-C --chdir=PATH Change current directory to path.
-v --verbose Verbose output.
-d --different Only Upload if remote file is different to local file.
"""

import time
Expand All @@ -31,21 +32,83 @@
from typing import List, Iterable, TypeVar, Sequence, Set

from docopt import docopt
from ampy.pyboard import Pyboard
from ampy.pyboard import Pyboard, PyboardError
from ampy.files import Files, DirectoryExistsError
from hashlib import sha1
import textwrap


__all__ = []

verbose = False
verbose = True
T = TypeVar('T')

def get_hash(self, filename):
command = """
import sys
from uhashlib import sha1
import ubinascii
hash = sha1()
with open('{0}', 'rb') as infile:
while True:
result = infile.read({1})
hash.update(result)
if result == b'':
break
len = sys.stdout.write(ubinascii.hexlify(hash.digest()))
infile.close()
""".format(
filename, 32
)
self._pyboard.enter_raw_repl()
try:
out = self._pyboard.exec_(textwrap.dedent(command))
except PyboardError as ex:
# Check if this is an OSError #2, i.e. file doesn't exist and
# rethrow it as something more descriptive.
if ex.args[2].decode("utf-8").find("OSError: [Errno 2] ENOENT") != -1:
self._pyboard.exit_raw_repl()
return ""
else:
raise ex
self._pyboard.exit_raw_repl()
return out.decode('utf-8')

def get_size(self, filename):
command = """
import sys
import os

len = sys.stdout.write(str(os.stat('{0}')[6]).encode('utf-8'))
""".format(
filename
)
self._pyboard.enter_raw_repl()
try:
out = self._pyboard.exec_(textwrap.dedent(command))
except PyboardError as ex:
# Check if this is an OSError #2, i.e. file doesn't exist and
# rethrow it as something more descriptive.
if ex.args[2].decode("utf-8").find("OSError: [Errno 2] ENOENT") != -1:
self._pyboard.exit_raw_repl()
return "-1"
else:
raise ex
self._pyboard.exit_raw_repl()
return out.decode('utf-8')

Files.get_hash = get_hash
Files.get_size = get_size

def main(args: List[str]) -> None:
global verbose

start_time = time.time()

opts = docopt(__doc__, argv=args)
verbose = opts['--verbose']
root = opts['PATH']
different = opts['--different']

chdir = opts['--chdir']
if chdir:
Expand All @@ -64,22 +127,40 @@ def main(args: List[str]) -> None:
for x in list_files(root, opts['--exclude'])]
else:
to_upload = [rel_root]

created_cache = set()
for path in progress('Uploading files', to_upload):
local_path = os.path.abspath(path)
remote_path = os.path.normpath(path)
remote_path = os.path.normpath(path).replace(os.path.sep, '/')
if verbose:
print('\n{} -> {}'.format(local_path, remote_path),
file=sys.stderr, flush=True)
remote_dir = os.path.dirname(path)
if remote_dir:
make_dirs(files, remote_dir, created_cache)

with open(local_path, 'rb') as fd:
files.put(remote_path, fd.read())
if different:
raw = fd.read()
local_file_size = str(os.stat(local_path)[6])
local_file_hash = sha1(raw).hexdigest()

remote_file_size = files.get_size(remote_path)
if local_file_size == remote_file_size:
remote_file_hash = files.get_hash(remote_path)
if remote_file_hash == local_file_hash:
print("File Identical... Skipping upload", file=sys.stderr, flush=True)
else:
wait_for_board()
files.put(remote_path, raw)
else:
wait_for_board()
files.put(remote_path, raw)
Comment on lines +147 to +157
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can simplify to something like,

Suggested change
remote_file_size = files.get_size(remote_path)
if local_file_size == remote_file_size:
remote_file_hash = files.get_hash(remote_path)
if remote_file_hash == local_file_hash:
print("File Identical... Skipping upload", file=sys.stderr, flush=True)
else:
wait_for_board()
files.put(remote_path, raw)
else:
wait_for_board()
files.put(remote_path, raw)
if local_file_size == files.get_size(remote_path) and local_file_hash == files.get_hash(remote_path):
print("File Identical... Skipping upload", file=sys.stderr, flush=True)
else:
wait_for_board()
files.put(remote_path, raw)
else:
files.put(remote_path, fd.read())

The interpreter will short-circuit if the size check local_file_size == files.get_size(remote_path) evaluates false, and not calculate the hash too.

else:
files.put(remote_path, fd.read())

print('Soft reboot', file=sys.stderr, flush=True)
soft_reset(board)
print("--- %s seconds ---" % (time.time() - start_time), file=sys.stderr, flush=True)


def make_dirs(files: Files, path: str,
Expand Down