示例#1
0
文件: tvfs.py 项目: bup/bup
def run_augment_item_meta_tests(repo,
                                file_path, file_size,
                                link_path, link_target):
    _, file_item = vfs.resolve(repo, file_path)[-1]
    _, link_item = vfs.resolve(repo, link_path, follow=False)[-1]
    wvpass(isinstance(file_item.meta, Metadata))
    wvpass(isinstance(link_item.meta, Metadata))
    # Note: normally, modifying item.meta values is forbidden
    file_item.meta.size = file_item.meta.size or vfs.item_size(repo, file_item)
    link_item.meta.size = link_item.meta.size or vfs.item_size(repo, link_item)

    ## Ensure a fully populated item is left alone
    augmented = vfs.augment_item_meta(repo, file_item)
    wvpass(augmented is file_item)
    wvpass(augmented.meta is file_item.meta)
    augmented = vfs.augment_item_meta(repo, file_item, include_size=True)
    wvpass(augmented is file_item)
    wvpass(augmented.meta is file_item.meta)

    ## Ensure a missing size is handled poperly
    file_item.meta.size = None
    augmented = vfs.augment_item_meta(repo, file_item)
    wvpass(augmented is file_item)
    wvpass(augmented.meta is file_item.meta)
    augmented = vfs.augment_item_meta(repo, file_item, include_size=True)
    wvpass(augmented is not file_item)
    wvpasseq(file_size, augmented.meta.size)

    ## Ensure a meta mode is handled properly
    mode_item = file_item._replace(meta=vfs.default_file_mode)
    augmented = vfs.augment_item_meta(repo, mode_item)
    augmented_w_size = vfs.augment_item_meta(repo, mode_item, include_size=True)
    for item in (augmented, augmented_w_size):
        meta = item.meta
        wvpass(item is not file_item)
        wvpass(isinstance(meta, Metadata))
        wvpasseq(vfs.default_file_mode, meta.mode)
        wvpasseq((0, 0, 0, 0, 0),
                 (meta.uid, meta.gid, meta.atime, meta.mtime, meta.ctime))
    wvpass(augmented.meta.size is None)
    wvpasseq(file_size, augmented_w_size.meta.size)

    ## Ensure symlinks are handled properly
    mode_item = link_item._replace(meta=vfs.default_symlink_mode)
    augmented = vfs.augment_item_meta(repo, mode_item)
    wvpass(augmented is not mode_item)
    wvpass(isinstance(augmented.meta, Metadata))
    wvpasseq(link_target, augmented.meta.symlink_target)
    wvpasseq(len(link_target), augmented.meta.size)
    augmented = vfs.augment_item_meta(repo, mode_item, include_size=True)
    wvpass(augmented is not mode_item)
    wvpass(isinstance(augmented.meta, Metadata))
    wvpasseq(link_target, augmented.meta.symlink_target)
    wvpasseq(len(link_target), augmented.meta.size)
示例#2
0
文件: tvfs.py 项目: bup/bup
def test_duplicate_save_dates():
    with no_lingering_errors():
        with test_tempdir('bup-tvfs-') as tmpdir:
            bup_dir = tmpdir + '/bup'
            environ['GIT_DIR'] = bup_dir
            environ['BUP_DIR'] = bup_dir
            environ['TZ'] = 'UTC'
            git.repodir = bup_dir
            data_path = tmpdir + '/src'
            os.mkdir(data_path)
            with open(data_path + '/file', 'w+') as tmpfile:
                tmpfile.write(b'canary\n')
            ex((bup_path, 'init'))
            ex((bup_path, 'index', '-v', data_path))
            for i in range(11):
                ex((bup_path, 'save', '-d', '100000', '-n', 'test', data_path))
            repo = LocalRepo()
            res = vfs.resolve(repo, '/test')
            wvpasseq(2, len(res))
            name, revlist = res[-1]
            wvpasseq('test', name)
            wvpasseq(('.',
                      '1970-01-02-034640-00',
                      '1970-01-02-034640-01',
                      '1970-01-02-034640-02',
                      '1970-01-02-034640-03',
                      '1970-01-02-034640-04',
                      '1970-01-02-034640-05',
                      '1970-01-02-034640-06',
                      '1970-01-02-034640-07',
                      '1970-01-02-034640-08',
                      '1970-01-02-034640-09',
                      '1970-01-02-034640-10',
                      'latest'),
                     tuple(sorted(x[0] for x in vfs.contents(repo, revlist))))
示例#3
0
文件: fuse-cmd.py 项目: bup/bup
 def readlink(self, path):
     if self.verbose > 0:
         log('--readlink(%r)\n' % path)
     res = vfs.resolve(self.repo, path, follow=False)
     name, item = res[-1]
     if not item:
         return -errno.ENOENT
     return vfs.readlink(repo, item)
示例#4
0
文件: tvfs.py 项目: bup/bup
def test_misc():
    with no_lingering_errors():
        with test_tempdir('bup-tvfs-') as tmpdir:
            bup_dir = tmpdir + '/bup'
            environ['GIT_DIR'] = bup_dir
            environ['BUP_DIR'] = bup_dir
            git.repodir = bup_dir
            data_path = tmpdir + '/src'
            os.mkdir(data_path)
            with open(data_path + '/file', 'w+') as tmpfile:
                tmpfile.write(b'canary\n')
            symlink('file', data_path + '/symlink')
            ex((bup_path, 'init'))
            ex((bup_path, 'index', '-v', data_path))
            ex((bup_path, 'save', '-d', '100000', '-tvvn', 'test', '--strip',
                data_path))
            repo = LocalRepo()

            wvstart('readlink')
            ls_tree = exo(('git', 'ls-tree', 'test', 'symlink')).out
            mode, typ, oidx, name = ls_tree.strip().split(None, 3)
            assert name == 'symlink'
            link_item = vfs.Item(oid=oidx.decode('hex'), meta=int(mode, 8))
            wvpasseq('file', vfs.readlink(repo, link_item))

            ls_tree = exo(('git', 'ls-tree', 'test', 'file')).out
            mode, typ, oidx, name = ls_tree.strip().split(None, 3)
            assert name == 'file'
            file_item = vfs.Item(oid=oidx.decode('hex'), meta=int(mode, 8))
            wvexcept(Exception, vfs.readlink, repo, file_item)

            wvstart('item_size')
            wvpasseq(4, vfs.item_size(repo, link_item))
            wvpasseq(7, vfs.item_size(repo, file_item))
            meta = metadata.from_path(__file__)
            meta.size = 42
            fake_item = file_item._replace(meta=meta)
            wvpasseq(42, vfs.item_size(repo, fake_item))

            wvstart('augment_item_meta')
            run_augment_item_meta_tests(repo,
                                        '/test/latest/file', 7,
                                        '/test/latest/symlink', 'file')

            wvstart('copy_item')
            # FIXME: this caused StopIteration
            #_, file_item = vfs.resolve(repo, '/file')[-1]
            _, file_item = vfs.resolve(repo, '/test/latest/file')[-1]
            file_copy = vfs.copy_item(file_item)
            wvpass(file_copy is not file_item)
            wvpass(file_copy.meta is not file_item.meta)
            wvpass(isinstance(file_copy, tuple))
            wvpass(file_item.meta.user)
            wvpass(file_copy.meta.user)
            file_copy.meta.user = None
            wvpass(file_item.meta.user)
示例#5
0
文件: fuse-cmd.py 项目: bup/bup
 def read(self, path, size, offset):
     if self.verbose > 0:
         log('--read(%r)\n' % path)
     res = vfs.resolve(self.repo, path, follow=False)
     name, item = res[-1]
     if not item:
         return -errno.ENOENT
     with vfs.fopen(repo, item) as f:
         f.seek(offset)
         return f.read(size)
