diff --git a/ui/Makefile b/ui/Makefile index de25223..198c823 100644 --- a/ui/Makefile +++ b/ui/Makefile @@ -1,6 +1,6 @@ -test: fixtures/sample.data.pasn1 +test: fixtures/sample.data.pasn1 fixtures/sample.mtree (. ./p/bin/activate && \ - (echo cli.py | entr sh -c 'python -m coverage run -m unittest cli && coverage report -m --omit=p/\*')) + (ls cli.py mtree.py | entr sh -c 'python -m coverage run -m unittest cli mtree && coverage report -m --omit=p/\*')) env: virtualenv p @@ -9,3 +9,6 @@ env: fixtures/sample.data.pasn1: fixtures/genfixtures.py (. ./p/bin/activate && cd fixtures && PYTHONPATH=.. python genfixtures.py ) + +fixtures/sample.mtree: fixtures/mtree.dir + bsdtar -cf - --format mtree --options='!all,time,sha512,size,indent' -C fixtures/mtree.dir . > $@ diff --git "a/ui/fixtures/mtree.dir/\\ \r\n\\*\\?\\['\n" "b/ui/fixtures/mtree.dir/\\ \r\n\\*\\?\\['\n" new file mode 100644 index 0000000..e69de29 diff --git a/ui/fixtures/mtree.dir/test.txt b/ui/fixtures/mtree.dir/test.txt new file mode 100644 index 0000000..90bfcb5 --- /dev/null +++ b/ui/fixtures/mtree.dir/test.txt @@ -0,0 +1 @@ +this is a test diff --git a/ui/fixtures/sample.mtree b/ui/fixtures/sample.mtree new file mode 100644 index 0000000..a6aafa0 --- /dev/null +++ b/ui/fixtures/sample.mtree @@ -0,0 +1,7 @@ +#mtree +. time=1567323634.0 +./\134\040\015\012\134*\134?\134['\012 \ + time=1567323609.0 size=0 \ + sha512digest=cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e +./test.txt time=1567323634.0 size=15 \ + sha512digest=7d5768d47b6bc27dc4fa7e9732cfa2de506ca262a2749cb108923e5dddffde842bbfee6cb8d692fb43aca0f12946c521cce2633887914ca1f96898478d10ad3f diff --git a/ui/mtree.py b/ui/mtree.py new file mode 100644 index 0000000..98fdd17 --- /dev/null +++ b/ui/mtree.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python + +import unittest + +def _destrvis(s): + r = [] + state = 0 + for i in s: + if state == 0: + if i == '\\': + state = 1 + v = 0 + else: + r.append(i) + elif state in (1, 2): + v = v * 8 + int(i) + state += 1 + elif state == 3: + v = v * 8 + int(i) + r.append(chr(v)) + state = 0 + + return ''.join(r) + +def parse(fname): + with open(fname) as fp: + i = fp.readline().strip() + if not i.startswith('#mtree'): + raise ValueError('not an mtree file') + + path = [] + res = {} + + while True: + i = fp.readline().strip() + + # don't believe the bsdtar mtree output + # contains the cases marked below + if not i: + break + elif i.startswith('#'): # pragma: no cover + raise NotImplementedError + elif i.startswith('/set'): # pragma: no cover + raise NotImplementedError + elif i.startswith('/unset'): # pragma: no cover + raise NotImplementedError + + parts = i.split() + fname = parts.pop(0) + while parts[-1] == '\\': + del parts[-1] + parts.extend(fp.readline().strip().split()) + + res[fname] = dict(x.split('=') for x in parts) + + return res + +class Test(unittest.TestCase): + def test_parsemtree(self): + self.assertRaises(ValueError, parse, 'fixtures/genfixtures.py') + + data = parse('fixtures/sample.mtree') + + proof = { + '.': { + 'time': '1567323634.0' + }, + "./\\134\\040\\015\\012\\134*\\134?\\134['\\012": { + 'size': '0', + 'sha512digest': 'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e', + 'time': '1567323609.0' + }, + './test.txt': { + 'size': '15', + 'sha512digest': '7d5768d47b6bc27dc4fa7e9732cfa2de506ca262a2749cb108923e5dddffde842bbfee6cb8d692fb43aca0f12946c521cce2633887914ca1f96898478d10ad3f', + 'time': '1567323634.0' + }, + } + + self.assertEqual(data, proof) + + def test_debsstr(self): + self.assertEqual(_destrvis(r'\015'), '\r') + self.assertEqual(_destrvis(r'\011'), '\t') + self.assertEqual(_destrvis( + "./\\134\\040\\015\\012\\134*\\134?\\134['\\012"), + "./\134\040\015\012\134*\134?\134['\012")