Example #1
0
def main(argv):
    o = options.Options(optspec)
    opt, flags, extra = o.parse_bytes(argv[1:])

    if not opt.unsafe:
        o.fatal(
            'refusing to run dangerous, experimental command without --unsafe')

    if extra:
        o.fatal('no positional parameters expected')

    if opt.threshold:
        try:
            opt.threshold = int(opt.threshold)
        except ValueError:
            o.fatal('threshold must be an integer percentage value')
        if opt.threshold < 0 or opt.threshold > 100:
            o.fatal('threshold must be an integer percentage value')

    bup_gc(LocalRepo(),
           threshold=opt.threshold,
           compression=opt.compress,
           verbosity=opt.verbose)

    die_if_errors()
Example #2
0
File: rm.py Project: xeyownt/bup
def bup_rm(paths, compression=6, verbosity=None):
    root = vfs.RefList(None)

    dead_branches, dead_saves = dead_items(root, paths)
    die_if_errors('not proceeding with any removals\n')

    updated_refs = {}  # ref_name -> (original_ref, tip_commit(bin))

    for branch, node in dead_branches.iteritems():
        ref = 'refs/heads/' + branch
        assert(not ref in updated_refs)
        updated_refs[ref] = (node.hash, None)

    if dead_saves:
        writer = git.PackWriter(compression_level=compression)
        try:
            for branch, saves in dead_saves.iteritems():
                assert(saves)
                updated_refs['refs/heads/' + branch] = rm_saves(saves, writer)
        except:
            if writer:
                writer.abort()
            raise
        else:
            if writer:
                # Must close before we can update the ref(s) below.
                writer.close()

    # Only update the refs here, at the very end, so that if something
    # goes wrong above, the old refs will be undisturbed.  Make an attempt
    # to update each ref.
    for ref_name, info in updated_refs.iteritems():
        orig_ref, new_ref = info
        try:
            if not new_ref:
                git.delete_ref(ref_name, orig_ref.encode('hex'))
            else:
                git.update_ref(ref_name, new_ref, orig_ref)
                if verbosity:
                    new_hex = new_ref.encode('hex')
                    if orig_ref:
                        orig_hex = orig_ref.encode('hex')
                        log('updated %r (%s -> %s)\n'
                            % (ref_name, orig_hex, new_hex))
                    else:
                        log('updated %r (%s)\n' % (ref_name, new_hex))
        except (git.GitError, ClientError) as ex:
            if new_ref:
                add_error('while trying to update %r (%s -> %s): %s'
                          % (ref_name, orig_ref, new_ref, ex))
            else:
                add_error('while trying to delete %r (%s): %s'
                          % (ref_name, orig_ref, ex))
Example #3
0
def main(argv):
    o = Options(optspec)
    opt, flags, extra = o.parse_bytes(argv[1:])

    if not opt.unsafe:
        o.fatal(
            'refusing to run dangerous, experimental command without --unsafe')

    if len(extra) < 1:
        o.fatal('no paths specified')

    repo = from_opts(opt)
    bup_rm(repo, [argv_bytes(x) for x in extra], verbosity=opt.verbose)
    die_if_errors()
Example #4
0
def bup_rm(repo, paths, compression=6, verbosity=None):
    dead_branches, dead_saves = dead_items(repo, paths)
    die_if_errors('not proceeding with any removals\n')

    updated_refs = {}  # ref_name -> (original_ref, tip_commit(bin))

    for branchname, branchitem in dead_branches.items():
        ref = b'refs/heads/' + branchname
        assert(not ref in updated_refs)
        updated_refs[ref] = (branchitem.oid, None)

    if dead_saves:
        writer = git.PackWriter(compression_level=compression)
        try:
            for branch, saves in dead_saves.items():
                assert(saves)
                updated_refs[b'refs/heads/' + branch] = rm_saves(saves, writer)
        except BaseException as ex:
            with pending_raise(ex):
                writer.abort()
        finally:
            writer.close()

    # Only update the refs here, at the very end, so that if something
    # goes wrong above, the old refs will be undisturbed.  Make an attempt
    # to update each ref.
    for ref_name, info in updated_refs.items():
        orig_ref, new_ref = info
        try:
            if not new_ref:
                git.delete_ref(ref_name, hexlify(orig_ref))
            else:
                git.update_ref(ref_name, new_ref, orig_ref)
                if verbosity:
                    log('updated %s (%s%s)\n'
                        % (path_msg(ref_name),
                           hexstr(orig_ref) + ' -> ' if orig_ref else '',
                           hexstr(new_ref)))
        except (git.GitError, ClientError) as ex:
            if new_ref:
                add_error('while trying to update %s (%s%s): %s'
                          % (path_msg(ref_name),
                             hexstr(orig_ref) + ' -> ' if orig_ref else '',
                             hexstr(new_ref),
                             ex))
            else:
                add_error('while trying to delete %r (%s): %s'
                          % (ref_name, hexstr(orig_ref), ex))
