mirror of https://github.com/borgbackup/borg.git
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:
parent
738ed5d91b
commit
608c0935e0
|
@ -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("""
|
||||
|
|
|
@ -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')
|
||||
|
|
Loading…
Reference in New Issue