#!/usr/bin/env python2 # -*- coding: utf-8 -*- """ This code is public domain. Used as a demo for Blockstack. """ import sys import os import json import argparse import traceback from .bsk import * from .version import __version__ CONFIG_PATH = os.path.expanduser('~/.blockstack_files.conf') DRIVERS = ['disk'] def load_datastore_info( config_path=CONFIG_PATH ): """ Get our config. Returns { 'session': session, 'datastore': datastore } Or, returns None if there's no such file. Raise on exception. """ if not os.path.exists(config_path): return None with open(config_path, 'r') as f: dat = f.read().strip() conf = json.loads(dat) return conf def store_datastore_info( session, datastore, config_path=CONFIG_PATH ): """ Store our config. Return True on success Raise on error """ conf = { 'session': session, 'datastore': datastore } with open(config_path, 'w') as f: f.write( json.dumps(conf) ) return True def login( api_password=None, drivers=DRIVERS, config_path=CONFIG_PATH ): """ Authenticate to Blockstack, get a session, and create the datastore if it doesn't exist already. Store the session and datastore ID to disk. Returns {'session': session, 'datastore': ...} on success Returns None on error """ creds = load_datastore_info( config_path=config_path ) if creds is not None: return creds assert api_password, 'API password required' # first-time signing in session = bsk_get_session( api_password ) datastore_res = bsk_make_datastore( session, drivers=drivers ) assert 'error' not in datastore_res store_datastore_info( session, datastore_res['datastore'], config_path=config_path ) return {'session': session, 'datastore': datastore_res['datastore']} def logout( config_path=CONFIG_PATH ): """ Remove our cached credentials. Return True on success Raise on error """ if os.path.exists(config_path): os.unlink(config_path) return True def run_cli( argv ): """ Run the CLI. Return True on success Return False on error """ argparser = argparse.ArgumentParser(description="blockstack-files version {}".format(__version__)) subparsers = argparser.add_subparsers( dest='action', help='the action to be taken') # --------------------------- subparser = subparsers.add_parser( 'login', help='authenticate and log into your Blockstack node') subparser.add_argument( 'api_password', action='store', help='Blockstack API password') # --------------------------- subparser = subparsers.add_parser( 'logout', help='log out of your Blockstack node') # --------------------------- subparser = subparsers.add_parser( 'ls', help='list a given directory') subparser.add_argument( 'path', action='store', help='the path to the directory to list') # --------------------------- subparser = subparsers.add_parser( 'cat', help='cat a file to stdout') subparser.add_argument( 'path', action='store', help='the path to the file to read') # --------------------------- subparser = subparsers.add_parser( 'mkdir', help='make a directory') subparser.add_argument( 'path', action='store', help='the path to the directory to create') # --------------------------- subparser = subparsers.add_parser( 'put', help='store a file') subparser.add_argument( 'local_path', action='store', help='the path to the local data on disk') subparser.add_argument( 'path', action='store', help='the path in the data store to host this data') # --------------------------- subparser = subparsers.add_parser( 'rm', help='remove a file') subparser.add_argument( 'path', action='store', help='the path to the file to delete') # --------------------------- subparser = subparsers.add_parser( 'rmdir', help='remove a directory') subparser.add_argument( 'path', action='store', help='the path to the directory to remove.') # act on it args = argparser.parse_args() try: # authenticate, or get credentials if args.action == 'login': creds = login( args.api_password ) else: try: creds = login() except: print >> sys.stderr, 'Unable to log in. Try `{} login`'.format(argv[0]) return False # bsk paths must be absolute path = getattr(args, 'path', None) if path: if not path.startswith('/'): print >> sys.stderr, "Error: {} is not absolute".format(path) return False session = creds['session'] datastore = creds['datastore'] if args.action == 'ls': res = bsk_stat( session, datastore, path ) if res['type'] == 2: bsk_listdir( session, datastore, path ) else: print os.path.basename(path) elif args.action == 'cat': bsk_get_file( session, datastore, path ) elif args.action == 'mkdir': bsk_mkdir( session, datastore, path ) elif args.action == 'put': bsk_put_file( session, datastore, args.local_path, path ) elif args.action == 'rm': bsk_delete_file( session, datastore, path ) elif args.action == 'rmdir': bsk_rmdir( session, datastore, path ) elif args.action == 'logout': logout() else: return False return True except Exception as e: traceback.print_exc() return False