Example #5
0
def main(argv):
    o = Options(optspec)
    opt, flags, extra = o.parse_bytes(argv[1:])

    if not opt.unsafe:
        o.fatal(
            'refusing to run dangerous, experimental command without --unsafe')

    if len(extra) < 1:
        o.fatal('no paths specified')

    check_repo_or_die()
    with LocalRepo() as repo:
        bup_rm(repo, [argv_bytes(x) for x in extra],
               compression=opt.compress,
               verbosity=opt.verbose)
    die_if_errors()
Example #6
0
# FIXME: server mode?
# FIXME: make sure client handles server-side changes reasonably

handle_ctrl_c()

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

if not opt.unsafe:
    o.fatal('refusing to run dangerous, experimental command without --unsafe')

if extra:
    o.fatal('no positional parameters expected')

if opt.threshold:
    try:
        opt.threshold = int(opt.threshold)
    except ValueError:
        o.fatal('threshold must be an integer percentage value')
    if opt.threshold < 0 or opt.threshold > 100:
        o.fatal('threshold must be an integer percentage value')

git.check_repo_or_die()

bup_gc(threshold=opt.threshold,
       compression=opt.compress,
       verbosity=opt.verbose)

die_if_errors()
Example #7
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()
Example #8
0
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 = vfs2.lresolve(repo, path, want_meta=True)
        except vfs2.IOError as e:
            add_error(e)
            continue
        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 = vfs2.item_mode(leaf_item)
            if not treeish:
                add_error('%r cannot be restored as a directory' % path)
            else:
                items = vfs2.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 = vfs2.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()
Example #9
0
def main(argv):
    o = options.Options(optspec)
    opt, flags, roots = o.parse_bytes(argv[1:])
    roots = [argv_bytes(x) for x in roots]

    if not opt.unsafe:
        o.fatal(
            'refusing to run dangerous, experimental command without --unsafe')

    now = int(time()) if opt.wrt is None else opt.wrt
    if not isinstance(now, int_types):
        o.fatal('--wrt value ' + str(now) + ' is not an integer')

    period_start = {}
    for period, extent in (('all', opt.keep_all_for), ('dailies',
                                                       opt.keep_dailies_for),
                           ('monthlies', opt.keep_monthlies_for),
                           ('yearlies', opt.keep_yearlies_for)):
        if extent:
            secs = period_as_secs(extent.encode('ascii'))
            if not secs:
                o.fatal('%r is not a valid period' % extent)
            period_start[period] = now - secs

    if not period_start:
        o.fatal('at least one keep argument is required')

    period_start = defaultdict(lambda: float('inf'), period_start)

    if opt.verbose:
        epoch_ymd = strftime('%Y-%m-%d-%H%M%S', localtime(0))
        for kind in ['all', 'dailies', 'monthlies', 'yearlies']:
            period_utc = period_start[kind]
            if period_utc != float('inf'):
                if not (period_utc > float('-inf')):
                    log('keeping all ' + kind)
                else:
                    try:
                        when = strftime('%Y-%m-%d-%H%M%S',
                                        localtime(period_utc))
                        log('keeping ' + kind + ' since ' + when + '\n')
                    except ValueError as ex:
                        if period_utc < 0:
                            log('keeping %s since %d seconds before %s\n' %
                                (kind, abs(period_utc), epoch_ymd))
                        elif period_utc > 0:
                            log('keeping %s since %d seconds after %s\n' %
                                (kind, period_utc, epoch_ymd))
                        else:
                            log('keeping %s since %s\n' % (kind, epoch_ymd))

    git.check_repo_or_die()

    # This could be more efficient, but for now just build the whole list
    # in memory and let bup_rm() do some redundant work.

    def parse_info(f):
        author_secs = f.readline().strip()
        return int(author_secs)

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

    removals = []
    for branch, branch_id in branches(roots):
        die_if_errors()
        saves = ((utc, unhexlify(oidx)) for (
            oidx,
            utc) in git.rev_list(branch_id, format=b'%at', parse=parse_info))
        for keep_save, (utc, id) in classify_saves(saves, period_start):
            assert (keep_save in (False, True))
            # FIXME: base removals on hashes
            if opt.pretend:
                out.write((b'+ ' if keep_save else b'- ') +
                          save_name(branch, utc) + b'\n')
            elif not keep_save:
                removals.append(save_name(branch, utc))

    if not opt.pretend:
        die_if_errors()
        repo = LocalRepo()
        bup_rm(repo, removals, compression=opt.compress, verbosity=opt.verbose)
        if opt.gc:
            die_if_errors()
            bup_gc(threshold=opt.gc_threshold,
                   compression=opt.compress,
                   verbosity=opt.verbose)

    die_if_errors()
Example #10
0
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()