示例#6
0
文件: fuse-cmd.py 项目: bup/bup
 def open(self, path, flags):
     if self.verbose > 0:
         log('--open(%r)\n' % path)
     res = vfs.resolve(self.repo, path, follow=False)
     name, item = res[-1]
     if not item:
         return -errno.ENOENT
     accmode = os.O_RDONLY | os.O_WRONLY | os.O_RDWR
     if (flags & accmode) != os.O_RDONLY:
         return -errno.EACCES
示例#7
0
文件: fuse-cmd.py 项目: bup/bup
 def readdir(self, path, offset):
     assert not offset  # We don't return offsets, so offset should be unused
     res = vfs.resolve(self.repo, path, follow=False)
     dir_name, dir_item = res[-1]
     if not dir_item:
         yield -errno.ENOENT
     yield fuse.Direntry('..')
     # FIXME: make sure want_meta=False is being completely respected
     for ent_name, ent_item in vfs.contents(repo, dir_item, want_meta=False):
         yield fuse.Direntry(ent_name.replace('/', '-'))
示例#8
0
文件: tvfs.py 项目: mdedonno1337/bup
def run_augment_item_meta_tests(repo, file_path, file_size, link_path,
                                link_target):
    _, file_item = vfs.resolve(repo, file_path)[-1]
    _, link_item = vfs.lresolve(repo, link_path)[-1]
    wvpass(isinstance(file_item.meta, Metadata))
    wvpass(isinstance(link_item.meta, Metadata))
    # Note: normally, modifying item.meta values is forbidden
    file_item.meta.size = file_item.meta.size or vfs.item_size(repo, file_item)
    link_item.meta.size = link_item.meta.size or vfs.item_size(repo, link_item)

    ## Ensure a fully populated item is left alone
    augmented = vfs.augment_item_meta(repo, file_item)
    wvpass(augmented is file_item)
    wvpass(augmented.meta is file_item.meta)
    augmented = vfs.augment_item_meta(repo, file_item, include_size=True)
    wvpass(augmented is file_item)
    wvpass(augmented.meta is file_item.meta)

    ## Ensure a missing size is handled poperly
    file_item.meta.size = None
    augmented = vfs.augment_item_meta(repo, file_item)
    wvpass(augmented is file_item)
    wvpass(augmented.meta is file_item.meta)
    augmented = vfs.augment_item_meta(repo, file_item, include_size=True)
    wvpass(augmented is not file_item)
    wvpasseq(file_size, augmented.meta.size)

    ## Ensure a meta mode is handled properly
    mode_item = file_item._replace(meta=vfs.default_file_mode)
    augmented = vfs.augment_item_meta(repo, mode_item)
    augmented_w_size = vfs.augment_item_meta(repo,
                                             mode_item,
                                             include_size=True)
    for item in (augmented, augmented_w_size):
        meta = item.meta
        wvpass(item is not file_item)
        wvpass(isinstance(meta, Metadata))
        wvpasseq(vfs.default_file_mode, meta.mode)
        wvpasseq((0, 0, 0, 0, 0),
                 (meta.uid, meta.gid, meta.atime, meta.mtime, meta.ctime))
    wvpass(augmented.meta.size is None)
    wvpasseq(file_size, augmented_w_size.meta.size)

    ## Ensure symlinks are handled properly
    mode_item = link_item._replace(meta=vfs.default_symlink_mode)
    augmented = vfs.augment_item_meta(repo, mode_item)
    wvpass(augmented is not mode_item)
    wvpass(isinstance(augmented.meta, Metadata))
    wvpasseq(link_target, augmented.meta.symlink_target)
    wvpasseq(len(link_target), augmented.meta.size)
    augmented = vfs.augment_item_meta(repo, mode_item, include_size=True)
    wvpass(augmented is not mode_item)
    wvpass(isinstance(augmented.meta, Metadata))
    wvpasseq(link_target, augmented.meta.symlink_target)
    wvpasseq(len(link_target), augmented.meta.size)
示例#9
0
文件: cat_file.py 项目: fakegit/bup
def main(argv):
    o = options.Options(optspec)
    opt, flags, extra = o.parse_bytes(argv[1:])

    git.check_repo_or_die()

    if not extra:
        o.fatal('must specify a target')
    if len(extra) > 1:
        o.fatal('only one target file allowed')
    if opt.bupm and opt.meta:
        o.fatal('--meta and --bupm are incompatible')

    target = argv_bytes(extra[0])

    if not re.match(br'/*[^/]+/[^/]+', target):
        o.fatal("path %r doesn't include a branch and revision" % target)

    with LocalRepo() as repo:
        resolved = vfs.resolve(repo, target, follow=False)
        leaf_name, leaf_item = resolved[-1]
        if not leaf_item:
            log('error: cannot access %r in %r\n' %
                (b'/'.join(name for name, item in resolved), target))
            sys.exit(1)

        mode = vfs.item_mode(leaf_item)

        sys.stdout.flush()
        out = byte_stream(sys.stdout)

        if opt.bupm:
            if not stat.S_ISDIR(mode):
                o.fatal('%r is not a directory' % target)
            _, bupm_oid = vfs.tree_data_and_bupm(repo, leaf_item.oid)
            if bupm_oid:
                with vfs.tree_data_reader(repo, bupm_oid) as meta_stream:
                    out.write(meta_stream.read())
        elif opt.meta:
            augmented = vfs.augment_item_meta(repo,
                                              leaf_item,
                                              include_size=True)
            out.write(augmented.meta.encode())
        else:
            if stat.S_ISREG(mode):
                with vfs.fopen(repo, leaf_item) as f:
                    for b in chunkyreader(f):
                        out.write(b)
            else:
                o.fatal('%r is not a plain file' % target)

    if saved_errors:
        log('warning: %d errors encountered\n' % len(saved_errors))
        sys.exit(1)
示例#10
0
 def read(self, path, size, offset):
     path = argv_bytes(path)
     if self.verbose > 0:
         log('--read(%r)\n' % path)
     res = vfs.resolve(self.repo, path, follow=False)
     name, item = res[-1]
     if not item:
         return -errno.ENOENT
     with vfs.fopen(self.repo, item) as f:
         f.seek(offset)
         return f.read(size)
示例#11
0
 def readdir(self, path, offset):
     assert not offset  # We don't return offsets, so offset should be unused
     res = vfs.resolve(self.repo, path, follow=False)
     dir_name, dir_item = res[-1]
     if not dir_item:
         yield -errno.ENOENT
     yield fuse.Direntry('..')
     # FIXME: make sure want_meta=False is being completely respected
     for ent_name, ent_item in vfs.contents(repo, dir_item,
                                            want_meta=False):
         yield fuse.Direntry(ent_name.replace('/', '-'))
示例#12
0
 def open(self, path, flags):
     path = argv_bytes(path)
     if self.verbose > 0:
         log('--open(%r)\n' % path)
     res = vfs.resolve(self.repo, path, follow=False)
     name, item = res[-1]
     if not item:
         return -errno.ENOENT
     accmode = os.O_RDONLY | os.O_WRONLY | os.O_RDWR
     if (flags & accmode) != os.O_RDONLY:
         return -errno.EACCES
示例#13
0
文件: ftp-cmd.py 项目: bup/bup
def _completer_get_subs(repo, line):
    (qtype, lastword) = shquote.unfinished_word(line)
    (dir,name) = os.path.split(lastword)
    dir_path = vfs.resolve(repo, dir or '/')
    _, dir_item = dir_path[-1]
    if not dir_item:
        subs = tuple()
    else:
        subs = tuple(dir_path + (entry,)
                     for entry in vfs.contents(repo, dir_item)
                     if (entry[0] != '.' and entry[0].startswith(name)))
    return dir, name, qtype, lastword, subs
