2007-07-11 02:37:37 +00:00
2007-08-17 19:54:47 +00:00
import os . path , re , sys
2007-07-11 02:37:37 +00:00
from twisted . python import usage
2008-05-20 21:36:04 +00:00
from allmydata . scripts . common import BaseOptions , get_aliases
2007-07-11 02:37:37 +00:00
2007-08-17 19:54:47 +00:00
NODEURL_RE = re . compile ( " http://([^:]*)(:([1-9][0-9]*))? " )
2007-08-16 19:50:19 +00:00
class VDriveOptions ( BaseOptions , usage . Options ) :
2007-07-11 02:37:37 +00:00
optParameters = [
2007-10-11 07:30:36 +00:00
[ " node-directory " , " d " , " ~/.tahoe " ,
" Look here to find out which Tahoe node should be used for all "
" operations. The directory should either contain a full Tahoe node, "
" or a file named node.url which points to some other Tahoe node. "
2008-06-03 00:54:56 +00:00
" It should also contain a file named private/aliases which contains "
" the mapping from alias name to root dirnode URI. "
2007-10-11 07:30:36 +00:00
] ,
2007-08-16 23:53:27 +00:00
[ " node-url " , " u " , None ,
2008-11-26 00:57:37 +00:00
" URL of the tahoe node to use, a URL like \" http://127.0.0.1:3456 \" . "
2007-10-11 07:30:36 +00:00
" This overrides the URL found in the --node-directory . " ] ,
2008-05-22 00:55:32 +00:00
[ " dir-cap " , None , None ,
2008-05-20 02:28:50 +00:00
" Which dirnode URI should be used as the ' tahoe ' alias. " ]
2007-07-11 02:37:37 +00:00
]
2007-08-17 19:54:47 +00:00
def postOptions ( self ) :
2007-10-11 07:30:36 +00:00
# compute a node-url from the existing options, put in self['node-url']
if self [ ' node-directory ' ] :
2008-01-11 02:32:18 +00:00
if sys . platform == ' win32 ' and self [ ' node-directory ' ] == ' ~/.tahoe ' :
from allmydata . windows import registry
self [ ' node-directory ' ] = registry . get_base_dir_path ( )
else :
self [ ' node-directory ' ] = os . path . expanduser ( self [ ' node-directory ' ] )
2007-10-11 07:30:36 +00:00
if self [ ' node-url ' ] :
if ( not isinstance ( self [ ' node-url ' ] , basestring )
or not NODEURL_RE . match ( self [ ' node-url ' ] ) ) :
msg = ( " --node-url is required to be a string and look like "
" \" http://HOSTNAMEORADDR:PORT \" , not: %r " %
( self [ ' node-url ' ] , ) )
raise usage . UsageError ( msg )
else :
node_url_file = os . path . join ( self [ ' node-directory ' ] , " node.url " )
self [ ' node-url ' ] = open ( node_url_file , " r " ) . read ( ) . strip ( )
2009-02-03 04:08:56 +00:00
if self [ ' node-url ' ] [ - 1 ] != " / " :
self [ ' node-url ' ] + = " / "
2007-10-11 07:30:36 +00:00
2008-05-20 21:36:04 +00:00
aliases = get_aliases ( self [ ' node-directory ' ] )
2008-05-20 02:28:50 +00:00
if self [ ' dir-cap ' ] :
aliases [ " tahoe " ] = self [ ' dir-cap ' ]
self . aliases = aliases # maps alias name to dircap
class MakeDirectoryOptions ( VDriveOptions ) :
def parseArgs ( self , where = " " ) :
self . where = where
longdesc = """ Create a new directory, either unlinked or as a subdirectory. """
class AddAliasOptions ( VDriveOptions ) :
def parseArgs ( self , alias , cap ) :
self . alias = alias
self . cap = cap
2007-10-11 07:30:36 +00:00
2009-02-21 01:31:06 +00:00
def getSynopsis ( self ) :
return " %s add-alias ALIAS DIRCAP " % ( os . path . basename ( sys . argv [ 0 ] ) , )
longdesc = """ Add a new alias for an existing directory. """
2008-08-02 02:10:41 +00:00
class CreateAliasOptions ( VDriveOptions ) :
def parseArgs ( self , alias ) :
self . alias = alias
2009-02-21 01:31:06 +00:00
def getSynopsis ( self ) :
return " %s create-alias ALIAS " % ( os . path . basename ( sys . argv [ 0 ] ) , )
longdesc = """ Creates a new directory and adds an alias for it. """
2008-05-20 21:36:04 +00:00
class ListAliasOptions ( VDriveOptions ) :
2009-02-21 01:31:06 +00:00
longdesc = """ Displays a table of all configured aliases. """
2008-05-20 21:36:04 +00:00
2007-07-11 02:37:37 +00:00
class ListOptions ( VDriveOptions ) :
2008-05-20 02:28:50 +00:00
optFlags = [
( " long " , " l " , " Use long format: show file sizes, and timestamps " ) ,
2008-05-20 19:49:11 +00:00
( " uri " , " u " , " Show file/directory URIs " ) ,
( " readonly-uri " , None , " Show readonly file/directory URIs " ) ,
2008-05-20 02:28:50 +00:00
( " classify " , " F " , " Append ' / ' to directory names, and ' * ' to mutable " ) ,
( " json " , None , " Show the raw JSON output " ) ,
]
def parseArgs ( self , where = " " ) :
self . where = where
2007-07-11 02:37:37 +00:00
2007-08-16 19:50:19 +00:00
longdesc = """ List the contents of some portion of the virtual drive. """
2007-07-11 02:37:37 +00:00
class GetOptions ( VDriveOptions ) :
2008-05-20 02:28:50 +00:00
def parseArgs ( self , arg1 , arg2 = None ) :
# tahoe get FOO |less # write to stdout
# tahoe get tahoe:FOO |less # same
# tahoe get FOO bar # write to local file
# tahoe get tahoe:FOO bar # same
self . from_file = arg1
self . to_file = arg2
if self . to_file == " - " :
self . to_file = None
2007-07-11 02:37:37 +00:00
2007-07-11 17:26:19 +00:00
def getSynopsis ( self ) :
return " %s get VDRIVE_FILE LOCAL_FILE " % ( os . path . basename ( sys . argv [ 0 ] ) , )
longdesc = """ Retrieve a file from the virtual drive and write it to the
2007-08-16 19:15:38 +00:00
local filesystem . If LOCAL_FILE is omitted or ' - ' , the contents of the file
2007-07-11 17:26:19 +00:00
will be written to stdout . """
2008-06-03 00:54:56 +00:00
def getUsage ( self , width = None ) :
t = VDriveOptions . getUsage ( self , width )
t + = """
Examples :
% tahoe get FOO | less # write to stdout
% tahoe get tahoe : FOO | less # same
% tahoe get FOO bar # write to local file
% tahoe get tahoe : FOO bar # same
"""
return t
2007-08-16 19:15:38 +00:00
class PutOptions ( VDriveOptions ) :
2008-05-20 19:36:55 +00:00
optFlags = [
( " mutable " , " m " , " Create a mutable file instead of an immutable one. " ) ,
]
2008-05-20 02:28:50 +00:00
def parseArgs ( self , arg1 = None , arg2 = None ) :
2009-01-27 22:39:09 +00:00
# cat FILE | tahoe put # create unlinked file from stdin
# cat FILE | tahoe put - # same
2008-08-02 02:27:29 +00:00
# tahoe put bar # create unlinked file from local 'bar'
2009-01-27 22:39:09 +00:00
# cat FILE | tahoe put - FOO # create tahoe:FOO from stdin
2008-05-20 02:28:50 +00:00
# tahoe put bar FOO # copy local 'bar' to tahoe:FOO
# tahoe put bar tahoe:FOO # same
if arg1 is not None and arg2 is not None :
self . from_file = arg1
self . to_file = arg2
elif arg1 is not None and arg2 is None :
2008-08-02 02:27:29 +00:00
self . from_file = arg1 # might be "-"
self . to_file = None
2008-05-20 02:28:50 +00:00
else :
2008-08-02 02:27:29 +00:00
self . from_file = None
self . to_file = None
2008-05-20 02:28:50 +00:00
if self . from_file == " - " :
self . from_file = None
2007-08-16 19:15:38 +00:00
def getSynopsis ( self ) :
2007-08-17 00:47:24 +00:00
return " %s put LOCAL_FILE VDRIVE_FILE " % ( os . path . basename ( sys . argv [ 0 ] ) , )
2007-08-16 19:15:38 +00:00
longdesc = """ Put a file into the virtual drive (copying the file ' s
2008-08-02 02:27:29 +00:00
contents from the local filesystem ) . If VDRIVE_FILE is missing , upload
the file but do not link it into a directory : prints the new filecap to
stdout . If LOCAL_FILE is missing or ' - ' , data will be copied from stdin .
VDRIVE_FILE is assumed to start with tahoe : unless otherwise specified . """
2008-06-03 00:54:56 +00:00
def getUsage ( self , width = None ) :
t = VDriveOptions . getUsage ( self , width )
t + = """
Examples :
2009-01-27 22:39:09 +00:00
% cat FILE | tahoe put # create unlinked file from stdin
% cat FILE | tahoe - # same
2008-08-02 02:27:29 +00:00
% tahoe put bar # create unlinked file from local 'bar'
2009-01-27 22:39:09 +00:00
% cat FILE | tahoe put - FOO # create tahoe:FOO from stdin
2008-08-02 02:27:29 +00:00
% tahoe put bar FOO # copy local 'bar' to tahoe:FOO
% tahoe put bar tahoe : FOO # same
% tahoe put bar MUTABLE - FILE - WRITECAP # modify the mutable file in-place
2008-06-03 00:54:56 +00:00
"""
return t
2007-08-16 19:15:38 +00:00
2008-05-20 23:56:03 +00:00
class CpOptions ( VDriveOptions ) :
optFlags = [
( " recursive " , " r " , " Copy source directory recursively. " ) ,
2008-05-22 00:35:21 +00:00
( " verbose " , " v " , " Be noisy about what is happening. " ) ,
2008-05-20 23:56:03 +00:00
]
def parseArgs ( self , * args ) :
if len ( args ) < 2 :
raise usage . UsageError ( " cp requires at least two arguments " )
self . sources = args [ : - 1 ]
self . destination = args [ - 1 ]
2007-08-17 20:23:16 +00:00
class RmOptions ( VDriveOptions ) :
2008-05-20 02:28:50 +00:00
def parseArgs ( self , where ) :
self . where = where
2007-08-17 20:23:16 +00:00
def getSynopsis ( self ) :
2009-02-16 22:08:33 +00:00
return " %s rm VDRIVE_FILE " % ( os . path . basename ( sys . argv [ 0 ] ) , )
2007-08-16 19:15:38 +00:00
2007-10-12 03:31:48 +00:00
class MvOptions ( VDriveOptions ) :
def parseArgs ( self , frompath , topath ) :
2008-05-20 02:28:50 +00:00
self . from_file = frompath
self . to_file = topath
2007-10-12 03:31:48 +00:00
def getSynopsis ( self ) :
return " %s mv FROM TO " % ( os . path . basename ( sys . argv [ 0 ] ) , )
2008-05-20 20:30:31 +00:00
class LnOptions ( VDriveOptions ) :
def parseArgs ( self , frompath , topath ) :
self . from_file = frompath
self . to_file = topath
def getSynopsis ( self ) :
return " %s ln FROM TO " % ( os . path . basename ( sys . argv [ 0 ] ) , )
2009-02-03 04:09:02 +00:00
class BackupOptions ( VDriveOptions ) :
optFlags = [
( " verbose " , " v " , " Be noisy about what is happening. " ) ,
2009-02-11 01:49:10 +00:00
( " no-backupdb " , None , " Do not use the SQLite-based backup-database (always upload all files). " ) ,
2009-02-06 02:56:40 +00:00
( " ignore-timestamps " , None , " Do not use backupdb timestamps to decide if a local file is unchanged. " ) ,
2009-02-03 04:09:02 +00:00
]
def parseArgs ( self , localdir , topath ) :
self . from_dir = localdir
self . to_dir = topath
def getSynopsis ( Self ) :
return " %s backup FROM ALIAS:TO " % os . path . basename ( sys . argv [ 0 ] )
longdesc = """ Add a versioned backup of the local FROM directory to a timestamped subdir of the (tahoe) TO/Archives directory, sharing as many files and directories as possible with the previous backup. Creates TO/Latest as a reference to the latest backup. Behaves somewhat like ' rsync -a --link-dest=TO/Archives/(previous) FROM TO/Archives/(new); ln -sf TO/Archives/(new) TO/Latest ' . """
2008-01-05 01:34:10 +00:00
class WebopenOptions ( VDriveOptions ) :
CLI: rework webopen, and moreover its tests w.r.t. path handling
in the recent reconciliation of webopen patches, I wound up adjusting
webopen to 'pass through' the state of the trailing slash on the given
argument to the resultant url passed to the browser. this change
removes the requirement that arguments must be directories, and allows
webopen to be used with files. it also broke the tests that assumed
that webopen would always normalise the url to have a trailing slash.
in fixing the tests, I realised that, IMHO, there's something deeply
awry with the way tahoe handles paths; specifically in the combination
of '/' being the name of the root path within an alias, but a leading
slash on paths, e.g. 'alias:/path', is catagorically incorrect. i.e.
'tahoe:' == 'tahoe:/' == '/'
but 'tahoe:/foo' is an invalid path, and must be 'tahoe:foo'
I wound up making the internals of webopen simply spot a 'path' of
'/' and smash it to '', which 'fixes' webopen to match the behaviour
of tahoe's path handling elsewhere, but that special case sort of
points to the weirdness.
(fwiw, I personally found the fact that the leading / in a path was
disallowed to be weird - I'm just used to seeing paths qualified by
the leading / I guess - so in a debate about normalising path handling
I'd vote to include the /)
2008-09-24 16:45:23 +00:00
def parseArgs ( self , where = ' ' ) :
2008-09-24 15:20:02 +00:00
self . where = where
def getSynopsis ( self ) :
return " %s webopen [ALIAS:PATH] " % ( os . path . basename ( sys . argv [ 0 ] ) , )
2008-01-05 01:34:10 +00:00
longdesc = """ Opens a webbrowser to the contents of some portion of the virtual drive. """
2007-07-11 02:37:37 +00:00
2008-11-13 03:17:25 +00:00
class ManifestOptions ( VDriveOptions ) :
optFlags = [
( " storage-index " , " s " , " Only print storage index strings, not pathname+cap " ) ,
2009-01-23 23:33:21 +00:00
( " verify-cap " , None , " Only print verifycap, not pathname+cap " ) ,
( " repair-cap " , None , " Only print repaircap, not pathname+cap " ) ,
2008-11-19 23:00:27 +00:00
( " raw " , " r " , " Display raw JSON data instead of parsed " ) ,
2008-11-13 03:17:25 +00:00
]
def parseArgs ( self , where = ' ' ) :
self . where = where
def getSynopsis ( self ) :
return " %s manifest [ALIAS:PATH] " % ( os . path . basename ( sys . argv [ 0 ] ) , )
longdesc = """ Print a list of all files/directories reachable from the given starting point. """
2008-11-14 02:43:50 +00:00
class StatsOptions ( VDriveOptions ) :
2008-11-18 05:02:19 +00:00
optFlags = [
2008-11-19 01:36:08 +00:00
( " raw " , " r " , " Display raw JSON data instead of parsed " ) ,
2008-11-18 05:02:19 +00:00
]
2008-11-14 02:43:50 +00:00
def parseArgs ( self , where = ' ' ) :
self . where = where
def getSynopsis ( self ) :
return " %s stats [ALIAS:PATH] " % ( os . path . basename ( sys . argv [ 0 ] ) , )
longdesc = """ Print statistics about of all files/directories reachable from the given starting point. """
2008-11-19 02:12:10 +00:00
class CheckOptions ( VDriveOptions ) :
optFlags = [
2009-02-18 00:15:11 +00:00
( " raw " , None , " Display raw JSON data instead of parsed " ) ,
( " verify " , None , " Verify all hashes, instead of merely querying share presence " ) ,
( " repair " , None , " Automatically repair any problems found " ) ,
2009-02-18 02:32:43 +00:00
( " add-lease " , None , " Add/renew lease on all shares " ) ,
2008-11-19 02:12:10 +00:00
]
def parseArgs ( self , where = ' ' ) :
self . where = where
def getSynopsis ( self ) :
return " %s check [ALIAS:PATH] " % ( os . path . basename ( sys . argv [ 0 ] ) , )
longdesc = """ Check a single file or directory: count how many shares are available, verify their hashes. Optionally repair the file if any problems were found. """
class DeepCheckOptions ( VDriveOptions ) :
optFlags = [
2009-02-18 00:15:11 +00:00
( " raw " , None , " Display raw JSON data instead of parsed " ) ,
( " verify " , None , " Verify all hashes, instead of merely querying share presence " ) ,
( " repair " , None , " Automatically repair any problems found " ) ,
2009-02-18 02:32:43 +00:00
( " add-lease " , None , " Add/renew lease on all shares " ) ,
2009-02-18 00:15:11 +00:00
( " verbose " , " v " , " Be noisy about what is happening. " ) ,
2008-11-19 02:12:10 +00:00
]
def parseArgs ( self , where = ' ' ) :
self . where = where
def getSynopsis ( self ) :
return " %s deep-check [ALIAS:PATH] " % ( os . path . basename ( sys . argv [ 0 ] ) , )
longdesc = """ Check all files/directories reachable from the given starting point (which must be a directory), like ' tahoe check ' but for multiple files. Optionally repair any problems found. """
2007-07-11 02:37:37 +00:00
subCommands = [
2008-05-20 02:28:50 +00:00
[ " mkdir " , None , MakeDirectoryOptions , " Create a new directory " ] ,
[ " add-alias " , None , AddAliasOptions , " Add a new alias cap " ] ,
2008-08-02 02:10:41 +00:00
[ " create-alias " , None , CreateAliasOptions , " Create a new alias cap " ] ,
2008-05-20 21:36:04 +00:00
[ " list-aliases " , None , ListAliasOptions , " List all alias caps " ] ,
2007-07-11 02:37:37 +00:00
[ " ls " , None , ListOptions , " List a directory " ] ,
2007-07-11 17:26:19 +00:00
[ " get " , None , GetOptions , " Retrieve a file from the virtual drive. " ] ,
2007-08-16 19:15:38 +00:00
[ " put " , None , PutOptions , " Upload a file into the virtual drive. " ] ,
2008-05-20 23:56:03 +00:00
[ " cp " , None , CpOptions , " Copy one or more files. " ] ,
2007-08-17 20:23:16 +00:00
[ " rm " , None , RmOptions , " Unlink a file or directory in the virtual drive. " ] ,
2007-10-12 03:31:48 +00:00
[ " mv " , None , MvOptions , " Move a file within the virtual drive. " ] ,
2008-05-20 20:30:31 +00:00
[ " ln " , None , LnOptions , " Make an additional link to an existing file. " ] ,
2009-02-03 04:09:02 +00:00
[ " backup " , None , BackupOptions , " Make target dir look like local dir. " ] ,
2008-01-05 01:34:10 +00:00
[ " webopen " , None , WebopenOptions , " Open a webbrowser to the root_dir " ] ,
2008-11-13 03:17:25 +00:00
[ " manifest " , None , ManifestOptions , " List all files/dirs in a subtree " ] ,
2008-11-14 02:43:50 +00:00
[ " stats " , None , StatsOptions , " Print statistics about all files/dirs in a subtree " ] ,
2008-11-19 02:12:10 +00:00
[ " check " , None , CheckOptions , " Check a single file or directory " ] ,
[ " deep-check " , None , DeepCheckOptions , " Check all files/directories reachable from a starting point " ] ,
2007-07-11 02:37:37 +00:00
]
2008-08-01 18:46:24 +00:00
def mkdir ( options ) :
2008-05-20 02:28:50 +00:00
from allmydata . scripts import tahoe_mkdir
2008-08-01 18:46:24 +00:00
rc = tahoe_mkdir . mkdir ( options )
2008-05-20 02:28:50 +00:00
return rc
2008-08-01 18:46:24 +00:00
def add_alias ( options ) :
2008-05-20 02:28:50 +00:00
from allmydata . scripts import tahoe_add_alias
2008-08-01 18:46:24 +00:00
rc = tahoe_add_alias . add_alias ( options )
2008-05-20 02:28:50 +00:00
return rc
2008-08-02 02:10:41 +00:00
def create_alias ( options ) :
from allmydata . scripts import tahoe_add_alias
rc = tahoe_add_alias . create_alias ( options )
return rc
2008-08-01 18:46:24 +00:00
def list_aliases ( options ) :
2008-05-20 21:36:04 +00:00
from allmydata . scripts import tahoe_add_alias
2008-08-01 18:46:24 +00:00
rc = tahoe_add_alias . list_aliases ( options )
2008-05-20 21:36:04 +00:00
return rc
2008-08-01 18:46:24 +00:00
def list ( options ) :
2007-07-11 02:37:37 +00:00
from allmydata . scripts import tahoe_ls
2008-08-01 18:46:24 +00:00
rc = tahoe_ls . list ( options )
2007-07-11 02:37:37 +00:00
return rc
2008-08-01 18:46:24 +00:00
def get ( options ) :
2007-07-11 02:37:37 +00:00
from allmydata . scripts import tahoe_get
2008-08-01 18:46:24 +00:00
rc = tahoe_get . get ( options )
2007-07-11 17:26:19 +00:00
if rc == 0 :
2008-08-01 18:46:24 +00:00
if options . to_file is None :
2007-07-11 17:26:19 +00:00
# be quiet, since the file being written to stdout should be
# proof enough that it worked, unless the user is unlucky
# enough to have picked an empty file
pass
else :
2008-08-01 18:46:24 +00:00
print >> options . stderr , " %s retrieved and written to %s " % \
( options . from_file , options . to_file )
2007-07-11 02:37:37 +00:00
return rc
2008-08-01 18:46:24 +00:00
def put ( options ) :
2007-08-16 19:15:38 +00:00
from allmydata . scripts import tahoe_put
2008-08-01 18:46:24 +00:00
rc = tahoe_put . put ( options )
2007-08-17 20:23:16 +00:00
return rc
2008-08-01 18:46:24 +00:00
def cp ( options ) :
2008-05-20 23:56:03 +00:00
from allmydata . scripts import tahoe_cp
2008-08-01 18:46:24 +00:00
rc = tahoe_cp . copy ( options )
2008-05-20 23:56:03 +00:00
return rc
2008-08-01 18:46:24 +00:00
def rm ( options ) :
2007-08-17 20:23:16 +00:00
from allmydata . scripts import tahoe_rm
2008-08-01 18:46:24 +00:00
rc = tahoe_rm . rm ( options )
2007-08-16 19:15:38 +00:00
return rc
2008-08-01 18:46:24 +00:00
def mv ( options ) :
2007-10-12 03:31:48 +00:00
from allmydata . scripts import tahoe_mv
2008-08-01 18:46:24 +00:00
rc = tahoe_mv . mv ( options , mode = " move " )
2008-05-20 20:30:31 +00:00
return rc
2008-08-01 18:46:24 +00:00
def ln ( options ) :
2008-05-20 20:30:31 +00:00
from allmydata . scripts import tahoe_mv
2008-08-01 18:46:24 +00:00
rc = tahoe_mv . mv ( options , mode = " link " )
2007-10-12 03:31:48 +00:00
return rc
2009-02-03 04:09:02 +00:00
def backup ( options ) :
from allmydata . scripts import tahoe_backup
rc = tahoe_backup . backup ( options )
return rc
2008-08-12 01:20:23 +00:00
def webopen ( options , opener = None ) :
2008-09-24 15:20:02 +00:00
from allmydata . scripts import tahoe_webopen
rc = tahoe_webopen . webopen ( options , opener = opener )
return rc
2008-01-05 01:34:10 +00:00
2008-11-13 03:17:25 +00:00
def manifest ( options ) :
from allmydata . scripts import tahoe_manifest
rc = tahoe_manifest . manifest ( options )
return rc
2008-11-14 02:43:50 +00:00
def stats ( options ) :
from allmydata . scripts import tahoe_manifest
rc = tahoe_manifest . stats ( options )
return rc
2008-11-19 02:12:10 +00:00
def check ( options ) :
from allmydata . scripts import tahoe_check
rc = tahoe_check . check ( options )
return rc
def deepcheck ( options ) :
from allmydata . scripts import tahoe_check
rc = tahoe_check . deepcheck ( options )
return rc
2007-07-11 02:37:37 +00:00
dispatch = {
2008-05-20 02:28:50 +00:00
" mkdir " : mkdir ,
" add-alias " : add_alias ,
2008-08-02 02:10:41 +00:00
" create-alias " : create_alias ,
2008-05-20 21:36:04 +00:00
" list-aliases " : list_aliases ,
2007-07-11 02:37:37 +00:00
" ls " : list ,
" get " : get ,
2007-08-16 19:15:38 +00:00
" put " : put ,
2008-05-20 23:56:03 +00:00
" cp " : cp ,
2007-08-17 20:23:16 +00:00
" rm " : rm ,
2007-10-12 03:31:48 +00:00
" mv " : mv ,
2008-05-20 20:30:31 +00:00
" ln " : ln ,
2009-02-03 04:09:02 +00:00
" backup " : backup ,
2008-01-05 01:34:10 +00:00
" webopen " : webopen ,
2008-11-13 03:17:25 +00:00
" manifest " : manifest ,
2008-11-14 02:43:50 +00:00
" stats " : stats ,
2008-11-19 02:12:10 +00:00
" check " : check ,
" deep-check " : deepcheck ,
2007-07-11 02:37:37 +00:00
}