u2cli: option to ignore inaccessible files

This commit is contained in:
ed 2021-11-16 21:53:00 +01:00
parent c9b1c48c72
commit d01bb69a9c

View file

@ -3,7 +3,7 @@ from __future__ import print_function, unicode_literals
""" """
up2k.py: upload to copyparty up2k.py: upload to copyparty
2021-10-31, v0.11, ed <irc.rizon.net>, MIT-Licensed 2021-11-16, v0.12, ed <irc.rizon.net>, MIT-Licensed
https://github.com/9001/copyparty/blob/hovudstraum/bin/up2k.py https://github.com/9001/copyparty/blob/hovudstraum/bin/up2k.py
- dependencies: requests - dependencies: requests
@ -224,29 +224,47 @@ class CTermsize(object):
ss = CTermsize() ss = CTermsize()
def statdir(top): def _scd(err, top):
"""non-recursive listing of directory contents, along with stat() info""" """non-recursive listing of directory contents, along with stat() info"""
if hasattr(os, "scandir"): with os.scandir(top) as dh:
with os.scandir(top) as dh: for fh in dh:
for fh in dh: abspath = os.path.join(top, fh.name)
yield [os.path.join(top, fh.name), fh.stat()] try:
else: yield [abspath, fh.stat()]
for name in os.listdir(top): except:
abspath = os.path.join(top, name) err.append(abspath)
def _lsd(err, top):
"""non-recursive listing of directory contents, along with stat() info"""
for name in os.listdir(top):
abspath = os.path.join(top, name)
try:
yield [abspath, os.stat(abspath)] yield [abspath, os.stat(abspath)]
except:
err.append(abspath)
def walkdir(top): if hasattr(os, "scandir"):
statdir = _scd
else:
statdir = _lsd
def walkdir(err, top):
"""recursive statdir""" """recursive statdir"""
for ap, inf in sorted(statdir(top)): for ap, inf in sorted(statdir(err, top)):
if stat.S_ISDIR(inf.st_mode): if stat.S_ISDIR(inf.st_mode):
for x in walkdir(ap): try:
yield x for x in walkdir(err, ap):
yield x
except:
err.append(ap)
else: else:
yield ap, inf yield ap, inf
def walkdirs(tops): def walkdirs(err, tops):
"""recursive statdir for a list of tops, yields [top, relpath, stat]""" """recursive statdir for a list of tops, yields [top, relpath, stat]"""
sep = "{0}".format(os.sep).encode("ascii") sep = "{0}".format(os.sep).encode("ascii")
for top in tops: for top in tops:
@ -256,7 +274,7 @@ def walkdirs(tops):
stop = os.path.dirname(top) stop = os.path.dirname(top)
if os.path.isdir(top): if os.path.isdir(top):
for ap, inf in walkdir(top): for ap, inf in walkdir(err, top):
yield stop, ap[len(stop) :].lstrip(sep), inf yield stop, ap[len(stop) :].lstrip(sep), inf
else: else:
d, n = top.rsplit(sep, 1) d, n = top.rsplit(sep, 1)
@ -446,10 +464,21 @@ class Ctl(object):
nfiles = 0 nfiles = 0
nbytes = 0 nbytes = 0
for _, _, inf in walkdirs(ar.files): err = []
for _, _, inf in walkdirs(err, ar.files):
nfiles += 1 nfiles += 1
nbytes += inf.st_size nbytes += inf.st_size
if err:
eprint("\n# failed to access {} paths:\n".format(len(err)))
for x in err:
eprint(x.decode("utf-8", "replace") + "\n")
eprint("^ failed to access those {} paths ^\n\n".format(len(err)))
if not ar.ok:
eprint("aborting because --ok is not set\n")
return
eprint("found {0} files, {1}\n\n".format(nfiles, humansize(nbytes))) eprint("found {0} files, {1}\n\n".format(nfiles, humansize(nbytes)))
self.nfiles = nfiles self.nfiles = nfiles
self.nbytes = nbytes self.nbytes = nbytes
@ -460,7 +489,7 @@ class Ctl(object):
if ar.te: if ar.te:
req_ses.verify = ar.te req_ses.verify = ar.te
self.filegen = walkdirs(ar.files) self.filegen = walkdirs([], ar.files)
if ar.safe: if ar.safe:
self.safe() self.safe()
else: else:
@ -783,6 +812,7 @@ source file/folder selection uses rsync syntax, meaning that:
ap.add_argument("files", type=unicode, nargs="+", help="files and/or folders to process") ap.add_argument("files", type=unicode, nargs="+", help="files and/or folders to process")
ap.add_argument("-a", metavar="PASSWORD", help="password") ap.add_argument("-a", metavar="PASSWORD", help="password")
ap.add_argument("-s", action="store_true", help="file-search (disables upload)") ap.add_argument("-s", action="store_true", help="file-search (disables upload)")
ap.add_argument("--ok", action="store_true", help="continue even if some local files are inaccessible")
ap = app.add_argument_group("performance tweaks") ap = app.add_argument_group("performance tweaks")
ap.add_argument("-j", type=int, metavar="THREADS", default=4, help="parallel connections") ap.add_argument("-j", type=int, metavar="THREADS", default=4, help="parallel connections")
ap.add_argument("-nh", action="store_true", help="disable hashing while uploading") ap.add_argument("-nh", action="store_true", help="disable hashing while uploading")