示例#14
0
文件: ftp-cmd.py 项目: zeonin/bup
def _completer_get_subs(repo, line):
    (qtype, lastword) = shquote.unfinished_word(line)
    dir, name = os.path.split(lastword)
    dir_path = vfs.resolve(repo, dir or b'/')
    _, dir_item = dir_path[-1]
    if not dir_item:
        subs = tuple()
    else:
        subs = tuple(dir_path + (entry, )
                     for entry in vfs.contents(repo, dir_item)
                     if (entry[0] != b'.' and entry[0].startswith(name)))
    return qtype, lastword, subs
示例#15
0
 def open(self, path, flags):
     path = argv_bytes(path)
     if self.verbose > 0:
         log('--open(%r)\n' % path)
     res = vfs.resolve(self.repo, path, follow=False)
     name, item = res[-1]
     if not item:
         return -errno.ENOENT
     accmode = os.O_RDONLY | os.O_WRONLY | os.O_RDWR
     if (flags & accmode) != os.O_RDONLY:
         return -errno.EACCES
     # Return None since read doesn't need the file atm...
     # If we *do* return the file, it'll show up as the last argument
     #return vfs.fopen(repo, item)
     return None
示例#16
0
 def _process_request(self, path):
     print('Handling request for %s' % path)
     sys.stdout.flush()
     # Set want_meta because dir metadata won't be fetched, and if
     # it's not a dir, then we're going to want the metadata.
     res = vfs.resolve(self.repo, path, want_meta=True)
     leaf_name, leaf_item = res[-1]
     if not leaf_item:
         self.send_error(404)
         return
     mode = vfs.item_mode(leaf_item)
     if stat.S_ISDIR(mode):
         self._list_directory(path, res)
     else:
         self._get_file(self.repo, path, res)
示例#17
0
文件: web-cmd.py 项目: bup/bup
 def _process_request(self, path):
     path = urllib.unquote(path)
     print('Handling request for %s' % path)
     # Set want_meta because dir metadata won't be fetched, and if
     # it's not a dir, then we're going to want the metadata.
     res = vfs.resolve(self.repo, path, want_meta=True)
     leaf_name, leaf_item = res[-1]
     if not leaf_item:
         self.send_error(404)
         return
     mode = vfs.item_mode(leaf_item)
     if stat.S_ISDIR(mode):
         self._list_directory(path, res)
     else:
         self._get_file(self.repo, path, res)
示例#18
0
def test_contents_with_mismatched_bupm_git_ordering():
    with no_lingering_errors():
        with test_tempdir(b'bup-tvfs-') as tmpdir:
            bup_dir = tmpdir + b'/bup'
            environ[b'GIT_DIR'] = bup_dir
            environ[b'BUP_DIR'] = bup_dir
            git.repodir = bup_dir
            data_path = tmpdir + b'/src'
            os.mkdir(data_path)
            os.mkdir(data_path + b'/foo')
            with open(data_path + b'/foo.', 'wb+') as tmpfile:
                tmpfile.write(b'canary\n')
            ex((bup_path, b'init'))
            ex((bup_path, b'index', b'-v', data_path))
            save_utc = 100000
            save_name = strftime('%Y-%m-%d-%H%M%S',
                                 localtime(save_utc)).encode('ascii')
            ex((bup_path, b'save', b'-tvvn', b'test', b'-d', b'%d' % save_utc,
                b'--strip', data_path))
            repo = LocalRepo()
            tip_sref = exo((b'git', b'show-ref', b'refs/heads/test')).out
            tip_oidx = tip_sref.strip().split()[0]
            tip_tree_oidx = exo((b'git', b'log', b'--pretty=%T', b'-n1',
                                 tip_oidx)).out.strip()
            tip_tree_oid = unhexlify(tip_tree_oidx)
            tip_tree = tree_dict(repo, tip_tree_oid)

            name, item = vfs.resolve(repo, b'/test/latest')[2]
            wvpasseq(save_name, name)
            expected = frozenset(
                (x.name, vfs.Item(oid=x.oid, meta=x.meta))
                for x in (tip_tree[name] for name in (b'.', b'foo', b'foo.')))
            contents = tuple(vfs.contents(repo, item))
            wvpasseq(expected, frozenset(contents))
            # Spot check, in case tree_dict shares too much code with the vfs
            name, item = next(((n, i) for n, i in contents if n == b'foo'))
            wvpass(S_ISDIR(item.meta))
            name, item = next(((n, i) for n, i in contents if n == b'foo.'))
            wvpass(S_ISREG(item.meta.mode))
示例#19
0
def test_metadata_method():
    with no_lingering_errors():
        with test_tempdir(b'bup-tmetadata-') as tmpdir:
            bup_dir = tmpdir + b'/bup'
            data_path = tmpdir + b'/foo'
            os.mkdir(data_path)
            ex(b'touch', data_path + b'/file')
            ex(b'ln', b'-s', b'file', data_path + b'/symlink')
            test_time1 = 13 * 1000000000
            test_time2 = 42 * 1000000000
            utime(data_path + b'/file', (0, test_time1))
            lutime(data_path + b'/symlink', (0, 0))
            utime(data_path, (0, test_time2))
            ex(bup_path, b'-d', bup_dir, b'init')
            ex(bup_path, b'-d', bup_dir, b'index', b'-v', data_path)
            ex(bup_path, b'-d', bup_dir, b'save', b'-tvvn', b'test', data_path)
            git.check_repo_or_die(bup_dir)
            repo = LocalRepo()
            resolved = vfs.resolve(repo,
                                   b'/test/latest' + resolve_parent(data_path),
                                   follow=False)
            leaf_name, leaf_item = resolved[-1]
            m = leaf_item.meta
            WVPASS(m.mtime == test_time2)
            WVPASS(leaf_name == b'foo')
            contents = tuple(vfs.contents(repo, leaf_item))
            WVPASS(len(contents) == 3)
            WVPASSEQ(frozenset(name for name, item in contents),
                     frozenset((b'.', b'file', b'symlink')))
            for name, item in contents:
                if name == b'file':
                    m = item.meta
                    WVPASS(m.mtime == test_time1)
                elif name == b'symlink':
                    m = item.meta
                    WVPASSEQ(m.symlink_target, b'file')
                    WVPASSEQ(m.size, 4)
                    WVPASSEQ(m.mtime, 0)
示例#20
0
文件: tvfs.py 项目: presto8/bup
def test_duplicate_save_dates():
    with no_lingering_errors():
        with test_tempdir(b'bup-tvfs-') as tmpdir:
            bup_dir = tmpdir + b'/bup'
            environ[b'GIT_DIR'] = bup_dir
            environ[b'BUP_DIR'] = bup_dir
            environ[b'TZ'] = b'UTC'
            tzset()
            git.repodir = bup_dir
            data_path = tmpdir + b'/src'
            os.mkdir(data_path)
            with open(data_path + b'/file', 'wb+') as tmpfile:
                tmpfile.write(b'canary\n')
            ex((b'env',))
            ex((bup_path, b'init'))
            ex((bup_path, b'index', b'-v', data_path))
            for i in range(11):
                ex((bup_path, b'save', b'-d', b'100000', b'-n', b'test',
                    data_path))
            repo = LocalRepo()
            res = vfs.resolve(repo, b'/test')
            wvpasseq(2, len(res))
            name, revlist = res[-1]
            wvpasseq(b'test', name)
            wvpasseq((b'.',
                      b'1970-01-02-034640-00',
                      b'1970-01-02-034640-01',
                      b'1970-01-02-034640-02',
                      b'1970-01-02-034640-03',
                      b'1970-01-02-034640-04',
                      b'1970-01-02-034640-05',
                      b'1970-01-02-034640-06',
                      b'1970-01-02-034640-07',
                      b'1970-01-02-034640-08',
                      b'1970-01-02-034640-09',
                      b'1970-01-02-034640-10',
                      b'latest'),
                     tuple(sorted(x[0] for x in vfs.contents(repo, revlist))))
示例#21
0
文件: tmetadata.py 项目: bup/bup
def test_metadata_method():
    with no_lingering_errors():
        with test_tempdir('bup-tmetadata-') as tmpdir:
            bup_dir = tmpdir + '/bup'
            data_path = tmpdir + '/foo'
            os.mkdir(data_path)
            ex('touch', data_path + '/file')
            ex('ln', '-s', 'file', data_path + '/symlink')
            test_time1 = 13 * 1000000000
            test_time2 = 42 * 1000000000
            utime(data_path + '/file', (0, test_time1))
            lutime(data_path + '/symlink', (0, 0))
            utime(data_path, (0, test_time2))
            ex(bup_path, '-d', bup_dir, 'init')
            ex(bup_path, '-d', bup_dir, 'index', '-v', data_path)
            ex(bup_path, '-d', bup_dir, 'save', '-tvvn', 'test', data_path)
            git.check_repo_or_die(bup_dir)
            repo = LocalRepo()
            resolved = vfs.resolve(repo,
                                   '/test/latest' + resolve_parent(data_path),
                                   follow=False)
            leaf_name, leaf_item = resolved[-1]
            m = leaf_item.meta
            WVPASS(m.mtime == test_time2)
            WVPASS(leaf_name == 'foo')
            contents = tuple(vfs.contents(repo, leaf_item))
            WVPASS(len(contents) == 3)
            WVPASSEQ(frozenset(name for name, item in contents),
                     frozenset(('.', 'file', 'symlink')))
            for name, item in contents:
                if name == 'file':
                    m = item.meta
                    WVPASS(m.mtime == test_time1)
                elif name == 'symlink':
                    m = item.meta
                    WVPASSEQ(m.symlink_target, 'file')
                    WVPASSEQ(m.size, 4)
                    WVPASSEQ(m.mtime, 0)
示例#22
0
文件: tvfs.py 项目: bup/bup
def test_contents_with_mismatched_bupm_git_ordering():
    with no_lingering_errors():
        with test_tempdir('bup-tvfs-') as tmpdir:
            bup_dir = tmpdir + '/bup'
            environ['GIT_DIR'] = bup_dir
            environ['BUP_DIR'] = bup_dir
            git.repodir = bup_dir
            data_path = tmpdir + '/src'
            os.mkdir(data_path)
            os.mkdir(data_path + '/foo')
            with open(data_path + '/foo.', 'w+') as tmpfile:
                tmpfile.write(b'canary\n')
            ex((bup_path, 'init'))
            ex((bup_path, 'index', '-v', data_path))
            save_utc = 100000
            save_name = strftime('%Y-%m-%d-%H%M%S', localtime(save_utc))
            ex((bup_path, 'save', '-tvvn', 'test', '-d', str(save_utc),
                '--strip', data_path))
            repo = LocalRepo()
            tip_sref = exo(('git', 'show-ref', 'refs/heads/test')).out
            tip_oidx = tip_sref.strip().split()[0]
            tip_tree_oidx = exo(('git', 'log', '--pretty=%T', '-n1',
                                 tip_oidx)).out.strip()
            tip_tree_oid = tip_tree_oidx.decode('hex')
            tip_tree = tree_dict(repo, tip_tree_oid)

            name, item = vfs.resolve(repo, '/test/latest')[2]
            wvpasseq(save_name, name)
            expected = frozenset((x.name, vfs.Item(oid=x.oid, meta=x.meta))
                                 for x in (tip_tree[name]
                                           for name in ('.', 'foo', 'foo.')))
            contents = tuple(vfs.contents(repo, item))
            wvpasseq(expected, frozenset(contents))
            # Spot check, in case tree_dict shares too much code with the vfs
            name, item = next(((n, i) for n, i in contents if n == 'foo'))
            wvpass(S_ISDIR(item.meta))
            name, item = next(((n, i) for n, i in contents if n == 'foo.'))
            wvpass(S_ISREG(item.meta.mode))
示例#23
0
def resolve(conn, args):
    _init_session()
    (flags,) = args.split()
    flags = int(flags)
    want_meta = bool(flags & 1)
    follow = bool(flags & 2)
    have_parent = bool(flags & 4)
    parent = vfs.read_resolution(conn) if have_parent else None
    path = vint.read_bvec(conn)
    if not len(path):
        raise Exception('Empty resolve path')
    try:
        res = list(vfs.resolve(repo, path, parent=parent, want_meta=want_meta,
                               follow=follow))
    except vfs.IOError as ex:
        res = ex
    if isinstance(res, vfs.IOError):
        conn.write(b'\x00')  # error
        vfs.write_ioerror(conn, res)
    else:
        conn.write(b'\x01')  # success
        vfs.write_resolution(conn, res)
    conn.ok()
示例#24
0
def dead_items(repo, paths):
    """Return an optimized set of removals, reporting errors via
    add_error, and if there are any errors, return None, None."""
    dead_branches = {}
    dead_saves = {}
    # Scan for bad requests, and opportunities to optimize
    for path in paths:
        try:
            resolved = vfs.resolve(repo, path, follow=False)
        except vfs.IOError as e:
            add_error(e)
            continue
        else:
            leaf_name, leaf_item = resolved[-1]
            if not leaf_item:
                add_error('error: cannot access %s in %s' % (path_msg(
                    b'/'.join(name
                              for name, item in resolved)), path_msg(path)))
                continue
            if isinstance(leaf_item, vfs.RevList):  # rm /foo
                branchname = leaf_name
                dead_branches[branchname] = leaf_item
                dead_saves.pop(branchname,
                               None)  # rm /foo obviates rm /foo/bar
            elif isinstance(leaf_item, vfs.Commit):  # rm /foo/bar
                if leaf_name == b'latest':
                    add_error("error: cannot delete 'latest' symlink")
                else:
                    branchname, branchitem = resolved[-2]
                    if branchname not in dead_branches:
                        dead = leaf_item, branchitem
                        dead_saves.setdefault(branchname, []).append(dead)
            else:
                add_error("don't know how to remove %s yet" % path_msg(path))
    if saved_errors:
        return None, None
    return dead_branches, dead_saves
示例#25
0
 def getattr(self, path):
     path = argv_bytes(path)
     if self.verbose > 0:
         log('--getattr(%r)\n' % path)
     res = vfs.resolve(self.repo, path, want_meta=(not self.fake_metadata),
                       follow=False)
     name, item = res[-1]
     if not item:
         return -errno.ENOENT
     if self.fake_metadata:
         item = vfs.augment_item_meta(self.repo, item, include_size=True)
     else:
         item = vfs.ensure_item_has_metadata(self.repo, item,
                                             include_size=True)
     meta = item.meta
     # FIXME: do we want/need to do anything more with nlink?
     st = fuse.Stat(st_mode=meta.mode, st_nlink=1, st_size=meta.size)
     st.st_mode = meta.mode
     st.st_uid = meta.uid or 0
     st.st_gid = meta.gid or 0
     st.st_atime = max(0, xstat.fstime_floor_secs(meta.atime))
     st.st_mtime = max(0, xstat.fstime_floor_secs(meta.mtime))
     st.st_ctime = max(0, xstat.fstime_floor_secs(meta.ctime))
     return st
