Skip to content
Snippets Groups Projects
Commit e99562a8 authored by ale's avatar ale
Browse files

Implement our own upload logic

Compare size/mtime of remote files before uploading them, do not wipe
remote directory before the upload. Add a --delete option to remove
remote files that do not exist locally.

The results should be more usable than the previous version.
parent 79df0c95
No related branches found
No related tags found
No related merge requests found
import argparse
import logging
import os
import time
from urllib.parse import urlparse
from webdav3.client import Client
from webdav3.client import Client, Urn, RemoteResourceNotFound
TIME_FMT = '%a, %d %b %Y %H:%M:%S %Z'
def upload(client, local_path, remote_path, do_force, do_delete):
if os.path.isdir(local_path):
upload_directory(client, local_path, remote_path, do_force, do_delete)
else:
upload_file(client, local_path, remote_path, do_force)
def upload_directory(client, local_path, remote_path, do_force, do_delete):
client.mkdir(remote_path)
remote_files = set(x.rstrip('/') for x in client.list(remote_path))
urn = Urn(remote_path, directory=True)
for resource_name in os.listdir(local_path):
_remote_path = "{parent}{name}".format(parent=urn.path(), name=resource_name).replace('\\', '')
_local_path = os.path.join(local_path, resource_name)
upload(client, _local_path, _remote_path, do_force, do_delete)
remote_files.discard(resource_name)
if remote_files:
for f in remote_files:
_remote_path = "{parent}{name}".format(parent=urn.path(), name=f).replace('\\', '')
logging.info('deleting %s' % _remote_path)
client.clean(_remote_path)
def upload_file(client, local_path, remote_path, do_force):
if not do_force:
# Stat remote path and compare size and mtime.
local_stat = os.stat(local_path)
try:
remote_stat = client.info(remote_path)
local_mtime = time.mktime(time.gmtime(local_stat.st_mtime))
remote_mtime = time.mktime(time.strptime(remote_stat['modified'], TIME_FMT))
if int(remote_stat['size']) != local_stat.st_size:
logging.info('%s has changed (size differs)', remote_path)
elif remote_mtime <= local_mtime:
logging.info('%s has changed (local file is newer)', remote_path)
else:
logging.info('%s is unchanged, skipping...', remote_path)
return
except RemoteResourceNotFound:
pass
logging.info('uploading %s to %s', local_path, remote_path)
urn = Urn(remote_path)
with open(local_path, 'rb') as fd:
client.execute_request(action='upload', path=urn.quote(), data=fd)
def main():
......@@ -24,7 +77,10 @@ def main():
'like "https://www.autistici.org/dav/myuser/")')
parser.add_argument(
'--force', action='store_true',
help='always overwrite remote files')
help='always upload files even if they seem to not have changed')
parser.add_argument(
'--delete', action='store_true',
help='delete remote files that do not exist locally')
parser.add_argument(
'--verbose', action='store_true',
help='enable WebDAV logging')
......@@ -39,7 +95,7 @@ def main():
parsed_url = urlparse(args.url)
logging.basicConfig(level=logging.DEBUG if args.verbose else logging.ERROR)
logging.basicConfig(level=logging.INFO if args.verbose else logging.ERROR)
logging.getLogger('urllib3.connectionpool').setLevel(logging.ERROR)
client = Client({
......@@ -49,12 +105,8 @@ def main():
'webdav_root': parsed_url.path,
'webdav_verbose': True,
})
if args.force:
client.upload_sync(args.dstdir, args.srcdir)
else:
client.push(
remote_directory=args.dstdir,
local_directory=args.srcdir)
upload(client, args.srcdir, args.dstdir, args.force, args.delete)
if __name__ == '__main__':
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment