#!/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")