示例#26
0
文件: rm.py 项目: bup/bup
def dead_items(repo, paths):
    """Return an optimized set of removals, reporting errors via
    add_error, and if there are any errors, return None, None."""
    dead_branches = {}
    dead_saves = {}
    # Scan for bad requests, and opportunities to optimize
    for path in paths:
        try:
            resolved = vfs.resolve(repo, path, follow=False)
        except vfs.IOError as e:
            add_error(e)
            continue
        else:
            leaf_name, leaf_item = resolved[-1]
            if not leaf_item:
                add_error('error: cannot access %r in %r'
                          % ('/'.join(name for name, item in resolved),
                             path))
                continue
            if isinstance(leaf_item, vfs.RevList):  # rm /foo
                branchname = leaf_name
                dead_branches[branchname] = leaf_item
                dead_saves.pop(branchname, None)  # rm /foo obviates rm /foo/bar
            elif isinstance(leaf_item, vfs.Commit):  # rm /foo/bar
                if leaf_name == 'latest':
                    add_error("error: cannot delete 'latest' symlink")
                else:
                    branchname, branchitem = resolved[-2]
                    if branchname not in dead_branches:
                        dead = leaf_item, branchitem
                        dead_saves.setdefault(branchname, []).append(dead)
            else:
                add_error("don't know how to remove %r yet" % path)
    if saved_errors:
        return None, None
    return dead_branches, dead_saves
示例#27
0
文件: fuse-cmd.py 项目: bup/bup
 def getattr(self, path):
     global opt
     if self.verbose > 0:
         log('--getattr(%r)\n' % path)
     res = vfs.resolve(self.repo, path, want_meta=(not self.fake_metadata),
                       follow=False)
     name, item = res[-1]
     if not item:
         return -errno.ENOENT
     if self.fake_metadata:
         item = vfs.augment_item_meta(self.repo, item, include_size=True)
     else:
         item = vfs.ensure_item_has_metadata(self.repo, item,
                                             include_size=True)
     meta = item.meta
     # FIXME: do we want/need to do anything more with nlink?
     st = fuse.Stat(st_mode=meta.mode, st_nlink=1, st_size=meta.size)
     st.st_mode = meta.mode
     st.st_uid = meta.uid
     st.st_gid = meta.gid
     st.st_atime = max(0, xstat.fstime_floor_secs(meta.atime))
     st.st_mtime = max(0, xstat.fstime_floor_secs(meta.mtime))
     st.st_ctime = max(0, xstat.fstime_floor_secs(meta.ctime))
     return st
示例#28
0
文件: ftp-cmd.py 项目: zeonin/bup
        log('\nError in completion: %s\n' % e)


optspec = """
bup ftp [commands...]
"""
o = options.Options(optspec)
opt, flags, extra = o.parse(compat.argv[1:])

git.check_repo_or_die()

sys.stdout.flush()
out = byte_stream(sys.stdout)
stdin = byte_stream(sys.stdin)
repo = LocalRepo()
pwd = vfs.resolve(repo, b'/')
rv = 0

if extra:
    lines = (argv_bytes(arg) for arg in extra)
else:
    if hasattr(_helpers, 'readline'):
        _helpers.set_completer_word_break_characters(b' \t\n\r/')
        _helpers.set_attempted_completion_function(attempt_completion)
        _helpers.set_completion_entry_function(enter_completion)
        if sys.platform.startswith('darwin'):
            # MacOS uses a slightly incompatible clone of libreadline
            _helpers.parse_and_bind(b'bind ^I rl_complete')
        _helpers.parse_and_bind(b'tab: complete')
    lines = inputiter()
示例#29
0
文件: cat-file-cmd.py 项目: bup/bup
git.check_repo_or_die()

if not extra:
    o.fatal('must specify a target')
if len(extra) > 1:
    o.fatal('only one target file allowed')
if opt.bupm and opt.meta:
    o.fatal('--meta and --bupm are incompatible')
    
target = extra[0]

if not re.match(r'/*[^/]+/[^/]+', target):
    o.fatal("path %r doesn't include a branch and revision" % target)

repo = LocalRepo()
resolved = vfs.resolve(repo, target, follow=False)
leaf_name, leaf_item = resolved[-1]
if not leaf_item:
    log('error: cannot access %r in %r\n'
        % ('/'.join(name for name, item in resolved), path))
    sys.exit(1)

mode = vfs.item_mode(leaf_item)

if opt.bupm:
    if not stat.S_ISDIR(mode):
        o.fatal('%r is not a directory' % target)
    _, bupm_oid = vfs.tree_data_and_bupm(repo, leaf_item.oid)
    if bupm_oid:
        with vfs.tree_data_reader(repo, bupm_oid) as meta_stream:
            sys.stdout.write(meta_stream.read())
示例#30
0
文件: restore-cmd.py 项目: bup/bup
def main():
    o = options.Options(optspec)
    opt, flags, extra = o.parse(sys.argv[1:])
    verbosity = opt.verbose if not opt.quiet else -1
    
    git.check_repo_or_die()

    if not extra:
        o.fatal('must specify at least one filename to restore')

    exclude_rxs = parse_rx_excludes(flags, o.fatal)

    owner_map = {}
    for map_type in ('user', 'group', 'uid', 'gid'):
        owner_map[map_type] = parse_owner_mappings(map_type, flags, o.fatal)

    if opt.outdir:
        mkdirp(opt.outdir)
        os.chdir(opt.outdir)

    repo = RemoteRepo(opt.remote) if opt.remote else LocalRepo()
    top = os.getcwd()
    hardlinks = {}
    for path in extra:
        if not valid_restore_path(path):
            add_error("path %r doesn't include a branch and revision" % path)
            continue
        try:
            resolved = vfs.resolve(repo, path, want_meta=True, follow=False)
        except vfs.IOError as e:
            add_error(e)
            continue
        if len(resolved) == 3 and resolved[2][0] == 'latest':
            # Follow latest symlink to the actual save
            try:
                resolved = vfs.resolve(repo, 'latest', parent=resolved[:-1],
                                       want_meta=True)
            except vfs.IOError as e:
                add_error(e)
                continue
            # Rename it back to 'latest'
            resolved = tuple(elt if i != 2 else ('latest',) + elt[1:]
                             for i, elt in enumerate(resolved))
        path_parent, path_name = os.path.split(path)
        leaf_name, leaf_item = resolved[-1]
        if not leaf_item:
            add_error('error: cannot access %r in %r'
                      % ('/'.join(name for name, item in resolved),
                         path))
            continue
        if not path_name or path_name == '.':
            # Source is /foo/what/ever/ or /foo/what/ever/. -- extract
            # what/ever/* to the current directory, and if name == '.'
            # (i.e. /foo/what/ever/.), then also restore what/ever's
            # metadata to the current directory.
            treeish = vfs.item_mode(leaf_item)
            if not treeish:
                add_error('%r cannot be restored as a directory' % path)
            else:
                items = vfs.contents(repo, leaf_item, want_meta=True)
                dot, leaf_item = next(items, None)
                assert(dot == '.')
                for sub_name, sub_item in items:
                    restore(repo, '', sub_name, sub_item, top,
                            opt.sparse, opt.numeric_ids, owner_map,
                            exclude_rxs, verbosity, hardlinks)
                if path_name == '.':
                    leaf_item = vfs.augment_item_meta(repo, leaf_item,
                                                      include_size=True)
                    apply_metadata(leaf_item.meta, '.',
                                   opt.numeric_ids, owner_map)
        else:
            restore(repo, '', leaf_name, leaf_item, top,
                    opt.sparse, opt.numeric_ids, owner_map,
                    exclude_rxs, verbosity, hardlinks)

    if verbosity >= 0:
        progress('Restoring: %d, done.\n' % total_restored)
    die_if_errors()
