##// END OF EJS Templates
tests: add 'f' tool for cross platform file operations in the tests...
Mads Kiilerich -
r23860:bead0c7b default
parent child Browse files
Show More
@@ -0,0 +1,158 b''
1 #!/usr/bin/env python
2
3 """
4 Utility for inspecting files in various ways.
5
6 This tool is like the collection of tools found in a unix environment but are
7 cross platform and stable and suitable for our needs in the test suite.
8
9 This can be used instead of tools like:
10 [
11 dd
12 find
13 head
14 hexdump
15 ls
16 md5sum
17 readlink
18 sha1sum
19 stat
20 tail
21 test
22 readlink.py
23 md5sum.py
24 """
25
26 import sys, os, errno, re, glob, optparse
27
28 def visit(opts, filenames, outfile):
29 """Process filenames in the way specified in opts, writing output to
30 outfile."""
31 for f in sorted(filenames):
32 isstdin = f == '-'
33 if not isstdin and not os.path.lexists(f):
34 outfile.write('%s: file not found\n' % f)
35 continue
36 quiet = opts.quiet and not opts.recurse or isstdin
37 isdir = os.path.isdir(f)
38 islink = os.path.islink(f)
39 isfile = os.path.isfile(f) and not islink
40 dirfiles = None
41 content = None
42 facts = []
43 if isfile:
44 if opts.type:
45 facts.append('file')
46 if opts.hexdump or opts.dump or opts.md5:
47 content = file(f).read()
48 elif islink:
49 if opts.type:
50 facts.append('link')
51 content = os.readlink(f)
52 elif isstdin:
53 content = sys.stdin.read()
54 if opts.size:
55 facts.append('size=%s' % len(content))
56 elif isdir:
57 if opts.recurse or opts.type:
58 dirfiles = glob.glob(f + '/*')
59 facts.append('directory with %s files' % len(dirfiles))
60 elif opts.type:
61 facts.append('type unknown')
62 if not isstdin:
63 stat = os.lstat(f)
64 if opts.size:
65 facts.append('size=%s' % stat.st_size)
66 if opts.mode:
67 facts.append('mode=%o' % (stat.st_mode & 0777))
68 if opts.links:
69 facts.append('links=%s' % stat.st_nlink)
70 if opts.newer:
71 # mtime might be in whole seconds so newer file might be same
72 if stat.st_mtime >= os.stat(opts.newer).st_mtime:
73 facts.append('newer than %s' % opts.newer)
74 else:
75 facts.append('older than %s' % opts.newer)
76 if opts.md5 and content is not None:
77 try:
78 from hashlib import md5
79 except ImportError:
80 from md5 import md5
81 facts.append('md5=%s' % md5(content).hexdigest()[:opts.bytes])
82 if opts.sha1 and content is not None:
83 try:
84 from hashlib import sha1
85 except ImportError:
86 from sha import sha as sha1
87 facts.append('sha1=%s' % sha1(content).hexdigest()[:opts.bytes])
88 if isstdin:
89 outfile.write(', '.join(facts) + '\n')
90 elif facts:
91 outfile.write('%s: %s\n' % (f, ', '.join(facts)))
92 elif not quiet:
93 outfile.write('%s:\n' % f)
94 if content is not None:
95 chunk = content
96 if not islink:
97 if opts.lines:
98 if opts.lines >= 0:
99 chunk = ''.join(chunk.splitlines(True)[:opts.lines])
100 else:
101 chunk = ''.join(chunk.splitlines(True)[opts.lines:])
102 if opts.bytes:
103 if opts.bytes >= 0:
104 chunk = chunk[:opts.bytes]
105 else:
106 chunk = chunk[opts.bytes:]
107 if opts.hexdump:
108 for i in range(0, len(chunk), 16):
109 s = chunk[i:i+16]
110 outfile.write('%04x: %-47s |%s|\n' %
111 (i, ' '.join('%02x' % ord(c) for c in s),
112 re.sub('[^ -~]', '.', s)))
113 if opts.dump:
114 if not quiet:
115 outfile.write('>>>\n')
116 outfile.write(chunk)
117 if not quiet:
118 if chunk.endswith('\n'):
119 outfile.write('<<<\n')
120 else:
121 outfile.write('\n<<< no trailing newline\n')
122 if opts.recurse and dirfiles:
123 assert not isstdin
124 visit(opts, dirfiles, outfile)
125
126 if __name__ == "__main__":
127 parser = optparse.OptionParser("%prog [options] [filenames]")
128 parser.add_option("-t", "--type", action="store_true",
129 help="show file type (file or directory)")
130 parser.add_option("-m", "--mode", action="store_true",
131 help="show file mode")
132 parser.add_option("-l", "--links", action="store_true",
133 help="show number of links")
134 parser.add_option("-s", "--size", action="store_true",
135 help="show size of file")
136 parser.add_option("-n", "--newer", action="store",
137 help="check if file is newer (or same)")
138 parser.add_option("-r", "--recurse", action="store_true",
139 help="recurse into directories")
140 parser.add_option("-S", "--sha1", action="store_true",
141 help="show sha1 hash of the content")
142 parser.add_option("-M", "--md5", action="store_true",
143 help="show md5 hash of the content")
144 parser.add_option("-D", "--dump", action="store_true",
145 help="dump file content")
146 parser.add_option("-H", "--hexdump", action="store_true",
147 help="hexdump file content")
148 parser.add_option("-B", "--bytes", type="int",
149 help="number of characters to dump")
150 parser.add_option("-L", "--lines", type="int",
151 help="number of lines to dump")
152 parser.add_option("-q", "--quiet", action="store_true",
153 help="no default output")
154 (opts, filenames) = parser.parse_args(sys.argv[1:])
155 if not filenames:
156 filenames = ['-']
157
158 visit(opts, filenames, sys.stdout)
@@ -0,0 +1,87 b''
1 Tests of the file helper tool
2
3 $ f -h
4 Usage: f [options] [filenames]
5
6 Options:
7 -h, --help show this help message and exit
8 -t, --type show file type (file or directory)
9 -m, --mode show file mode
10 -l, --links show number of links
11 -s, --size show size of file
12 -n NEWER, --newer=NEWER
13 check if file is newer (or same)
14 -r, --recurse recurse into directories
15 -S, --sha1 show sha1 hash of the content
16 -M, --md5 show md5 hash of the content
17 -D, --dump dump file content
18 -H, --hexdump hexdump file content
19 -B BYTES, --bytes=BYTES
20 number of characters to dump
21 -L LINES, --lines=LINES
22 number of lines to dump
23 -q, --quiet no default output
24
25 $ mkdir dir
26 $ cd dir
27
28 $ f --size
29 size=0
30
31 $ echo hello | f --md5 --size
32 size=6, md5=b1946ac92492d2347c6235b4d2611184
33
34 $ f foo
35 foo: file not found
36
37 $ echo foo > foo
38 $ f foo
39 foo:
40
41 $ f foo --mode
42 foo: mode=644
43
44 $ seq 10 > bar
45 $ chmod +x bar
46 $ f bar --newer foo --mode --type --size --dump --links --bytes 7
47 bar: file, size=21, mode=755, links=1, newer than foo
48 >>>
49 1
50 2
51 3
52 4
53 <<< no trailing newline
54
55 $ ln bar baz
56 $ f bar -n baz -l --hexdump -t --sha1 --lines=9 -B 20
57 bar: file, links=2, newer than baz, sha1=612ca68d0305c821750a
58 0000: 31 0a 32 0a 33 0a 34 0a 35 0a 36 0a 37 0a 38 0a |1.2.3.4.5.6.7.8.|
59 0010: 39 0a |9.|
60
61 $ ln -s yadda l
62 $ f . --recurse -MStmsB4
63 .: directory with 4 files, size=120, mode=755
64 ./bar: file, size=21, mode=755, md5=3b03, sha1=612c
65 ./baz: file, size=21, mode=755, md5=3b03, sha1=612c
66 ./foo: file, size=4, mode=644, md5=d3b0, sha1=f1d2
67 ./l: link, size=5, mode=777, md5=2faa, sha1=af93
68
69 $ f --quiet bar -DL 3
70 1
71 2
72 3
73
74 $ cd ..
75
76 $ f -qr dir -HB 17
77 dir: directory with 4 files
78 dir/bar:
79 0000: 31 0a 32 0a 33 0a 34 0a 35 0a 36 0a 37 0a 38 0a |1.2.3.4.5.6.7.8.|
80 0010: 39 |9|
81 dir/baz:
82 0000: 31 0a 32 0a 33 0a 34 0a 35 0a 36 0a 37 0a 38 0a |1.2.3.4.5.6.7.8.|
83 0010: 39 |9|
84 dir/foo:
85 0000: 66 6f 6f 0a |foo.|
86 dir/l:
87 0000: 79 61 64 64 61 |yadda|
General Comments 0
You need to be logged in to leave comments. Login now