1 | Mon Apr 27 11:58:49 CEST 2009 francois@ctrlaltdel.ch |
---|
2 | * cli: plumbing for unicode support |
---|
3 | |
---|
4 | Mon Apr 27 10:59:31 CEST 2009 francois@ctrlaltdel.ch |
---|
5 | * cli: tahoe backup unicode support |
---|
6 | |
---|
7 | Mon Apr 27 11:01:44 CEST 2009 francois@ctrlaltdel.ch |
---|
8 | * cli: tahoe manifest unicode support |
---|
9 | |
---|
10 | Mon Apr 27 11:18:50 CEST 2009 francois@ctrlaltdel.ch |
---|
11 | * cli: tahoe ls unicode support |
---|
12 | |
---|
13 | Mon Apr 27 11:18:20 CEST 2009 francois@ctrlaltdel.ch |
---|
14 | * cli: tahoe get unicode support |
---|
15 | |
---|
16 | Mon Apr 27 11:00:59 CEST 2009 francois@ctrlaltdel.ch |
---|
17 | * cli: tahoe webopen unicode support |
---|
18 | |
---|
19 | Mon Apr 27 10:58:47 CEST 2009 francois@ctrlaltdel.ch |
---|
20 | * cli: tahoe rm unicode support |
---|
21 | |
---|
22 | Mon Apr 27 10:59:13 CEST 2009 francois@ctrlaltdel.ch |
---|
23 | * cli: tahoe ln unicode support |
---|
24 | |
---|
25 | Mon Apr 27 11:02:13 CEST 2009 francois@ctrlaltdel.ch |
---|
26 | * cli: tahoe status unicode support |
---|
27 | |
---|
28 | Mon Apr 27 11:02:26 CEST 2009 francois@ctrlaltdel.ch |
---|
29 | * cli: tahoe check unicode support |
---|
30 | |
---|
31 | Mon Apr 27 11:02:43 CEST 2009 francois@ctrlaltdel.ch |
---|
32 | * cli: tahoe deep-check unicode support |
---|
33 | |
---|
34 | Mon Apr 27 11:10:47 CEST 2009 francois@ctrlaltdel.ch |
---|
35 | * cli: tahoe mkdir unicode support |
---|
36 | |
---|
37 | Mon Apr 27 11:12:52 CEST 2009 francois@ctrlaltdel.ch |
---|
38 | * docs: explain the current unicode support in CLI |
---|
39 | |
---|
40 | Mon Apr 27 15:52:03 CEST 2009 francois@ctrlaltdel.ch |
---|
41 | * cli: tahoe cp unicode support |
---|
42 | |
---|
43 | Wed Apr 29 18:20:03 CEST 2009 francois@ctrlaltdel.ch |
---|
44 | * cli: tahoe put unicode support + encode path elements using unicode_to_url |
---|
45 | |
---|
46 | Both changes (tahoe put and url encoding) had to be included in the same patch |
---|
47 | to prevent failing tests. |
---|
48 | |
---|
49 | Mon Apr 27 11:58:07 CEST 2009 francois@ctrlaltdel.ch |
---|
50 | * cli: aliases unicode support |
---|
51 | |
---|
52 | Mon Apr 27 15:52:39 CEST 2009 francois@ctrlaltdel.ch |
---|
53 | * cli: previous cli related patches should fix #534 |
---|
54 | |
---|
55 | New patches: |
---|
56 | |
---|
57 | [cli: plumbing for unicode support |
---|
58 | francois@ctrlaltdel.ch**20090427095849 |
---|
59 | Ignore-this: 9cc8871d8fe54cde0dba52912754e4f4 |
---|
60 | ] { |
---|
61 | hunk ./src/allmydata/scripts/cli.py 4 |
---|
62 | import os.path, re, sys, fnmatch |
---|
63 | from twisted.python import usage |
---|
64 | from allmydata.scripts.common import BaseOptions, get_aliases |
---|
65 | +from allmydata.util.stringutils import argv_to_unicode |
---|
66 | |
---|
67 | NODEURL_RE=re.compile("http://([^:]*)(:([1-9][0-9]*))?") |
---|
68 | |
---|
69 | hunk ./src/allmydata/scripts/common.py 4 |
---|
70 | |
---|
71 | import os, sys, urllib |
---|
72 | from twisted.python import usage |
---|
73 | - |
---|
74 | +from allmydata.util.stringutils import unicode_to_url |
---|
75 | |
---|
76 | class BaseOptions: |
---|
77 | # unit tests can override these to point at StringIO instances |
---|
78 | hunk ./src/allmydata/test/test_cli.py 9 |
---|
79 | import urllib |
---|
80 | import re |
---|
81 | import simplejson |
---|
82 | +import sys |
---|
83 | |
---|
84 | from allmydata.util import fileutil, hashutil, base32 |
---|
85 | from allmydata import uri |
---|
86 | addfile ./src/allmydata/util/stringutils.py |
---|
87 | hunk ./src/allmydata/util/stringutils.py 1 |
---|
88 | +""" |
---|
89 | +Functions used to convert inputs from whatever encoding used in the system to |
---|
90 | +unicode and back. |
---|
91 | + |
---|
92 | +TODO: |
---|
93 | + * Accept two cli arguments --argv-encoding and --filesystem-encoding |
---|
94 | +""" |
---|
95 | + |
---|
96 | +import sys |
---|
97 | +from allmydata.util.assertutil import precondition |
---|
98 | +from twisted.python import usage |
---|
99 | + |
---|
100 | +def argv_to_unicode(s): |
---|
101 | + """ |
---|
102 | + Decode given argv element to unicode. |
---|
103 | + """ |
---|
104 | + # sys.argv encoding detection in Python is not trivial so utf-8 is |
---|
105 | + # currently used by default and an informative error message is given if |
---|
106 | + # the argument cannot be correctly decoded. |
---|
107 | + |
---|
108 | + precondition(isinstance(s, str), s) |
---|
109 | + try: |
---|
110 | + return unicode(s, 'utf-8') |
---|
111 | + except UnicodeEncodeError: |
---|
112 | + raise usageError("Argument '%s' cannot be decoded as UTF-8." % s) |
---|
113 | + |
---|
114 | +def fs_to_unicode(s): |
---|
115 | + """ |
---|
116 | + Decode a filename (or a directory name) to unicode using the same encoding |
---|
117 | + as the filesystem. |
---|
118 | + """ |
---|
119 | + # Filename encoding detection is a little bit better thanks to |
---|
120 | + # getfilesystemencoding() in the sys module. However, filenames can be |
---|
121 | + # encoded using another encoding than the one used on the filesystem. |
---|
122 | + |
---|
123 | + precondition(isinstance(s, str), s) |
---|
124 | + encoding = sys.getfilesystemencoding() |
---|
125 | + try: |
---|
126 | + return unicode(s, encoding) |
---|
127 | + except UnicodeDecodeError: |
---|
128 | + raise usage.UsageError("Filename '%s' cannot be decoded using the current encoding of your filesystem (%s). Please rename this file." % (s, encoding)) |
---|
129 | + |
---|
130 | +def unicode_to_fs(s): |
---|
131 | + """ |
---|
132 | + Encode an unicode object used in file or directoy name. |
---|
133 | + """ |
---|
134 | + |
---|
135 | + precondition(isinstance(s, unicode), s) |
---|
136 | + encoding = sys.getfilesystemencoding() |
---|
137 | + try: |
---|
138 | + return s.encode(encoding) |
---|
139 | + except UnicodeEncodeError: |
---|
140 | + raise usage.UsageError("Filename '%s' cannot be encoded using the current encoding of your filesystem (%s). Please configure your locale correctly or rename this file." % (s, encoding)) |
---|
141 | + |
---|
142 | +def unicode_to_url(s): |
---|
143 | + """ |
---|
144 | + Encode an unicode object used in an URL. |
---|
145 | + """ |
---|
146 | + # According to RFC 2718, non-ascii characters in url's must be UTF-8 encoded. |
---|
147 | + |
---|
148 | + precondition(isinstance(s, unicode), s) |
---|
149 | + return s.encode('utf-8') |
---|
150 | + |
---|
151 | +def unicode_to_stdout(s): |
---|
152 | + """ |
---|
153 | + Encode an unicode object for representation on stdout. |
---|
154 | + """ |
---|
155 | + |
---|
156 | + precondition(isinstance(s, unicode), s) |
---|
157 | + return s.encode(sys.stdout.encoding, 'replace') |
---|
158 | } |
---|
159 | [cli: tahoe backup unicode support |
---|
160 | francois@ctrlaltdel.ch**20090427085931 |
---|
161 | Ignore-this: 1270f10115dfbc6a1661678cce279072 |
---|
162 | ] { |
---|
163 | hunk ./src/allmydata/scripts/cli.py 225 |
---|
164 | self['exclude'] = set() |
---|
165 | |
---|
166 | def parseArgs(self, localdir, topath): |
---|
167 | - self.from_dir = localdir |
---|
168 | - self.to_dir = topath |
---|
169 | + self.from_dir = argv_to_unicode(localdir) |
---|
170 | + self.to_dir = argv_to_unicode(topath) |
---|
171 | |
---|
172 | def getSynopsis(Self): |
---|
173 | return "%s backup FROM ALIAS:TO" % os.path.basename(sys.argv[0]) |
---|
174 | hunk ./src/allmydata/scripts/tahoe_backup.py 7 |
---|
175 | import urllib |
---|
176 | import simplejson |
---|
177 | import datetime |
---|
178 | +import sys |
---|
179 | from allmydata.scripts.common import get_alias, escape_path, DEFAULT_ALIAS |
---|
180 | from allmydata.scripts.common_http import do_http |
---|
181 | from allmydata import uri |
---|
182 | hunk ./src/allmydata/scripts/tahoe_backup.py 13 |
---|
183 | from allmydata.util import time_format |
---|
184 | from allmydata.scripts import backupdb |
---|
185 | +from allmydata.util.stringutils import fs_to_unicode, unicode_to_fs, unicode_to_stdout |
---|
186 | +from allmydata.util.assertutil import precondition |
---|
187 | +from twisted.python import usage |
---|
188 | |
---|
189 | class HTTPError(Exception): |
---|
190 | pass |
---|
191 | hunk ./src/allmydata/scripts/tahoe_backup.py 252 |
---|
192 | |
---|
193 | def verboseprint(self, msg): |
---|
194 | if self.verbosity >= 2: |
---|
195 | - print >>self.options.stdout, msg |
---|
196 | + print >>self.options.stdout, unicode_to_stdout(msg) |
---|
197 | |
---|
198 | def process(self, localpath, olddircap): |
---|
199 | hunk ./src/allmydata/scripts/tahoe_backup.py 255 |
---|
200 | + precondition(isinstance(localpath, unicode), localpath) |
---|
201 | # returns newdircap |
---|
202 | |
---|
203 | self.verboseprint("processing %s, olddircap %s" % (localpath, olddircap)) |
---|
204 | hunk ./src/allmydata/scripts/tahoe_backup.py 264 |
---|
205 | olddircontents = self.readdir(olddircap) |
---|
206 | |
---|
207 | newdircontents = {} # childname -> (type, rocap, metadata) |
---|
208 | - for child in self.options.filter_listdir(os.listdir(localpath)): |
---|
209 | + for child in self.options.filter_listdir(os.listdir(unicode_to_fs(localpath))): |
---|
210 | + child = fs_to_unicode(child) |
---|
211 | childpath = os.path.join(localpath, child) |
---|
212 | if os.path.isdir(childpath): |
---|
213 | metadata = get_local_metadata(childpath) |
---|
214 | hunk ./src/allmydata/scripts/tahoe_backup.py 351 |
---|
215 | return contents |
---|
216 | |
---|
217 | def upload(self, childpath): |
---|
218 | + precondition(isinstance(childpath, unicode), childpath) |
---|
219 | + |
---|
220 | #self.verboseprint("uploading %s.." % childpath) |
---|
221 | metadata = get_local_metadata(childpath) |
---|
222 | |
---|
223 | hunk ./src/allmydata/scripts/tahoe_backup.py 361 |
---|
224 | |
---|
225 | if must_upload: |
---|
226 | self.verboseprint("uploading %s.." % childpath) |
---|
227 | - infileobj = open(os.path.expanduser(childpath), "rb") |
---|
228 | + infileobj = open(unicode_to_fs(os.path.expanduser(childpath)), "rb") |
---|
229 | url = self.options['node-url'] + "uri" |
---|
230 | resp = do_http("PUT", url, infileobj) |
---|
231 | if resp.status not in (200, 201): |
---|
232 | hunk ./src/allmydata/test/test_cli.py 875 |
---|
233 | self.writeto("parent/subdir/bar.txt", "bar\n" * 1000) |
---|
234 | self.writeto("parent/blah.txt", "blah") |
---|
235 | |
---|
236 | + if sys.getfilesystemencoding() == "ANSI_X3.4-1968": |
---|
237 | + self.writeto(u"parent/artonwall.txt", "Marmelade Jacuzzi") |
---|
238 | + else: |
---|
239 | + self.writeto(u"parent/ärtonwall.txt", "Marmelade Jacuzzi") |
---|
240 | + |
---|
241 | def do_backup(use_backupdb=True, verbose=False): |
---|
242 | cmd = ["backup"] |
---|
243 | if not have_bdb or not use_backupdb: |
---|
244 | hunk ./src/allmydata/test/test_cli.py 904 |
---|
245 | self.failUnlessEqual(err, "") |
---|
246 | self.failUnlessEqual(rc, 0) |
---|
247 | fu, fr, dc, dr = self.count_output(out) |
---|
248 | - # foo.txt, bar.txt, blah.txt |
---|
249 | - self.failUnlessEqual(fu, 3) |
---|
250 | + # foo.txt, bar.txt, blah.txt, ärtonwall.txt |
---|
251 | + self.failUnlessEqual(fu, 4) |
---|
252 | self.failUnlessEqual(fr, 0) |
---|
253 | # empty, home, home/parent, home/parent/subdir |
---|
254 | self.failUnlessEqual(dc, 4) |
---|
255 | hunk ./src/allmydata/test/test_cli.py 954 |
---|
256 | self.failUnlessEqual(rc, 0) |
---|
257 | if have_bdb: |
---|
258 | fu, fr, dc, dr = self.count_output(out) |
---|
259 | - # foo.txt, bar.txt, blah.txt |
---|
260 | + # foo.txt, bar.txt, blah.txt, ärtonwall.txt |
---|
261 | self.failUnlessEqual(fu, 0) |
---|
262 | hunk ./src/allmydata/test/test_cli.py 956 |
---|
263 | - self.failUnlessEqual(fr, 3) |
---|
264 | + self.failUnlessEqual(fr, 4) |
---|
265 | # empty, home, home/parent, home/parent/subdir |
---|
266 | self.failUnlessEqual(dc, 0) |
---|
267 | self.failUnlessEqual(dr, 4) |
---|
268 | hunk ./src/allmydata/test/test_cli.py 984 |
---|
269 | self.failUnlessEqual(rc, 0) |
---|
270 | fu, fr, dc, dr = self.count_output(out) |
---|
271 | fchecked, dchecked, dread = self.count_output2(out) |
---|
272 | - self.failUnlessEqual(fchecked, 3) |
---|
273 | + self.failUnlessEqual(fchecked, 4) |
---|
274 | self.failUnlessEqual(fu, 0) |
---|
275 | hunk ./src/allmydata/test/test_cli.py 986 |
---|
276 | - self.failUnlessEqual(fr, 3) |
---|
277 | + self.failUnlessEqual(fr, 4) |
---|
278 | # TODO: backupdb doesn't do dirs yet; when it does, this will |
---|
279 | # change to dchecked=4, and maybe dread=0 |
---|
280 | self.failUnlessEqual(dchecked, 0) |
---|
281 | hunk ./src/allmydata/test/test_cli.py 1032 |
---|
282 | fu, fr, dc, dr = self.count_output(out) |
---|
283 | # new foo.txt, surprise file, subfile, empty |
---|
284 | self.failUnlessEqual(fu, 4) |
---|
285 | - # old bar.txt |
---|
286 | - self.failUnlessEqual(fr, 1) |
---|
287 | + # old bar.txt, ärtonwall.txt |
---|
288 | + self.failUnlessEqual(fr, 2) |
---|
289 | # home, parent, subdir, blah.txt, surprisedir |
---|
290 | self.failUnlessEqual(dc, 5) |
---|
291 | self.failUnlessEqual(dr, 0) |
---|
292 | hunk ./src/allmydata/test/test_cli.py 1072 |
---|
293 | self.failUnlessEqual(err, "") |
---|
294 | self.failUnlessEqual(rc, 0) |
---|
295 | fu, fr, dc, dr = self.count_output(out) |
---|
296 | - self.failUnlessEqual(fu, 5) |
---|
297 | + self.failUnlessEqual(fu, 6) |
---|
298 | self.failUnlessEqual(fr, 0) |
---|
299 | self.failUnlessEqual(dc, 0) |
---|
300 | self.failUnlessEqual(dr, 5) |
---|
301 | } |
---|
302 | [cli: tahoe manifest unicode support |
---|
303 | francois@ctrlaltdel.ch**20090427090144 |
---|
304 | Ignore-this: d2d3ca0614d6cbf725a4b0a0f06f7694 |
---|
305 | ] { |
---|
306 | hunk ./src/allmydata/scripts/cli.py 289 |
---|
307 | ("raw", "r", "Display raw JSON data instead of parsed"), |
---|
308 | ] |
---|
309 | def parseArgs(self, where=''): |
---|
310 | - self.where = where |
---|
311 | + self.where = argv_to_unicode(where) |
---|
312 | |
---|
313 | def getSynopsis(self): |
---|
314 | return "%s manifest [ALIAS:PATH]" % (os.path.basename(sys.argv[0]),) |
---|
315 | hunk ./src/allmydata/scripts/tahoe_manifest.py 83 |
---|
316 | try: |
---|
317 | print >>stdout, d["cap"], "/".join(d["path"]) |
---|
318 | except UnicodeEncodeError: |
---|
319 | - print >>stdout, d["cap"], "/".join([p.encode("utf-8") |
---|
320 | + print >>stdout, d["cap"], "/".join([unicode_to_stdout(p) |
---|
321 | for p in d["path"]]) |
---|
322 | |
---|
323 | def manifest(options): |
---|
324 | } |
---|
325 | [cli: tahoe ls unicode support |
---|
326 | francois@ctrlaltdel.ch**20090427091850 |
---|
327 | Ignore-this: 38257c3ddea0cbab857c2eb194c349ec |
---|
328 | ] { |
---|
329 | hunk ./src/allmydata/scripts/cli.py 87 |
---|
330 | ("json", None, "Show the raw JSON output"), |
---|
331 | ] |
---|
332 | def parseArgs(self, where=""): |
---|
333 | - self.where = where |
---|
334 | + self.where = argv_to_unicode(where) |
---|
335 | |
---|
336 | longdesc = """List the contents of some portion of the virtual drive.""" |
---|
337 | |
---|
338 | hunk ./src/allmydata/scripts/tahoe_ls.py 6 |
---|
339 | import simplejson |
---|
340 | from allmydata.scripts.common import get_alias, DEFAULT_ALIAS, escape_path |
---|
341 | from allmydata.scripts.common_http import do_http |
---|
342 | +from allmydata.util.stringutils import unicode_to_stdout |
---|
343 | |
---|
344 | def list(options): |
---|
345 | nodeurl = options['node-url'] |
---|
346 | hunk ./src/allmydata/scripts/tahoe_ls.py 116 |
---|
347 | line.append(ctime_s) |
---|
348 | if not options["classify"]: |
---|
349 | classify = "" |
---|
350 | - line.append(name + classify) |
---|
351 | + line.append(unicode_to_stdout(name) + classify) |
---|
352 | if options["uri"]: |
---|
353 | line.append(uri) |
---|
354 | if options["readonly-uri"]: |
---|
355 | } |
---|
356 | [cli: tahoe get unicode support |
---|
357 | francois@ctrlaltdel.ch**20090427091820 |
---|
358 | Ignore-this: 9cae48ab0055113379beab9d4ee504e5 |
---|
359 | ] hunk ./src/allmydata/scripts/cli.py 98 |
---|
360 | # tahoe get FOO bar # write to local file |
---|
361 | # tahoe get tahoe:FOO bar # same |
---|
362 | |
---|
363 | - self.from_file = arg1 |
---|
364 | - self.to_file = arg2 |
---|
365 | + self.from_file = argv_to_unicode(arg1) |
---|
366 | + |
---|
367 | + if arg2: |
---|
368 | + self.to_file = argv_to_unicode(arg2) |
---|
369 | + else: |
---|
370 | + self.to_file = None |
---|
371 | + |
---|
372 | if self.to_file == "-": |
---|
373 | self.to_file = None |
---|
374 | |
---|
375 | [cli: tahoe webopen unicode support |
---|
376 | francois@ctrlaltdel.ch**20090427090059 |
---|
377 | Ignore-this: 2b972b5f3f240dfbb7545b5acd388f81 |
---|
378 | ] hunk ./src/allmydata/scripts/cli.py 279 |
---|
379 | |
---|
380 | class WebopenOptions(VDriveOptions): |
---|
381 | def parseArgs(self, where=''): |
---|
382 | - self.where = where |
---|
383 | + self.where = argv_to_unicode(where) |
---|
384 | |
---|
385 | def getSynopsis(self): |
---|
386 | return "%s webopen [ALIAS:PATH]" % (os.path.basename(sys.argv[0]),) |
---|
387 | [cli: tahoe rm unicode support |
---|
388 | francois@ctrlaltdel.ch**20090427085847 |
---|
389 | Ignore-this: dadad2700725c85440b9c34d8ce3c68c |
---|
390 | ] hunk ./src/allmydata/scripts/cli.py 197 |
---|
391 | |
---|
392 | class MvOptions(VDriveOptions): |
---|
393 | def parseArgs(self, frompath, topath): |
---|
394 | - self.from_file = frompath |
---|
395 | - self.to_file = topath |
---|
396 | + self.from_file = argv_to_unicode(frompath) |
---|
397 | + self.to_file = argv_to_unicode(topath) |
---|
398 | |
---|
399 | def getSynopsis(self): |
---|
400 | return "%s mv FROM TO" % (os.path.basename(sys.argv[0]),) |
---|
401 | [cli: tahoe ln unicode support |
---|
402 | francois@ctrlaltdel.ch**20090427085913 |
---|
403 | Ignore-this: 82ced82ded50a925a5650ae6000b46a2 |
---|
404 | ] hunk ./src/allmydata/scripts/cli.py 205 |
---|
405 | |
---|
406 | class LnOptions(VDriveOptions): |
---|
407 | def parseArgs(self, frompath, topath): |
---|
408 | - self.from_file = frompath |
---|
409 | - self.to_file = topath |
---|
410 | + self.from_file = argv_to_unicode(frompath) |
---|
411 | + self.to_file = argv_to_unicode(topath) |
---|
412 | |
---|
413 | def getSynopsis(self): |
---|
414 | return "%s ln FROM TO" % (os.path.basename(sys.argv[0]),) |
---|
415 | [cli: tahoe status unicode support |
---|
416 | francois@ctrlaltdel.ch**20090427090213 |
---|
417 | Ignore-this: 370469b0cea44162bfa8d11e58ee72d4 |
---|
418 | ] hunk ./src/allmydata/scripts/cli.py 306 |
---|
419 | ("raw", "r", "Display raw JSON data instead of parsed"), |
---|
420 | ] |
---|
421 | def parseArgs(self, where=''): |
---|
422 | - self.where = where |
---|
423 | + self.where = argv_to_unicode(where) |
---|
424 | |
---|
425 | def getSynopsis(self): |
---|
426 | return "%s stats [ALIAS:PATH]" % (os.path.basename(sys.argv[0]),) |
---|
427 | [cli: tahoe check unicode support |
---|
428 | francois@ctrlaltdel.ch**20090427090226 |
---|
429 | Ignore-this: 59700729d6dc91c77ae46f4d053e79ce |
---|
430 | ] hunk ./src/allmydata/scripts/cli.py 321 |
---|
431 | ("add-lease", None, "Add/renew lease on all shares"), |
---|
432 | ] |
---|
433 | def parseArgs(self, where=''): |
---|
434 | - self.where = where |
---|
435 | + self.where = argv_to_unicode(where) |
---|
436 | |
---|
437 | def getSynopsis(self): |
---|
438 | return "%s check [ALIAS:PATH]" % (os.path.basename(sys.argv[0]),) |
---|
439 | [cli: tahoe deep-check unicode support |
---|
440 | francois@ctrlaltdel.ch**20090427090243 |
---|
441 | Ignore-this: 2d0bb5592ae8735a184e325bd1515dec |
---|
442 | ] hunk ./src/allmydata/scripts/cli.py 337 |
---|
443 | ("verbose", "v", "Be noisy about what is happening."), |
---|
444 | ] |
---|
445 | def parseArgs(self, where=''): |
---|
446 | - self.where = where |
---|
447 | + self.where = argv_to_unicode(where) |
---|
448 | |
---|
449 | def getSynopsis(self): |
---|
450 | return "%s deep-check [ALIAS:PATH]" % (os.path.basename(sys.argv[0]),) |
---|
451 | [cli: tahoe mkdir unicode support |
---|
452 | francois@ctrlaltdel.ch**20090427091047 |
---|
453 | Ignore-this: 1375e8ea621d862ed4e261a8fc6cd772 |
---|
454 | ] { |
---|
455 | hunk ./src/allmydata/scripts/cli.py 53 |
---|
456 | |
---|
457 | class MakeDirectoryOptions(VDriveOptions): |
---|
458 | def parseArgs(self, where=""): |
---|
459 | - self.where = where |
---|
460 | + self.where = argv_to_unicode(where) |
---|
461 | longdesc = """Create a new directory, either unlinked or as a subdirectory.""" |
---|
462 | |
---|
463 | class AddAliasOptions(VDriveOptions): |
---|
464 | hunk ./src/allmydata/scripts/tahoe_mkdir.py 5 |
---|
465 | import urllib |
---|
466 | from allmydata.scripts.common_http import do_http, check_http_error |
---|
467 | from allmydata.scripts.common import get_alias, DEFAULT_ALIAS |
---|
468 | +from allmydata.util.stringutils import unicode_to_url |
---|
469 | |
---|
470 | def mkdir(options): |
---|
471 | nodeurl = options['node-url'] |
---|
472 | hunk ./src/allmydata/scripts/tahoe_mkdir.py 35 |
---|
473 | path = path[:-1] |
---|
474 | # path (in argv) must be "/".join([s.encode("utf-8") for s in segments]) |
---|
475 | url = nodeurl + "uri/%s/%s?t=mkdir" % (urllib.quote(rootcap), |
---|
476 | - urllib.quote(path)) |
---|
477 | + urllib.quote(unicode_to_url(path))) |
---|
478 | resp = do_http("POST", url) |
---|
479 | check_http_error(resp, stderr) |
---|
480 | new_uri = resp.read().strip() |
---|
481 | hunk ./src/allmydata/test/test_cli.py 841 |
---|
482 | dn, "tahoe:")) |
---|
483 | return d |
---|
484 | |
---|
485 | +class Mkdir(GridTestMixin, CLITestMixin, unittest.TestCase): |
---|
486 | + def test_unicode_mkdir(self): |
---|
487 | + self.basedir = os.path.dirname(self.mktemp()) |
---|
488 | + self.set_up_grid() |
---|
489 | + |
---|
490 | + d = self.do_cli("create-alias", "tahoe") |
---|
491 | + d.addCallback(lambda res: self.do_cli("mkdir", "tahoe:Motörhead")) |
---|
492 | + |
---|
493 | + return d |
---|
494 | + |
---|
495 | + |
---|
496 | class Backup(GridTestMixin, CLITestMixin, StallMixin, unittest.TestCase): |
---|
497 | |
---|
498 | def writeto(self, path, data): |
---|
499 | } |
---|
500 | [docs: explain the current unicode support in CLI |
---|
501 | francois@ctrlaltdel.ch**20090427091252 |
---|
502 | Ignore-this: 42f2c3107c0c94172f878559944779ca |
---|
503 | ] hunk ./docs/frontends/CLI.txt 94 |
---|
504 | These commands also use a table of "aliases" to figure out which directory |
---|
505 | they ought to use a starting point. This is explained in more detail below. |
---|
506 | |
---|
507 | -In Tahoe v1.3.0, passing non-ascii characters to the cli is not guaranteed to |
---|
508 | -work, although it might work on your platform, especially if your platform |
---|
509 | -uses utf-8 encoding. |
---|
510 | +As of Tahoe v1.3.1, filenames containing non-ascii characters are |
---|
511 | +supported on the commande line if your terminal is correctly configured |
---|
512 | +for UTF-8 support. This is usually the case on moderns GNU/Linux |
---|
513 | +distributions. |
---|
514 | + |
---|
515 | +If your terminal doesn't support UTF-8, you will still be able to list |
---|
516 | +directories but non-ascii characters will be replaced by a question mark |
---|
517 | +(?) on display. |
---|
518 | + |
---|
519 | +Reading from and writing to files whose name contain non-ascii |
---|
520 | +characters is also supported when your system correctly understand them. |
---|
521 | +Under Unix, this is usually handled by locale settings. If Tahoe cannot |
---|
522 | +correctly decode a filename, it will raise an error. In such case, |
---|
523 | +you'll need to correct the name of your file, possibly with help from |
---|
524 | +tools such as convmv. |
---|
525 | |
---|
526 | === Starting Directories === |
---|
527 | |
---|
528 | [cli: tahoe cp unicode support |
---|
529 | francois@ctrlaltdel.ch**20090427135203 |
---|
530 | Ignore-this: cd26cdd0753625d1c1252cffd976abd6 |
---|
531 | ] { |
---|
532 | hunk ./src/allmydata/scripts/cli.py 185 |
---|
533 | def parseArgs(self, *args): |
---|
534 | if len(args) < 2: |
---|
535 | raise usage.UsageError("cp requires at least two arguments") |
---|
536 | - self.sources = args[:-1] |
---|
537 | - self.destination = args[-1] |
---|
538 | + self.sources = map(argv_to_unicode, args[:-1]) |
---|
539 | + self.destination = argv_to_unicode(args[-1]) |
---|
540 | |
---|
541 | class RmOptions(VDriveOptions): |
---|
542 | def parseArgs(self, where): |
---|
543 | hunk ./src/allmydata/scripts/cli.py 190 |
---|
544 | - self.where = where |
---|
545 | + self.where = argv_to_unicode(where) |
---|
546 | |
---|
547 | def getSynopsis(self): |
---|
548 | return "%s rm VDRIVE_FILE" % (os.path.basename(sys.argv[0]),) |
---|
549 | hunk ./src/allmydata/scripts/tahoe_cp.py 7 |
---|
550 | import simplejson |
---|
551 | from cStringIO import StringIO |
---|
552 | from twisted.python.failure import Failure |
---|
553 | +import sys |
---|
554 | from allmydata.scripts.common import get_alias, escape_path, DefaultAliasMarker |
---|
555 | from allmydata.scripts.common_http import do_http |
---|
556 | from allmydata import uri |
---|
557 | hunk ./src/allmydata/scripts/tahoe_cp.py 11 |
---|
558 | +from twisted.python import usage |
---|
559 | +from allmydata.util.stringutils import fs_to_unicode, unicode_to_fs, unicode_to_url |
---|
560 | +from allmydata.util.assertutil import precondition |
---|
561 | |
---|
562 | def ascii_or_none(s): |
---|
563 | if s is None: |
---|
564 | hunk ./src/allmydata/scripts/tahoe_cp.py 76 |
---|
565 | |
---|
566 | class LocalFileSource: |
---|
567 | def __init__(self, pathname): |
---|
568 | + precondition(isinstance(pathname, unicode), pathname) |
---|
569 | self.pathname = pathname |
---|
570 | |
---|
571 | def need_to_copy_bytes(self): |
---|
572 | hunk ./src/allmydata/scripts/tahoe_cp.py 87 |
---|
573 | |
---|
574 | class LocalFileTarget: |
---|
575 | def __init__(self, pathname): |
---|
576 | + precondition(isinstance(pathname, unicode), pathname) |
---|
577 | self.pathname = pathname |
---|
578 | def put_file(self, inf): |
---|
579 | outf = open(self.pathname, "wb") |
---|
580 | hunk ./src/allmydata/scripts/tahoe_cp.py 100 |
---|
581 | |
---|
582 | class LocalMissingTarget: |
---|
583 | def __init__(self, pathname): |
---|
584 | + precondition(isinstance(pathname, unicode), pathname) |
---|
585 | self.pathname = pathname |
---|
586 | |
---|
587 | def put_file(self, inf): |
---|
588 | hunk ./src/allmydata/scripts/tahoe_cp.py 114 |
---|
589 | |
---|
590 | class LocalDirectorySource: |
---|
591 | def __init__(self, progressfunc, pathname): |
---|
592 | + precondition(isinstance(pathname, unicode), pathname) |
---|
593 | + |
---|
594 | self.progressfunc = progressfunc |
---|
595 | self.pathname = pathname |
---|
596 | self.children = None |
---|
597 | hunk ./src/allmydata/scripts/tahoe_cp.py 124 |
---|
598 | if self.children is not None: |
---|
599 | return |
---|
600 | self.children = {} |
---|
601 | - children = os.listdir(self.pathname) |
---|
602 | + children = os.listdir(unicode_to_fs(self.pathname)) |
---|
603 | for i,n in enumerate(children): |
---|
604 | hunk ./src/allmydata/scripts/tahoe_cp.py 126 |
---|
605 | + n = fs_to_unicode(n) |
---|
606 | self.progressfunc("examining %d of %d" % (i, len(children))) |
---|
607 | pn = os.path.join(self.pathname, n) |
---|
608 | if os.path.isdir(pn): |
---|
609 | hunk ./src/allmydata/scripts/tahoe_cp.py 142 |
---|
610 | |
---|
611 | class LocalDirectoryTarget: |
---|
612 | def __init__(self, progressfunc, pathname): |
---|
613 | + precondition(isinstance(pathname, unicode), pathname) |
---|
614 | + |
---|
615 | self.progressfunc = progressfunc |
---|
616 | self.pathname = pathname |
---|
617 | self.children = None |
---|
618 | hunk ./src/allmydata/scripts/tahoe_cp.py 152 |
---|
619 | if self.children is not None: |
---|
620 | return |
---|
621 | self.children = {} |
---|
622 | - children = os.listdir(self.pathname) |
---|
623 | + children = os.listdir(unicode_to_fs(self.pathname)) |
---|
624 | for i,n in enumerate(children): |
---|
625 | hunk ./src/allmydata/scripts/tahoe_cp.py 154 |
---|
626 | + n = fs_to_unicode(n) |
---|
627 | self.progressfunc("examining %d of %d" % (i, len(children))) |
---|
628 | pn = os.path.join(self.pathname, n) |
---|
629 | if os.path.isdir(pn): |
---|
630 | hunk ./src/allmydata/scripts/tahoe_cp.py 176 |
---|
631 | return LocalDirectoryTarget(self.progressfunc, pathname) |
---|
632 | |
---|
633 | def put_file(self, name, inf): |
---|
634 | + precondition(isinstance(name, unicode), name) |
---|
635 | pathname = os.path.join(self.pathname, name) |
---|
636 | hunk ./src/allmydata/scripts/tahoe_cp.py 178 |
---|
637 | - outf = open(pathname, "wb") |
---|
638 | + outf = open(unicode_to_fs(pathname), "wb") |
---|
639 | while True: |
---|
640 | data = inf.read(32768) |
---|
641 | if not data: |
---|
642 | hunk ./src/allmydata/scripts/tahoe_cp.py 367 |
---|
643 | if self.writecap: |
---|
644 | url = self.nodeurl + "/".join(["uri", |
---|
645 | urllib.quote(self.writecap), |
---|
646 | - urllib.quote(name.encode('utf-8'))]) |
---|
647 | + urllib.quote(unicode_to_url(name))]) |
---|
648 | self.children[name] = TahoeFileTarget(self.nodeurl, mutable, |
---|
649 | writecap, readcap, url) |
---|
650 | else: |
---|
651 | hunk ./src/allmydata/test/test_cli.py 799 |
---|
652 | def test_unicode_filename(self): |
---|
653 | self.basedir = "cli/Cp/unicode_filename" |
---|
654 | self.set_up_grid() |
---|
655 | + d = self.do_cli("create-alias", "tahoe") |
---|
656 | + |
---|
657 | + # Use unicode strings when calling os functions |
---|
658 | + if sys.getfilesystemencoding() == "ANSI_X3.4-1968": |
---|
659 | + fn1 = os.path.join(self.basedir, u"Artonwall") |
---|
660 | + else: |
---|
661 | + fn1 = os.path.join(self.basedir, u"Ärtonwall") |
---|
662 | |
---|
663 | hunk ./src/allmydata/test/test_cli.py 807 |
---|
664 | - fn1 = os.path.join(self.basedir, "Ärtonwall") |
---|
665 | DATA1 = "unicode file content" |
---|
666 | open(fn1, "wb").write(DATA1) |
---|
667 | hunk ./src/allmydata/test/test_cli.py 809 |
---|
668 | + d.addCallback(lambda res: self.do_cli("cp", fn1.encode('utf-8'), "tahoe:Ärtonwall")) |
---|
669 | + |
---|
670 | + d.addCallback(lambda res: self.do_cli("get", "tahoe:Ärtonwall")) |
---|
671 | + d.addCallback(lambda (rc,out,err): self.failUnlessEqual(out, DATA1)) |
---|
672 | + |
---|
673 | |
---|
674 | hunk ./src/allmydata/test/test_cli.py 815 |
---|
675 | - fn2 = os.path.join(self.basedir, "Metallica") |
---|
676 | + fn2 = os.path.join(self.basedir, u"Metallica") |
---|
677 | DATA2 = "non-unicode file content" |
---|
678 | open(fn2, "wb").write(DATA2) |
---|
679 | |
---|
680 | hunk ./src/allmydata/test/test_cli.py 822 |
---|
681 | # Bug #534 |
---|
682 | # Assure that uploading a file whose name contains unicode character doesn't |
---|
683 | # prevent further uploads in the same directory |
---|
684 | - d = self.do_cli("create-alias", "tahoe") |
---|
685 | - d.addCallback(lambda res: self.do_cli("cp", fn1, "tahoe:")) |
---|
686 | - d.addCallback(lambda res: self.do_cli("cp", fn2, "tahoe:")) |
---|
687 | - |
---|
688 | - d.addCallback(lambda res: self.do_cli("get", "tahoe:Ärtonwall")) |
---|
689 | - d.addCallback(lambda (rc,out,err): self.failUnlessEqual(out, DATA1)) |
---|
690 | + d.addCallback(lambda res: self.do_cli("cp", fn2.encode('utf-8'), "tahoe:")) |
---|
691 | |
---|
692 | d.addCallback(lambda res: self.do_cli("get", "tahoe:Metallica")) |
---|
693 | d.addCallback(lambda (rc,out,err): self.failUnlessEqual(out, DATA2)) |
---|
694 | hunk ./src/allmydata/test/test_cli.py 827 |
---|
695 | |
---|
696 | + d.addCallback(lambda res: self.do_cli("ls", "tahoe:")) |
---|
697 | + |
---|
698 | return d |
---|
699 | test_unicode_filename.todo = "This behavior is not yet supported, although it does happen to work (for reasons that are ill-understood) on many platforms. See issue ticket #534." |
---|
700 | |
---|
701 | } |
---|
702 | [cli: tahoe put unicode support + encode path elements using unicode_to_url |
---|
703 | francois@ctrlaltdel.ch**20090429162003 |
---|
704 | Ignore-this: 6285a8c89837290173e9a4d3744e1173 |
---|
705 | |
---|
706 | Both changes (tahoe put and url encoding) had to be included in the same patch |
---|
707 | to prevent failing tests. |
---|
708 | ] { |
---|
709 | hunk ./src/allmydata/scripts/cli.py 140 |
---|
710 | # tahoe put bar tahoe:FOO # same |
---|
711 | |
---|
712 | if arg1 is not None and arg2 is not None: |
---|
713 | - self.from_file = arg1 |
---|
714 | - self.to_file = arg2 |
---|
715 | + self.from_file = argv_to_unicode(arg1) |
---|
716 | + self.to_file = argv_to_unicode(arg2) |
---|
717 | elif arg1 is not None and arg2 is None: |
---|
718 | hunk ./src/allmydata/scripts/cli.py 143 |
---|
719 | - self.from_file = arg1 # might be "-" |
---|
720 | + self.from_file = argv_to_unicode(arg1) # might be "-" |
---|
721 | self.to_file = None |
---|
722 | else: |
---|
723 | self.from_file = None |
---|
724 | hunk ./src/allmydata/scripts/cli.py 148 |
---|
725 | self.to_file = None |
---|
726 | - if self.from_file == "-": |
---|
727 | + if self.from_file == u"-": |
---|
728 | self.from_file = None |
---|
729 | |
---|
730 | def getSynopsis(self): |
---|
731 | hunk ./src/allmydata/scripts/common.py 166 |
---|
732 | |
---|
733 | def escape_path(path): |
---|
734 | segments = path.split("/") |
---|
735 | - return "/".join([urllib.quote(s) for s in segments]) |
---|
736 | + return "/".join([urllib.quote(unicode_to_url(s)) for s in segments]) |
---|
737 | hunk ./src/allmydata/test/test_cli.py 743 |
---|
738 | d.addCallback(lambda (rc,out,err): self.failUnlessEqual(out, DATA2)) |
---|
739 | return d |
---|
740 | |
---|
741 | + def test_immutable_from_file_unicode(self): |
---|
742 | + # tahoe put file.txt "à trier.txt" |
---|
743 | + self.basedir = os.path.dirname(self.mktemp()) |
---|
744 | + self.set_up_grid() |
---|
745 | + |
---|
746 | + rel_fn = os.path.join(self.basedir, "DATAFILE") |
---|
747 | + abs_fn = os.path.abspath(rel_fn) |
---|
748 | + # we make the file small enough to fit in a LIT file, for speed |
---|
749 | + DATA = "short file" |
---|
750 | + f = open(rel_fn, "w") |
---|
751 | + f.write(DATA) |
---|
752 | + f.close() |
---|
753 | + |
---|
754 | + d = self.do_cli("create-alias", "tahoe") |
---|
755 | + |
---|
756 | + d.addCallback(lambda res: |
---|
757 | + self.do_cli("put", rel_fn, "à trier.txt")) |
---|
758 | + def _uploaded((rc,stdout,stderr)): |
---|
759 | + readcap = stdout.strip() |
---|
760 | + self.failUnless(readcap.startswith("URI:LIT:")) |
---|
761 | + self.failUnless("201 Created" in stderr, stderr) |
---|
762 | + self.readcap = readcap |
---|
763 | + d.addCallback(_uploaded) |
---|
764 | + |
---|
765 | + d.addCallback(lambda res: |
---|
766 | + self.do_cli("get", "tahoe:à trier.txt")) |
---|
767 | + d.addCallback(lambda (rc,stdout,stderr): |
---|
768 | + self.failUnlessEqual(stdout, DATA)) |
---|
769 | + |
---|
770 | + return d |
---|
771 | + |
---|
772 | class List(GridTestMixin, CLITestMixin, unittest.TestCase): |
---|
773 | def test_list(self): |
---|
774 | self.basedir = "cli/List/list" |
---|
775 | } |
---|
776 | [cli: aliases unicode support |
---|
777 | francois@ctrlaltdel.ch**20090427095807 |
---|
778 | Ignore-this: e2c49f5851ab89819acc633a196cc3df |
---|
779 | ] { |
---|
780 | hunk ./src/allmydata/scripts/cli.py 58 |
---|
781 | |
---|
782 | class AddAliasOptions(VDriveOptions): |
---|
783 | def parseArgs(self, alias, cap): |
---|
784 | - self.alias = alias |
---|
785 | + self.alias = argv_to_unicode(alias) |
---|
786 | self.cap = cap |
---|
787 | |
---|
788 | def getSynopsis(self): |
---|
789 | hunk ./src/allmydata/scripts/cli.py 68 |
---|
790 | |
---|
791 | class CreateAliasOptions(VDriveOptions): |
---|
792 | def parseArgs(self, alias): |
---|
793 | - self.alias = alias |
---|
794 | + self.alias = argv_to_unicode(alias) |
---|
795 | |
---|
796 | def getSynopsis(self): |
---|
797 | return "%s create-alias ALIAS" % (os.path.basename(sys.argv[0]),) |
---|
798 | hunk ./src/allmydata/scripts/common.py 3 |
---|
799 | |
---|
800 | import os, sys, urllib |
---|
801 | +import codecs |
---|
802 | from twisted.python import usage |
---|
803 | from allmydata.util.stringutils import unicode_to_url |
---|
804 | |
---|
805 | hunk ./src/allmydata/scripts/common.py 104 |
---|
806 | except EnvironmentError: |
---|
807 | pass |
---|
808 | try: |
---|
809 | - f = open(aliasfile, "r") |
---|
810 | + f = codecs.open(aliasfile, "r", "utf-8") |
---|
811 | for line in f.readlines(): |
---|
812 | line = line.strip() |
---|
813 | if line.startswith("#") or not line: |
---|
814 | hunk ./src/allmydata/scripts/common.py 111 |
---|
815 | continue |
---|
816 | name, cap = line.split(":", 1) |
---|
817 | # normalize it: remove http: prefix, urldecode |
---|
818 | - cap = cap.strip() |
---|
819 | + cap = cap.strip().encode('ascii') |
---|
820 | aliases[name] = uri.from_string_dirnode(cap).to_string() |
---|
821 | except EnvironmentError: |
---|
822 | pass |
---|
823 | hunk ./src/allmydata/scripts/tahoe_add_alias.py 3 |
---|
824 | |
---|
825 | import os.path |
---|
826 | +import codecs |
---|
827 | +import sys |
---|
828 | from allmydata import uri |
---|
829 | from allmydata.scripts.common_http import do_http, check_http_error |
---|
830 | from allmydata.scripts.common import get_aliases |
---|
831 | hunk ./src/allmydata/scripts/tahoe_add_alias.py 8 |
---|
832 | +from allmydata.util.stringutils import unicode_to_stdout |
---|
833 | |
---|
834 | def add_alias(options): |
---|
835 | nodedir = options['node-directory'] |
---|
836 | hunk ./src/allmydata/scripts/tahoe_add_alias.py 58 |
---|
837 | new_uri = resp.read().strip() |
---|
838 | |
---|
839 | # probably check for others.. |
---|
840 | - f = open(aliasfile, "a") |
---|
841 | + f = codecs.open(aliasfile, "a", "utf-8") |
---|
842 | f.write("%s: %s\n" % (alias, new_uri)) |
---|
843 | f.close() |
---|
844 | hunk ./src/allmydata/scripts/tahoe_add_alias.py 61 |
---|
845 | - print >>stdout, "Alias '%s' created" % (alias,) |
---|
846 | + print >>stdout, "Alias '%s' created" % (unicode_to_stdout(alias),) |
---|
847 | return 0 |
---|
848 | |
---|
849 | def list_aliases(options): |
---|
850 | hunk ./src/allmydata/test/test_cli.py 522 |
---|
851 | self._test_webopen(["two:"], self.two_url) |
---|
852 | d.addCallback(_test_urls) |
---|
853 | |
---|
854 | + d.addCallback(lambda res: self.do_cli("create-alias", "études")) |
---|
855 | + def _check_create_unicode((rc,stdout,stderr)): |
---|
856 | + self.failUnlessEqual(rc, 0) |
---|
857 | + self.failIf(stderr) |
---|
858 | + |
---|
859 | + # If stdout only supports ascii, accentuated characters are |
---|
860 | + # being replaced by '?' |
---|
861 | + if sys.stdout.encoding == "ANSI_X3.4-1968": |
---|
862 | + self.failUnless("Alias '?tudes' created" in stdout) |
---|
863 | + else: |
---|
864 | + self.failUnless("Alias 'études' created" in stdout) |
---|
865 | + |
---|
866 | + aliases = get_aliases(self.get_clientdir()) |
---|
867 | + self.failUnless(aliases[u"études"].startswith("URI:DIR2:")) |
---|
868 | + d.addCallback(_check_create_unicode) |
---|
869 | + |
---|
870 | + d.addCallback(lambda res: self.do_cli("ls", "études:")) |
---|
871 | + def _check_ls1((rc, stdout, stderr)): |
---|
872 | + self.failUnlessEqual(rc, 0) |
---|
873 | + self.failIf(stderr) |
---|
874 | + |
---|
875 | + self.failUnlessEqual(stdout, "") |
---|
876 | + d.addCallback(_check_ls1) |
---|
877 | + |
---|
878 | + d.addCallback(lambda res: self.do_cli("put", "-", "études:uploaded.txt", |
---|
879 | + stdin="Blah blah blah")) |
---|
880 | + |
---|
881 | + d.addCallback(lambda res: self.do_cli("ls", "études:")) |
---|
882 | + def _check_ls2((rc, stdout, stderr)): |
---|
883 | + self.failUnlessEqual(rc, 0) |
---|
884 | + self.failIf(stderr) |
---|
885 | + |
---|
886 | + self.failUnlessEqual(stdout, "uploaded.txt\n") |
---|
887 | + d.addCallback(_check_ls2) |
---|
888 | + |
---|
889 | + d.addCallback(lambda res: self.do_cli("get", "études:uploaded.txt")) |
---|
890 | + def _check_get((rc, stdout, stderr)): |
---|
891 | + self.failUnlessEqual(rc, 0) |
---|
892 | + self.failIf(stderr) |
---|
893 | + self.failUnlessEqual(stdout, "Blah blah blah") |
---|
894 | + d.addCallback(_check_get) |
---|
895 | + |
---|
896 | return d |
---|
897 | |
---|
898 | class Put(GridTestMixin, CLITestMixin, unittest.TestCase): |
---|
899 | } |
---|
900 | [cli: previous cli related patches should fix #534 |
---|
901 | francois@ctrlaltdel.ch**20090427135239 |
---|
902 | Ignore-this: 82709853d0d871651b6673929616ec08 |
---|
903 | ] hunk ./src/allmydata/test/test_cli.py 903 |
---|
904 | d.addCallback(lambda res: self.do_cli("ls", "tahoe:")) |
---|
905 | |
---|
906 | return d |
---|
907 | - test_unicode_filename.todo = "This behavior is not yet supported, although it does happen to work (for reasons that are ill-understood) on many platforms. See issue ticket #534." |
---|
908 | |
---|
909 | def test_dangling_symlink_vs_recursion(self): |
---|
910 | if not hasattr(os, 'symlink'): |
---|
911 | |
---|
912 | Context: |
---|
913 | |
---|
914 | [docs: setup: Norm Hardy suggested that it would be easier if users realized that they already had Python (especially true for Mac users) |
---|
915 | zooko@zooko.com**20090325035459 |
---|
916 | Ignore-this: e1bb76a1be4d6d541090d8d9e7e73db9 |
---|
917 | ] |
---|
918 | [expirer: include crawler progress in the JSON status output |
---|
919 | warner@allmydata.com**20090324205137 |
---|
920 | Ignore-this: f65ccc0a57ed7c5d9565131350d87d2d |
---|
921 | ] |
---|
922 | [docs/proposed: new Accounting overview, discuss in #666 |
---|
923 | warner@allmydata.com**20090324015752 |
---|
924 | Ignore-this: 7379396536e85194b1c1bec21288adc7 |
---|
925 | ] |
---|
926 | [docs/proposed: move old accounting docs out of the way |
---|
927 | warner@allmydata.com**20090324015457 |
---|
928 | Ignore-this: 196fe85ef3592f7ef8e58a101eed0494 |
---|
929 | ] |
---|
930 | [move GC docs out of proposed/, since it's all implemented now. Add reference to configuration.txt . Add expire.*= suggestions to tahoe.cfg . |
---|
931 | warner@allmydata.com**20090323230820 |
---|
932 | Ignore-this: ce0ec977f49c4a3642cf3a7ea7789dc4 |
---|
933 | ] |
---|
934 | [storage: use constant-time comparison for write-enablers and lease-secrets |
---|
935 | warner@lothar.com**20090323032128 |
---|
936 | Ignore-this: efbbb15242b3f306c32498aae7fd75d |
---|
937 | ] |
---|
938 | [hashutil: add constant-time comparison function, to avoid timing attacks when python's short-circuiting data-dependent == operator is used to, say, check a write-enabler |
---|
939 | warner@lothar.com**20090323032055 |
---|
940 | Ignore-this: c5c1f5e529ab1b352c949f3e0d9abf20 |
---|
941 | ] |
---|
942 | [WUI: fix display of empty directories, it threw an exception before |
---|
943 | warner@allmydata.com**20090320235809 |
---|
944 | Ignore-this: e598bb806d75411d202ba90fc251ad2b |
---|
945 | ] |
---|
946 | [storage webstatus: insert spaces when we're configured to expire multiple sharetypes |
---|
947 | warner@allmydata.com**20090320224450 |
---|
948 | Ignore-this: 18f44396384c8598d984eaa11dc92cf7 |
---|
949 | ] |
---|
950 | [expirer: tolerate empty buckets, refactor bucketsize-counting code a bit, don't increment -mutable/-immutable counters unless we actually know the sharetype |
---|
951 | warner@allmydata.com**20090320191816 |
---|
952 | Ignore-this: 16827fe12b874a0205b0a7fdb6b7f960 |
---|
953 | ] |
---|
954 | [storage: improve wording of status message |
---|
955 | warner@allmydata.com**20090319184837 |
---|
956 | Ignore-this: 66684623d50c89fa02915665dbbfec98 |
---|
957 | ] |
---|
958 | [parse_date: insist that it returns an int |
---|
959 | warner@allmydata.com**20090319184443 |
---|
960 | Ignore-this: a1f5ae0c16a151d218c06fc4411f03c1 |
---|
961 | ] |
---|
962 | [storage status: report expiration-cutoff-date like 19-Mar-2009 (as opposed to the tahoe.cfg input format of 2009-03-19), for redundancy: someone who gets the month and day switched will have a better chance to spot the problem in the storage-status output if it's in a different format |
---|
963 | warner@allmydata.com**20090319180756 |
---|
964 | Ignore-this: df2c3778260c6389d32f4b47b004ab35 |
---|
965 | ] |
---|
966 | [expirer: clean up constructor args, add tahoe.cfg controls, use cutoff_date instead of date_cutoff |
---|
967 | warner@allmydata.com**20090319010009 |
---|
968 | Ignore-this: 2b6aaa6d5e6ff9fd417f32978b443fd2 |
---|
969 | ] |
---|
970 | [util/time_format: new routine to parse dates like 2009-03-18, switch expirer to use it. I'd prefer to use 18-Mar-2009, but it is surprisingly non-trivial to build a parser that will take UTC dates instead of local dates |
---|
971 | warner@allmydata.com**20090319005814 |
---|
972 | Ignore-this: 4f08b301c780a78084fa02a09b5dda3 |
---|
973 | ] |
---|
974 | [expirer: change setup, config options, in preparation for adding tahoe.cfg controls |
---|
975 | warner@allmydata.com**20090319002138 |
---|
976 | Ignore-this: b23a53e97f2a9fb7a005e9fe40e83fac |
---|
977 | ] |
---|
978 | [expirer: track mutable-vs-immutable sharecounts and sizes, report them on the web status page for comparison |
---|
979 | warner@allmydata.com**20090318202504 |
---|
980 | Ignore-this: 87e809bf5dedef3f0bc8f4a7b90e42d2 |
---|
981 | ] |
---|
982 | [add utility function to parse durations, for lease-expiration config |
---|
983 | warner@lothar.com**20090317070117 |
---|
984 | Ignore-this: 2f4fa4352c887b4767969f0ea7931644 |
---|
985 | ] |
---|
986 | [expirer: add mode to expire only-mutable or only-immutable shares |
---|
987 | warner@lothar.com**20090317065118 |
---|
988 | Ignore-this: b0b25427e3b1516bdfe293528b8e4a4e |
---|
989 | ] |
---|
990 | [tahoe_ls.py: add comment about error cases to improve |
---|
991 | warner@lothar.com**20090317051206 |
---|
992 | Ignore-this: 7c678b92a55b2f7c6f0d96fb6ece74ed |
---|
993 | ] |
---|
994 | [GC: add date-cutoff -based expiration, add proposed docs |
---|
995 | warner@lothar.com**20090317051041 |
---|
996 | Ignore-this: a5c0ecbcc2666eb04f2daa67331d1948 |
---|
997 | ] |
---|
998 | [test_deepcheck: remove the 10s timeout: our dapper buildslave requires 30s, and the reduced timeout was only there because this tests fails by timeout rather than explicitly |
---|
999 | warner@lothar.com**20090316005134 |
---|
1000 | Ignore-this: 4ce081283c26719be513b5ce8381a81a |
---|
1001 | ] |
---|
1002 | [tahoe cp -r: add --caps-only flag, to write filecaps into local files instead of actual file contents. Used only for debugging and as a quick tree-comparison tool. |
---|
1003 | warner@lothar.com**20090315231958 |
---|
1004 | Ignore-this: 8ecdf2b08601ae9e9fec5885bf640262 |
---|
1005 | ] |
---|
1006 | [dirnode deep_traverse: insert a turn break (fireEventually) at least once every 100 files, otherwise a CHK followed by more than 158 LITs can overflow the stack, sort of like #237. |
---|
1007 | warner@allmydata.com**20090313233135 |
---|
1008 | Ignore-this: 39b78faa947ed9461f2d120f6843e59f |
---|
1009 | ] |
---|
1010 | [consolidate: remove pointless 'else' after for loop |
---|
1011 | warner@allmydata.com**20090313082751 |
---|
1012 | Ignore-this: 517f41316f7ae40b92b9eef8269a4b69 |
---|
1013 | ] |
---|
1014 | [consolidate: add eta, flush stdout |
---|
1015 | warner@allmydata.com**20090313082451 |
---|
1016 | Ignore-this: 845f63adccc32557c6864ae6120ba836 |
---|
1017 | ] |
---|
1018 | [consolidate: tolerate unicode dirnames |
---|
1019 | warner@allmydata.com**20090313065402 |
---|
1020 | Ignore-this: 7e65703ed3d12d4bd5ec14b693e5f61f |
---|
1021 | ] |
---|
1022 | [dirnode.py: when doing deep-traverse, walk each directory in alphabetical order, to make things like 'manifest' more predictable |
---|
1023 | warner@allmydata.com**20090313065046 |
---|
1024 | Ignore-this: 9a80055a93a6b11853d4e8202bacec14 |
---|
1025 | ] |
---|
1026 | [consolidator: add progress to scan-old-directory passes |
---|
1027 | warner@allmydata.com**20090313054728 |
---|
1028 | Ignore-this: adc67a34f4f19fd58c5bc76301b3df36 |
---|
1029 | ] |
---|
1030 | [consolidator: fix cycle detection to not trigger on merely shared directories, add snapshot counter to progress |
---|
1031 | warner@allmydata.com**20090313042229 |
---|
1032 | Ignore-this: eba2cf9f1b1364b8e4c5ae4fa030a99f |
---|
1033 | ] |
---|
1034 | [consolidator: re-use more directories, add total directories seen-vs-used counts |
---|
1035 | warner@allmydata.com**20090313034801 |
---|
1036 | Ignore-this: 6e743d2940a9fe129cee31008c894d70 |
---|
1037 | ] |
---|
1038 | [tahoe_backup.py: tolerate more time formats |
---|
1039 | warner@allmydata.com**20090313011600 |
---|
1040 | Ignore-this: ca74f56f0dce7d19810c5a7a75bc623c |
---|
1041 | ] |
---|
1042 | [consolidator: add more verbose traversal of directories |
---|
1043 | warner@allmydata.com**20090312232900 |
---|
1044 | Ignore-this: 8ff0e17c6174566832a566a111032db4 |
---|
1045 | ] |
---|
1046 | [consolidate: create multiple numbered backups of the original Archives directory, not just the first time |
---|
1047 | warner@allmydata.com**20090312230427 |
---|
1048 | Ignore-this: e4985f76969b584d099b050781aa561c |
---|
1049 | ] |
---|
1050 | [add 'tahoe debug consolidate' command, to merge directories created by repeated 'tahoe cp -r' or the allmydata win32 backup tool, into the form that would have been created by 'tahoe backup'. |
---|
1051 | warner@allmydata.com**20090312205606 |
---|
1052 | Ignore-this: 66569ca2190aa7b0f9199bcf09dcb27e |
---|
1053 | ] |
---|
1054 | [tahoe_cp.py: return 0 for success, instead of None |
---|
1055 | warner@allmydata.com**20090312205345 |
---|
1056 | Ignore-this: 808f6d8617f8c4e7fde455e6c7639fab |
---|
1057 | ] |
---|
1058 | [setup: specify in the debian/control files that tahoe is compatible with Python 2.6 |
---|
1059 | zooko@zooko.com**20090311225902 |
---|
1060 | Ignore-this: d0793013e4c868d92793d932ef92a62d |
---|
1061 | ] |
---|
1062 | [setup: update the debian/copyright text to reflect the current licences |
---|
1063 | zooko@zooko.com**20090311152952 |
---|
1064 | Ignore-this: 806a95b1b79d6bb20507db5c7201af45 |
---|
1065 | ] |
---|
1066 | [expirer: fix prediction math, thanks to Zandr for the catch |
---|
1067 | warner@allmydata.com**20090309204217 |
---|
1068 | Ignore-this: e20f784483ea1a15e35627fe95506272 |
---|
1069 | ] |
---|
1070 | [storage.expirer: oops, fix upgrade-handler code |
---|
1071 | warner@lothar.com**20090309035516 |
---|
1072 | Ignore-this: af8bc0ea1c7f305b33c06f4a9bf58de3 |
---|
1073 | ] |
---|
1074 | [storage.expirer: handle upgrades better |
---|
1075 | warner@lothar.com**20090309034220 |
---|
1076 | Ignore-this: dd654305b94bc3209426a3e008d57363 |
---|
1077 | ] |
---|
1078 | [storage.expirer: exercise the last missing line of webstatus code |
---|
1079 | warner@lothar.com**20090309033828 |
---|
1080 | Ignore-this: fc4aa34734cae32eec1db623ca0b145b |
---|
1081 | ] |
---|
1082 | [expirer: tolerate corrupt shares, add them to the state and history for future examination |
---|
1083 | warner@lothar.com**20090309030840 |
---|
1084 | Ignore-this: 5ae7e68471ed700cc68beb408e0f303 |
---|
1085 | ] |
---|
1086 | [storage/immutable: raise a specific error upon seeing a bad version number, instead of using assert. Also wrap to 80cols. |
---|
1087 | warner@lothar.com**20090309030732 |
---|
1088 | Ignore-this: 5331d9680ffceff029fbbbcdece7f282 |
---|
1089 | ] |
---|
1090 | [storage: add test coverage for BucketReader.__repr__ |
---|
1091 | warner@lothar.com**20090309030527 |
---|
1092 | Ignore-this: 60ce4e8c5200cc9885a3057f914e78b4 |
---|
1093 | ] |
---|
1094 | [storage/mutable: raise a specific error upon seeing bad magic, instead of using assert |
---|
1095 | warner@lothar.com**20090309020201 |
---|
1096 | Ignore-this: 8daa77362902f5d6ef793e9602a1383b |
---|
1097 | ] |
---|
1098 | [nodeadmin: node stops itself if a hotline file hasn't been touched in 120 seconds now, instead of in 60 seconds |
---|
1099 | zooko@zooko.com**20090308025039 |
---|
1100 | Ignore-this: a9cfc605d3fcad912bd2d0b35d5143ec |
---|
1101 | A test failed on draco (MacPPC) because it took 67.1 seconds to get around to running the test, and the node had already stopped itself when the hotline file was 60 seconds old. |
---|
1102 | ] |
---|
1103 | [expirer: make web display a bit more consistent |
---|
1104 | warner@lothar.com**20090307221442 |
---|
1105 | Ignore-this: 7fec9d9bffc0bddeb51c1baa8e7ea020 |
---|
1106 | ] |
---|
1107 | [web/storage.py: tolerate unknown-future displays, I'm not sure why LeaseCrawler.test_unpredictable_future didn't catch this |
---|
1108 | warner@lothar.com**20090307220243 |
---|
1109 | Ignore-this: 3d4e5baa8cc6d5d26edcea29fda8593d |
---|
1110 | ] |
---|
1111 | [tahoe_cp.py: improve error reporting slightly: don't json-interpret HTTP errors, pass through tahoe webapi error messages |
---|
1112 | warner@lothar.com**20090307114051 |
---|
1113 | Ignore-this: a8beccb67adb082a92509d439b27d68e |
---|
1114 | ] |
---|
1115 | [test_cli.py: assert that 'ls' on an unrecoverable file now gives a better error message |
---|
1116 | warner@lothar.com**20090307110815 |
---|
1117 | Ignore-this: 18e9758e4d0ca7faeaf5bd481c2d72ff |
---|
1118 | ] |
---|
1119 | [test_web: test behavior of broken-dirnode GET, both html and json |
---|
1120 | warner@lothar.com**20090307105707 |
---|
1121 | Ignore-this: c0e5b45eee28959f899efa1bd189d6bd |
---|
1122 | ] |
---|
1123 | [web: when a dirnode can't be read, emit a regular HTML page but with the child-table and upload-forms replaced with an apologetic message. Make sure to include the 'get info' links so the user can do a filecheck |
---|
1124 | warner@lothar.com**20090307105601 |
---|
1125 | Ignore-this: f949d6bd58c0c2fd60fd5fa730115f3f |
---|
1126 | ] |
---|
1127 | [web/common: split out exception-to-explanation+code mapping to a separate humanize_failure() function, so it can be used by other code. Add explanation for mutable UnrecoverableFileError. |
---|
1128 | warner@lothar.com**20090307105408 |
---|
1129 | Ignore-this: 92f326804ba73bb446c5df5992b7d72e |
---|
1130 | ] |
---|
1131 | [test_cli: use explicit (and stable) testdirs, instead of using self.mktemp |
---|
1132 | warner@lothar.com**20090307090428 |
---|
1133 | Ignore-this: 7c58d159e4f33d01635c3445d9e591f9 |
---|
1134 | ] |
---|
1135 | [test_storage: solaris doesn't appear to give the same block count as other platforms, so don't assert as much about 'diskbytes' recovered |
---|
1136 | warner@lothar.com**20090307084518 |
---|
1137 | Ignore-this: 55b35c094ce78c50c8ede42062c5ea13 |
---|
1138 | ] |
---|
1139 | [tahoe_cp.py: don't be verbose unless --verbose is passed: default is one line of success |
---|
1140 | warner@lothar.com**20090307084421 |
---|
1141 | Ignore-this: f75bb818081e0c2993378154775a69d1 |
---|
1142 | ] |
---|
1143 | [setup.cfg: use allmydata.org as a mirror for some of our necessary dependencies |
---|
1144 | warner@allmydata.com**20090307045753 |
---|
1145 | Ignore-this: ce174de4ad2dd96f184eadf4d62ea779 |
---|
1146 | ] |
---|
1147 | [storage: add a lease-checker-and-expirer crawler, plus web status page. |
---|
1148 | warner@allmydata.com**20090307044517 |
---|
1149 | Ignore-this: 4355224f89b959c6f1a256a7e6c88c3b |
---|
1150 | |
---|
1151 | This walks slowly through all shares, examining their leases, deciding which |
---|
1152 | are still valid and which have expired. Once enabled, it will then remove the |
---|
1153 | expired leases, and delete shares which no longer have any valid leases. Note |
---|
1154 | that there is not yet a tahoe.cfg option to enable lease-deletion: the |
---|
1155 | current code is read-only. A subsequent patch will add a tahoe.cfg knob to |
---|
1156 | control this, as well as docs. Some other minor items included in this patch: |
---|
1157 | |
---|
1158 | tahoe debug dump-share has a new --leases-only flag |
---|
1159 | storage sharefile/leaseinfo code is cleaned up |
---|
1160 | storage web status page (/storage) has more info, more tests coverage |
---|
1161 | space-left measurement on OS-X should be more accurate (it was off by 2048x) |
---|
1162 | (use stat .f_frsize instead of f_bsize) |
---|
1163 | ] |
---|
1164 | [setup: comment-out the use of the directory full of dependency packages on the test grid -- the test grid is too unreliable! :-( |
---|
1165 | zooko@zooko.com**20090307044332 |
---|
1166 | Ignore-this: c09f2e5f0b383b4227df4b07c267cb05 |
---|
1167 | ] |
---|
1168 | [setup: create a "make deb-lenny-head" target |
---|
1169 | zooko@zooko.com**20090306191057 |
---|
1170 | Ignore-this: 4b2ff187a3d08dcfe9318980ca92f097 |
---|
1171 | I made this patch by copying [20090305220021-92b7f-89d987c7d05306b5cb03a64f2956a652c10a7296] and changing the name from "intrepid" to "lenny". I haven't tested it. |
---|
1172 | ] |
---|
1173 | [trivial: remove unused import detected by pyflakes, and remove trailing whitespace |
---|
1174 | zooko@zooko.com**20090305223204 |
---|
1175 | Ignore-this: 991001a50da1a357a519c3cb880d7ee1 |
---|
1176 | ] |
---|
1177 | [setup: enable build of .debs for Ubuntu Intrepid, thanks to DarKNesS_WolF |
---|
1178 | zooko@zooko.com**20090305220021 |
---|
1179 | Ignore-this: 88dbb3f72c2446b7734ac437189b67df |
---|
1180 | ] |
---|
1181 | [trivial: use more specific function for ascii-encoding storage index |
---|
1182 | zooko@zooko.com**20090222175751 |
---|
1183 | Ignore-this: c1a78a71cf04d7dbd80a71106f9b21a1 |
---|
1184 | ] |
---|
1185 | [doc: update how_to_make_a_tahoe_release.txt |
---|
1186 | zooko@zooko.com**20090222175739 |
---|
1187 | Ignore-this: 6a2e1592741b362bc170167a9cadc0b |
---|
1188 | ] |
---|
1189 | [test_cli: validate non-HTML error response of 'tahoe get' on an unrecoverable file |
---|
1190 | warner@lothar.com**20090304041146] |
---|
1191 | [web: full patch for HTML-vs-plaintext traceback renderings, improve test coverage of exception rendering |
---|
1192 | warner@lothar.com**20090304035630] |
---|
1193 | [web/common.py: use 'Accept:' header to control HTML-vs-text/plain traceback renderings |
---|
1194 | warner@lothar.com**20090304035457] |
---|
1195 | [test/common: rearrange shouldHTTPError |
---|
1196 | warner@lothar.com**20090304014059] |
---|
1197 | [web: move plural() to common.py |
---|
1198 | warner@lothar.com**20090304014019] |
---|
1199 | [add more information to NotEnoughSharesError, split out new exceptions for no-servers and no-source-of-ueb-hash |
---|
1200 | warner@lothar.com**20090304013715] |
---|
1201 | [test_web: move shouldHTTPError into common.WebErrorMixin |
---|
1202 | warner@lothar.com**20090303225620] |
---|
1203 | [test_web: clean up shouldHTTPError methods |
---|
1204 | warner@lothar.com**20090303224604] |
---|
1205 | [immutable checker add-lease: catch remote IndexError here too |
---|
1206 | warner@allmydata.com**20090227071724 |
---|
1207 | Ignore-this: 94ee6064ce26409381c6451cd50fdade |
---|
1208 | ] |
---|
1209 | [servermap add-lease: fix the code that's supposed to catch remote IndexErrors, I forgot that they present as ServerFailures instead. This should stop the deluge of Incidents that occur when you do add-lease against 1.3.0 servers |
---|
1210 | warner@allmydata.com**20090227070426 |
---|
1211 | Ignore-this: 3d7bc87d9587b51d44b27317d9eded23 |
---|
1212 | ] |
---|
1213 | [rrefutil: add check_remote utility function |
---|
1214 | warner@allmydata.com**20090227065957 |
---|
1215 | Ignore-this: d859d0fae87b7e84ad3c2893350ed519 |
---|
1216 | ] |
---|
1217 | [rrefutil: add trap_remote utility and friends |
---|
1218 | warner@allmydata.com**20090227065524 |
---|
1219 | Ignore-this: a594050cdd9bcca073d8029819dbc35 |
---|
1220 | ] |
---|
1221 | [web: improve layout of storage status with a table |
---|
1222 | warner@allmydata.com**20090227015838 |
---|
1223 | Ignore-this: 5c12f5e296ad1cf224f85e307813eb09 |
---|
1224 | ] |
---|
1225 | [crawler: add ETA to get_progress() |
---|
1226 | warner@allmydata.com**20090227014248 |
---|
1227 | Ignore-this: 27ae76c0530b83323209be70df3d8a4b |
---|
1228 | ] |
---|
1229 | [Fix for bug #645, correct path handling logic so that it works from sshfs |
---|
1230 | Alberto Berti <alberto@metapensiero.it>**20090226150237 |
---|
1231 | Ignore-this: e9c1b2d48ebf4ba68100d76e54154a78 |
---|
1232 | ] |
---|
1233 | [wui: s/Provisioning/Reliability/ ; suggested by Terrell |
---|
1234 | zooko@zooko.com**20090226030904 |
---|
1235 | Ignore-this: f9559702e760dc3c57e2fc36f087d91e |
---|
1236 | ] |
---|
1237 | [startstop_node.py: when restarting, tolerate a stale pid too |
---|
1238 | warner@allmydata.com**20090226015245 |
---|
1239 | Ignore-this: 59197d3f400417be64fa0f91a64fae12 |
---|
1240 | ] |
---|
1241 | [web: fix the ERROR: line to work the same in python2.4 and 2.5 |
---|
1242 | warner@lothar.com**20090225074621] |
---|
1243 | [test_cli/test_web: fix spurious test failure on solaris (maybe python2.4?) due to variations in the way that exceptions are stringified |
---|
1244 | warner@allmydata.com**20090225060128 |
---|
1245 | Ignore-this: 829fb7d67fd199babdde1443b64a5381 |
---|
1246 | ] |
---|
1247 | [CLI: modify 'tahoe manifest' and 'tahoe deep-check' to report ERROR: properly. For #590. |
---|
1248 | warner@allmydata.com**20090225054415 |
---|
1249 | Ignore-this: 99162f894fdd24112a869e14848c3dea |
---|
1250 | ] |
---|
1251 | [webapi: modify streaming deep-manifest/deep-checker to emit an ERROR: line if they encounter an unrecoverable+untraversable directory. For #590. |
---|
1252 | warner@allmydata.com**20090225051335 |
---|
1253 | Ignore-this: e6bc49368fb0e7ada7cff477fd63ffe6 |
---|
1254 | ] |
---|
1255 | [scripts/common: fix alias handling on windows again, emit slightly nicer error message in response to an unknown alias |
---|
1256 | warner@allmydata.com**20090225042136 |
---|
1257 | Ignore-this: 76df800d131aed6701b5c7408105b134 |
---|
1258 | ] |
---|
1259 | [#165: make 'tahoe restart --force' the default behavior: warn but do not stop if restart is used on something that wasn't a running node, and always try to start it afterwards. This is particularly important for #315 (restart -m), because otherwise a single not-already-running node will prevent all nodes from being restarted, resulting in longer downtime than necessary |
---|
1260 | warner@allmydata.com**20090225034213 |
---|
1261 | Ignore-this: 26d8b0eea0279ca793faf23c5e948d90 |
---|
1262 | ] |
---|
1263 | [test_deepcheck: switch deep-check tests to use no-network too. This cuts the runtime down by about 50% |
---|
1264 | warner@allmydata.com**20090225030457 |
---|
1265 | Ignore-this: b3a98ed18c5752c9016c047e95d42b |
---|
1266 | ] |
---|
1267 | [test_deepcheck: convert MutableChecker to no-network GridTest |
---|
1268 | warner@allmydata.com**20090225020010 |
---|
1269 | Ignore-this: eccba7fda129330b642886271a61a573 |
---|
1270 | ] |
---|
1271 | [tests/no_network: move GET into the GridTestMixin class |
---|
1272 | warner@allmydata.com**20090225003300 |
---|
1273 | Ignore-this: 7779ad38c2d687ae328ba3cb6164a7a4 |
---|
1274 | ] |
---|
1275 | [common_web.py: oops, add .fields to the other FakeRequest |
---|
1276 | warner@allmydata.com**20090225000459 |
---|
1277 | Ignore-this: 7144269b5e083553ee2c3e7afea00604 |
---|
1278 | ] |
---|
1279 | [test_cli: exercise the recent tolerate-'c:\dir\file.txt' fix in scripts/common, recorded in a separate match to make it easier to merge the fix to prod |
---|
1280 | warner@allmydata.com**20090224235620 |
---|
1281 | Ignore-this: 2cae196dd4ccb578b2abae085376e0d7 |
---|
1282 | ] |
---|
1283 | [scripts/common: on windows, tolerate paths like 'c:\dir\file.txt', by treating single-letter aliases on windows/cygwin as non-aliases |
---|
1284 | warner@allmydata.com**20090224235522 |
---|
1285 | Ignore-this: 96d37644b7f81ac768ff4a1d1915eb46 |
---|
1286 | ] |
---|
1287 | [test/common_web.py: add a .fields attribute to our FakeRequest, since we support versions of Nevow that are old enough to not do it themselves |
---|
1288 | warner@allmydata.com**20090224232050 |
---|
1289 | Ignore-this: 239aaed746128e54e886762782541a1f |
---|
1290 | ] |
---|
1291 | [Two small fixes on documentation for cli backup command. |
---|
1292 | Alberto Berti <alberto@metapensiero.it>**20090224223634 |
---|
1293 | Ignore-this: 5634a6dadad6e4e43a112de7fe5c74c |
---|
1294 | ] |
---|
1295 | [test_web: add (disabled) test to see what happens when deep-check encounters an unrecoverable directory. We still need code changes to improve this behavior. |
---|
1296 | warner@lothar.com**20090224214017 |
---|
1297 | Ignore-this: e839f1b0ec40f53fedcd809c2a30d5f9 |
---|
1298 | ] |
---|
1299 | [Add elapsed timestamp to cli backup command final summary. |
---|
1300 | Alberto Berti <alberto@metapensiero.it>**20090224171425 |
---|
1301 | Ignore-this: 9a042d11f95ee9f6858a5096d513c0bc |
---|
1302 | ] |
---|
1303 | [Added documentation for '--exclude' and friends cli backup command. |
---|
1304 | Alberto Berti <alberto@metapensiero.it>**20090224153049 |
---|
1305 | Ignore-this: bbc791fa56e38535bb82cc3077ffde90 |
---|
1306 | ] |
---|
1307 | [test_repairer: change to use faster no_network.GridTestMixin, split Verifier tests into separate cases, refactor judgement funcs into shared methods |
---|
1308 | warner@lothar.com**20090224041506 |
---|
1309 | Ignore-this: 584ce72d6276da5edc00562793d4ee53 |
---|
1310 | ] |
---|
1311 | [immutable/checker.py: trap ShareVersionIncompatible too. Also, use f.check |
---|
1312 | warner@lothar.com**20090224041405 |
---|
1313 | Ignore-this: b667e8d3192116293babcacdeed42898 |
---|
1314 | instead of examining the value returned by f.trap, because the latter appears |
---|
1315 | to squash exception types down into their base classes (i.e. since |
---|
1316 | ShareVersionIncompatible is a subclass of LayoutInvalid, |
---|
1317 | f.trap(Failure(ShareVersionIncompatible)) == LayoutInvalid). |
---|
1318 | |
---|
1319 | All this resulted in 'incompatible' shares being misclassified as 'corrupt'. |
---|
1320 | ] |
---|
1321 | [immutable/layout.py: wrap to 80 cols, no functional changes |
---|
1322 | warner@lothar.com**20090224005837 |
---|
1323 | Ignore-this: 40019480180ec34141506a28d7711608 |
---|
1324 | ] |
---|
1325 | [test_repairer: change Repairer to use much-faster no_network.GridTestMixin. As a side-effect, fix what I think was a bug: some of the assert-minimal-effort-expended checks were mixing write counts and allocate counts |
---|
1326 | warner@lothar.com**20090223234227 |
---|
1327 | Ignore-this: d58bd0a909f9939775730cda4a858cae |
---|
1328 | ] |
---|
1329 | [test/no_network.py: add a basic stats provider |
---|
1330 | warner@lothar.com**20090223233937 |
---|
1331 | Ignore-this: c9f3cc4eed99cfc36f68938ceff4162c |
---|
1332 | ] |
---|
1333 | [tests: stop using setUpClass/tearDownClass, since they've been deprecated in Twisted-8.2.0 |
---|
1334 | warner@lothar.com**20090223204312 |
---|
1335 | Ignore-this: 24c6592141cf64103530c024f93a5b88 |
---|
1336 | ] |
---|
1337 | [test_checker: improve test coverage for checker results |
---|
1338 | warner@lothar.com**20090223201943 |
---|
1339 | Ignore-this: 83e173602f0f4c811a7a9893d85385df |
---|
1340 | ] |
---|
1341 | [Fixed tests again so they will pass on windows. |
---|
1342 | Alberto Berti <alberto@metapensiero.it>**20090223003502 |
---|
1343 | Ignore-this: 80d5074e7153642a2fa2a77958bfb50d |
---|
1344 | ] |
---|
1345 | [misc/*: remove RuntimeError too |
---|
1346 | warner@lothar.com**20090222233401 |
---|
1347 | Ignore-this: b76f8a184f75bb28eb9d8002f957936a |
---|
1348 | ] |
---|
1349 | [scripts: stop using RuntimeError, for #639 |
---|
1350 | warner@lothar.com**20090222233106 |
---|
1351 | Ignore-this: 686a424442670fffbd4d1816c284a601 |
---|
1352 | ] |
---|
1353 | [mutable/publish: stop using RuntimeError, for #639 |
---|
1354 | warner@lothar.com**20090222233056 |
---|
1355 | Ignore-this: 2a80a661c7850d97357caddad48c6e9d |
---|
1356 | ] |
---|
1357 | [remove more RuntimeError from unit tests, for #639 |
---|
1358 | warner@lothar.com**20090222232855 |
---|
1359 | Ignore-this: 1a1c3e1457f3f29ba7101fe406ee5f43 |
---|
1360 | ] |
---|
1361 | [stop using RuntimeError in unit tests, for #639 |
---|
1362 | warner@lothar.com**20090222232722 |
---|
1363 | Ignore-this: 475ce0c0dcd7a1f5ed83ef460312efea |
---|
1364 | ] |
---|
1365 | [ftpd/sftpd: stop using RuntimeError, for #639 |
---|
1366 | warner@lothar.com**20090222232426 |
---|
1367 | Ignore-this: 97001362c4ba9e94b2e254e229b79987 |
---|
1368 | ] |
---|
1369 | [Added tests for the cse when listdir is an iterator |
---|
1370 | Alberto Berti <alberto@metapensiero.it>**20090222224356 |
---|
1371 | Ignore-this: 218fb2aba02c28b4b1e5324bdb5adeaa |
---|
1372 | ] |
---|
1373 | [Fixed tests so that they pass also on buildbots. |
---|
1374 | Alberto Berti <alberto@metapensiero.it>**20090222224311 |
---|
1375 | Ignore-this: fcb91cd6acf028382411d23d380a4576 |
---|
1376 | ] |
---|
1377 | [Use failUnlessEqual instead of failUnless(a == b) |
---|
1378 | Alberto Berti <alberto@metapensiero.it>**20090222224214 |
---|
1379 | Ignore-this: 8f9144632e3ac9acb4726fb48a083bf4 |
---|
1380 | ] |
---|
1381 | [Better implementation of filtering algorithm. |
---|
1382 | Alberto Berti <alberto@metapensiero.it>**20090222224049 |
---|
1383 | Ignore-this: 67a8bd2f99bcc87ca2443bef13370a87 |
---|
1384 | ] |
---|
1385 | [Removed '.hgrags' from vcs excludes |
---|
1386 | Alberto Berti <alberto@metapensiero.it>**20090222223946 |
---|
1387 | Ignore-this: 3e94c22fc9d85f380ee11fb8bdb4d1e9 |
---|
1388 | ] |
---|
1389 | [docs: CREDITS to Alberto Berti |
---|
1390 | zooko@zooko.com**20090222193314 |
---|
1391 | Ignore-this: 74d370ada3234cce9e58aec15d739f71 |
---|
1392 | ] |
---|
1393 | [Added tests for the --exclude* options of backup command. |
---|
1394 | Alberto Berti <alberto@metapensiero.it>**20090222165106 |
---|
1395 | Ignore-this: f1b931cf2e7929ce47b737c022bca707 |
---|
1396 | ] |
---|
1397 | [Added --exclude, --exclude-from and --exclude-vcs options to backup command. |
---|
1398 | Alberto Berti <alberto@metapensiero.it>**20090222170829 |
---|
1399 | Ignore-this: 4912890229cd54a2f61f14f06bc4afcc |
---|
1400 | |
---|
1401 | It is still impossible to specify absolute exclusion path, only |
---|
1402 | relative. I must check with tar or rsync how they allow them to be |
---|
1403 | specified. |
---|
1404 | ] |
---|
1405 | [Raise a more explanatory exception for errors encountered during backup processing. |
---|
1406 | Alberto Berti <alberto@metapensiero.it>**20090222170252 |
---|
1407 | Ignore-this: f6b8ffe2a903ba07a2c1c59130dac1e4 |
---|
1408 | ] |
---|
1409 | [Added tests for the fixed alias related command's synopsis |
---|
1410 | Alberto Berti <alberto@metapensiero.it>**20090222163732 |
---|
1411 | Ignore-this: 4432b4e88e990ba53a5b3fe0f12db2ac |
---|
1412 | ] |
---|
1413 | [Add missing synopsis and descriptions for alias commands. |
---|
1414 | Alberto Berti <alberto@metapensiero.it>**20090221003106 |
---|
1415 | Ignore-this: 8aedd03d36d92d912102c7f29e4ca697 |
---|
1416 | ] |
---|
1417 | [docs: move many specification-like documents into specifications/ |
---|
1418 | warner@lothar.com**20090222054054 |
---|
1419 | Ignore-this: a4110cc478198c0611205aba1ccf54f4 |
---|
1420 | ] |
---|
1421 | [test_web.py: increase test coverage of web.status.plural() |
---|
1422 | warner@lothar.com**20090222000116 |
---|
1423 | Ignore-this: 3138c9d5d2410d8e1121e9b2ed694169 |
---|
1424 | ] |
---|
1425 | [crawler: fix performance problems: only save state once per timeslice (not after every bucket), don't start the crawler until 5 minutes after node startup |
---|
1426 | warner@lothar.com**20090221205649 |
---|
1427 | Ignore-this: e6551569982bd31d19779ff15c2d6f58 |
---|
1428 | ] |
---|
1429 | [test_system: oops, don't assume that all files in storage/ are in a deep storage/shares/prefix/si/shnum path, since now the crawler pickle has a short path |
---|
1430 | warner@lothar.com**20090221061710 |
---|
1431 | Ignore-this: fde76d0e5cae853014d1bb18b5f17dae |
---|
1432 | ] |
---|
1433 | [crawler: tolerate low-resolution system clocks (i.e. windows) |
---|
1434 | warner@lothar.com**20090221061533 |
---|
1435 | Ignore-this: 57286a3abcaf44f6d1a78c3c1ad547a5 |
---|
1436 | ] |
---|
1437 | [BucketCountingCrawler: store just the count, not cycle+count, since it's too easy to make usage mistakes otherwise |
---|
1438 | warner@lothar.com**20090221035831 |
---|
1439 | Ignore-this: 573b6f651af74380cdd64059fbbdda4b |
---|
1440 | ] |
---|
1441 | [test_storage: startService the server, as is now the standard practice |
---|
1442 | warner@lothar.com**20090221035755 |
---|
1443 | Ignore-this: 3999889bd628fe4039bbcf1b29160453 |
---|
1444 | ] |
---|
1445 | [crawler: load state from the pickle in init, rather than waiting until startService, so get_state() can be called early |
---|
1446 | warner@lothar.com**20090221035720 |
---|
1447 | Ignore-this: ecd128a5f4364c0daf4b72d791340b66 |
---|
1448 | ] |
---|
1449 | [BucketCountingCrawler: rename status and state keys to use 'bucket' instead of 'share', because the former is more accurate |
---|
1450 | warner@lothar.com**20090221034606 |
---|
1451 | Ignore-this: cf819f63fac9506c878d6c9715ce35b7 |
---|
1452 | ] |
---|
1453 | [storage: also report space-free-for-root and space-free-for-nonroot, since that helps users understand the space-left-for-tahoe number better |
---|
1454 | warner@lothar.com**20090221032856 |
---|
1455 | Ignore-this: 9fdf0475f758acd98b73026677170b45 |
---|
1456 | ] |
---|
1457 | [storage: add bucket-counting share crawler, add its output (number of files+directories maintained by a storage server) and status to the webapi /storage page |
---|
1458 | warner@lothar.com**20090221030408 |
---|
1459 | Ignore-this: 28761c5e076648026bc5f518506db65c |
---|
1460 | ] |
---|
1461 | [storage: move si_b2a/si_a2b/storage_index_to_dir out of server.py and into common.py |
---|
1462 | warner@lothar.com**20090221030309 |
---|
1463 | Ignore-this: 645056428ab797f0b542831c82bf192a |
---|
1464 | ] |
---|
1465 | [crawler: add get_progress, clean up get_state |
---|
1466 | warner@lothar.com**20090221002743 |
---|
1467 | Ignore-this: 9bea69f154c75b31a53425a8ea67789b |
---|
1468 | ] |
---|
1469 | [web/storage: make sure we can handle platforms without os.statvfs too |
---|
1470 | warner@lothar.com**20090220220353 |
---|
1471 | Ignore-this: 79d4cb8482a8543b9759dc949c86c587 |
---|
1472 | ] |
---|
1473 | [crawler: provide for one-shot crawlers, which stop after their first full cycle, for share-upgraders and database-populaters |
---|
1474 | warner@lothar.com**20090220211911 |
---|
1475 | Ignore-this: fcdf72c5ffcafa374d376388be6fa5c5 |
---|
1476 | ] |
---|
1477 | [web: add Storage status page, improve tests |
---|
1478 | warner@lothar.com**20090220202926 |
---|
1479 | Ignore-this: e34d5270dcf0237fe72f573f717c7a4 |
---|
1480 | ] |
---|
1481 | [storage: include reserved_space in stats |
---|
1482 | warner@lothar.com**20090220202920 |
---|
1483 | Ignore-this: b5b480fe0abad0148ecad0c1fb47ecae |
---|
1484 | ] |
---|
1485 | [web/check_results: sort share identifiers in the sharemap display |
---|
1486 | warner@lothar.com**20090220182922 |
---|
1487 | Ignore-this: 5c7bfcee3e15c7082c3653eb8a460960 |
---|
1488 | ] |
---|
1489 | [webapi: pass client through constructor arguments, remove IClient, should make it easier to test web renderers in isolation |
---|
1490 | warner@lothar.com**20090220181554 |
---|
1491 | Ignore-this: e7848cd1bee8faf2ce7aaf040b9bf8e3 |
---|
1492 | ] |
---|
1493 | [test/no_network: do startService on the storage servers, make it easier to customize the storage servers |
---|
1494 | warner@lothar.com**20090220022254 |
---|
1495 | Ignore-this: e62f328721c007e4c5ee023a6efdf66d |
---|
1496 | ] |
---|
1497 | [crawler: modify API to support upcoming bucket-counting crawler |
---|
1498 | warner@lothar.com**20090220013142 |
---|
1499 | Ignore-this: 808f8382837b13082f8b245db2ebee06 |
---|
1500 | ] |
---|
1501 | [test_backupdb: make the not-a-database file larger, since the older sqlite-2.3.2 on OS-X is easily fooled |
---|
1502 | warner@lothar.com**20090220000409 |
---|
1503 | Ignore-this: 694d2ca5053bb96e91670765d0cedf2e |
---|
1504 | ] |
---|
1505 | [web/reliability: add parameter descriptions, adapted from a patch from Terrell Russell. |
---|
1506 | warner@lothar.com**20090219222918 |
---|
1507 | Ignore-this: 835f5ab01e1aff31b2ff9febb9a51f3 |
---|
1508 | ] |
---|
1509 | [test_crawler: hush pyflakes |
---|
1510 | warner@lothar.com**20090219202340 |
---|
1511 | Ignore-this: 765d22c9c9682cc86c5205dc130500af |
---|
1512 | ] |
---|
1513 | [test_crawler: disable the percentage-of-cpu-used test, since it is too unreliable on our slow buildslaves. But leave the code in place for developers to run by hand. |
---|
1514 | warner@lothar.com**20090219201654 |
---|
1515 | Ignore-this: ff7cf5cfa79c6f2ef0cf959495dd989a |
---|
1516 | ] |
---|
1517 | [reliability.py: fix the numpy conversion, it was completely broken. Thanks to Terrell Russell for the help. |
---|
1518 | warner@lothar.com**20090219195515 |
---|
1519 | Ignore-this: f2b1eb65855111b338e1487feee1bbcf |
---|
1520 | ] |
---|
1521 | [reliability: switch to NumPy, since Numeric is deprecated |
---|
1522 | warner@lothar.com**20090219074435 |
---|
1523 | Ignore-this: f588a68e9bcd3b0bc3653570882b6fd5 |
---|
1524 | ] |
---|
1525 | [setup.py: fix pyflakes complaints |
---|
1526 | warner@lothar.com**20090219073643 |
---|
1527 | Ignore-this: a314e5456b0a796bc9f70232a119ec68 |
---|
1528 | ] |
---|
1529 | [move show-tool-versions out of setup.py and into a separate script in misc/ , since setuptools is trying to build and install a bunch of stuff first |
---|
1530 | warner@lothar.com**20090219073558 |
---|
1531 | Ignore-this: 9e56bc43026379212e6b6671ed6a1fd4 |
---|
1532 | ] |
---|
1533 | [test_crawler: don't require >=1 cycle on cygwin |
---|
1534 | warner@lothar.com**20090219065818 |
---|
1535 | Ignore-this: b8d2d40f26aeb30a7622479840a04635 |
---|
1536 | ] |
---|
1537 | [setup.py: add show_tool_versions command, for the benefit of a new buildbot step |
---|
1538 | warner@lothar.com**20090219062436 |
---|
1539 | Ignore-this: 21d761c76a033e481831584bedc60c86 |
---|
1540 | ] |
---|
1541 | [setup.py: wrap to 80 cols, no functional changes |
---|
1542 | warner@lothar.com**20090219055751 |
---|
1543 | Ignore-this: d29e57c6ee555f2ee435667b7e13e60b |
---|
1544 | ] |
---|
1545 | [crawler: use fileutil.move_info_place in preference to our own version |
---|
1546 | warner@lothar.com**20090219051342 |
---|
1547 | Ignore-this: ee4e46f3de965610503ba36b28184db9 |
---|
1548 | ] |
---|
1549 | [fileutil: add move_into_place(), to perform the standard unix trick of atomically replacing a file, with a fallback for windows |
---|
1550 | warner@lothar.com**20090219051310 |
---|
1551 | Ignore-this: c1d35e8ca88fcb223ea194513611c511 |
---|
1552 | ] |
---|
1553 | [crawler: fix problems on windows and our slow cygwin slave |
---|
1554 | warner@lothar.com**20090219042431 |
---|
1555 | Ignore-this: 8019cb0da79ba00c536183a6f57b4cab |
---|
1556 | ] |
---|
1557 | [#633: first version of a rate-limited interruptable share-crawler |
---|
1558 | warner@lothar.com**20090219034633 |
---|
1559 | Ignore-this: 5d2d30c743e3b096a8e775d5a9b33601 |
---|
1560 | ] |
---|
1561 | [change StorageServer to take nodeid in the constructor, instead of assigning it later, since it's cleaner and because the original problem (Tubs not being ready until later) went away |
---|
1562 | warner@lothar.com**20090218222301 |
---|
1563 | Ignore-this: 740d582f20c93bebf60e21d9a446d3d2 |
---|
1564 | ] |
---|
1565 | [test_system: split off checker tests to test_deepcheck.py, this file is too big |
---|
1566 | warner@lothar.com**20090218214234 |
---|
1567 | Ignore-this: 82bf8db81dfbc98224bbf694054a8761 |
---|
1568 | ] |
---|
1569 | [break storage.py into smaller pieces in storage/*.py . No behavioral changes. |
---|
1570 | warner@lothar.com**20090218204655 |
---|
1571 | Ignore-this: 312d408d1cacc5a764d791b53ebf8f91 |
---|
1572 | ] |
---|
1573 | [immutable/layout: minor change to repr name |
---|
1574 | warner@lothar.com**20090218204648 |
---|
1575 | Ignore-this: c8781ef15b7dea63b39236a1899b86ce |
---|
1576 | ] |
---|
1577 | [docs: add lease-tradeoffs diagram |
---|
1578 | warner@lothar.com**20090218204137 |
---|
1579 | Ignore-this: c22a589ad465dac846da834c30dc4083 |
---|
1580 | ] |
---|
1581 | [interfaces.py: allow add/renew/cancel-lease to return Any, so that 1.3.1 clients (the first to use these calls) can tolerate future storage servers which might return something other than None |
---|
1582 | warner@lothar.com**20090218192903 |
---|
1583 | Ignore-this: dcbb704a05416ecc66d90fb486c3d75b |
---|
1584 | ] |
---|
1585 | [docs/debian.txt: minor edit |
---|
1586 | warner@lothar.com**20090218032212 |
---|
1587 | Ignore-this: 64ff1fb163ffca4bcfd920254f1cf866 |
---|
1588 | ] |
---|
1589 | [add --add-lease to 'tahoe check', 'tahoe deep-check', and webapi. |
---|
1590 | warner@lothar.com**20090218013243 |
---|
1591 | Ignore-this: 176b2006cef5041adcb592ee83e084dd |
---|
1592 | ] |
---|
1593 | [change RIStorageServer.remote_add_lease to exit silently in case of no-such-bucket, instead of raising IndexError, because that makes the upcoming --add-lease feature faster and less noisy |
---|
1594 | warner@lothar.com**20090218013053 |
---|
1595 | Ignore-this: 6fdfcea2c832178f1ce72ab0ff510f3a |
---|
1596 | ] |
---|
1597 | [CLI #590: convert 'tahoe deep-check' to streaming form, improve display, add tests |
---|
1598 | warner@lothar.com**20090217231511 |
---|
1599 | Ignore-this: 6d88eb94b1c877eacc8c5ca7d0aac776 |
---|
1600 | ] |
---|
1601 | [interfaces.py: document behavior of add_lease/renew_lease/cancel_lease, before I change it |
---|
1602 | warner@lothar.com**20090217194809 |
---|
1603 | Ignore-this: 703c6712926b8edb19d55d790b65a400 |
---|
1604 | ] |
---|
1605 | [test_backupdb: improve error messages if the test fails |
---|
1606 | warner@lothar.com**20090217170838 |
---|
1607 | Ignore-this: ef657e87c66e4304d3e0aca9831b84c |
---|
1608 | ] |
---|
1609 | [webapi #590: add streaming deep-check. Still need a CLI tool to use it. |
---|
1610 | warner@lothar.com**20090217053553 |
---|
1611 | Ignore-this: a0edd3d2a531c48a64d8397f7e4b208c |
---|
1612 | ] |
---|
1613 | [test_web.Grid: change the CHECK() function to make it easier to test t= values with hyphens in them |
---|
1614 | warner@lothar.com**20090217050034 |
---|
1615 | Ignore-this: 410c08735347c2057df52f6716520228 |
---|
1616 | ] |
---|
1617 | [test_web: improve checker-results coverage with a no-network -based test, enhance no-network harness to assist, fix some bugs in web/check_results.py that were exposed |
---|
1618 | warner@lothar.com**20090217041242 |
---|
1619 | Ignore-this: fe54bb66a9ae073c002a7af51cd1e18 |
---|
1620 | ] |
---|
1621 | [web: fix handling of reliability page when Numeric is not available |
---|
1622 | warner@lothar.com**20090217015658 |
---|
1623 | Ignore-this: 9d329182f1b2e5f812e5e7eb5f4cf2ed |
---|
1624 | ] |
---|
1625 | [test/no_network: update comments with setup timing: no_network takes 50ms, SystemTestMixin takes 2s (on my laptop) |
---|
1626 | warner@lothar.com**20090217000643 |
---|
1627 | Ignore-this: cc778fa3219775b25057bfc9491f8f34 |
---|
1628 | ] |
---|
1629 | [test_upload: rewrite in terms of no-network GridTestMixin, improve no_network.py as necessary |
---|
1630 | warner@lothar.com**20090216234457 |
---|
1631 | Ignore-this: 80a341d5aa3036d24de98e267499d70d |
---|
1632 | ] |
---|
1633 | [test_download: rewrite in terms of no-network GridTestMixin, improve no_network.py as necessary |
---|
1634 | warner@lothar.com**20090216233658 |
---|
1635 | Ignore-this: ec2febafd2403830519120fb3f3ca04e |
---|
1636 | ] |
---|
1637 | [test_dirnode.py: convert Deleter to new no-network gridtest |
---|
1638 | warner@lothar.com**20090216232348 |
---|
1639 | Ignore-this: 8041739442ec4db726675e48f9775ae9 |
---|
1640 | ] |
---|
1641 | [test_cli.py: modify to use the new 'no-network' gridtest instead of SystemTestMixin, which speeds it up from 73s to 43s on my system |
---|
1642 | warner@lothar.com**20090216232005 |
---|
1643 | Ignore-this: ec6d010c9182aa72049d1fb894cf890e |
---|
1644 | ] |
---|
1645 | [tests: fix no_network framework to work with upload/download and checker |
---|
1646 | warner@lothar.com**20090216231947 |
---|
1647 | Ignore-this: 74b4dbd66b8384ae7c7544969fe4f744 |
---|
1648 | ] |
---|
1649 | [client.py: improve docstring |
---|
1650 | warner@lothar.com**20090216231532 |
---|
1651 | Ignore-this: bbaa9e3f63fdb0048e3125c4681b2d1f |
---|
1652 | ] |
---|
1653 | [test_cli: add test coverage for help strings |
---|
1654 | warner@lothar.com**20090216210833 |
---|
1655 | Ignore-this: d2020849107f687448e159a19d0e5dab |
---|
1656 | ] |
---|
1657 | [test/no_network: new test harness, like system-test but doesn't use the network so it's faster |
---|
1658 | warner@lothar.com**20090216205844 |
---|
1659 | Ignore-this: 31678f7bdef30b0216fd657fc6145534 |
---|
1660 | ] |
---|
1661 | [interfaces.py: minor docstring edit |
---|
1662 | warner@lothar.com**20090216205816 |
---|
1663 | Ignore-this: cec3855070197f7920b370f95e8b07bd |
---|
1664 | ] |
---|
1665 | [setup: if you sdist_dsc (to produce the input files for dpkg-buildpackage) then run darcsver first |
---|
1666 | zooko@zooko.com**20090216201558 |
---|
1667 | Ignore-this: b85be51b3d4a9a19a3366e690f1063e2 |
---|
1668 | ] |
---|
1669 | [doc: a few edits to docs made after the 1.3.0 release |
---|
1670 | zooko@zooko.com**20090216201539 |
---|
1671 | Ignore-this: dbff3b929d88134d862f1dffd1ef068a |
---|
1672 | ] |
---|
1673 | [test_cli: improve test coverage slightly |
---|
1674 | warner@lothar.com**20090216030451 |
---|
1675 | Ignore-this: e01ccc6a6fb44aaa4fb14fe8669e2065 |
---|
1676 | ] |
---|
1677 | [test_util: get almost full test coverage of dictutil, starting with the original pyutil tests as a base. The remaining three uncovered lines involve funny cases of ValueOrderedDict that I can't figure out how to get at |
---|
1678 | warner@lothar.com**20090216023210 |
---|
1679 | Ignore-this: dc1f0c6d8c003c0ade38bc8f8516b04d |
---|
1680 | ] |
---|
1681 | [provisioning/reliability: add tests, hush pyflakes, remove dead code, fix web links |
---|
1682 | warner@lothar.com**20090215222451 |
---|
1683 | Ignore-this: 7854df3e0130d9388f06efd4c797262f |
---|
1684 | ] |
---|
1685 | [util/statistics: add tests, fix mean_repair_cost |
---|
1686 | warner@lothar.com**20090215222326 |
---|
1687 | Ignore-this: c576eabc74c23b170702018fc3c122d9 |
---|
1688 | ] |
---|
1689 | [test_repairer: hush pyflakes |
---|
1690 | warner@lothar.com**20090215222310 |
---|
1691 | Ignore-this: 875eb52e86077cda77efd02da77f8cfa |
---|
1692 | ] |
---|
1693 | [lossmodel.lyx: move draft paper into docs/proposed/, since it's unfinished |
---|
1694 | warner@lothar.com**20090215221905 |
---|
1695 | Ignore-this: 7f7ee204e47fd66932759c94deefe68 |
---|
1696 | ] |
---|
1697 | [build a 'reliability' web page, with a simulation of file decay and repair over time |
---|
1698 | warner@lothar.com**20090213234234 |
---|
1699 | Ignore-this: 9e9623eaac7b0637bbd0071f082bd345 |
---|
1700 | ] |
---|
1701 | [More lossmodel work, on repair. |
---|
1702 | Shawn Willden <shawn-tahoe@willden.org>**20090116025648] |
---|
1703 | [Loss model work (temp1) |
---|
1704 | Shawn Willden <shawn@willden.org>**20090115030058] |
---|
1705 | [Statistics module |
---|
1706 | Shawn Willden <shawn-tahoe@willden.org>**20090114021235 |
---|
1707 | |
---|
1708 | Added a statistics module for calculating various facets of |
---|
1709 | share survival statistics. |
---|
1710 | ] |
---|
1711 | [docs: relnotes-short.txt |
---|
1712 | zooko@zooko.com**20090215163510 |
---|
1713 | Ignore-this: 683649bb13499bbe0e5cea2e1716ff59 |
---|
1714 | linkedin.com imposed a strict limit on the number of characters I could post. This forced me to prune and prune and edit and edit until relnotes.txt was a quarter of its former size. Here's the short version. |
---|
1715 | ] |
---|
1716 | [TAG allmydata-tahoe-1.3.0 |
---|
1717 | zooko@zooko.com**20090214000556 |
---|
1718 | Ignore-this: aa6c9a31a14a58ad2298cb7b08d3ea70 |
---|
1719 | ] |
---|
1720 | Patch bundle hash: |
---|
1721 | 6422bf98b0a47e7b946934be2164e89ae0c9f6b2 |
---|