示例#31
0
文件: ftp-cmd.py 项目: bup/bup
            traceback.print_tb(sys.exc_traceback)
        except Exception as e2:
            log('Error printing traceback: %s\n' % e2)
        log('\nError in completion: %s\n' % e)


optspec = """
bup ftp [commands...]
"""
o = options.Options(optspec)
(opt, flags, extra) = o.parse(sys.argv[1:])

git.check_repo_or_die()

repo = LocalRepo()
pwd = vfs.resolve(repo, '/')
rv = 0

if extra:
    lines = extra
else:
    try:
        import readline
    except ImportError:
        log('* readline module not available: line editing disabled.\n')
        readline = None

    if readline:
        readline.set_completer_delims(' \t\n\r/')
        readline.set_completer(completer)
        if sys.platform.startswith('darwin'):
示例#32
0
            log('Error printing traceback: %s\n' % e2)
        log('\nError in completion: %s\n' % e)


optspec = """
bup ftp [commands...]
"""
o = options.Options(optspec)
(opt, flags, extra) = o.parse(sys.argv[1:])

git.check_repo_or_die()

sys.stdout.flush()
out = byte_stream(sys.stdout)
repo = LocalRepo()
pwd = vfs.resolve(repo, b'/')
rv = 0

if extra:
    lines = extra
else:
    try:
        import readline
    except ImportError:
        log('* readline module not available: line editing disabled.\n')
        readline = None

    if readline:
        readline.set_completer_delims(' \t\n\r/')
        readline.set_completer(completer)
        if sys.platform.startswith('darwin'):
示例#33
0
def present_interface(stdin, out, extra, repo):
    pwd = vfs.resolve(repo, b'/')

    if extra:
        lines = (argv_bytes(arg) for arg in extra)
    else:
        if hasattr(_helpers, 'readline'):
            _helpers.set_completer_word_break_characters(b' \t\n\r/')
            _helpers.set_attempted_completion_function(attempt_completion)
            _helpers.set_completion_entry_function(enter_completion)
            if sys.platform.startswith('darwin'):
                # MacOS uses a slightly incompatible clone of libreadline
                _helpers.parse_and_bind(b'bind ^I rl_complete')
            _helpers.parse_and_bind(b'tab: complete')
        lines = inputiter(stdin, pwd, out)

    for line in lines:
        if not line.strip():
            continue
        words = [word for (wordstart, word) in shquote.quotesplit(line)]
        cmd = words[0].lower()
        #log('execute: %r %r\n' % (cmd, parm))
        try:
            if cmd == b'ls':
                do_ls(repo, pwd, words[1:], out)
                out.flush()
            elif cmd == b'cd':
                np = pwd
                for parm in words[1:]:
                    res = vfs.resolve(repo, parm, parent=np)
                    _, leaf_item = res[-1]
                    if not leaf_item:
                        raise CommandError('path does not exist: ' +
                                           rpath_msg(res))
                    if not stat.S_ISDIR(vfs.item_mode(leaf_item)):
                        raise CommandError('path is not a directory: ' +
                                           path_msg(parm))
                    np = res
                pwd = np
            elif cmd == b'pwd':
                if len(pwd) == 1:
                    out.write(b'/')
                out.write(b'/'.join(name for name, item in pwd) + b'\n')
                out.flush()
            elif cmd == b'cat':
                for parm in words[1:]:
                    res = vfs.resolve(repo, parm, parent=pwd)
                    _, leaf_item = res[-1]
                    if not leaf_item:
                        raise CommandError('path does not exist: ' +
                                           rpath_msg(res))
                    with vfs.fopen(repo, leaf_item) as srcfile:
                        write_to_file(srcfile, out)
                out.flush()
            elif cmd == b'get':
                if len(words) not in [2, 3]:
                    raise CommandError('Usage: get <filename> [localname]')
                rname = words[1]
                (dir, base) = os.path.split(rname)
                lname = len(words) > 2 and words[2] or base
                res = vfs.resolve(repo, rname, parent=pwd)
                _, leaf_item = res[-1]
                if not leaf_item:
                    raise CommandError('path does not exist: ' +
                                       rpath_msg(res))
                with vfs.fopen(repo, leaf_item) as srcfile:
                    with open(lname, 'wb') as destfile:
                        log('Saving %s\n' % path_msg(lname))
                        write_to_file(srcfile, destfile)
            elif cmd == b'mget':
                for parm in words[1:]:
                    dir, base = os.path.split(parm)

                    res = vfs.resolve(repo, dir, parent=pwd)
                    _, dir_item = res[-1]
                    if not dir_item:
                        raise CommandError('path does not exist: ' +
                                           path_msg(dir))
                    for name, item in vfs.contents(repo, dir_item):
                        if name == b'.':
                            continue
                        if fnmatch.fnmatch(name, base):
                            if stat.S_ISLNK(vfs.item_mode(item)):
                                deref = vfs.resolve(repo, name, parent=res)
                                deref_name, deref_item = deref[-1]
                                if not deref_item:
                                    raise CommandError(
                                        'path does not exist: ' +
                                        rpath_msg(res))
                                item = deref_item
                            with vfs.fopen(repo, item) as srcfile:
                                with open(name, 'wb') as destfile:
                                    log('Saving %s\n' % path_msg(name))
                                    write_to_file(srcfile, destfile)
            elif cmd in (b'help', b'?'):
                out.write(b'Commands: ls cd pwd cat get mget help quit\n')
                out.flush()
            elif cmd in (b'quit', b'exit', b'bye'):
                break
            else:
                raise CommandError('no such command: ' +
                                   cmd.encode(errors='backslashreplace'))
        except CommandError as ex:
            out.write(b'error: %s\n' %
                      str(ex).encode(errors='backslashreplace'))
            out.flush()
示例#34
0
文件: ls.py 项目: westes/bup
def within_repo(repo, opt):

    if opt.commit_hash:
        opt.hash = True

    def item_line(item, name):
        return item_info(item,
                         name,
                         show_hash=opt.hash,
                         commit_hash=opt.commit_hash,
                         long_fmt=opt.long_listing,
                         classification=opt.classification,
                         numeric_ids=opt.numeric_ids,
                         human_readable=opt.human_readable)

    ret = 0
    pending = []
    for path in opt.paths:
        try:
            if opt.directory:
                resolved = vfs.resolve(repo, path, follow=False)
            else:
                resolved = vfs.try_resolve(repo, path)

            leaf_name, leaf_item = resolved[-1]
            if not leaf_item:
                log('error: cannot access %r in %r\n' %
                    ('/'.join(name for name, item in resolved), path))
                ret = 1
                continue
            if not opt.directory and S_ISDIR(vfs.item_mode(leaf_item)):
                items = vfs.contents(repo, leaf_item)
                if opt.show_hidden == 'all':
                    # Match non-bup "ls -a ... /".
                    parent = resolved[-2] if len(resolved) > 1 else resolved[0]
                    items = chain(items, (('..', parent[1]), ))
                for sub_name, sub_item in sorted(items, key=lambda x: x[0]):
                    if opt.show_hidden != 'all' and sub_name == '.':
                        continue
                    if sub_name.startswith('.') and \
                       opt.show_hidden not in ('almost', 'all'):
                        continue
                    if opt.l:
                        sub_item = vfs.ensure_item_has_metadata(
                            repo, sub_item, include_size=True)
                    else:
                        sub_item = vfs.augment_item_meta(repo,
                                                         sub_item,
                                                         include_size=True)
                    line = item_line(sub_item, sub_name)
                    if not opt.long_listing and istty1:
                        pending.append(line)
                    else:
                        print(line)
            else:
                leaf_item = vfs.augment_item_meta(repo,
                                                  leaf_item,
                                                  include_size=True)
                line = item_line(leaf_item, os.path.normpath(path))
                if not opt.long_listing and istty1:
                    pending.append(line)
                else:
                    print(line)
        except vfs.IOError as ex:
            log('bup: %s\n' % ex)
            ret = 1

    if pending:
        sys.stdout.write(columnate(pending, ''))

    return ret
