1 """Code for the B{0store} command-line interface."""
2
3
4
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
17
19
38
50
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:
77 raise UsageError(str(ex))
78 raise UsageError("No such file or directory '%s'" % args[1])
79
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
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
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
136 import difflib
137 for line in difflib.unified_diff(saved, actual, 'Recorded', 'Actual'):
138 print line,
139
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
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
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