borg list --short, remove requirement for fakeroot, xfail a test

borg list --short just spills out the list of files / dirs - better for some tests
and also useful on the commandline for interactive use.

the tests previously needed fakeroot because in the test setup it always
made calls to mknod and chown, which require (fake)root.
now, the tests adapt to whether it detects (fake)root or not - to run the
the tests completely, you still need fakeroot, but it won't fail all the archiver
tests just due to failing test setup.

also, a test not working correctly due to fakeroot was found:
it should detect whether a read-only repo is usable, but it failed to do that
because with (fake)root, there is no "read only" (at least not via taking away
 the w permission bits).
This commit is contained in:
Thomas Waldmann 2015-08-15 20:52:14 +02:00
parent 738ed5d91b
commit 608c0935e0
2 changed files with 74 additions and 35 deletions

View File

@ -337,34 +337,38 @@ Type "Yes I am sure" if you understand this and want to continue.\n""")
repository = self.open_repository(args.src)
manifest, key = Manifest.load(repository)
if args.src.archive:
tmap = {1: 'p', 2: 'c', 4: 'd', 6: 'b', 0o10: '-', 0o12: 'l', 0o14: 's'}
archive = Archive(repository, key, manifest, args.src.archive)
for item in archive.iter_items():
type = tmap.get(item[b'mode'] // 4096, '?')
mode = format_file_mode(item[b'mode'])
size = 0
if type == '-':
if args.short:
for item in archive.iter_items():
print(remove_surrogates(item[b'path']))
else:
tmap = {1: 'p', 2: 'c', 4: 'd', 6: 'b', 0o10: '-', 0o12: 'l', 0o14: 's'}
for item in archive.iter_items():
type = tmap.get(item[b'mode'] // 4096, '?')
mode = format_file_mode(item[b'mode'])
size = 0
if type == '-':
try:
size = sum(size for _, size, _ in item[b'chunks'])
except KeyError:
pass
try:
size = sum(size for _, size, _ in item[b'chunks'])
except KeyError:
pass
try:
mtime = datetime.fromtimestamp(bigint_to_int(item[b'mtime']) / 1e9)
except ValueError:
# likely a broken mtime and datetime did not want to go beyond year 9999
mtime = datetime(9999, 12, 31, 23, 59, 59)
if b'source' in item:
if type == 'l':
extra = ' -> %s' % item[b'source']
mtime = datetime.fromtimestamp(bigint_to_int(item[b'mtime']) / 1e9)
except ValueError:
# likely a broken mtime and datetime did not want to go beyond year 9999
mtime = datetime(9999, 12, 31, 23, 59, 59)
if b'source' in item:
if type == 'l':
extra = ' -> %s' % item[b'source']
else:
type = 'h'
extra = ' link to %s' % item[b'source']
else:
type = 'h'
extra = ' link to %s' % item[b'source']
else:
extra = ''
print('%s%s %-6s %-6s %8d %s %s%s' % (
type, mode, item[b'user'] or item[b'uid'],
item[b'group'] or item[b'gid'], size, format_time(mtime),
remove_surrogates(item[b'path']), extra))
extra = ''
print('%s%s %-6s %-6s %8d %s %s%s' % (
type, mode, item[b'user'] or item[b'uid'],
item[b'group'] or item[b'gid'], size, format_time(mtime),
remove_surrogates(item[b'path']), extra))
else:
for archive_info in manifest.list_archive_infos(sort_by='ts'):
print(format_archive(archive_info))
@ -766,6 +770,9 @@ Type "Yes I am sure" if you understand this and want to continue.\n""")
epilog=list_epilog,
formatter_class=argparse.RawDescriptionHelpFormatter)
subparser.set_defaults(func=self.do_list)
subparser.add_argument('--short', dest='short',
action='store_true', default=False,
help='only print file/directory names, nothing else')
subparser.add_argument('src', metavar='REPOSITORY_OR_ARCHIVE', type=location_validator(),
help='repository/archive to list contents of')
mount_epilog = textwrap.dedent("""

View File

@ -12,6 +12,7 @@ import unittest
from hashlib import sha256
from mock import patch
import pytest
from .. import xattr
from ..archive import Archive, ChunkBuffer, CHUNK_MAX_EXP
@ -33,6 +34,12 @@ has_lchflags = hasattr(os, 'lchflags')
src_dir = os.path.join(os.getcwd(), os.path.dirname(__file__), '..')
# Python <= 3.2 raises OSError instead of PermissionError (See #164)
try:
PermissionError = PermissionError
except NameError:
PermissionError = OSError
class changedir:
def __init__(self, dir):
@ -154,15 +161,8 @@ class ArchiverTestCase(ArchiverTestCaseBase):
self.create_regular_file('flagfile', size=1024)
# Directory
self.create_regular_file('dir2/file2', size=1024 * 80)
# File owner
os.chown('input/file1', 100, 200)
# File mode
os.chmod('input/file1', 0o7755)
os.chmod('input/dir2', 0o555)
# Block device
os.mknod('input/bdev', 0o600 | stat.S_IFBLK, os.makedev(10, 20))
# Char device
os.mknod('input/cdev', 0o600 | stat.S_IFCHR, os.makedev(30, 40))
# Hard link
os.link(os.path.join(self.input_path, 'file1'),
os.path.join(self.input_path, 'hardlink'))
@ -180,20 +180,50 @@ class ArchiverTestCase(ArchiverTestCaseBase):
os.mkfifo(os.path.join(self.input_path, 'fifo1'))
if has_lchflags:
os.lchflags(os.path.join(self.input_path, 'flagfile'), stat.UF_NODUMP)
try:
# Block device
os.mknod('input/bdev', 0o600 | stat.S_IFBLK, os.makedev(10, 20))
# Char device
os.mknod('input/cdev', 0o600 | stat.S_IFCHR, os.makedev(30, 40))
# File mode
os.chmod('input/dir2', 0o555) # if we take away write perms, we need root to remove contents
# File owner
os.chown('input/file1', 100, 200)
have_root = True # we have (fake)root
except PermissionError:
have_root = False
return have_root
def test_basic_functionality(self):
self.create_test_files()
have_root = self.create_test_files()
self.cmd('init', self.repository_location)
self.cmd('create', self.repository_location + '::test', 'input')
self.cmd('create', '--stats', self.repository_location + '::test.2', 'input')
with changedir('output'):
self.cmd('extract', self.repository_location + '::test')
self.assert_equal(len(self.cmd('list', self.repository_location).splitlines()), 2)
item_count = 10 if has_lchflags else 11 # one file is UF_NODUMP
self.assert_equal(len(self.cmd('list', self.repository_location + '::test').splitlines()), item_count)
expected = [
'input',
'input/bdev',
'input/cdev',
'input/dir2',
'input/dir2/file2',
'input/empty',
'input/fifo1',
'input/file1',
'input/flagfile',
'input/hardlink',
'input/link1',
]
if not have_root:
# we could not create these device files without (fake)root
expected.remove('input/bdev')
expected.remove('input/cdev')
if has_lchflags:
# remove the file we did not backup, so input and output become equal
expected.remove('input/flagfile') # this file is UF_NODUMP
os.remove(os.path.join('input', 'flagfile'))
self.assert_equal(self.cmd('list', '--short', self.repository_location + '::test').splitlines(), expected)
self.assert_dirs_equal('input', 'output/input')
info_output = self.cmd('info', self.repository_location + '::test')
item_count = 3 if has_lchflags else 4 # one file is UF_NODUMP
@ -436,6 +466,8 @@ class ArchiverTestCase(ArchiverTestCaseBase):
fd.write(b'XXXX')
self.cmd('check', self.repository_location, exit_code=1)
# we currently need to be able to create a lock directory inside the repo:
@pytest.mark.xfail(reason="we need to be able to create the lock directory inside the repo")
def test_readonly_repository(self):
self.cmd('init', self.repository_location)
self.create_src_archive('test')