示例#35
0
文件: ls.py 项目: bup/bup
def within_repo(repo, opt):

    if opt.commit_hash:
        opt.hash = True

    def item_line(item, name):
        return item_info(item, name,
                         show_hash=opt.hash,
                         commit_hash=opt.commit_hash,
                         long_fmt=opt.long_listing,
                         classification=opt.classification,
                         numeric_ids=opt.numeric_ids,
                         human_readable=opt.human_readable)

    ret = 0
    pending = []
    for path in opt.paths:
        try:
            if opt.directory:
                resolved = vfs.resolve(repo, path, follow=False)
            else:
                resolved = vfs.try_resolve(repo, path)

            leaf_name, leaf_item = resolved[-1]
            if not leaf_item:
                log('error: cannot access %r in %r\n'
                    % ('/'.join(name for name, item in resolved),
                       path))
                ret = 1
                continue
            if not opt.directory and S_ISDIR(vfs.item_mode(leaf_item)):
                items = vfs.contents(repo, leaf_item)
                if opt.show_hidden == 'all':
                    # Match non-bup "ls -a ... /".
                    parent = resolved[-2] if len(resolved) > 1 else resolved[0]
                    items = chain(items, (('..', parent[1]),))
                for sub_name, sub_item in sorted(items, key=lambda x: x[0]):
                    if opt.show_hidden != 'all' and sub_name == '.':
                        continue
                    if sub_name.startswith('.') and \
                       opt.show_hidden not in ('almost', 'all'):
                        continue
                    if opt.l:
                        sub_item = vfs.ensure_item_has_metadata(repo, sub_item,
                                                                include_size=True)
                    else:
                        sub_item = vfs.augment_item_meta(repo, sub_item,
                                                         include_size=True)
                    line = item_line(sub_item, sub_name)
                    if not opt.long_listing and istty1:
                        pending.append(line)
                    else:
                        print(line)
            else:
                leaf_item = vfs.augment_item_meta(repo, leaf_item,
                                                  include_size=True)
                line = item_line(leaf_item, os.path.normpath(path))
                if not opt.long_listing and istty1:
                    pending.append(line)
                else:
                    print(line)
        except vfs.IOError as ex:
            log('bup: %s\n' % ex)
            ret = 1

    if pending:
        sys.stdout.write(columnate(pending, ''))

    return ret
示例#36
0
文件: ftp.py 项目: jmberg/bup
def main(argv):
    o = options.Options(optspec)
    opt, flags, extra = o.parse_bytes(argv[1:])

    global repo

    repo = from_opts(opt, reverse=False)

    sys.stdout.flush()
    out = byte_stream(sys.stdout)
    stdin = byte_stream(sys.stdin)
    pwd = vfs.resolve(repo, b'/')
    rv = 0

    def inputiter(f):
        if os.isatty(f.fileno()):
            while 1:
                prompt = b'bup %s> ' % (b'/'.join(name for name, item in pwd) or b'/', )
                if hasattr(_helpers, 'readline'):
                    try:
                        yield _helpers.readline(prompt)
                    except EOFError:
                        print()  # Clear the line for the terminal's next prompt
                        break
                else:
                    out.write(prompt)
                    out.flush()
                    read_line = f.readline()
                    if not read_line:
                        print('')
                        break
                    yield read_line
        else:
            for line in f:
                yield line


    if extra:
        lines = (argv_bytes(arg) for arg in extra)
    else:
        if hasattr(_helpers, 'readline'):
            _helpers.set_completer_word_break_characters(b' \t\n\r/')
            _helpers.set_attempted_completion_function(attempt_completion)
            _helpers.set_completion_entry_function(enter_completion)
            if sys.platform.startswith('darwin'):
                # MacOS uses a slightly incompatible clone of libreadline
                _helpers.parse_and_bind(b'bind ^I rl_complete')
            _helpers.parse_and_bind(b'tab: complete')
        lines = inputiter(stdin)

    for line in lines:
        if not line.strip():
            continue
        words = [word for (wordstart,word) in shquote.quotesplit(line)]
        cmd = words[0].lower()
        #log('execute: %r %r\n' % (cmd, parm))
        try:
            if cmd == b'ls':
                do_ls(repo, pwd, words[1:], out)
                out.flush()
            elif cmd == b'cd':
                np = pwd
                for parm in words[1:]:
                    res = vfs.resolve(repo, parm, parent=np)
                    _, leaf_item = res[-1]
                    if not leaf_item:
                        raise CommandError(b'"%s" does not exist' %
                                           b'/'.join(name for name, item in res))
                    if not stat.S_ISDIR(vfs.item_mode(leaf_item)):
                        raise CommandError(b'"%s" is not a directory' % parm)
                    np = res
                pwd = np
            elif cmd == b'pwd':
                if len(pwd) == 1:
                    out.write(b'/')
                out.write(b'/'.join(name for name, item in pwd) + b'\n')
                out.flush()
            elif cmd == b'cat':
                for parm in words[1:]:
                    res = vfs.resolve(repo, parm, parent=pwd)
                    _, leaf_item = res[-1]
                    if not leaf_item:
                        raise CommandError(b'"%s" does not exist' %
                                           b'/'.join(name for name, item in res))
                    with vfs.fopen(repo, leaf_item) as srcfile:
                        write_to_file(srcfile, out)
                out.flush()
            elif cmd == b'get':
                if len(words) not in [2,3]:
                    rv = 1
                    raise CommandError(b'Usage: get <filename> [localname]')
                rname = words[1]
                (dir,base) = os.path.split(rname)
                lname = len(words) > 2 and words[2] or base
                res = vfs.resolve(repo, rname, parent=pwd)
                _, leaf_item = res[-1]
                if not leaf_item:
                    raise CommandError(b'"%s" does not exist' %
                                       b'/'.join(name for name, item in res))
                with vfs.fopen(repo, leaf_item) as srcfile:
                    with open(lname, 'wb') as destfile:
                        log('Saving %s\n' % path_msg(lname))
                        write_to_file(srcfile, destfile)
            elif cmd == b'mget':
                for parm in words[1:]:
                    dir, base = os.path.split(parm)

                    res = vfs.resolve(repo, dir, parent=pwd)
                    _, dir_item = res[-1]
                    if not dir_item:
                        raise CommandError(b'"%s" does not exist' % dir)
                    for name, item in vfs.contents(repo, dir_item):
                        if name == b'.':
                            continue
                        if fnmatch.fnmatch(name, base):
                            if stat.S_ISLNK(vfs.item_mode(item)):
                                deref = vfs.resolve(repo, name, parent=res)
                                deref_name, deref_item = deref[-1]
                                if not deref_item:
                                    raise CommandError(b'"%s" does not exist' %
                                                       b'/'.join(name for name, item in res))
                                item = deref_item
                            with vfs.fopen(repo, item) as srcfile:
                                with open(name, 'wb') as destfile:
                                    log('Saving %s\n' % path_msg(name))
                                    write_to_file(srcfile, destfile)
            elif cmd == b'help' or cmd == b'?':
                out.write(b'Commands: ls cd pwd cat get mget help quit\n')
                out.flush()
            elif cmd in (b'quit', b'exit', b'bye'):
                break
            else:
                rv = 1
                raise CommandError(b'no such command "%s"' % cmd)
        except CommandError as e:
            rv = 1
            out.write(b'error: %s\n' % e.args[0])
            out.flush()
        except Exception as e:
            rv = 1
            out.write(b'error: %s\n' % str(e).encode())
            out.flush()

    sys.exit(rv)
