Package zeroinstall :: Package zerostore :: Module cli
[frames] | no frames]

Source Code for Module zeroinstall.zerostore.cli

  1  """Code for the B{0store} command-line interface.""" 
  2   
  3  # Copyright (C) 2006, Thomas Leonard 
  4  # See the README file for details, or visit http://0install.net. 
  5   
  6  import sys, os 
  7  from zeroinstall.zerostore.manifest import verify, get_algorithm, copy_tree_with_verify 
  8  from zeroinstall import zerostore, SafeException, support 
  9   
 10  stores = None 
 11   
12 -def init_stores():
13 global stores 14 assert stores is None 15 if stores is None: 16 stores = zerostore.Stores()
17
18 -class UsageError(SafeException): pass
19
20 -def do_manifest(args):
21 """manifest DIRECTORY [ALGORITHM]""" 22 if len(args) < 1 or len(args) > 2: raise UsageError("Wrong number of arguments") 23 if len(args) == 2: 24 alg = get_algorithm(args[1]) 25 else: 26 # If no algorithm was given, guess from the directory name 27 name = os.path.basename(args[0]) 28 if '=' in name: 29 alg = get_algorithm(name.split('=', 1)[0]) 30 else: 31 alg = get_algorithm('sha1new') 32 digest = alg.new_digest() 33 for line in alg.generate_manifest(args[0]): 34 print line 35 digest.update(line + '\n') 36 print alg.getID(digest) 37 sys.exit(0)
38
39 -def do_find(args):
40 """find DIGEST""" 41 if len(args) != 1: raise UsageError("Wrong number of arguments") 42 try: 43 print stores.lookup(args[0]) 44 sys.exit(0) 45 except zerostore.BadDigest, ex: 46 print >>sys.stderr, ex 47 except zerostore.NotStored, ex: 48 print >>sys.stderr, ex 49 sys.exit(1)
50
51 -def do_add(args):
52 """add DIGEST (DIRECTORY | (ARCHIVE [EXTRACT]))""" 53 from zeroinstall.zerostore import unpack 54 if len(args) < 2: raise UsageError("Missing arguments") 55 digest = args[0] 56 if os.path.isdir(args[1]): 57 if len(args) > 2: raise UsageError("Too many arguments") 58 stores.add_dir_to_cache(digest, args[1]) 59 elif os.path.isfile(args[1]): 60 if len(args) > 3: raise UsageError("Too many arguments") 61 if len(args) > 2: 62 extract = args[2] 63 else: 64 extract = None 65 66 type = unpack.type_from_url(args[1]) 67 if not type: 68 raise SafeException("Unknown extension in '%s' - can't guess MIME type" % args[1]) 69 unpack.check_type_ok(type) 70 71 stores.add_archive_to_cache(digest, file(args[1]), args[1], extract, type = type) 72 else: 73 try: 74 os.stat(args[1]) 75 except OSError, ex: 76 if ex.errno != 2: # No such file or directory 77 raise UsageError(str(ex)) # E.g. permission denied 78 raise UsageError("No such file or directory '%s'" % args[1])
79
80 -def do_optimise(args):
81 """optimise [ CACHE ]""" 82 if len(args) == 1: 83 cache_dir = args[0] 84 else: 85 cache_dir = stores.stores[0].dir 86 87 cache_dir = os.path.realpath(cache_dir) 88 89 import stat 90 info = os.stat(cache_dir) 91 if not stat.S_ISDIR(info.st_mode): 92 raise UsageError("Not a directory: '%s'" % cache_dir) 93 94 impl_name = os.path.basename(cache_dir) 95 if impl_name != 'implementations': 96 raise UsageError("Cache directory should be named 'implementations', not\n" 97 "'%s' (in '%s')" % (impl_name, cache_dir)) 98 99 print "Optimising", cache_dir 100 101 import optimise 102 uniq_size, dup_size, already_linked, man_size = optimise.optimise(cache_dir) 103 print "Original size :", support.pretty_size(uniq_size + dup_size) + " (excluding the %s of manifests)" % support.pretty_size(man_size) 104 print "Already saved :", support.pretty_size(already_linked) 105 if dup_size == 0: 106 print "No duplicates found; no changes made." 107 else: 108 print "Optimised size :", support.pretty_size(uniq_size) 109 perc = (100 * float(dup_size)) / (uniq_size + dup_size) 110 print "Space freed up :", support.pretty_size(dup_size), "(%.2f%%)" % perc 111 print "Optimisation complete."
112
113 -def do_verify(args):
114 """verify (DIGEST | (DIRECTORY [DIGEST])""" 115 if len(args) == 2: 116 required_digest = args[1] 117 root = args[0] 118 elif len(args) == 1: 119 root = get_stored(args[0]) 120 required_digest = None # Get from name 121 else: 122 raise UsageError("Missing DIGEST or DIRECTORY") 123 124 print "Verifying", root 125 try: 126 verify(root, required_digest) 127 print "OK" 128 except zerostore.BadDigest, ex: 129 print str(ex) 130 if ex.detail: 131 print 132 print ex.detail 133 sys.exit(1)
134
135 -def show_changes(actual, saved):
136 import difflib 137 for line in difflib.unified_diff(saved, actual, 'Recorded', 'Actual'): 138 print line,
139
140 -def do_list(args):
141 """list""" 142 if args: raise UsageError("List takes no arguments") 143 print "User store (writable) : " + stores.stores[0].dir 144 for s in stores.stores[1:]: 145 print "System store : " + s.dir 146 if len(stores.stores) < 2: 147 print "No system stores."
148
149 -def get_stored(dir_or_digest):
150 if os.path.isdir(dir_or_digest): 151 return dir_or_digest 152 else: 153 try: 154 return stores.lookup(dir_or_digest) 155 except zerostore.NotStored, ex: 156 print >>sys.stderr, ex 157 sys.exit(1)
158
159 -def do_copy(args):
160 """copy SOURCE [ TARGET ]""" 161 if len(args) == 2: 162 source, target = args 163 elif len(args) == 1: 164 source = args[0] 165 target = stores.stores[0].dir 166 else: 167 raise UsageError("Wrong number of arguments.") 168 169 if not os.path.isdir(source): 170 raise UsageError("Source directory '%s' not found" % source) 171 if not os.path.isdir(target): 172 raise UsageError("Target directory '%s' not found" % target) 173 manifest_path = os.path.join(source, '.manifest') 174 if not os.path.isfile(manifest_path): 175 raise UsageError("Source manifest '%s' not found" % manifest_path) 176 required_digest = os.path.basename(source) 177 manifest_data = file(manifest_path).read() 178 179 copy_tree_with_verify(source, target, manifest_data, required_digest)
180 181 commands = [do_add, do_copy, do_find, do_list, do_manifest, do_optimise, do_verify] 182