Ticket #534: unicode-v3.dpatch

File unicode-v3.dpatch, 53.6 KB (added by francois, at 2009-04-01T19:41:52Z)
Line 
1Wed Apr  1 10:15:17 CEST 2009  francois@ctrlaltdel.ch
2  * CLI: Improved handling of non-ascii filenames
3 
4  The patch allows users to pass non-ascii filenames to the Tahoe CLI, it stores
5  aliase names as UTF-8 and fix handling of non-ascii filenames on commands like
6  tahoe cp or tahoe backup.
7 
8  As Tahoe internal filename storage is unicode, we have to decode the parameters
9  we received according to the alleged filesystem encoding which varies depending
10  on the platform.
11 
12  On Windows and MacOS X, the filesystem make uses of unicode strings so no
13  decoding should ever happen.
14 
15  On Linux, the filesystem stores only bytestrings we have to be interepreted
16  according to the current locale configuration. This operation can fail in which
17  case an error is raised.
18 
19
20New patches:
21
22[CLI: Improved handling of non-ascii filenames
23francois@ctrlaltdel.ch**20090401081517
24 
25 The patch allows users to pass non-ascii filenames to the Tahoe CLI, it stores
26 aliase names as UTF-8 and fix handling of non-ascii filenames on commands like
27 tahoe cp or tahoe backup.
28 
29 As Tahoe internal filename storage is unicode, we have to decode the parameters
30 we received according to the alleged filesystem encoding which varies depending
31 on the platform.
32 
33 On Windows and MacOS X, the filesystem make uses of unicode strings so no
34 decoding should ever happen.
35 
36 On Linux, the filesystem stores only bytestrings we have to be interepreted
37 according to the current locale configuration. This operation can fail in which
38 case an error is raised.
39 
40] {
41hunk ./docs/frontends/CLI.txt 94
42-In Tahoe v1.3.0, passing non-ascii characters to the cli is not guaranteed to
43-work, although it might work on your platform, especially if your platform
44-uses utf-8 encoding.
45+As of Tahoe v1.3.1, filenames containing non-ascii characters are
46+supported on the commande line if your terminal is correctly configured
47+for UTF-8 support. This is usually the case on moderns GNU/Linux
48+distributions.
49+
50+If your terminal doesn't support UTF-8, you will still be able to list
51+directories but non-ascii characters will be replaced by a question mark
52+(?) on display.
53+
54+Reading from and writing to files whose name contain non-ascii
55+characters is also supported when your system correctly understand them.
56+Under Unix, this is usually handled by locale settings. If Tahoe cannot
57+correctly decode a filename, it will raise an error. In such case,
58+you'll need to correct the name of your file, possibly with help from
59+tools such as convmv.
60hunk ./src/allmydata/scripts/cli.py 4
61+from allmydata.util.stringutils import argv_to_unicode
62hunk ./src/allmydata/scripts/cli.py 53
63-        self.where = where
64+        self.where = argv_to_unicode(where)
65hunk ./src/allmydata/scripts/cli.py 58
66-        self.alias = alias
67+        self.alias = argv_to_unicode(alias)
68hunk ./src/allmydata/scripts/cli.py 68
69-        self.alias = alias
70+        self.alias = argv_to_unicode(alias)
71hunk ./src/allmydata/scripts/cli.py 87
72-        self.where = where
73+        self.where = argv_to_unicode(where)
74hunk ./src/allmydata/scripts/cli.py 98
75-        self.from_file = arg1
76-        self.to_file = arg2
77+        self.from_file = argv_to_unicode(arg1)
78+
79+        if arg2:
80+            self.to_file = argv_to_unicode(arg2)
81+        else:
82+            self.to_file = None
83+
84hunk ./src/allmydata/scripts/cli.py 140
85-            self.from_file = arg1
86-            self.to_file = arg2
87+            self.from_file = argv_to_unicode(arg1)
88+            self.to_file =  argv_to_unicode(arg2)
89hunk ./src/allmydata/scripts/cli.py 143
90-            self.from_file = arg1 # might be "-"
91+            self.from_file = argv_to_unicode(arg1) # might be "-"
92hunk ./src/allmydata/scripts/cli.py 148
93-        if self.from_file == "-":
94+        if self.from_file == u"-":
95hunk ./src/allmydata/scripts/cli.py 185
96-        self.sources = args[:-1]
97-        self.destination = args[-1]
98+        self.sources = map(argv_to_unicode, args[:-1])
99+        self.destination = argv_to_unicode(args[-1])
100hunk ./src/allmydata/scripts/cli.py 190
101-        self.where = where
102+        self.where = argv_to_unicode(where)
103hunk ./src/allmydata/scripts/cli.py 197
104-        self.from_file = frompath
105-        self.to_file = topath
106+        self.from_file = argv_to_unicode(frompath)
107+        self.to_file = argv_to_unicode(topath)
108hunk ./src/allmydata/scripts/cli.py 205
109-        self.from_file = frompath
110-        self.to_file = topath
111+        self.from_file = argv_to_unicode(frompath)
112+        self.to_file = argv_to_unicode(topath)
113hunk ./src/allmydata/scripts/cli.py 230
114-        self.from_dir = localdir
115-        self.to_dir = topath
116+        self.from_dir = argv_to_unicode(localdir)
117+        self.to_dir = argv_to_unicode(topath)
118hunk ./src/allmydata/scripts/cli.py 279
119-        self.where = where
120+        self.where = argv_to_unicode(where)
121hunk ./src/allmydata/scripts/cli.py 294
122-        self.where = where
123+        self.where = argv_to_unicode(where)
124hunk ./src/allmydata/scripts/cli.py 306
125-        self.where = where
126+        self.where = argv_to_unicode(where)
127hunk ./src/allmydata/scripts/cli.py 321
128-        self.where = where
129+        self.where = argv_to_unicode(where)
130hunk ./src/allmydata/scripts/cli.py 337
131-        self.where = where
132+        self.where = argv_to_unicode(where)
133hunk ./src/allmydata/scripts/common.py 3
134+import codecs
135hunk ./src/allmydata/scripts/common.py 5
136-
137+from allmydata.util.stringutils import unicode_to_url
138hunk ./src/allmydata/scripts/common.py 104
139-        f = open(aliasfile, "r")
140+        f = codecs.open(aliasfile, "r", "utf-8")
141hunk ./src/allmydata/scripts/common.py 111
142-            cap = cap.strip()
143+            cap = cap.strip().encode('ascii')
144hunk ./src/allmydata/scripts/common.py 167
145-    return "/".join([urllib.quote(s) for s in segments])
146+    return "/".join([urllib.quote(unicode_to_url(s)) for s in segments])
147hunk ./src/allmydata/scripts/tahoe_add_alias.py 3
148+import codecs
149+import sys
150hunk ./src/allmydata/scripts/tahoe_add_alias.py 8
151+from allmydata.util.stringutils import unicode_to_stdout
152hunk ./src/allmydata/scripts/tahoe_add_alias.py 58
153-    f = open(aliasfile, "a")
154+    f = codecs.open(aliasfile, "a", "utf-8")
155hunk ./src/allmydata/scripts/tahoe_add_alias.py 61
156-    print >>stdout, "Alias '%s' created" % (alias,)
157+    print >>stdout, "Alias '%s' created" % (unicode_to_stdout(alias),)
158hunk ./src/allmydata/scripts/tahoe_backup.py 7
159+import sys
160hunk ./src/allmydata/scripts/tahoe_backup.py 13
161+from allmydata.util.stringutils import fs_to_unicode, unicode_to_fs, unicode_to_stdout
162+from allmydata.util.assertutil import precondition
163+from twisted.python import usage
164hunk ./src/allmydata/scripts/tahoe_backup.py 252
165-            print >>self.options.stdout, msg
166+            print >>self.options.stdout, unicode_to_stdout(msg)
167hunk ./src/allmydata/scripts/tahoe_backup.py 255
168+        precondition(isinstance(localpath, unicode), localpath)
169hunk ./src/allmydata/scripts/tahoe_backup.py 264
170-        for child in self.options.filter_listdir(os.listdir(localpath)):
171+        for child in self.options.filter_listdir(os.listdir(unicode_to_fs(localpath))):
172+            child = fs_to_unicode(child)
173hunk ./src/allmydata/scripts/tahoe_backup.py 351
174+        precondition(isinstance(childpath, unicode), childpath)
175+
176hunk ./src/allmydata/scripts/tahoe_backup.py 361
177-            infileobj = open(os.path.expanduser(childpath), "rb")
178+            infileobj = open(unicode_to_fs(os.path.expanduser(childpath)), "rb")
179hunk ./src/allmydata/scripts/tahoe_cp.py 7
180+import sys
181hunk ./src/allmydata/scripts/tahoe_cp.py 11
182+from twisted.python import usage
183+from allmydata.util.stringutils import fs_to_unicode, unicode_to_fs, unicode_to_url
184+from allmydata.util.assertutil import precondition
185hunk ./src/allmydata/scripts/tahoe_cp.py 76
186+        precondition(isinstance(pathname, unicode), pathname)
187hunk ./src/allmydata/scripts/tahoe_cp.py 87
188+        precondition(isinstance(pathname, unicode), pathname)
189hunk ./src/allmydata/scripts/tahoe_cp.py 100
190+        precondition(isinstance(pathname, unicode), pathname)
191hunk ./src/allmydata/scripts/tahoe_cp.py 114
192+        precondition(isinstance(pathname, unicode), pathname)
193+
194hunk ./src/allmydata/scripts/tahoe_cp.py 124
195-        children = os.listdir(self.pathname)
196+        children = os.listdir(unicode_to_fs(self.pathname))
197hunk ./src/allmydata/scripts/tahoe_cp.py 126
198+            n = fs_to_unicode(n)
199hunk ./src/allmydata/scripts/tahoe_cp.py 142
200+        precondition(isinstance(pathname, unicode), pathname)
201+
202hunk ./src/allmydata/scripts/tahoe_cp.py 152
203-        children = os.listdir(self.pathname)
204+        children = os.listdir(unicode_to_fs(self.pathname))
205hunk ./src/allmydata/scripts/tahoe_cp.py 154
206+            n = fs_to_unicode(n)
207hunk ./src/allmydata/scripts/tahoe_cp.py 176
208+        precondition(isinstance(name, unicode), name)
209hunk ./src/allmydata/scripts/tahoe_cp.py 178
210-        outf = open(pathname, "wb")
211+        outf = open(unicode_to_fs(pathname), "wb")
212hunk ./src/allmydata/scripts/tahoe_cp.py 367
213-                                                   urllib.quote(name.encode('utf-8'))])
214+                                                   urllib.quote(unicode_to_url(name))])
215hunk ./src/allmydata/scripts/tahoe_ls.py 6
216+from allmydata.util.stringutils import unicode_to_stdout
217hunk ./src/allmydata/scripts/tahoe_ls.py 116
218-        line.append(name + classify)
219+        line.append(unicode_to_stdout(name) + classify)
220hunk ./src/allmydata/scripts/tahoe_manifest.py 83
221-                    print >>stdout, d["cap"], "/".join([p.encode("utf-8")
222+                    print >>stdout, d["cap"], "/".join([unicode_to_stdout(p)
223hunk ./src/allmydata/scripts/tahoe_mkdir.py 5
224+from allmydata.util.stringutils import unicode_to_url
225hunk ./src/allmydata/scripts/tahoe_mkdir.py 35
226-                                           urllib.quote(path))
227+                                           urllib.quote(unicode_to_url(path)))
228hunk ./src/allmydata/test/test_cli.py 3
229+import sys
230hunk ./src/allmydata/test/test_cli.py 522
231+        d.addCallback(lambda res: self.do_cli("create-alias", "études"))
232+        def _check_create_unicode((rc,stdout,stderr)):
233+            self.failUnlessEqual(rc, 0)
234+            self.failIf(stderr)
235+
236+            # If stdout only supports ascii, accentuated characters are
237+            # being replaced by '?'
238+            if sys.stdout.encoding == "ANSI_X3.4-1968":
239+                self.failUnless("Alias '?tudes' created" in stdout)
240+            else:
241+                self.failUnless("Alias 'études' created" in stdout)
242+
243+            aliases = get_aliases(self.get_clientdir())
244+            self.failUnless(aliases[u"études"].startswith("URI:DIR2:"))
245+        d.addCallback(_check_create_unicode)
246+
247+        d.addCallback(lambda res: self.do_cli("ls", "études:"))
248+        def _check_ls1((rc, stdout, stderr)):
249+            self.failUnlessEqual(rc, 0)
250+            self.failIf(stderr)
251+
252+            self.failUnlessEqual(stdout, "")
253+        d.addCallback(_check_ls1)
254+
255+        d.addCallback(lambda res: self.do_cli("put", "-", "études:uploaded.txt",
256+          stdin="Blah blah blah"))
257+
258+        d.addCallback(lambda res: self.do_cli("ls", "études:"))
259+        def _check_ls2((rc, stdout, stderr)):
260+            self.failUnlessEqual(rc, 0)
261+            self.failIf(stderr)
262+
263+            self.failUnlessEqual(stdout, "uploaded.txt\n")
264+        d.addCallback(_check_ls2)
265+
266hunk ./src/allmydata/test/test_cli.py 778
267+    def test_immutable_from_file_unicode(self):
268+        # tahoe put file.txt "à trier.txt"
269+        self.basedir = os.path.dirname(self.mktemp())
270+        self.set_up_grid()
271+
272+        rel_fn = os.path.join(self.basedir, "DATAFILE")
273+        abs_fn = os.path.abspath(rel_fn)
274+        # we make the file small enough to fit in a LIT file, for speed
275+        DATA = "short file"
276+        f = open(rel_fn, "w")
277+        f.write(DATA)
278+        f.close()
279+
280+        d = self.do_cli("create-alias", "tahoe")
281+
282+        d.addCallback(lambda res:
283+                      self.do_cli("put", rel_fn, "à trier.txt"))
284+        def _uploaded((rc,stdout,stderr)):
285+            readcap = stdout.strip()
286+            self.failUnless(readcap.startswith("URI:LIT:"))
287+            self.failUnless("201 Created" in stderr, stderr)
288+            self.readcap = readcap
289+        d.addCallback(_uploaded)
290+
291+        d.addCallback(lambda res:
292+                      self.do_cli("get", "tahoe:à trier.txt"))
293+        d.addCallback(lambda (rc,stdout,stderr):
294+                      self.failUnlessEqual(stdout, DATA))
295+
296+        return d
297+
298hunk ./src/allmydata/test/test_cli.py 865
299+        d = self.do_cli("create-alias", "tahoe")
300+
301+        # Use unicode strings when calling os functions
302+        if sys.getfilesystemencoding() == "ANSI_X3.4-1968":
303+            fn1 = os.path.join(self.basedir, u"Artonwall")
304+        else:
305+            fn1 = os.path.join(self.basedir, u"Ärtonwall")
306hunk ./src/allmydata/test/test_cli.py 873
307-        fn1 = os.path.join(self.basedir, "Ärtonwall")
308hunk ./src/allmydata/test/test_cli.py 875
309+        d.addCallback(lambda res: self.do_cli("cp", fn1.encode('utf-8'), "tahoe:Ärtonwall"))
310+
311+        d.addCallback(lambda res: self.do_cli("get", "tahoe:Ärtonwall"))
312+        d.addCallback(lambda (rc,out,err): self.failUnlessEqual(out, DATA1))
313hunk ./src/allmydata/test/test_cli.py 880
314-        fn2 = os.path.join(self.basedir, "Metallica")
315+
316+        fn2 = os.path.join(self.basedir, u"Metallica")
317hunk ./src/allmydata/test/test_cli.py 888
318-        d = self.do_cli("create-alias", "tahoe")
319-        d.addCallback(lambda res: self.do_cli("cp", fn1, "tahoe:"))
320-        d.addCallback(lambda res: self.do_cli("cp", fn2, "tahoe:"))
321-
322-        d.addCallback(lambda res: self.do_cli("get", "tahoe:Ärtonwall"))
323-        d.addCallback(lambda (rc,out,err): self.failUnlessEqual(out, DATA1))
324+        d.addCallback(lambda res: self.do_cli("cp", fn2.encode('utf-8'), "tahoe:"))
325hunk ./src/allmydata/test/test_cli.py 893
326+        d.addCallback(lambda res: self.do_cli("ls", "tahoe:"))
327+
328hunk ./src/allmydata/test/test_cli.py 896
329-    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."
330hunk ./src/allmydata/test/test_cli.py 914
331+class Mkdir(GridTestMixin, CLITestMixin, unittest.TestCase):
332+    def test_unicode_mkdir(self):
333+        self.basedir = os.path.dirname(self.mktemp())
334+        self.set_up_grid()
335+
336+        d = self.do_cli("create-alias", "tahoe")
337+        d.addCallback(lambda res: self.do_cli("mkdir", "tahoe:Motörhead"))
338+
339+        return d
340+
341+
342hunk ./src/allmydata/test/test_cli.py 959
343+        if sys.getfilesystemencoding() == "ANSI_X3.4-1968":
344+            self.writeto(u"parent/artonwall.txt", "Marmelade Jacuzzi")
345+        else:
346+            self.writeto(u"parent/ärtonwall.txt", "Marmelade Jacuzzi")
347+
348hunk ./src/allmydata/test/test_cli.py 988
349-            # foo.txt, bar.txt, blah.txt
350-            self.failUnlessEqual(fu, 3)
351+            # foo.txt, bar.txt, blah.txt, ärtonwall.txt
352+            self.failUnlessEqual(fu, 4)
353hunk ./src/allmydata/test/test_cli.py 1038
354-                # foo.txt, bar.txt, blah.txt
355+                # foo.txt, bar.txt, blah.txt, ärtonwall.txt
356hunk ./src/allmydata/test/test_cli.py 1040
357-                self.failUnlessEqual(fr, 3)
358+                self.failUnlessEqual(fr, 4)
359hunk ./src/allmydata/test/test_cli.py 1068
360-                self.failUnlessEqual(fchecked, 3)
361+                self.failUnlessEqual(fchecked, 4)
362hunk ./src/allmydata/test/test_cli.py 1070
363-                self.failUnlessEqual(fr, 3)
364+                self.failUnlessEqual(fr, 4)
365hunk ./src/allmydata/test/test_cli.py 1116
366-                # old bar.txt
367-                self.failUnlessEqual(fr, 1)
368+                # old bar.txt, ärtonwall.txt
369+                self.failUnlessEqual(fr, 2)
370hunk ./src/allmydata/test/test_cli.py 1156
371-            self.failUnlessEqual(fu, 5)
372+            self.failUnlessEqual(fu, 6)
373addfile ./src/allmydata/util/stringutils.py
374hunk ./src/allmydata/util/stringutils.py 1
375+"""
376+Functions used to convert inputs from whatever encoding used in the system to
377+unicode and back.
378+
379+TODO:
380+  * Accept two cli arguments --argv-encoding and --filesystem-encoding
381+"""
382+
383+import sys
384+from allmydata.util.assertutil import precondition
385+from twisted.python import usage
386+
387+def argv_to_unicode(s):
388+    """
389+    Decode given argv element to unicode.
390+    """
391+    # sys.argv encoding detection in Python is not trivial so utf-8 is
392+    # currently used by default and an informative error message is given if
393+    # the argument cannot be correctly decoded.
394+
395+    precondition(isinstance(s, str), s)
396+    try:
397+        return unicode(s, 'utf-8')
398+    except UnicodeEncodeError:
399+        raise usageError("Argument '%s' cannot be decoded as UTF-8." % s)
400+
401+def fs_to_unicode(s):
402+    """
403+    Decode a filename (or a directory name) to unicode using the same encoding
404+    as the filesystem.
405+    """
406+    # Filename encoding detection is a little bit better thanks to
407+    # getfilesystemencoding() in the sys module. However, filenames can be
408+    # encoded using another encoding than the one used on the filesystem.
409+   
410+    precondition(isinstance(s, str), s)
411+    encoding = sys.getfilesystemencoding()
412+    try:
413+        return unicode(s, encoding)
414+    except UnicodeDecodeError:
415+        raise usage.UsageError("Filename '%s' cannot be decoded using the current encoding of your filesystem (%s). Please rename this file." % (s, encoding))
416+
417+def unicode_to_fs(s):
418+    """
419+    Encode an unicode object used in file or directoy name.
420+    """
421+
422+    precondition(isinstance(s, unicode), s)
423+    encoding = sys.getfilesystemencoding()
424+    try:
425+        return s.encode(encoding)
426+    except UnicodeEncodeError:
427+        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))
428+
429+def unicode_to_url(s):
430+    """
431+    Encode an unicode object used in an URL.
432+    """
433+    # According to RFC 2718, non-ascii characters in url's must be UTF-8 encoded.
434+
435+    precondition(isinstance(s, unicode), s)
436+    return s.encode('utf-8')
437+
438+def unicode_to_stdout(s):
439+    """
440+    Encode an unicode object for representation on stdout.
441+    """
442+
443+    precondition(isinstance(s, unicode), s)
444+    return s.encode(sys.stdout.encoding, 'replace')
445}
446
447Context:
448
449[docs: setup: Norm Hardy suggested that it would be easier if users realized that they already had Python (especially true for Mac users)
450zooko@zooko.com**20090325035459
451 Ignore-this: e1bb76a1be4d6d541090d8d9e7e73db9
452] 
453[expirer: include crawler progress in the JSON status output
454warner@allmydata.com**20090324205137
455 Ignore-this: f65ccc0a57ed7c5d9565131350d87d2d
456] 
457[docs/proposed: new Accounting overview, discuss in #666
458warner@allmydata.com**20090324015752
459 Ignore-this: 7379396536e85194b1c1bec21288adc7
460] 
461[docs/proposed: move old accounting docs out of the way
462warner@allmydata.com**20090324015457
463 Ignore-this: 196fe85ef3592f7ef8e58a101eed0494
464] 
465[move GC docs out of proposed/, since it's all implemented now. Add reference to configuration.txt . Add expire.*= suggestions to tahoe.cfg .
466warner@allmydata.com**20090323230820
467 Ignore-this: ce0ec977f49c4a3642cf3a7ea7789dc4
468] 
469[storage: use constant-time comparison for write-enablers and lease-secrets
470warner@lothar.com**20090323032128
471 Ignore-this: efbbb15242b3f306c32498aae7fd75d
472] 
473[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
474warner@lothar.com**20090323032055
475 Ignore-this: c5c1f5e529ab1b352c949f3e0d9abf20
476] 
477[WUI: fix display of empty directories, it threw an exception before
478warner@allmydata.com**20090320235809
479 Ignore-this: e598bb806d75411d202ba90fc251ad2b
480] 
481[storage webstatus: insert spaces when we're configured to expire multiple sharetypes
482warner@allmydata.com**20090320224450
483 Ignore-this: 18f44396384c8598d984eaa11dc92cf7
484] 
485[expirer: tolerate empty buckets, refactor bucketsize-counting code a bit, don't increment -mutable/-immutable counters unless we actually know the sharetype
486warner@allmydata.com**20090320191816
487 Ignore-this: 16827fe12b874a0205b0a7fdb6b7f960
488] 
489[storage: improve wording of status message
490warner@allmydata.com**20090319184837
491 Ignore-this: 66684623d50c89fa02915665dbbfec98
492] 
493[parse_date: insist that it returns an int
494warner@allmydata.com**20090319184443
495 Ignore-this: a1f5ae0c16a151d218c06fc4411f03c1
496] 
497[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
498warner@allmydata.com**20090319180756
499 Ignore-this: df2c3778260c6389d32f4b47b004ab35
500] 
501[expirer: clean up constructor args, add tahoe.cfg controls, use cutoff_date instead of date_cutoff
502warner@allmydata.com**20090319010009
503 Ignore-this: 2b6aaa6d5e6ff9fd417f32978b443fd2
504] 
505[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
506warner@allmydata.com**20090319005814
507 Ignore-this: 4f08b301c780a78084fa02a09b5dda3
508] 
509[expirer: change setup, config options, in preparation for adding tahoe.cfg controls
510warner@allmydata.com**20090319002138
511 Ignore-this: b23a53e97f2a9fb7a005e9fe40e83fac
512] 
513[expirer: track mutable-vs-immutable sharecounts and sizes, report them on the web status page for comparison
514warner@allmydata.com**20090318202504
515 Ignore-this: 87e809bf5dedef3f0bc8f4a7b90e42d2
516] 
517[add utility function to parse durations, for lease-expiration config
518warner@lothar.com**20090317070117
519 Ignore-this: 2f4fa4352c887b4767969f0ea7931644
520] 
521[expirer: add mode to expire only-mutable or only-immutable shares
522warner@lothar.com**20090317065118
523 Ignore-this: b0b25427e3b1516bdfe293528b8e4a4e
524] 
525[tahoe_ls.py: add comment about error cases to improve
526warner@lothar.com**20090317051206
527 Ignore-this: 7c678b92a55b2f7c6f0d96fb6ece74ed
528] 
529[GC: add date-cutoff -based expiration, add proposed docs
530warner@lothar.com**20090317051041
531 Ignore-this: a5c0ecbcc2666eb04f2daa67331d1948
532] 
533[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
534warner@lothar.com**20090316005134
535 Ignore-this: 4ce081283c26719be513b5ce8381a81a
536] 
537[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.
538warner@lothar.com**20090315231958
539 Ignore-this: 8ecdf2b08601ae9e9fec5885bf640262
540] 
541[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.
542warner@allmydata.com**20090313233135
543 Ignore-this: 39b78faa947ed9461f2d120f6843e59f
544] 
545[consolidate: remove pointless 'else' after for loop
546warner@allmydata.com**20090313082751
547 Ignore-this: 517f41316f7ae40b92b9eef8269a4b69
548] 
549[consolidate: add eta, flush stdout
550warner@allmydata.com**20090313082451
551 Ignore-this: 845f63adccc32557c6864ae6120ba836
552] 
553[consolidate: tolerate unicode dirnames
554warner@allmydata.com**20090313065402
555 Ignore-this: 7e65703ed3d12d4bd5ec14b693e5f61f
556] 
557[dirnode.py: when doing deep-traverse, walk each directory in alphabetical order, to make things like 'manifest' more predictable
558warner@allmydata.com**20090313065046
559 Ignore-this: 9a80055a93a6b11853d4e8202bacec14
560] 
561[consolidator: add progress to scan-old-directory passes
562warner@allmydata.com**20090313054728
563 Ignore-this: adc67a34f4f19fd58c5bc76301b3df36
564] 
565[consolidator: fix cycle detection to not trigger on merely shared directories, add snapshot counter to progress
566warner@allmydata.com**20090313042229
567 Ignore-this: eba2cf9f1b1364b8e4c5ae4fa030a99f
568] 
569[consolidator: re-use more directories, add total directories seen-vs-used counts
570warner@allmydata.com**20090313034801
571 Ignore-this: 6e743d2940a9fe129cee31008c894d70
572] 
573[tahoe_backup.py: tolerate more time formats
574warner@allmydata.com**20090313011600
575 Ignore-this: ca74f56f0dce7d19810c5a7a75bc623c
576] 
577[consolidator: add more verbose traversal of directories
578warner@allmydata.com**20090312232900
579 Ignore-this: 8ff0e17c6174566832a566a111032db4
580] 
581[consolidate: create multiple numbered backups of the original Archives directory, not just the first time
582warner@allmydata.com**20090312230427
583 Ignore-this: e4985f76969b584d099b050781aa561c
584] 
585[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'.
586warner@allmydata.com**20090312205606
587 Ignore-this: 66569ca2190aa7b0f9199bcf09dcb27e
588] 
589[tahoe_cp.py: return 0 for success, instead of None
590warner@allmydata.com**20090312205345
591 Ignore-this: 808f6d8617f8c4e7fde455e6c7639fab
592] 
593[setup: specify in the debian/control files that tahoe is compatible with Python 2.6
594zooko@zooko.com**20090311225902
595 Ignore-this: d0793013e4c868d92793d932ef92a62d
596] 
597[setup: update the debian/copyright text to reflect the current licences
598zooko@zooko.com**20090311152952
599 Ignore-this: 806a95b1b79d6bb20507db5c7201af45
600] 
601[expirer: fix prediction math, thanks to Zandr for the catch
602warner@allmydata.com**20090309204217
603 Ignore-this: e20f784483ea1a15e35627fe95506272
604] 
605[storage.expirer: oops, fix upgrade-handler code
606warner@lothar.com**20090309035516
607 Ignore-this: af8bc0ea1c7f305b33c06f4a9bf58de3
608] 
609[storage.expirer: handle upgrades better
610warner@lothar.com**20090309034220
611 Ignore-this: dd654305b94bc3209426a3e008d57363
612] 
613[storage.expirer: exercise the last missing line of webstatus code
614warner@lothar.com**20090309033828
615 Ignore-this: fc4aa34734cae32eec1db623ca0b145b
616] 
617[expirer: tolerate corrupt shares, add them to the state and history for future examination
618warner@lothar.com**20090309030840
619 Ignore-this: 5ae7e68471ed700cc68beb408e0f303
620] 
621[storage/immutable: raise a specific error upon seeing a bad version number, instead of using assert. Also wrap to 80cols.
622warner@lothar.com**20090309030732
623 Ignore-this: 5331d9680ffceff029fbbbcdece7f282
624] 
625[storage: add test coverage for BucketReader.__repr__
626warner@lothar.com**20090309030527
627 Ignore-this: 60ce4e8c5200cc9885a3057f914e78b4
628] 
629[storage/mutable: raise a specific error upon seeing bad magic, instead of using assert
630warner@lothar.com**20090309020201
631 Ignore-this: 8daa77362902f5d6ef793e9602a1383b
632] 
633[nodeadmin: node stops itself if a hotline file hasn't been touched in 120 seconds now, instead of in 60 seconds
634zooko@zooko.com**20090308025039
635 Ignore-this: a9cfc605d3fcad912bd2d0b35d5143ec
636 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.
637] 
638[expirer: make web display a bit more consistent
639warner@lothar.com**20090307221442
640 Ignore-this: 7fec9d9bffc0bddeb51c1baa8e7ea020
641] 
642[web/storage.py: tolerate unknown-future displays, I'm not sure why LeaseCrawler.test_unpredictable_future didn't catch this
643warner@lothar.com**20090307220243
644 Ignore-this: 3d4e5baa8cc6d5d26edcea29fda8593d
645] 
646[tahoe_cp.py: improve error reporting slightly: don't json-interpret HTTP errors, pass through tahoe webapi error messages
647warner@lothar.com**20090307114051
648 Ignore-this: a8beccb67adb082a92509d439b27d68e
649] 
650[test_cli.py: assert that 'ls' on an unrecoverable file now gives a better error message
651warner@lothar.com**20090307110815
652 Ignore-this: 18e9758e4d0ca7faeaf5bd481c2d72ff
653] 
654[test_web: test behavior of broken-dirnode GET, both html and json
655warner@lothar.com**20090307105707
656 Ignore-this: c0e5b45eee28959f899efa1bd189d6bd
657] 
658[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
659warner@lothar.com**20090307105601
660 Ignore-this: f949d6bd58c0c2fd60fd5fa730115f3f
661] 
662[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.
663warner@lothar.com**20090307105408
664 Ignore-this: 92f326804ba73bb446c5df5992b7d72e
665] 
666[test_cli: use explicit (and stable) testdirs, instead of using self.mktemp
667warner@lothar.com**20090307090428
668 Ignore-this: 7c58d159e4f33d01635c3445d9e591f9
669] 
670[test_storage: solaris doesn't appear to give the same block count as other platforms, so don't assert as much about 'diskbytes' recovered
671warner@lothar.com**20090307084518
672 Ignore-this: 55b35c094ce78c50c8ede42062c5ea13
673] 
674[tahoe_cp.py: don't be verbose unless --verbose is passed: default is one line of success
675warner@lothar.com**20090307084421
676 Ignore-this: f75bb818081e0c2993378154775a69d1
677] 
678[setup.cfg: use allmydata.org as a mirror for some of our necessary dependencies
679warner@allmydata.com**20090307045753
680 Ignore-this: ce174de4ad2dd96f184eadf4d62ea779
681] 
682[storage: add a lease-checker-and-expirer crawler, plus web status page.
683warner@allmydata.com**20090307044517
684 Ignore-this: 4355224f89b959c6f1a256a7e6c88c3b
685 
686 This walks slowly through all shares, examining their leases, deciding which
687 are still valid and which have expired. Once enabled, it will then remove the
688 expired leases, and delete shares which no longer have any valid leases. Note
689 that there is not yet a tahoe.cfg option to enable lease-deletion: the
690 current code is read-only. A subsequent patch will add a tahoe.cfg knob to
691 control this, as well as docs. Some other minor items included in this patch:
692 
693  tahoe debug dump-share has a new --leases-only flag
694  storage sharefile/leaseinfo code is cleaned up
695  storage web status page (/storage) has more info, more tests coverage
696  space-left measurement on OS-X should be more accurate (it was off by 2048x)
697   (use stat .f_frsize instead of f_bsize)
698] 
699[setup: comment-out the use of the directory full of dependency packages on the test grid -- the test grid is too unreliable!  :-(
700zooko@zooko.com**20090307044332
701 Ignore-this: c09f2e5f0b383b4227df4b07c267cb05
702] 
703[setup: create a "make deb-lenny-head" target
704zooko@zooko.com**20090306191057
705 Ignore-this: 4b2ff187a3d08dcfe9318980ca92f097
706 I made this patch by copying [20090305220021-92b7f-89d987c7d05306b5cb03a64f2956a652c10a7296] and changing the name from "intrepid" to "lenny".  I haven't tested it.
707] 
708[trivial: remove unused import detected by pyflakes, and remove trailing whitespace
709zooko@zooko.com**20090305223204
710 Ignore-this: 991001a50da1a357a519c3cb880d7ee1
711] 
712[setup: enable build of .debs for Ubuntu Intrepid, thanks to DarKNesS_WolF
713zooko@zooko.com**20090305220021
714 Ignore-this: 88dbb3f72c2446b7734ac437189b67df
715] 
716[trivial: use more specific function for ascii-encoding storage index
717zooko@zooko.com**20090222175751
718 Ignore-this: c1a78a71cf04d7dbd80a71106f9b21a1
719] 
720[doc: update how_to_make_a_tahoe_release.txt
721zooko@zooko.com**20090222175739
722 Ignore-this: 6a2e1592741b362bc170167a9cadc0b
723] 
724[test_cli: validate non-HTML error response of 'tahoe get' on an unrecoverable file
725warner@lothar.com**20090304041146] 
726[web: full patch for HTML-vs-plaintext traceback renderings, improve test coverage of exception rendering
727warner@lothar.com**20090304035630] 
728[web/common.py: use 'Accept:' header to control HTML-vs-text/plain traceback renderings
729warner@lothar.com**20090304035457] 
730[test/common: rearrange shouldHTTPError
731warner@lothar.com**20090304014059] 
732[web: move plural() to common.py
733warner@lothar.com**20090304014019] 
734[add more information to NotEnoughSharesError, split out new exceptions for no-servers and no-source-of-ueb-hash
735warner@lothar.com**20090304013715] 
736[test_web: move shouldHTTPError into common.WebErrorMixin
737warner@lothar.com**20090303225620] 
738[test_web: clean up shouldHTTPError methods
739warner@lothar.com**20090303224604] 
740[immutable checker add-lease: catch remote IndexError here too
741warner@allmydata.com**20090227071724
742 Ignore-this: 94ee6064ce26409381c6451cd50fdade
743] 
744[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
745warner@allmydata.com**20090227070426
746 Ignore-this: 3d7bc87d9587b51d44b27317d9eded23
747] 
748[rrefutil: add check_remote utility function
749warner@allmydata.com**20090227065957
750 Ignore-this: d859d0fae87b7e84ad3c2893350ed519
751] 
752[rrefutil: add trap_remote utility and friends
753warner@allmydata.com**20090227065524
754 Ignore-this: a594050cdd9bcca073d8029819dbc35
755] 
756[web: improve layout of storage status with a table
757warner@allmydata.com**20090227015838
758 Ignore-this: 5c12f5e296ad1cf224f85e307813eb09
759] 
760[crawler: add ETA to get_progress()
761warner@allmydata.com**20090227014248
762 Ignore-this: 27ae76c0530b83323209be70df3d8a4b
763] 
764[Fix for bug #645, correct path handling logic so that it works from sshfs
765Alberto Berti <alberto@metapensiero.it>**20090226150237
766 Ignore-this: e9c1b2d48ebf4ba68100d76e54154a78
767] 
768[wui: s/Provisioning/Reliability/ ; suggested by Terrell
769zooko@zooko.com**20090226030904
770 Ignore-this: f9559702e760dc3c57e2fc36f087d91e
771] 
772[startstop_node.py: when restarting, tolerate a stale pid too
773warner@allmydata.com**20090226015245
774 Ignore-this: 59197d3f400417be64fa0f91a64fae12
775] 
776[web: fix the ERROR: line to work the same in python2.4 and 2.5
777warner@lothar.com**20090225074621] 
778[test_cli/test_web: fix spurious test failure on solaris (maybe python2.4?) due to variations in the way that exceptions are stringified
779warner@allmydata.com**20090225060128
780 Ignore-this: 829fb7d67fd199babdde1443b64a5381
781] 
782[CLI: modify 'tahoe manifest' and 'tahoe deep-check' to report ERROR: properly. For #590.
783warner@allmydata.com**20090225054415
784 Ignore-this: 99162f894fdd24112a869e14848c3dea
785] 
786[webapi: modify streaming deep-manifest/deep-checker to emit an ERROR: line if they encounter an unrecoverable+untraversable directory. For #590.
787warner@allmydata.com**20090225051335
788 Ignore-this: e6bc49368fb0e7ada7cff477fd63ffe6
789] 
790[scripts/common: fix alias handling on windows again, emit slightly nicer error message in response to an unknown alias
791warner@allmydata.com**20090225042136
792 Ignore-this: 76df800d131aed6701b5c7408105b134
793] 
794[#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
795warner@allmydata.com**20090225034213
796 Ignore-this: 26d8b0eea0279ca793faf23c5e948d90
797] 
798[test_deepcheck: switch deep-check tests to use no-network too. This cuts the runtime down by about 50%
799warner@allmydata.com**20090225030457
800 Ignore-this: b3a98ed18c5752c9016c047e95d42b
801] 
802[test_deepcheck: convert MutableChecker to no-network GridTest
803warner@allmydata.com**20090225020010
804 Ignore-this: eccba7fda129330b642886271a61a573
805] 
806[tests/no_network: move GET into the GridTestMixin class
807warner@allmydata.com**20090225003300
808 Ignore-this: 7779ad38c2d687ae328ba3cb6164a7a4
809] 
810[common_web.py: oops, add .fields to the other FakeRequest
811warner@allmydata.com**20090225000459
812 Ignore-this: 7144269b5e083553ee2c3e7afea00604
813] 
814[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
815warner@allmydata.com**20090224235620
816 Ignore-this: 2cae196dd4ccb578b2abae085376e0d7
817] 
818[scripts/common: on windows, tolerate paths like 'c:\dir\file.txt', by treating single-letter aliases on windows/cygwin as non-aliases
819warner@allmydata.com**20090224235522
820 Ignore-this: 96d37644b7f81ac768ff4a1d1915eb46
821] 
822[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
823warner@allmydata.com**20090224232050
824 Ignore-this: 239aaed746128e54e886762782541a1f
825] 
826[Two small fixes on documentation for cli backup command.
827Alberto Berti <alberto@metapensiero.it>**20090224223634
828 Ignore-this: 5634a6dadad6e4e43a112de7fe5c74c
829] 
830[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.
831warner@lothar.com**20090224214017
832 Ignore-this: e839f1b0ec40f53fedcd809c2a30d5f9
833] 
834[Add elapsed timestamp to cli backup command final summary.
835Alberto Berti <alberto@metapensiero.it>**20090224171425
836 Ignore-this: 9a042d11f95ee9f6858a5096d513c0bc
837] 
838[Added documentation for '--exclude' and friends cli backup command.
839Alberto Berti <alberto@metapensiero.it>**20090224153049
840 Ignore-this: bbc791fa56e38535bb82cc3077ffde90
841] 
842[test_repairer: change to use faster no_network.GridTestMixin, split Verifier tests into separate cases, refactor judgement funcs into shared methods
843warner@lothar.com**20090224041506
844 Ignore-this: 584ce72d6276da5edc00562793d4ee53
845] 
846[immutable/checker.py: trap ShareVersionIncompatible too. Also, use f.check
847warner@lothar.com**20090224041405
848 Ignore-this: b667e8d3192116293babcacdeed42898
849 instead of examining the value returned by f.trap, because the latter appears
850 to squash exception types down into their base classes (i.e. since
851 ShareVersionIncompatible is a subclass of LayoutInvalid,
852 f.trap(Failure(ShareVersionIncompatible)) == LayoutInvalid).
853 
854 All this resulted in 'incompatible' shares being misclassified as 'corrupt'.
855] 
856[immutable/layout.py: wrap to 80 cols, no functional changes
857warner@lothar.com**20090224005837
858 Ignore-this: 40019480180ec34141506a28d7711608
859] 
860[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
861warner@lothar.com**20090223234227
862 Ignore-this: d58bd0a909f9939775730cda4a858cae
863] 
864[test/no_network.py: add a basic stats provider
865warner@lothar.com**20090223233937
866 Ignore-this: c9f3cc4eed99cfc36f68938ceff4162c
867] 
868[tests: stop using setUpClass/tearDownClass, since they've been deprecated in Twisted-8.2.0
869warner@lothar.com**20090223204312
870 Ignore-this: 24c6592141cf64103530c024f93a5b88
871] 
872[test_checker: improve test coverage for checker results
873warner@lothar.com**20090223201943
874 Ignore-this: 83e173602f0f4c811a7a9893d85385df
875] 
876[Fixed tests again so they will pass on windows.
877Alberto Berti <alberto@metapensiero.it>**20090223003502
878 Ignore-this: 80d5074e7153642a2fa2a77958bfb50d
879] 
880[misc/*: remove RuntimeError too
881warner@lothar.com**20090222233401
882 Ignore-this: b76f8a184f75bb28eb9d8002f957936a
883] 
884[scripts: stop using RuntimeError, for #639
885warner@lothar.com**20090222233106
886 Ignore-this: 686a424442670fffbd4d1816c284a601
887] 
888[mutable/publish: stop using RuntimeError, for #639
889warner@lothar.com**20090222233056
890 Ignore-this: 2a80a661c7850d97357caddad48c6e9d
891] 
892[remove more RuntimeError from unit tests, for #639
893warner@lothar.com**20090222232855
894 Ignore-this: 1a1c3e1457f3f29ba7101fe406ee5f43
895] 
896[stop using RuntimeError in unit tests, for #639
897warner@lothar.com**20090222232722
898 Ignore-this: 475ce0c0dcd7a1f5ed83ef460312efea
899] 
900[ftpd/sftpd: stop using RuntimeError, for #639
901warner@lothar.com**20090222232426
902 Ignore-this: 97001362c4ba9e94b2e254e229b79987
903] 
904[Added tests for the cse when listdir is an iterator
905Alberto Berti <alberto@metapensiero.it>**20090222224356
906 Ignore-this: 218fb2aba02c28b4b1e5324bdb5adeaa
907] 
908[Fixed tests so that they pass also on buildbots.
909Alberto Berti <alberto@metapensiero.it>**20090222224311
910 Ignore-this: fcb91cd6acf028382411d23d380a4576
911] 
912[Use failUnlessEqual instead of failUnless(a == b)
913Alberto Berti <alberto@metapensiero.it>**20090222224214
914 Ignore-this: 8f9144632e3ac9acb4726fb48a083bf4
915] 
916[Better implementation of filtering algorithm.
917Alberto Berti <alberto@metapensiero.it>**20090222224049
918 Ignore-this: 67a8bd2f99bcc87ca2443bef13370a87
919] 
920[Removed '.hgrags' from vcs excludes
921Alberto Berti <alberto@metapensiero.it>**20090222223946
922 Ignore-this: 3e94c22fc9d85f380ee11fb8bdb4d1e9
923] 
924[docs: CREDITS to Alberto Berti
925zooko@zooko.com**20090222193314
926 Ignore-this: 74d370ada3234cce9e58aec15d739f71
927] 
928[Added tests for the --exclude* options of backup command.
929Alberto Berti <alberto@metapensiero.it>**20090222165106
930 Ignore-this: f1b931cf2e7929ce47b737c022bca707
931] 
932[Added --exclude, --exclude-from and --exclude-vcs options to backup command.
933Alberto Berti <alberto@metapensiero.it>**20090222170829
934 Ignore-this: 4912890229cd54a2f61f14f06bc4afcc
935 
936 It is still impossible to specify absolute exclusion path, only
937 relative. I must check with tar or rsync how they allow them to be
938 specified.
939] 
940[Raise a more explanatory exception for errors encountered during backup processing.
941Alberto Berti <alberto@metapensiero.it>**20090222170252
942 Ignore-this: f6b8ffe2a903ba07a2c1c59130dac1e4
943] 
944[Added tests for the fixed alias related command's synopsis
945Alberto Berti <alberto@metapensiero.it>**20090222163732
946 Ignore-this: 4432b4e88e990ba53a5b3fe0f12db2ac
947] 
948[Add missing synopsis and descriptions for alias commands.
949Alberto Berti <alberto@metapensiero.it>**20090221003106
950 Ignore-this: 8aedd03d36d92d912102c7f29e4ca697
951] 
952[docs: move many specification-like documents into specifications/
953warner@lothar.com**20090222054054
954 Ignore-this: a4110cc478198c0611205aba1ccf54f4
955] 
956[test_web.py: increase test coverage of web.status.plural()
957warner@lothar.com**20090222000116
958 Ignore-this: 3138c9d5d2410d8e1121e9b2ed694169
959] 
960[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
961warner@lothar.com**20090221205649
962 Ignore-this: e6551569982bd31d19779ff15c2d6f58
963] 
964[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
965warner@lothar.com**20090221061710
966 Ignore-this: fde76d0e5cae853014d1bb18b5f17dae
967] 
968[crawler: tolerate low-resolution system clocks (i.e. windows)
969warner@lothar.com**20090221061533
970 Ignore-this: 57286a3abcaf44f6d1a78c3c1ad547a5
971] 
972[BucketCountingCrawler: store just the count, not cycle+count, since it's too easy to make usage mistakes otherwise
973warner@lothar.com**20090221035831
974 Ignore-this: 573b6f651af74380cdd64059fbbdda4b
975] 
976[test_storage: startService the server, as is now the standard practice
977warner@lothar.com**20090221035755
978 Ignore-this: 3999889bd628fe4039bbcf1b29160453
979] 
980[crawler: load state from the pickle in init, rather than waiting until startService, so get_state() can be called early
981warner@lothar.com**20090221035720
982 Ignore-this: ecd128a5f4364c0daf4b72d791340b66
983] 
984[BucketCountingCrawler: rename status and state keys to use 'bucket' instead of 'share', because the former is more accurate
985warner@lothar.com**20090221034606
986 Ignore-this: cf819f63fac9506c878d6c9715ce35b7
987] 
988[storage: also report space-free-for-root and space-free-for-nonroot, since that helps users understand the space-left-for-tahoe number better
989warner@lothar.com**20090221032856
990 Ignore-this: 9fdf0475f758acd98b73026677170b45
991] 
992[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
993warner@lothar.com**20090221030408
994 Ignore-this: 28761c5e076648026bc5f518506db65c
995] 
996[storage: move si_b2a/si_a2b/storage_index_to_dir out of server.py and into common.py
997warner@lothar.com**20090221030309
998 Ignore-this: 645056428ab797f0b542831c82bf192a
999] 
1000[crawler: add get_progress, clean up get_state
1001warner@lothar.com**20090221002743
1002 Ignore-this: 9bea69f154c75b31a53425a8ea67789b
1003] 
1004[web/storage: make sure we can handle platforms without os.statvfs too
1005warner@lothar.com**20090220220353
1006 Ignore-this: 79d4cb8482a8543b9759dc949c86c587
1007] 
1008[crawler: provide for one-shot crawlers, which stop after their first full cycle, for share-upgraders and database-populaters
1009warner@lothar.com**20090220211911
1010 Ignore-this: fcdf72c5ffcafa374d376388be6fa5c5
1011] 
1012[web: add Storage status page, improve tests
1013warner@lothar.com**20090220202926
1014 Ignore-this: e34d5270dcf0237fe72f573f717c7a4
1015] 
1016[storage: include reserved_space in stats
1017warner@lothar.com**20090220202920
1018 Ignore-this: b5b480fe0abad0148ecad0c1fb47ecae
1019] 
1020[web/check_results: sort share identifiers in the sharemap display
1021warner@lothar.com**20090220182922
1022 Ignore-this: 5c7bfcee3e15c7082c3653eb8a460960
1023] 
1024[webapi: pass client through constructor arguments, remove IClient, should make it easier to test web renderers in isolation
1025warner@lothar.com**20090220181554
1026 Ignore-this: e7848cd1bee8faf2ce7aaf040b9bf8e3
1027] 
1028[test/no_network: do startService on the storage servers, make it easier to customize the storage servers
1029warner@lothar.com**20090220022254
1030 Ignore-this: e62f328721c007e4c5ee023a6efdf66d
1031] 
1032[crawler: modify API to support upcoming bucket-counting crawler
1033warner@lothar.com**20090220013142
1034 Ignore-this: 808f8382837b13082f8b245db2ebee06
1035] 
1036[test_backupdb: make the not-a-database file larger, since the older sqlite-2.3.2 on OS-X is easily fooled
1037warner@lothar.com**20090220000409
1038 Ignore-this: 694d2ca5053bb96e91670765d0cedf2e
1039] 
1040[web/reliability: add parameter descriptions, adapted from a patch from Terrell Russell.
1041warner@lothar.com**20090219222918
1042 Ignore-this: 835f5ab01e1aff31b2ff9febb9a51f3
1043] 
1044[test_crawler: hush pyflakes
1045warner@lothar.com**20090219202340
1046 Ignore-this: 765d22c9c9682cc86c5205dc130500af
1047] 
1048[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.
1049warner@lothar.com**20090219201654
1050 Ignore-this: ff7cf5cfa79c6f2ef0cf959495dd989a
1051] 
1052[reliability.py: fix the numpy conversion, it was completely broken. Thanks to Terrell Russell for the help.
1053warner@lothar.com**20090219195515
1054 Ignore-this: f2b1eb65855111b338e1487feee1bbcf
1055] 
1056[reliability: switch to NumPy, since Numeric is deprecated
1057warner@lothar.com**20090219074435
1058 Ignore-this: f588a68e9bcd3b0bc3653570882b6fd5
1059] 
1060[setup.py: fix pyflakes complaints
1061warner@lothar.com**20090219073643
1062 Ignore-this: a314e5456b0a796bc9f70232a119ec68
1063] 
1064[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
1065warner@lothar.com**20090219073558
1066 Ignore-this: 9e56bc43026379212e6b6671ed6a1fd4
1067] 
1068[test_crawler: don't require >=1 cycle on cygwin
1069warner@lothar.com**20090219065818
1070 Ignore-this: b8d2d40f26aeb30a7622479840a04635
1071] 
1072[setup.py: add show_tool_versions command, for the benefit of a new buildbot step
1073warner@lothar.com**20090219062436
1074 Ignore-this: 21d761c76a033e481831584bedc60c86
1075] 
1076[setup.py: wrap to 80 cols, no functional changes
1077warner@lothar.com**20090219055751
1078 Ignore-this: d29e57c6ee555f2ee435667b7e13e60b
1079] 
1080[crawler: use fileutil.move_info_place in preference to our own version
1081warner@lothar.com**20090219051342
1082 Ignore-this: ee4e46f3de965610503ba36b28184db9
1083] 
1084[fileutil: add move_into_place(), to perform the standard unix trick of atomically replacing a file, with a fallback for windows
1085warner@lothar.com**20090219051310
1086 Ignore-this: c1d35e8ca88fcb223ea194513611c511
1087] 
1088[crawler: fix problems on windows and our slow cygwin slave
1089warner@lothar.com**20090219042431
1090 Ignore-this: 8019cb0da79ba00c536183a6f57b4cab
1091] 
1092[#633: first version of a rate-limited interruptable share-crawler
1093warner@lothar.com**20090219034633
1094 Ignore-this: 5d2d30c743e3b096a8e775d5a9b33601
1095] 
1096[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
1097warner@lothar.com**20090218222301
1098 Ignore-this: 740d582f20c93bebf60e21d9a446d3d2
1099] 
1100[test_system: split off checker tests to test_deepcheck.py, this file is too big
1101warner@lothar.com**20090218214234
1102 Ignore-this: 82bf8db81dfbc98224bbf694054a8761
1103] 
1104[break storage.py into smaller pieces in storage/*.py . No behavioral changes.
1105warner@lothar.com**20090218204655
1106 Ignore-this: 312d408d1cacc5a764d791b53ebf8f91
1107] 
1108[immutable/layout: minor change to repr name
1109warner@lothar.com**20090218204648
1110 Ignore-this: c8781ef15b7dea63b39236a1899b86ce
1111] 
1112[docs: add lease-tradeoffs diagram
1113warner@lothar.com**20090218204137
1114 Ignore-this: c22a589ad465dac846da834c30dc4083
1115] 
1116[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
1117warner@lothar.com**20090218192903
1118 Ignore-this: dcbb704a05416ecc66d90fb486c3d75b
1119] 
1120[docs/debian.txt: minor edit
1121warner@lothar.com**20090218032212
1122 Ignore-this: 64ff1fb163ffca4bcfd920254f1cf866
1123] 
1124[add --add-lease to 'tahoe check', 'tahoe deep-check', and webapi.
1125warner@lothar.com**20090218013243
1126 Ignore-this: 176b2006cef5041adcb592ee83e084dd
1127] 
1128[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
1129warner@lothar.com**20090218013053
1130 Ignore-this: 6fdfcea2c832178f1ce72ab0ff510f3a
1131] 
1132[CLI #590: convert 'tahoe deep-check' to streaming form, improve display, add tests
1133warner@lothar.com**20090217231511
1134 Ignore-this: 6d88eb94b1c877eacc8c5ca7d0aac776
1135] 
1136[interfaces.py: document behavior of add_lease/renew_lease/cancel_lease, before I change it
1137warner@lothar.com**20090217194809
1138 Ignore-this: 703c6712926b8edb19d55d790b65a400
1139] 
1140[test_backupdb: improve error messages if the test fails
1141warner@lothar.com**20090217170838
1142 Ignore-this: ef657e87c66e4304d3e0aca9831b84c
1143] 
1144[webapi #590: add streaming deep-check. Still need a CLI tool to use it.
1145warner@lothar.com**20090217053553
1146 Ignore-this: a0edd3d2a531c48a64d8397f7e4b208c
1147] 
1148[test_web.Grid: change the CHECK() function to make it easier to test t= values with hyphens in them
1149warner@lothar.com**20090217050034
1150 Ignore-this: 410c08735347c2057df52f6716520228
1151] 
1152[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
1153warner@lothar.com**20090217041242
1154 Ignore-this: fe54bb66a9ae073c002a7af51cd1e18
1155] 
1156[web: fix handling of reliability page when Numeric is not available
1157warner@lothar.com**20090217015658
1158 Ignore-this: 9d329182f1b2e5f812e5e7eb5f4cf2ed
1159] 
1160[test/no_network: update comments with setup timing: no_network takes 50ms, SystemTestMixin takes 2s (on my laptop)
1161warner@lothar.com**20090217000643
1162 Ignore-this: cc778fa3219775b25057bfc9491f8f34
1163] 
1164[test_upload: rewrite in terms of no-network GridTestMixin, improve no_network.py as necessary
1165warner@lothar.com**20090216234457
1166 Ignore-this: 80a341d5aa3036d24de98e267499d70d
1167] 
1168[test_download: rewrite in terms of no-network GridTestMixin, improve no_network.py as necessary
1169warner@lothar.com**20090216233658
1170 Ignore-this: ec2febafd2403830519120fb3f3ca04e
1171] 
1172[test_dirnode.py: convert Deleter to new no-network gridtest
1173warner@lothar.com**20090216232348
1174 Ignore-this: 8041739442ec4db726675e48f9775ae9
1175] 
1176[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
1177warner@lothar.com**20090216232005
1178 Ignore-this: ec6d010c9182aa72049d1fb894cf890e
1179] 
1180[tests: fix no_network framework to work with upload/download and checker
1181warner@lothar.com**20090216231947
1182 Ignore-this: 74b4dbd66b8384ae7c7544969fe4f744
1183] 
1184[client.py: improve docstring
1185warner@lothar.com**20090216231532
1186 Ignore-this: bbaa9e3f63fdb0048e3125c4681b2d1f
1187] 
1188[test_cli: add test coverage for help strings
1189warner@lothar.com**20090216210833
1190 Ignore-this: d2020849107f687448e159a19d0e5dab
1191] 
1192[test/no_network: new test harness, like system-test but doesn't use the network so it's faster
1193warner@lothar.com**20090216205844
1194 Ignore-this: 31678f7bdef30b0216fd657fc6145534
1195] 
1196[interfaces.py: minor docstring edit
1197warner@lothar.com**20090216205816
1198 Ignore-this: cec3855070197f7920b370f95e8b07bd
1199] 
1200[setup: if you sdist_dsc (to produce the input files for dpkg-buildpackage) then run darcsver first
1201zooko@zooko.com**20090216201558
1202 Ignore-this: b85be51b3d4a9a19a3366e690f1063e2
1203] 
1204[doc: a few edits to docs made after the 1.3.0 release
1205zooko@zooko.com**20090216201539
1206 Ignore-this: dbff3b929d88134d862f1dffd1ef068a
1207] 
1208[test_cli: improve test coverage slightly
1209warner@lothar.com**20090216030451
1210 Ignore-this: e01ccc6a6fb44aaa4fb14fe8669e2065
1211] 
1212[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
1213warner@lothar.com**20090216023210
1214 Ignore-this: dc1f0c6d8c003c0ade38bc8f8516b04d
1215] 
1216[provisioning/reliability: add tests, hush pyflakes, remove dead code, fix web links
1217warner@lothar.com**20090215222451
1218 Ignore-this: 7854df3e0130d9388f06efd4c797262f
1219] 
1220[util/statistics: add tests, fix mean_repair_cost
1221warner@lothar.com**20090215222326
1222 Ignore-this: c576eabc74c23b170702018fc3c122d9
1223] 
1224[test_repairer: hush pyflakes
1225warner@lothar.com**20090215222310
1226 Ignore-this: 875eb52e86077cda77efd02da77f8cfa
1227] 
1228[lossmodel.lyx: move draft paper into docs/proposed/, since it's unfinished
1229warner@lothar.com**20090215221905
1230 Ignore-this: 7f7ee204e47fd66932759c94deefe68
1231] 
1232[build a 'reliability' web page, with a simulation of file decay and repair over time
1233warner@lothar.com**20090213234234
1234 Ignore-this: 9e9623eaac7b0637bbd0071f082bd345
1235] 
1236[More lossmodel work, on repair.
1237Shawn Willden <shawn-tahoe@willden.org>**20090116025648] 
1238[Loss model work (temp1)
1239Shawn Willden <shawn@willden.org>**20090115030058] 
1240[Statistics module
1241Shawn Willden <shawn-tahoe@willden.org>**20090114021235
1242 
1243 Added a statistics module for calculating various facets of
1244 share survival statistics.
1245] 
1246[docs: relnotes-short.txt
1247zooko@zooko.com**20090215163510
1248 Ignore-this: 683649bb13499bbe0e5cea2e1716ff59
1249 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.
1250] 
1251[TAG allmydata-tahoe-1.3.0
1252zooko@zooko.com**20090214000556
1253 Ignore-this: aa6c9a31a14a58ad2298cb7b08d3ea70
1254] 
1255Patch bundle hash:
12560bedf208c0799063a51adaab9d20cd288d2b614c