示例#37
0
文件: ls.py 项目: jmberg/bup
def show_paths(repo, opt, paths, out, pwd, should_columnate, prefix=b''):
    def item_line(item, name):
        return item_info(item,
                         prefix + name,
                         show_hash=opt.hash,
                         commit_hash=opt.commit_hash,
                         long_fmt=opt.long_listing,
                         classification=opt.classification,
                         numeric_ids=opt.numeric_ids,
                         human_readable=opt.human_readable)

    ret = 0
    want_meta = bool(opt.long_listing or opt.classification)

    pending = []

    last_n = len(paths) - 1
    for n, printpath in enumerate(paths):
        path = posixpath.join(pwd, printpath)
        try:
            if last_n > 0:
                out.write(b'%s:\n' % printpath)

            if opt.directory:
                resolved = vfs.resolve(repo, path, follow=False)
            else:
                resolved = vfs.try_resolve(repo, path, want_meta=want_meta)

            leaf_name, leaf_item = resolved[-1]
            if not leaf_item:
                log('error: cannot access %r in %r\n' %
                    ('/'.join(path_msg(name)
                              for name, item in resolved), path_msg(path)))
                ret = 1
                continue
            if not opt.directory and S_ISDIR(vfs.item_mode(leaf_item)):
                items = vfs.contents(repo, leaf_item, want_meta=want_meta)
                if opt.show_hidden == 'all':
                    # Match non-bup "ls -a ... /".
                    parent = resolved[-2] if len(resolved) > 1 else resolved[0]
                    items = chain(items, ((b'..', parent[1]), ))
                for sub_name, sub_item in sorted(items, key=lambda x: x[0]):
                    if opt.show_hidden != 'all' and sub_name == b'.':
                        continue
                    if sub_name.startswith(b'.') and \
                       opt.show_hidden not in ('almost', 'all'):
                        continue
                    # always skip . and .. in the subfolders - already printed it anyway
                    if prefix and sub_name in (b'.', b'..'):
                        continue
                    if opt.l:
                        sub_item = vfs.ensure_item_has_metadata(
                            repo, sub_item, include_size=True)
                    elif want_meta:
                        sub_item = vfs.augment_item_meta(repo,
                                                         sub_item,
                                                         include_size=True)
                    line = item_line(sub_item, sub_name)
                    if should_columnate:
                        pending.append(line)
                    else:
                        out.write(line)
                        out.write(b'\n')
                    # recurse into subdirectories (apart from . and .., of course)
                    if opt.recursive and S_ISDIR(
                            vfs.item_mode(sub_item)) and sub_name not in (
                                b'.', b'..'):
                        show_paths(repo,
                                   opt, [path + b'/' + sub_name],
                                   out,
                                   pwd,
                                   should_columnate,
                                   prefix=prefix + sub_name + b'/')
            else:
                if opt.long_listing:
                    leaf_item = vfs.augment_item_meta(repo,
                                                      leaf_item,
                                                      include_size=True)
                line = item_line(leaf_item, os.path.normpath(path))
                if should_columnate:
                    pending.append(line)
                else:
                    out.write(line)
                    out.write(b'\n')
        except vfs.IOError as ex:
            log('bup: %s\n' % ex)
            ret = 1

        if pending:
            out.write(columnate(pending, b''))
            pending = []

        if n < last_n:
            out.write(b'\n')

    return ret
示例#38
0
def main(argv):
    o = options.Options(optspec)
    opt, flags, extra = o.parse_bytes(argv[1:])
    verbosity = (opt.verbose or 0) if not opt.quiet else -1
    if opt.remote:
        opt.remote = argv_bytes(opt.remote)
    if opt.outdir:
        opt.outdir = argv_bytes(opt.outdir)

    git.check_repo_or_die()

    if not extra:
        o.fatal('must specify at least one filename to restore')

    exclude_rxs = parse_rx_excludes(flags, o.fatal)

    owner_map = {}
    for map_type in ('user', 'group', 'uid', 'gid'):
        owner_map[map_type] = parse_owner_mappings(map_type, flags, o.fatal)

    if opt.outdir:
        mkdirp(opt.outdir)
        os.chdir(opt.outdir)

    repo = RemoteRepo(opt.remote) if opt.remote else LocalRepo()
    top = fsencode(os.getcwd())
    hardlinks = {}
    for path in [argv_bytes(x) for x in extra]:
        if not valid_restore_path(path):
            add_error("path %r doesn't include a branch and revision" % path)
            continue
        try:
            resolved = vfs.resolve(repo, path, want_meta=True, follow=False)
        except vfs.IOError as e:
            add_error(e)
            continue
        if len(resolved) == 3 and resolved[2][0] == b'latest':
            # Follow latest symlink to the actual save
            try:
                resolved = vfs.resolve(repo,
                                       b'latest',
                                       parent=resolved[:-1],
                                       want_meta=True)
            except vfs.IOError as e:
                add_error(e)
                continue
            # Rename it back to 'latest'
            resolved = tuple(elt if i != 2 else (b'latest', ) + elt[1:]
                             for i, elt in enumerate(resolved))
        path_parent, path_name = os.path.split(path)
        leaf_name, leaf_item = resolved[-1]
        if not leaf_item:
            add_error('error: cannot access %r in %r' %
                      (b'/'.join(name for name, item in resolved), path))
            continue
        if not path_name or path_name == b'.':
            # Source is /foo/what/ever/ or /foo/what/ever/. -- extract
            # what/ever/* to the current directory, and if name == '.'
            # (i.e. /foo/what/ever/.), then also restore what/ever's
            # metadata to the current directory.
            treeish = vfs.item_mode(leaf_item)
            if not treeish:
                add_error('%r cannot be restored as a directory' % path)
            else:
                items = vfs.contents(repo, leaf_item, want_meta=True)
                dot, leaf_item = next(items, None)
                assert dot == b'.'
                for sub_name, sub_item in items:
                    restore(repo, b'', sub_name, sub_item, top, opt.sparse,
                            opt.numeric_ids, owner_map, exclude_rxs, verbosity,
                            hardlinks)
                if path_name == b'.':
                    leaf_item = vfs.augment_item_meta(repo,
                                                      leaf_item,
                                                      include_size=True)
                    apply_metadata(leaf_item.meta, b'.', opt.numeric_ids,
                                   owner_map)
        else:
            restore(repo, b'', leaf_name, leaf_item, top, opt.sparse,
                    opt.numeric_ids, owner_map, exclude_rxs, verbosity,
                    hardlinks)

    if verbosity >= 0:
        progress('Restoring: %d, done.\n' % total_restored)
    die_if_errors()
示例#39
0
git.check_repo_or_die()

if not extra:
    o.fatal('must specify a target')
if len(extra) > 1:
    o.fatal('only one target file allowed')
if opt.bupm and opt.meta:
    o.fatal('--meta and --bupm are incompatible')
    
target = argv_bytes(extra[0])

if not re.match(br'/*[^/]+/[^/]+', target):
    o.fatal("path %r doesn't include a branch and revision" % target)

repo = LocalRepo()
resolved = vfs.resolve(repo, target, follow=False)
leaf_name, leaf_item = resolved[-1]
if not leaf_item:
    log('error: cannot access %r in %r\n'
        % ('/'.join(name for name, item in resolved), path))
    sys.exit(1)

mode = vfs.item_mode(leaf_item)

sys.stdout.flush()
out = byte_stream(sys.stdout)

if opt.bupm:
    if not stat.S_ISDIR(mode):
        o.fatal('%r is not a directory' % target)
    _, bupm_oid = vfs.tree_data_and_bupm(repo, leaf_item.oid)