annotate cutils/treesum.py @ 137:69f8a3db8fbd

Change the tag for symlinks given on the command line: no "filename" here
author Franz Glasner <fzglas.hg@dom66.de>
date Thu, 02 Jan 2025 23:40:05 +0100
parents db4fd1f64538
children 71747e45b52c
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
124
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
1 # -*- coding: utf-8 -*-
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
2 # :-
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
3 # :Copyright: (c) 2020-2025 Franz Glasner
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
4 # :License: BSD-3-Clause
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
5 # :-
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
6 r"""Generate and verify checksums for directory trees.
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
7
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
8 """
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
9
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
10 from __future__ import print_function, absolute_import
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
11
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
12
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
13 __all__ = []
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
14
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
15
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
16 import argparse
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
17 import base64
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
18 import binascii
128
7c646921a479 Add TIMESTAMP and ISOTIMESTAMP to the output
Franz Glasner <fzglas.hg@dom66.de>
parents: 127
diff changeset
19 import datetime
124
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
20 import os
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
21 import sys
128
7c646921a479 Add TIMESTAMP and ISOTIMESTAMP to the output
Franz Glasner <fzglas.hg@dom66.de>
parents: 127
diff changeset
22 import time
124
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
23
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
24 from . import (__version__, __revision__)
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
25 from . import util
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
26 from .util import cm
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
27 from .util import digest
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
28 from .util import walk
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
29
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
30
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
31 def main(argv=None):
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
32 aparser = argparse.ArgumentParser(
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
33 description="Generate checksums for directory trees",
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
34 fromfile_prefix_chars='@')
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
35 aparser.add_argument(
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
36 "--algorithm", "-a", action="store", type=util.argv2algo,
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
37 help="1 (aka sha1), 224, 256, 384, 512, "
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
38 "3 (alias for sha3-512), 3-224, 3-256, 3-384, 3-512, "
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
39 "blake2b, blake2b-256 (default), blake2s, "
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
40 "blake2 (alias for blake2b), blake2-256 (alias for blake2b-256), "
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
41 "md5")
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
42 aparser.add_argument(
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
43 "--append-output", action="store_true", dest="append_output",
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
44 help="Append to the output file instead of overwriting it.")
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
45 aparser.add_argument(
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
46 "--base64", action="store_true",
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
47 help="Output checksums in base64 notation, not hexadecimal (OpenBSD).")
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
48 aparser.add_argument(
135
dbf27681a1f6 Allow to put comments into the output with "--comment"
Franz Glasner <fzglas.hg@dom66.de>
parents: 134
diff changeset
49 "--comment", action="append", default=[],
dbf27681a1f6 Allow to put comments into the output with "--comment"
Franz Glasner <fzglas.hg@dom66.de>
parents: 134
diff changeset
50 help="Put given comment COMMENT into the output as \"COMMENT\"."
dbf27681a1f6 Allow to put comments into the output with "--comment"
Franz Glasner <fzglas.hg@dom66.de>
parents: 134
diff changeset
51 " Can be given more than once.")
dbf27681a1f6 Allow to put comments into the output with "--comment"
Franz Glasner <fzglas.hg@dom66.de>
parents: 134
diff changeset
52 aparser.add_argument(
136
db4fd1f64538 "-l" is now the sort form of "--follow-directory-symlinks"
Franz Glasner <fzglas.hg@dom66.de>
parents: 135
diff changeset
53 "--follow-directory-symlinks", "-l", action="store_true",
131
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
54 dest="follow_directory_symlinks",
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
55 help="Follow symbolic links to directories when walking a directory"
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
56 " tree. Note that this is different from using \"--logical\" or"
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
57 " \"--physical\" for arguments given directly on the command"
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
58 " line")
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
59 aparser.add_argument(
125
12d6ec1f8613 Implement "--logical" and "--physical" to control following symlinked directories when given on the commandline
Franz Glasner <fzglas.hg@dom66.de>
parents: 124
diff changeset
60 "--logical", "-L", dest="logical", action="store_true", default=None,
12d6ec1f8613 Implement "--logical" and "--physical" to control following symlinked directories when given on the commandline
Franz Glasner <fzglas.hg@dom66.de>
parents: 124
diff changeset
61 help="Follow symbolic links given on command line arguments."
12d6ec1f8613 Implement "--logical" and "--physical" to control following symlinked directories when given on the commandline
Franz Glasner <fzglas.hg@dom66.de>
parents: 124
diff changeset
62 " Note that this is a different setting as to follow symbolic"
12d6ec1f8613 Implement "--logical" and "--physical" to control following symlinked directories when given on the commandline
Franz Glasner <fzglas.hg@dom66.de>
parents: 124
diff changeset
63 " links to directories when traversing a directory tree.")
12d6ec1f8613 Implement "--logical" and "--physical" to control following symlinked directories when given on the commandline
Franz Glasner <fzglas.hg@dom66.de>
parents: 124
diff changeset
64 aparser.add_argument(
124
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
65 "--mmap", action="store_true", dest="mmap", default=None,
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
66 help="Use mmap if available. Default is to determine automatically "
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
67 "from the filesize.")
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
68 aparser.add_argument(
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
69 "--no-mmap", action="store_false", dest="mmap", default=None,
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
70 help="Dont use mmap.")
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
71 aparser.add_argument(
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
72 "--output", "-o", action="store", metavar="OUTPUT",
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
73 help="Put the checksum into given file. If not given of if it is given"
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
74 " as `-' then stdout is used.")
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
75 aparser.add_argument(
125
12d6ec1f8613 Implement "--logical" and "--physical" to control following symlinked directories when given on the commandline
Franz Glasner <fzglas.hg@dom66.de>
parents: 124
diff changeset
76 "--physical", "-P", dest="logical", action="store_false", default=None,
12d6ec1f8613 Implement "--logical" and "--physical" to control following symlinked directories when given on the commandline
Franz Glasner <fzglas.hg@dom66.de>
parents: 124
diff changeset
77 help="Do not follow symbolic links given on comment line arguments."
12d6ec1f8613 Implement "--logical" and "--physical" to control following symlinked directories when given on the commandline
Franz Glasner <fzglas.hg@dom66.de>
parents: 124
diff changeset
78 " This is the default.")
12d6ec1f8613 Implement "--logical" and "--physical" to control following symlinked directories when given on the commandline
Franz Glasner <fzglas.hg@dom66.de>
parents: 124
diff changeset
79 aparser.add_argument(
124
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
80 "--version", "-v", action="version",
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
81 version="%s (rv:%s)" % (__version__, __revision__))
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
82 aparser.add_argument(
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
83 "directories", nargs="*", metavar="DIRECTORY")
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
84
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
85 opts = aparser.parse_args(args=argv)
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
86
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
87 if not opts.algorithm:
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
88 opts.algorithm = util.argv2algo("blake2b-256")
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
89
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
90 return treesum(opts)
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
91
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
92
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
93 def gen_opts(directories=[],
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
94 algorithm="BLAKE2b-256",
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
95 append_output=False,
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
96 base64=False,
135
dbf27681a1f6 Allow to put comments into the output with "--comment"
Franz Glasner <fzglas.hg@dom66.de>
parents: 134
diff changeset
97 comment=[],
131
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
98 follow_directory_symlinks=False,
125
12d6ec1f8613 Implement "--logical" and "--physical" to control following symlinked directories when given on the commandline
Franz Glasner <fzglas.hg@dom66.de>
parents: 124
diff changeset
99 logical=None,
124
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
100 mmap=None,
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
101 output=None):
131
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
102 opts = argparse.Namespace(
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
103 directories=directories,
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
104 algorithm=(util.algotag2algotype(algorithm),
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
105 algorithm),
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
106 append_output=append_output,
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
107 base64=base64,
135
dbf27681a1f6 Allow to put comments into the output with "--comment"
Franz Glasner <fzglas.hg@dom66.de>
parents: 134
diff changeset
108 comment=comment,
131
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
109 follow_directory_symlinks=follow_directory_symlinks,
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
110 logical=logical,
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
111 mmap=mmap,
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
112 output=output)
124
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
113 return opts
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
114
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
115
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
116 def treesum(opts):
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
117 # XXX TBD: opts.check and opts.checklist (as in shasum.py)
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
118 return generate_treesum(opts)
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
119
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
120
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
121 def generate_treesum(opts):
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
122 if not opts.directories:
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
123 opts.directories.append(".")
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
124
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
125 if opts.output is None or opts.output == "-":
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
126 if hasattr(sys.stdout, "buffer"):
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
127 out_cm = cm.nullcontext(sys.stdout.buffer)
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
128 else:
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
129 out_cm = cm.nullcontext(sys.stdout)
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
130 else:
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
131 if opts.append_output:
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
132 out_cm = open(opts.output, "ab")
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
133 else:
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
134 out_cm = open(opts.output, "wb")
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
135
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
136 with out_cm as outfp:
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
137 for d in opts.directories:
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
138 generate_treesum_for_directory(
131
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
139 outfp, d, opts.algorithm, opts.mmap, opts.base64, opts.logical,
135
dbf27681a1f6 Allow to put comments into the output with "--comment"
Franz Glasner <fzglas.hg@dom66.de>
parents: 134
diff changeset
140 opts.follow_directory_symlinks,
dbf27681a1f6 Allow to put comments into the output with "--comment"
Franz Glasner <fzglas.hg@dom66.de>
parents: 134
diff changeset
141 comment=opts.comment)
124
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
142
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
143
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
144 def generate_treesum_for_directory(
131
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
145 outfp, root, algorithm, use_mmap, use_base64, handle_root_logical,
135
dbf27681a1f6 Allow to put comments into the output with "--comment"
Franz Glasner <fzglas.hg@dom66.de>
parents: 134
diff changeset
146 follow_directory_symlinks, comment=None):
124
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
147 """
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
148
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
149 :param outfp: a *binary* file with a "write()" and a "flush()" method
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
150
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
151 """
134
d2c303695fb8 Put a file version number into the output.
Franz Glasner <fzglas.hg@dom66.de>
parents: 133
diff changeset
152 outfp.write(format_bsd_line("VERSION", "1", None, False))
124
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
153 outfp.flush()
125
12d6ec1f8613 Implement "--logical" and "--physical" to control following symlinked directories when given on the commandline
Franz Glasner <fzglas.hg@dom66.de>
parents: 124
diff changeset
154
12d6ec1f8613 Implement "--logical" and "--physical" to control following symlinked directories when given on the commandline
Franz Glasner <fzglas.hg@dom66.de>
parents: 124
diff changeset
155 # Note given non-default flags that are relevant for directory traversal
12d6ec1f8613 Implement "--logical" and "--physical" to control following symlinked directories when given on the commandline
Franz Glasner <fzglas.hg@dom66.de>
parents: 124
diff changeset
156 flags = []
12d6ec1f8613 Implement "--logical" and "--physical" to control following symlinked directories when given on the commandline
Franz Glasner <fzglas.hg@dom66.de>
parents: 124
diff changeset
157 if handle_root_logical:
129
bdd8ea43074b Output FLAGS as line "FLAGS = ..." instead of "FLAGS (...)"
Franz Glasner <fzglas.hg@dom66.de>
parents: 128
diff changeset
158 flags.append("logical")
131
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
159 if follow_directory_symlinks:
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
160 flags.append("follow-directory-symlinks")
125
12d6ec1f8613 Implement "--logical" and "--physical" to control following symlinked directories when given on the commandline
Franz Glasner <fzglas.hg@dom66.de>
parents: 124
diff changeset
161 if flags:
129
bdd8ea43074b Output FLAGS as line "FLAGS = ..." instead of "FLAGS (...)"
Franz Glasner <fzglas.hg@dom66.de>
parents: 128
diff changeset
162 outfp.write(format_bsd_line("FLAGS", ",".join(flags), None, False))
134
d2c303695fb8 Put a file version number into the output.
Franz Glasner <fzglas.hg@dom66.de>
parents: 133
diff changeset
163 outfp.flush()
125
12d6ec1f8613 Implement "--logical" and "--physical" to control following symlinked directories when given on the commandline
Franz Glasner <fzglas.hg@dom66.de>
parents: 124
diff changeset
164
128
7c646921a479 Add TIMESTAMP and ISOTIMESTAMP to the output
Franz Glasner <fzglas.hg@dom66.de>
parents: 127
diff changeset
165 # Write execution timestamps in POSIX epoch and ISO format
7c646921a479 Add TIMESTAMP and ISOTIMESTAMP to the output
Franz Glasner <fzglas.hg@dom66.de>
parents: 127
diff changeset
166 ts = time.time()
7c646921a479 Add TIMESTAMP and ISOTIMESTAMP to the output
Franz Glasner <fzglas.hg@dom66.de>
parents: 127
diff changeset
167 outfp.write(format_bsd_line("TIMESTAMP", ts, None, False))
7c646921a479 Add TIMESTAMP and ISOTIMESTAMP to the output
Franz Glasner <fzglas.hg@dom66.de>
parents: 127
diff changeset
168 ts = (datetime.datetime.utcfromtimestamp(ts)).isoformat("T")
7c646921a479 Add TIMESTAMP and ISOTIMESTAMP to the output
Franz Glasner <fzglas.hg@dom66.de>
parents: 127
diff changeset
169 outfp.write(format_bsd_line("ISOTIMESTAMP", ts, None, False))
134
d2c303695fb8 Put a file version number into the output.
Franz Glasner <fzglas.hg@dom66.de>
parents: 133
diff changeset
170 outfp.flush()
d2c303695fb8 Put a file version number into the output.
Franz Glasner <fzglas.hg@dom66.de>
parents: 133
diff changeset
171
135
dbf27681a1f6 Allow to put comments into the output with "--comment"
Franz Glasner <fzglas.hg@dom66.de>
parents: 134
diff changeset
172 if comment:
dbf27681a1f6 Allow to put comments into the output with "--comment"
Franz Glasner <fzglas.hg@dom66.de>
parents: 134
diff changeset
173 for line in comment:
dbf27681a1f6 Allow to put comments into the output with "--comment"
Franz Glasner <fzglas.hg@dom66.de>
parents: 134
diff changeset
174 outfp.write(format_bsd_line("COMMENT", None, line, False))
134
d2c303695fb8 Put a file version number into the output.
Franz Glasner <fzglas.hg@dom66.de>
parents: 133
diff changeset
175 outfp.write(format_bsd_line("ROOT", None, root, False))
d2c303695fb8 Put a file version number into the output.
Franz Glasner <fzglas.hg@dom66.de>
parents: 133
diff changeset
176 outfp.flush()
128
7c646921a479 Add TIMESTAMP and ISOTIMESTAMP to the output
Franz Glasner <fzglas.hg@dom66.de>
parents: 127
diff changeset
177
124
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
178 dir_digests = {}
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
179
125
12d6ec1f8613 Implement "--logical" and "--physical" to control following symlinked directories when given on the commandline
Franz Glasner <fzglas.hg@dom66.de>
parents: 124
diff changeset
180 if not handle_root_logical and os.path.islink(root):
12d6ec1f8613 Implement "--logical" and "--physical" to control following symlinked directories when given on the commandline
Franz Glasner <fzglas.hg@dom66.de>
parents: 124
diff changeset
181 linktgt = util.fsencode(os.readlink(root))
12d6ec1f8613 Implement "--logical" and "--physical" to control following symlinked directories when given on the commandline
Franz Glasner <fzglas.hg@dom66.de>
parents: 124
diff changeset
182 linkdgst = algorithm[0]()
132
8b73dca5db97 Encode the link targets as netstrings also before digesting them
Franz Glasner <fzglas.hg@dom66.de>
parents: 131
diff changeset
183 linkdgst.update(b"%d:%s," % (len(linktgt), linktgt))
125
12d6ec1f8613 Implement "--logical" and "--physical" to control following symlinked directories when given on the commandline
Franz Glasner <fzglas.hg@dom66.de>
parents: 124
diff changeset
184 dir_dgst = algorithm[0]()
137
69f8a3db8fbd Change the tag for symlinks given on the command line: no "filename" here
Franz Glasner <fzglas.hg@dom66.de>
parents: 136
diff changeset
185 dir_dgst.update(b"1:L,")
125
12d6ec1f8613 Implement "--logical" and "--physical" to control following symlinked directories when given on the commandline
Franz Glasner <fzglas.hg@dom66.de>
parents: 124
diff changeset
186 dir_dgst.update(linkdgst.digest())
133
Franz Glasner <fzglas.hg@dom66.de>
parents: 132
diff changeset
187 outfp.write(
Franz Glasner <fzglas.hg@dom66.de>
parents: 132
diff changeset
188 format_bsd_line(
Franz Glasner <fzglas.hg@dom66.de>
parents: 132
diff changeset
189 algorithm[1],
Franz Glasner <fzglas.hg@dom66.de>
parents: 132
diff changeset
190 dir_dgst.digest(),
Franz Glasner <fzglas.hg@dom66.de>
parents: 132
diff changeset
191 "./@",
Franz Glasner <fzglas.hg@dom66.de>
parents: 132
diff changeset
192 use_base64))
125
12d6ec1f8613 Implement "--logical" and "--physical" to control following symlinked directories when given on the commandline
Franz Glasner <fzglas.hg@dom66.de>
parents: 124
diff changeset
193 outfp.flush()
12d6ec1f8613 Implement "--logical" and "--physical" to control following symlinked directories when given on the commandline
Franz Glasner <fzglas.hg@dom66.de>
parents: 124
diff changeset
194 return
12d6ec1f8613 Implement "--logical" and "--physical" to control following symlinked directories when given on the commandline
Franz Glasner <fzglas.hg@dom66.de>
parents: 124
diff changeset
195
131
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
196 for top, dirs, nondirs in walk.walk(
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
197 root,
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
198 follow_symlinks=follow_directory_symlinks):
124
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
199 dir_dgst = algorithm[0]()
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
200 for dn in dirs:
131
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
201 if dn.is_symlink and not follow_directory_symlinks:
124
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
202 linktgt = util.fsencode(os.readlink(dn.path))
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
203 linkdgst = algorithm[0]()
132
8b73dca5db97 Encode the link targets as netstrings also before digesting them
Franz Glasner <fzglas.hg@dom66.de>
parents: 131
diff changeset
204 linkdgst.update(b"%d:%s," % (len(linktgt), linktgt))
124
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
205 dir_dgst.update(b"1:S,%d:%s," % (len(dn.fsname), dn.fsname))
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
206 dir_dgst.update(linkdgst.digest())
127
6a50d02fe0ca Change the filename output: make it more consistent
Franz Glasner <fzglas.hg@dom66.de>
parents: 125
diff changeset
207 opath = "/".join(top) + "/" + dn.name if top else dn.name
124
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
208 outfp.write(
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
209 format_bsd_line(
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
210 algorithm[1],
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
211 linkdgst.digest(),
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
212 "%s/./@" % (opath,),
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
213 use_base64))
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
214 outfp.flush()
131
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
215 continue
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
216 # fetch from dir_digests
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
217 dgst = dir_digests[top + (dn.name,)]
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
218 dir_dgst.update(b"1:d,%d:%s," % (len(dn.fsname), dn.fsname))
3a18d71d7c50 Implement --follow-directory-symlinks when walking a directory tree
Franz Glasner <fzglas.hg@dom66.de>
parents: 130
diff changeset
219 dir_dgst.update(dgst)
124
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
220 for fn in nondirs:
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
221 dir_dgst.update(b"1:f,%d:%s," % (len(fn.fsname), fn.fsname))
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
222 dgst = digest.compute_digest_file(
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
223 algorithm[0], fn.path, use_mmap=use_mmap)
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
224 dir_dgst.update(dgst)
127
6a50d02fe0ca Change the filename output: make it more consistent
Franz Glasner <fzglas.hg@dom66.de>
parents: 125
diff changeset
225 opath = "/".join(top) + "/" + fn.name if top else fn.name
133
Franz Glasner <fzglas.hg@dom66.de>
parents: 132
diff changeset
226 outfp.write(
Franz Glasner <fzglas.hg@dom66.de>
parents: 132
diff changeset
227 format_bsd_line(
Franz Glasner <fzglas.hg@dom66.de>
parents: 132
diff changeset
228 algorithm[1], dgst, opath, use_base64))
124
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
229 outfp.flush()
127
6a50d02fe0ca Change the filename output: make it more consistent
Franz Glasner <fzglas.hg@dom66.de>
parents: 125
diff changeset
230 opath = "/".join(top) + "/" if top else ""
124
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
231 outfp.write(format_bsd_line(
127
6a50d02fe0ca Change the filename output: make it more consistent
Franz Glasner <fzglas.hg@dom66.de>
parents: 125
diff changeset
232 algorithm[1], dir_dgst.digest(), opath, use_base64))
124
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
233 outfp.flush()
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
234 dir_digests[top] = dir_dgst.digest()
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
235
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
236
128
7c646921a479 Add TIMESTAMP and ISOTIMESTAMP to the output
Franz Glasner <fzglas.hg@dom66.de>
parents: 127
diff changeset
237 def format_bsd_line(digestname, value, filename, use_base64):
124
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
238 ls = os.linesep if isinstance(os.linesep, bytes) \
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
239 else os.linesep.encode("utf-8")
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
240 if not isinstance(digestname, bytes):
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
241 digestname = digestname.encode("ascii")
128
7c646921a479 Add TIMESTAMP and ISOTIMESTAMP to the output
Franz Glasner <fzglas.hg@dom66.de>
parents: 127
diff changeset
242 if digestname == b"TIMESTAMP":
129
bdd8ea43074b Output FLAGS as line "FLAGS = ..." instead of "FLAGS (...)"
Franz Glasner <fzglas.hg@dom66.de>
parents: 128
diff changeset
243 assert filename is None
128
7c646921a479 Add TIMESTAMP and ISOTIMESTAMP to the output
Franz Glasner <fzglas.hg@dom66.de>
parents: 127
diff changeset
244 return b"TIMESTAMP = %d%s" % (value, ls)
134
d2c303695fb8 Put a file version number into the output.
Franz Glasner <fzglas.hg@dom66.de>
parents: 133
diff changeset
245 if digestname in (b"ISOTIMESTAMP", b"FLAGS", b"VERSION"):
129
bdd8ea43074b Output FLAGS as line "FLAGS = ..." instead of "FLAGS (...)"
Franz Glasner <fzglas.hg@dom66.de>
parents: 128
diff changeset
246 assert filename is None
128
7c646921a479 Add TIMESTAMP and ISOTIMESTAMP to the output
Franz Glasner <fzglas.hg@dom66.de>
parents: 127
diff changeset
247 if not isinstance(value, bytes):
7c646921a479 Add TIMESTAMP and ISOTIMESTAMP to the output
Franz Glasner <fzglas.hg@dom66.de>
parents: 127
diff changeset
248 value = value.encode("ascii")
129
bdd8ea43074b Output FLAGS as line "FLAGS = ..." instead of "FLAGS (...)"
Franz Glasner <fzglas.hg@dom66.de>
parents: 128
diff changeset
249 return b"%s = %s%s" % (digestname, value, ls)
bdd8ea43074b Output FLAGS as line "FLAGS = ..." instead of "FLAGS (...)"
Franz Glasner <fzglas.hg@dom66.de>
parents: 128
diff changeset
250 assert filename is not None
135
dbf27681a1f6 Allow to put comments into the output with "--comment"
Franz Glasner <fzglas.hg@dom66.de>
parents: 134
diff changeset
251 if digestname == b"COMMENT":
dbf27681a1f6 Allow to put comments into the output with "--comment"
Franz Glasner <fzglas.hg@dom66.de>
parents: 134
diff changeset
252 if not isinstance(filename, bytes):
dbf27681a1f6 Allow to put comments into the output with "--comment"
Franz Glasner <fzglas.hg@dom66.de>
parents: 134
diff changeset
253 filename = filename.encode("utf-8")
dbf27681a1f6 Allow to put comments into the output with "--comment"
Franz Glasner <fzglas.hg@dom66.de>
parents: 134
diff changeset
254 return b"COMMENT (%s)%s" % (filename, ls)
124
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
255 if not isinstance(filename, bytes):
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
256 filename = util.fsencode(filename)
128
7c646921a479 Add TIMESTAMP and ISOTIMESTAMP to the output
Franz Glasner <fzglas.hg@dom66.de>
parents: 127
diff changeset
257 if value is None:
124
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
258 return b"%s (%s)%s" % (digestname, filename, ls)
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
259 if use_base64:
128
7c646921a479 Add TIMESTAMP and ISOTIMESTAMP to the output
Franz Glasner <fzglas.hg@dom66.de>
parents: 127
diff changeset
260 value = base64.b64encode(value)
124
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
261 else:
128
7c646921a479 Add TIMESTAMP and ISOTIMESTAMP to the output
Franz Glasner <fzglas.hg@dom66.de>
parents: 127
diff changeset
262 value = binascii.hexlify(value)
130
d5621028ce39 Change again the filename tags to be used for symlinks
Franz Glasner <fzglas.hg@dom66.de>
parents: 129
diff changeset
263 if filename != b"./@":
127
6a50d02fe0ca Change the filename output: make it more consistent
Franz Glasner <fzglas.hg@dom66.de>
parents: 125
diff changeset
264 filename = util.normalize_filename(filename, True)
128
7c646921a479 Add TIMESTAMP and ISOTIMESTAMP to the output
Franz Glasner <fzglas.hg@dom66.de>
parents: 127
diff changeset
265 return b"%s (%s) = %s%s" % (digestname, filename, value, ls)
124
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
266
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
267
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
268 if __name__ == "__main__":
3bd3f32b5e60 A first version of "treesum" is working
Franz Glasner <fzglas.hg@dom66.de>
parents:
diff changeset
269 sys.exit(main())