Files @ 6a0ab4fe9f5e
Branch filter:

Location: Morevna/src/morevna.py

Laman
changed naming to snake case. sadly no love for camel case in this world
import sys
import os.path
import logging as log
from argparse import ArgumentParser

from util import spawn_daemon, split_host
import config as conf
import stats
from hashtree import HashTree
from client import Client, Connection as ClientConnection, FailedConnection, DeniedConnection, IncompatibleException
from server import Miniserver


def _check_file(f):
	if not os.path.isfile(f):
		print("invalid file specified:", f, file=sys.stderr)
		sys.exit(1)


def build_tree(args):
	_check_file(args.datafile)
	if os.path.isfile(args.treefile):
		tree_mod = os.stat(args.treefile).st_mtime
		data_mod = os.stat(args.datafile).st_mtime
		if data_mod<tree_mod and not args.force:
			print("tree file is up to date")
			return

	tree = HashTree.from_file(args.datafile)
	tree.save(args.treefile)


def push(args):
	_check_file(args.datafile)
	if args.tree:
		_check_file(args.tree)
	if args.host: conf.hosts = [args.host]
	if args.port: conf.port = args.port

	c = Client(args.datafile, args.tree)
	for h in conf.hosts:
		host = split_host(h, conf.port)
		stats.reset()
		try:
			with ClientConnection(*host) as con:
				c.set_connection(con)
				c.init("push")
				blocks_to_transfer = c.negotiate()
				c.send_data(blocks_to_transfer)
			print()
			print(stats.report())
			print()
		except FailedConnection: pass
		except DeniedConnection as e:
			print("Server {0}:{1} denied connection.".format(*host))
			print(e)
		except IncompatibleException as e: print(e)


def pull(args):
	_check_file(args.datafile)
	if args.tree:
		_check_file(args.tree)
	if args.host: conf.hosts = [args.host]
	if args.port: conf.port = args.port

	c = Client(args.datafile, args.tree)
	host = split_host(conf.hosts[0], conf.port)
	try:
		with ClientConnection(*host) as con:
			c.set_connection(con)
			c.init("pull")
			blocks_to_transfer = c.negotiate()
			c.pull_data(blocks_to_transfer, args.force)
		print()
		print(stats.report())
	except FailedConnection: pass
	except DeniedConnection as e:
		print("Server {0}:{1} denied connection.".format(*host))
		print(e)


def serve(args):
	_check_file(args.datafile)
	if args.tree:
		_check_file(args.tree)
	if args.host: conf.hosts.insert(0, args.host)
	if args.port: conf.port = args.port

	try:
		s = Miniserver(args.datafile, args.tree)
		spawn_daemon(s.serve)
	except Exception as e:
		log.exception("exception: %s", e)
		print("Failed to start:\n  ", e)


parser = ArgumentParser()
subparsers = parser.add_subparsers()

p_build = subparsers.add_parser("build")
p_build.add_argument("-f", "--force", action="store_true", help="force tree rebuild")
p_build.add_argument("treefile", help="stored hash tree location")
p_build.add_argument("datafile")
p_build.set_defaults(func=build_tree)

p_update = subparsers.add_parser("push")
p_update.add_argument("-p", "--port", type=int)
p_update.add_argument("--host")
p_update.add_argument("-t", "--tree", help="stored hash tree location")
p_update.add_argument("datafile")
p_update.set_defaults(func=push)

p_update = subparsers.add_parser("pull")
p_update.add_argument("-p", "--port", type=int)
p_update.add_argument("--host")
p_update.add_argument("-t", "--tree", help="stored hash tree location")
p_update.add_argument("-f", "--force", action="store_true", help="ignore lock file")
p_update.add_argument("datafile")
p_update.set_defaults(func=pull)

p_serve = subparsers.add_parser("serve")
p_serve.add_argument("-p", "--port", type=int)
p_serve.add_argument("--host")
p_serve.add_argument("-t", "--tree", help="stored hash tree location")
p_serve.add_argument("datafile")
p_serve.set_defaults(func=serve)

args = parser.parse_args()
try: args.func(args)
except AttributeError:
	parser.print_help()