mirror of https://github.com/borgbackup/borg.git
fork: s/attic/borg/g, fix URLs, add new section to AUTHORS
use borg instead attic except at the places where it was used: - as toplevel package name, directory name, file name - to refer to original attic remove sphinx upload make command, will be replaced by github.io site later remove references to binary downloads and linux packages for now remove some software name references, fix grammar use borgbackup rather than borg-backup (or borg) in URLs, less name collision issues, better search results, no validity issues with "-"
This commit is contained in:
parent
f9d90482c4
commit
cb5c9b63b3
10
AUTHORS
10
AUTHORS
|
@ -1,9 +1,13 @@
|
|||
Attic is written and maintained by Jonas Borgström and
|
||||
various contributors:
|
||||
Borg Developers / Contributors ("The Borg Collective")
|
||||
``````````````````````````````````````````````````````
|
||||
- Thomas Waldmann
|
||||
|
||||
|
||||
Borg is a fork of Attic. Attic is written and maintained
|
||||
by Jonas Borgström and various contributors:
|
||||
|
||||
Development Lead
|
||||
````````````````
|
||||
|
||||
- Jonas Borgström <jonas@borgstrom.se>
|
||||
|
||||
Patches and Suggestions
|
||||
|
|
1
LICENSE
1
LICENSE
|
@ -1,3 +1,4 @@
|
|||
Copyright (C) 2015 The Borg Collective (see AUTHORS file)
|
||||
Copyright (C) 2010-2014 Jonas Borgström <jonas@borgstrom.se>
|
||||
All rights reserved.
|
||||
|
||||
|
|
36
README.rst
36
README.rst
|
@ -1,16 +1,20 @@
|
|||
What is Attic?
|
||||
--------------
|
||||
Attic is a deduplicating backup program. The main goal of Attic is to provide
|
||||
|build|
|
||||
|
||||
What is Borg?
|
||||
-------------
|
||||
Borg is a deduplicating backup program. The main goal of Borg is to provide
|
||||
an efficient and secure way to backup data. The data deduplication
|
||||
technique used makes Attic suitable for daily backups since only changes
|
||||
technique used makes Borg suitable for daily backups since only changes
|
||||
are stored.
|
||||
|
||||
Borg is a fork of Attic and maintained by "The Borg Collective" (see AUTHORS file).
|
||||
|
||||
Easy to use
|
||||
~~~~~~~~~~~
|
||||
Initialize backup repository and create a backup archive::
|
||||
|
||||
$ attic init /usbdrive/my-backup.attic
|
||||
$ attic create -v /usbdrive/my-backup.attic::documents ~/Documents
|
||||
$ borg init /usbdrive/my-backup.borg
|
||||
$ borg create -v /usbdrive/my-backup.borg::documents ~/Documents
|
||||
|
||||
Main features
|
||||
~~~~~~~~~~~~~
|
||||
|
@ -25,8 +29,8 @@ Optional data encryption
|
|||
and authenticity is verified using HMAC-SHA256.
|
||||
|
||||
Off-site backups
|
||||
Attic can store data on any remote host accessible over SSH. This is
|
||||
most efficient if Attic is also installed on the remote host.
|
||||
Borg can store data on any remote host accessible over SSH. This is
|
||||
most efficient if Borg is also installed on the remote host.
|
||||
|
||||
Backups mountable as filesystems
|
||||
Backup archives are mountable as userspace filesystems for easy backup
|
||||
|
@ -34,24 +38,28 @@ Backups mountable as filesystems
|
|||
|
||||
What do I need?
|
||||
---------------
|
||||
Attic requires Python 3.2 or above to work. Besides Python, Attic also requires
|
||||
msgpack-python and sufficiently recent OpenSSL (>= 1.0.0).
|
||||
Borg requires Python 3.2 or above to work.
|
||||
Borg also requires a sufficiently recent OpenSSL (>= 1.0.0).
|
||||
In order to mount archives as filesystems, llfuse is required.
|
||||
|
||||
How do I install it?
|
||||
--------------------
|
||||
::
|
||||
|
||||
$ pip install Attic
|
||||
$ pip3 install borgbackup
|
||||
|
||||
Where are the docs?
|
||||
-------------------
|
||||
Go to https://attic-backup.org/ for a prebuilt version of the documentation.
|
||||
Go to https://borgbackup.github.io/ for a prebuilt version of the documentation.
|
||||
You can also build it yourself from the docs folder.
|
||||
|
||||
Where are the tests?
|
||||
--------------------
|
||||
The tests are in the attic/testsuite package. To run the test suite use the
|
||||
The tests are in the borg/testsuite package. To run the test suite use the
|
||||
following command::
|
||||
|
||||
$ fakeroot -u python -m attic.testsuite.run
|
||||
$ fakeroot -u tox # you need to have tox installed
|
||||
|
||||
.. |build| image:: https://travis-ci.org/borgbackup/borg.svg
|
||||
:alt: Build Status
|
||||
:target: https://travis-ci.org/borgbackup/borg
|
||||
|
|
|
@ -183,7 +183,7 @@ def versions_from_parentdir(parentdir_prefix, versionfile_source, verbose=False)
|
|||
return {"version": dirname[len(parentdir_prefix):], "full": ""}
|
||||
|
||||
tag_prefix = ""
|
||||
parentdir_prefix = "Attic-"
|
||||
parentdir_prefix = "borgbackup-"
|
||||
versionfile_source = "attic/_version.py"
|
||||
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ class Archiver:
|
|||
def print_error(self, msg, *args):
|
||||
msg = args and msg % args or msg
|
||||
self.exit_code = 1
|
||||
print('attic: ' + msg, file=sys.stderr)
|
||||
print('borg: ' + msg, file=sys.stderr)
|
||||
|
||||
def print_verbose(self, msg, *args, **kw):
|
||||
if self.verbose:
|
||||
|
@ -49,7 +49,7 @@ class Archiver:
|
|||
print(msg, end=' ')
|
||||
|
||||
def do_serve(self, args):
|
||||
"""Start Attic in server mode. This command is usually not used manually.
|
||||
"""Start in server mode. This command is usually not used manually.
|
||||
"""
|
||||
return RepositoryServer(restrict_to_paths=args.restrict_to_paths).serve()
|
||||
|
||||
|
@ -69,7 +69,7 @@ class Archiver:
|
|||
"""Check repository consistency"""
|
||||
repository = self.open_repository(args.repository, exclusive=args.repair)
|
||||
if args.repair:
|
||||
while not os.environ.get('ATTIC_CHECK_I_KNOW_WHAT_I_AM_DOING'):
|
||||
while not os.environ.get('BORG_CHECK_I_KNOW_WHAT_I_AM_DOING'):
|
||||
self.print_error("""Warning: 'check --repair' is an experimental feature that might result
|
||||
in data loss.
|
||||
|
||||
|
@ -102,7 +102,7 @@ Type "Yes I am sure" if you understand this and want to continue.\n""")
|
|||
archive = Archive(repository, key, manifest, args.archive.archive, cache=cache,
|
||||
create=True, checkpoint_interval=args.checkpoint_interval,
|
||||
numeric_owner=args.numeric_owner, progress=args.progress)
|
||||
# Add Attic cache dir to inode_skip list
|
||||
# Add cache dir to inode_skip list
|
||||
skip_inodes = set()
|
||||
try:
|
||||
st = os.stat(get_cache_dir())
|
||||
|
@ -198,7 +198,7 @@ Type "Yes I am sure" if you understand this and want to continue.\n""")
|
|||
return
|
||||
# Status output
|
||||
# A lowercase character means a file type other than a regular file,
|
||||
# attic usually just stores them. E.g. (d)irectory.
|
||||
# borg usually just stores them. E.g. (d)irectory.
|
||||
# Hardlinks to already seen content are indicated by (h).
|
||||
# A uppercase character means a regular file that was (A)dded,
|
||||
# (M)odified or was (U)nchanged.
|
||||
|
@ -435,17 +435,17 @@ Type "Yes I am sure" if you understand this and want to continue.\n""")
|
|||
Examples:
|
||||
|
||||
# Exclude '/home/user/file.o' but not '/home/user/file.odt':
|
||||
$ attic create -e '*.o' repo.attic /
|
||||
$ borg create -e '*.o' repo.borg /
|
||||
|
||||
# Exclude '/home/user/junk' and '/home/user/subdir/junk' but
|
||||
# not '/home/user/importantjunk' or '/etc/junk':
|
||||
$ attic create -e '/home/*/junk' repo.attic /
|
||||
$ borg create -e '/home/*/junk' repo.borg /
|
||||
|
||||
# Exclude the contents of '/home/user/cache' but not the directory itself:
|
||||
$ attic create -e /home/user/cache/ repo.attic /
|
||||
$ borg create -e /home/user/cache/ repo.borg /
|
||||
|
||||
# The file '/home/user/cache/important' is *not* backed up:
|
||||
$ attic create -e /home/user/cache/ repo.attic / /home/user/cache/important
|
||||
$ borg create -e /home/user/cache/ repo.borg / /home/user/cache/important
|
||||
'''
|
||||
|
||||
def do_help(self, parser, commands, args):
|
||||
|
@ -474,7 +474,7 @@ Type "Yes I am sure" if you understand this and want to continue.\n""")
|
|||
('--yearly', '--keep-yearly', 'Warning: "--yearly" has been deprecated. Use "--keep-yearly" instead.')
|
||||
]
|
||||
if args and args[0] == 'verify':
|
||||
print('Warning: "attic verify" has been deprecated. Use "attic extract --dry-run" instead.')
|
||||
print('Warning: "borg verify" has been deprecated. Use "borg extract --dry-run" instead.')
|
||||
args = ['extract', '--dry-run'] + args[1:]
|
||||
for i, arg in enumerate(args[:]):
|
||||
for old_name, new_name, warning in deprecations:
|
||||
|
@ -496,7 +496,7 @@ Type "Yes I am sure" if you understand this and want to continue.\n""")
|
|||
with open(os.path.join(cache_dir, 'CACHEDIR.TAG'), 'w') as fd:
|
||||
fd.write(textwrap.dedent("""
|
||||
Signature: 8a477f597d28d172789f06886806bc55
|
||||
# This file is a cache directory tag created by Attic.
|
||||
# This file is a cache directory tag created by Borg.
|
||||
# For information about cache directory tags, see:
|
||||
# http://www.brynosaurus.com/cachedir/
|
||||
""").lstrip())
|
||||
|
@ -510,7 +510,7 @@ Type "Yes I am sure" if you understand this and want to continue.\n""")
|
|||
if args:
|
||||
args = self.preprocess_args(args)
|
||||
|
||||
parser = argparse.ArgumentParser(description='Attic %s - Deduplicated Backups' % __version__)
|
||||
parser = argparse.ArgumentParser(description='Borg %s - Deduplicated Backups' % __version__)
|
||||
subparsers = parser.add_subparsers(title='Available commands')
|
||||
|
||||
subparser = subparsers.add_parser('serve', parents=[common_parser],
|
||||
|
@ -582,7 +582,7 @@ Type "Yes I am sure" if you understand this and want to continue.\n""")
|
|||
traversing all paths specified. The archive will consume almost no disk space for
|
||||
files or parts of files that have already been stored in other archives.
|
||||
|
||||
See "attic help patterns" for more help on exclude patterns.
|
||||
See "borg help patterns" for more help on exclude patterns.
|
||||
""")
|
||||
|
||||
subparser = subparsers.add_parser('create', parents=[common_parser],
|
||||
|
@ -631,7 +631,7 @@ Type "Yes I am sure" if you understand this and want to continue.\n""")
|
|||
by passing a list of ``PATHs`` as arguments. The file selection can further
|
||||
be restricted by using the ``--exclude`` option.
|
||||
|
||||
See "attic help patterns" for more help on exclude patterns.
|
||||
See "borg help patterns" for more help on exclude patterns.
|
||||
""")
|
||||
subparser = subparsers.add_parser('extract', parents=[common_parser],
|
||||
description=self.do_extract.__doc__,
|
||||
|
|
|
@ -43,14 +43,14 @@ class Cache:
|
|||
if not os.path.exists(self.path):
|
||||
if warn_if_unencrypted and isinstance(key, PlaintextKey):
|
||||
if not self._confirm('Warning: Attempting to access a previously unknown unencrypted repository',
|
||||
'ATTIC_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK'):
|
||||
'BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK'):
|
||||
raise self.CacheInitAbortedError()
|
||||
self.create()
|
||||
self.open()
|
||||
# Warn user before sending data to a relocated repository
|
||||
if self.previous_location and self.previous_location != repository._location.canonical_path():
|
||||
msg = 'Warning: The repository at location {} was previously located at {}'.format(repository._location.canonical_path(), self.previous_location)
|
||||
if not self._confirm(msg, 'ATTIC_RELOCATED_REPO_ACCESS_IS_OK'):
|
||||
if not self._confirm(msg, 'BORG_RELOCATED_REPO_ACCESS_IS_OK'):
|
||||
raise self.RepositoryAccessAborted()
|
||||
|
||||
if sync and self.manifest.id != self.manifest_id:
|
||||
|
@ -84,7 +84,7 @@ class Cache:
|
|||
"""
|
||||
os.makedirs(self.path)
|
||||
with open(os.path.join(self.path, 'README'), 'w') as fd:
|
||||
fd.write('This is an Attic cache')
|
||||
fd.write('This is a Borg cache')
|
||||
config = RawConfigParser()
|
||||
config.add_section('cache')
|
||||
config.set('cache', 'version', '1')
|
||||
|
@ -107,7 +107,7 @@ class Cache:
|
|||
self.config = RawConfigParser()
|
||||
self.config.read(os.path.join(self.path, 'config'))
|
||||
if self.config.getint('cache', 'version') != 1:
|
||||
raise Exception('%s Does not look like an Attic cache')
|
||||
raise Exception('%s Does not look like a Borg cache')
|
||||
self.id = self.config.get('cache', 'repository')
|
||||
self.manifest_id = unhexlify(self.config.get('cache', 'manifest'))
|
||||
self.timestamp = self.config.get('cache', 'timestamp', fallback=None)
|
||||
|
@ -118,7 +118,7 @@ class Cache:
|
|||
|
||||
def open(self):
|
||||
if not os.path.isdir(self.path):
|
||||
raise Exception('%s Does not look like an Attic cache' % self.path)
|
||||
raise Exception('%s Does not look like a Borg cache' % self.path)
|
||||
self.lock = UpgradableLock(os.path.join(self.path, 'config'), exclusive=True)
|
||||
self.rollback()
|
||||
|
||||
|
|
|
@ -30,8 +30,8 @@ class ItemCache:
|
|||
return next(msgpack.Unpacker(self.fd))
|
||||
|
||||
|
||||
class AtticOperations(llfuse.Operations):
|
||||
"""Export Attic archive as a fuse filesystem
|
||||
class FuseOperations(llfuse.Operations):
|
||||
"""Export archive as a fuse filesystem
|
||||
"""
|
||||
def __init__(self, key, repository, manifest, archive):
|
||||
super(AtticOperations, self).__init__()
|
||||
|
@ -226,7 +226,7 @@ class AtticOperations(llfuse.Operations):
|
|||
return os.fsencode(item[b'source'])
|
||||
|
||||
def mount(self, mountpoint, extra_options, foreground=False):
|
||||
options = ['fsname=atticfs', 'ro']
|
||||
options = ['fsname=borgfs', 'ro']
|
||||
if extra_options:
|
||||
options.extend(extra_options.split(','))
|
||||
llfuse.init(self, mountpoint, options)
|
||||
|
|
|
@ -27,7 +27,7 @@ class Error(Exception):
|
|||
|
||||
|
||||
class ExtensionModuleError(Error):
|
||||
"""The Attic binary extension modules does not seem to be properly installed"""
|
||||
"""The Borg binary extension modules do not seem to be properly installed"""
|
||||
|
||||
|
||||
class UpgradableLock:
|
||||
|
@ -182,14 +182,14 @@ class Statistics:
|
|||
|
||||
def get_keys_dir():
|
||||
"""Determine where to repository keys and cache"""
|
||||
return os.environ.get('ATTIC_KEYS_DIR',
|
||||
os.path.join(os.path.expanduser('~'), '.attic', 'keys'))
|
||||
return os.environ.get('BORG_KEYS_DIR',
|
||||
os.path.join(os.path.expanduser('~'), '.borg', 'keys'))
|
||||
|
||||
|
||||
def get_cache_dir():
|
||||
"""Determine where to repository keys and cache"""
|
||||
return os.environ.get('ATTIC_CACHE_DIR',
|
||||
os.path.join(os.path.expanduser('~'), '.cache', 'attic'))
|
||||
return os.environ.get('BORG_CACHE_DIR',
|
||||
os.path.join(os.path.expanduser('~'), '.cache', 'borg'))
|
||||
|
||||
|
||||
def to_localtime(ts):
|
||||
|
|
|
@ -160,7 +160,7 @@ class PassphraseKey(AESKeyBase):
|
|||
@classmethod
|
||||
def create(cls, repository, args):
|
||||
key = cls()
|
||||
passphrase = os.environ.get('ATTIC_PASSPHRASE')
|
||||
passphrase = os.environ.get('BORG_PASSPHRASE')
|
||||
if passphrase is not None:
|
||||
passphrase2 = passphrase
|
||||
else:
|
||||
|
@ -182,7 +182,7 @@ class PassphraseKey(AESKeyBase):
|
|||
def detect(cls, repository, manifest_data):
|
||||
prompt = 'Enter passphrase for %s: ' % repository._location.orig
|
||||
key = cls()
|
||||
passphrase = os.environ.get('ATTIC_PASSPHRASE')
|
||||
passphrase = os.environ.get('BORG_PASSPHRASE')
|
||||
if passphrase is None:
|
||||
passphrase = getpass(prompt)
|
||||
while True:
|
||||
|
@ -215,7 +215,7 @@ class KeyfileKey(AESKeyBase):
|
|||
key = cls()
|
||||
path = cls.find_key_file(repository)
|
||||
prompt = 'Enter passphrase for key file %s: ' % path
|
||||
passphrase = os.environ.get('ATTIC_PASSPHRASE', '')
|
||||
passphrase = os.environ.get('BORG_PASSPHRASE', '')
|
||||
while not key.load(path, passphrase):
|
||||
passphrase = getpass(prompt)
|
||||
num_blocks = num_aes_blocks(len(manifest_data) - 41)
|
||||
|
@ -310,7 +310,7 @@ class KeyfileKey(AESKeyBase):
|
|||
while os.path.exists(path):
|
||||
i += 1
|
||||
path = filename + '.%d' % i
|
||||
passphrase = os.environ.get('ATTIC_PASSPHRASE')
|
||||
passphrase = os.environ.get('BORG_PASSPHRASE')
|
||||
if passphrase is not None:
|
||||
passphrase2 = passphrase
|
||||
else:
|
||||
|
|
|
@ -79,7 +79,7 @@ class RepositoryServer:
|
|||
f = getattr(self.repository, method)
|
||||
res = f(*args)
|
||||
except BaseException as e:
|
||||
exc = "Remote Traceback by Attic %s%s%s" % (__version__, os.linesep, traceback.format_exc())
|
||||
exc = "Remote Traceback by Borg %s%s%s" % (__version__, os.linesep, traceback.format_exc())
|
||||
os.write(stdout_fd, msgpack.packb((1, msgid, e.__class__.__name__, exc)))
|
||||
else:
|
||||
os.write(stdout_fd, msgpack.packb((1, msgid, None, res)))
|
||||
|
@ -132,7 +132,7 @@ class RemoteRepository:
|
|||
args.append('%s@%s' % (location.user, location.host))
|
||||
else:
|
||||
args.append('%s' % location.host)
|
||||
args += ['attic', 'serve']
|
||||
args += ['borg', 'serve']
|
||||
self.p = Popen(args, bufsize=0, stdin=PIPE, stdout=PIPE)
|
||||
self.stdin_fd = self.p.stdin.fileno()
|
||||
self.stdout_fd = self.p.stdout.fileno()
|
||||
|
|
|
@ -42,7 +42,7 @@ class Repository:
|
|||
"""{} is not a valid repository."""
|
||||
|
||||
class CheckNeeded(Error):
|
||||
"""Inconsistency detected. Please run "attic check {}"."""
|
||||
"""Inconsistency detected. Please run "borg check {}"."""
|
||||
|
||||
class ObjectNotFound(Error):
|
||||
"""Object with key {} not found in repository {}."""
|
||||
|
@ -68,7 +68,7 @@ class Repository:
|
|||
if not os.path.exists(path):
|
||||
os.mkdir(path)
|
||||
with open(os.path.join(path, 'README'), 'w') as fd:
|
||||
fd.write('This is an Attic repository\n')
|
||||
fd.write('This is a Borg repository\n')
|
||||
os.mkdir(os.path.join(path, 'data'))
|
||||
config = RawConfigParser()
|
||||
config.add_section('repository')
|
||||
|
|
|
@ -65,7 +65,7 @@ class ArchiverTestCaseBase(AtticTestCase):
|
|||
prefix = ''
|
||||
|
||||
def setUp(self):
|
||||
os.environ['ATTIC_CHECK_I_KNOW_WHAT_I_AM_DOING'] = '1'
|
||||
os.environ['BORG_CHECK_I_KNOW_WHAT_I_AM_DOING'] = '1'
|
||||
self.archiver = Archiver()
|
||||
self.tmpdir = tempfile.mkdtemp()
|
||||
self.repository_path = os.path.join(self.tmpdir, 'repository')
|
||||
|
@ -75,8 +75,8 @@ class ArchiverTestCaseBase(AtticTestCase):
|
|||
self.keys_path = os.path.join(self.tmpdir, 'keys')
|
||||
self.cache_path = os.path.join(self.tmpdir, 'cache')
|
||||
self.exclude_file_path = os.path.join(self.tmpdir, 'excludes')
|
||||
os.environ['ATTIC_KEYS_DIR'] = self.keys_path
|
||||
os.environ['ATTIC_CACHE_DIR'] = self.cache_path
|
||||
os.environ['BORG_KEYS_DIR'] = self.keys_path
|
||||
os.environ['BORG_CACHE_DIR'] = self.cache_path
|
||||
os.mkdir(self.input_path)
|
||||
os.mkdir(self.output_path)
|
||||
os.mkdir(self.keys_path)
|
||||
|
@ -190,7 +190,7 @@ class ArchiverTestCase(ArchiverTestCaseBase):
|
|||
info_output = self.attic('info', self.repository_location + '::test')
|
||||
self.assert_in('Number of files: 4', info_output)
|
||||
shutil.rmtree(self.cache_path)
|
||||
with environment_variable(ATTIC_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK='1'):
|
||||
with environment_variable(BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK='1'):
|
||||
info_output2 = self.attic('info', self.repository_location + '::test')
|
||||
# info_output2 starts with some "initializing cache" text but should
|
||||
# end the same way as info_output
|
||||
|
@ -244,7 +244,7 @@ class ArchiverTestCase(ArchiverTestCaseBase):
|
|||
|
||||
def test_repository_swap_detection(self):
|
||||
self.create_test_files()
|
||||
os.environ['ATTIC_PASSPHRASE'] = 'passphrase'
|
||||
os.environ['BORG_PASSPHRASE'] = 'passphrase'
|
||||
self.attic('init', '--encryption=passphrase', self.repository_location)
|
||||
repository_id = self._extract_repository_id(self.repository_path)
|
||||
self.attic('create', self.repository_location + '::test', 'input')
|
||||
|
@ -257,7 +257,7 @@ class ArchiverTestCase(ArchiverTestCaseBase):
|
|||
def test_repository_swap_detection2(self):
|
||||
self.create_test_files()
|
||||
self.attic('init', '--encryption=none', self.repository_location + '_unencrypted')
|
||||
os.environ['ATTIC_PASSPHRASE'] = 'passphrase'
|
||||
os.environ['BORG_PASSPHRASE'] = 'passphrase'
|
||||
self.attic('init', '--encryption=passphrase', self.repository_location + '_encrypted')
|
||||
self.attic('create', self.repository_location + '_encrypted::test', 'input')
|
||||
shutil.rmtree(self.repository_path + '_encrypted')
|
||||
|
@ -419,7 +419,7 @@ class ArchiverTestCase(ArchiverTestCaseBase):
|
|||
self.attic('init', self.repository_location)
|
||||
self.attic('create', self.repository_location + '::test', 'input')
|
||||
output = self.attic('verify', '-v', self.repository_location + '::test')
|
||||
self.assert_in('"attic verify" has been deprecated', output)
|
||||
self.assert_in('"borg verify" has been deprecated', output)
|
||||
output = self.attic('prune', self.repository_location, '--hourly=1')
|
||||
self.assert_in('"--hourly" has been deprecated. Use "--keep-hourly" instead', output)
|
||||
|
||||
|
@ -502,7 +502,7 @@ class ArchiverTestCase(ArchiverTestCaseBase):
|
|||
used.add(counter)
|
||||
|
||||
self.create_test_files()
|
||||
os.environ['ATTIC_PASSPHRASE'] = 'passphrase'
|
||||
os.environ['BORG_PASSPHRASE'] = 'passphrase'
|
||||
self.attic('init', '--encryption=' + method, self.repository_location)
|
||||
verify_uniqueness()
|
||||
self.attic('create', self.repository_location + '::test', 'input')
|
||||
|
|
|
@ -38,8 +38,8 @@ class LocationTestCase(AtticTestCase):
|
|||
"Location(proto='ssh', user='user', host='host', port=None, path='/some/path', archive='archive')"
|
||||
)
|
||||
self.assert_equal(
|
||||
repr(Location('mybackup.attic::archive')),
|
||||
"Location(proto='file', user=None, host=None, port=None, path='mybackup.attic', archive='archive')"
|
||||
repr(Location('mybackup.borg::archive')),
|
||||
"Location(proto='file', user=None, host=None, port=None, path='mybackup.borg', archive='archive')"
|
||||
)
|
||||
self.assert_equal(
|
||||
repr(Location('/some/absolute/path::archive')),
|
||||
|
|
|
@ -32,7 +32,7 @@ class KeyTestCase(AtticTestCase):
|
|||
|
||||
def setUp(self):
|
||||
self.tmppath = tempfile.mkdtemp()
|
||||
os.environ['ATTIC_KEYS_DIR'] = self.tmppath
|
||||
os.environ['BORG_KEYS_DIR'] = self.tmppath
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.tmppath)
|
||||
|
@ -51,7 +51,7 @@ class KeyTestCase(AtticTestCase):
|
|||
self.assert_equal(data, key.decrypt(key.id_hash(data), key.encrypt(data)))
|
||||
|
||||
def test_keyfile(self):
|
||||
os.environ['ATTIC_PASSPHRASE'] = 'test'
|
||||
os.environ['BORG_PASSPHRASE'] = 'test'
|
||||
key = KeyfileKey.create(self.MockRepository(), self.MockArgs())
|
||||
self.assert_equal(bytes_to_long(key.enc_cipher.iv, 8), 0)
|
||||
manifest = key.encrypt(b'XXX')
|
||||
|
@ -70,14 +70,14 @@ class KeyTestCase(AtticTestCase):
|
|||
self.assert_equal(data, key2.decrypt(key.id_hash(data), key.encrypt(data)))
|
||||
|
||||
def test_keyfile2(self):
|
||||
with open(os.path.join(os.environ['ATTIC_KEYS_DIR'], 'keyfile'), 'w') as fd:
|
||||
with open(os.path.join(os.environ['BORG_KEYS_DIR'], 'keyfile'), 'w') as fd:
|
||||
fd.write(self.keyfile2_key_file)
|
||||
os.environ['ATTIC_PASSPHRASE'] = 'passphrase'
|
||||
os.environ['BORG_PASSPHRASE'] = 'passphrase'
|
||||
key = KeyfileKey.detect(self.MockRepository(), self.keyfile2_cdata)
|
||||
self.assert_equal(key.decrypt(self.keyfile2_id, self.keyfile2_cdata), b'payload')
|
||||
|
||||
def test_passphrase(self):
|
||||
os.environ['ATTIC_PASSPHRASE'] = 'test'
|
||||
os.environ['BORG_PASSPHRASE'] = 'test'
|
||||
key = PassphraseKey.create(self.MockRepository(), None)
|
||||
self.assert_equal(bytes_to_long(key.enc_cipher.iv, 8), 0)
|
||||
self.assert_equal(hexlify(key.id_key), b'793b0717f9d8fb01c751a487e9b827897ceea62409870600013fbc6b4d8d7ca6')
|
||||
|
|
|
@ -73,17 +73,17 @@ qthelp:
|
|||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/attic.qhcp"
|
||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/borg.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/attic.qhc"
|
||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/borg.qhc"
|
||||
|
||||
devhelp:
|
||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||
@echo
|
||||
@echo "Build finished."
|
||||
@echo "To view the help file:"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/attic"
|
||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/attic"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/borg"
|
||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/borg"
|
||||
@echo "# devhelp"
|
||||
|
||||
epub:
|
||||
|
@ -140,7 +140,3 @@ gh-pages: html
|
|||
|
||||
inotify: html
|
||||
while inotifywait -r . --exclude usage.rst --exclude '_build/*' ; do make html ; done
|
||||
|
||||
upload: html
|
||||
rsync -va -e ssh _build/html/ sushi.edgewall.com:/srv/attic/www/
|
||||
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
<link href='//fonts.googleapis.com/css?family=Oswald:700|Inconsolata:400,700'
|
||||
rel='stylesheet' type='text/css'>
|
||||
<div class="sidebarlogo">
|
||||
<a href="{{ pathto('index') }}">
|
||||
<div class="title">Attic</div>
|
||||
</a>
|
||||
</div>
|
|
@ -1,10 +0,0 @@
|
|||
<a href="https://github.com/jborg/attic"><img style="position: fixed; top: 0; right: 0; border: 0;"
|
||||
src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png" alt="Fork me on GitHub"></a>
|
||||
|
||||
<h3>Useful Links</h3>
|
||||
<ul>
|
||||
<li><a href="https://pypi.python.org/pypi/Attic">Attic @ PyPI</a></li>
|
||||
<li><a href="https://github.com/jborg/attic">Attic @ github</a></li>
|
||||
<li><a href="https://attic-backup.org/">Online Documentation</a></li>
|
||||
<li><a href="https://github.com/jborg/attic/issues">Issue Tracker</a></li>
|
||||
</ul>
|
|
@ -0,0 +1,5 @@
|
|||
<div class="sidebarlogo">
|
||||
<a href="{{ pathto('index') }}">
|
||||
<div class="title">Borg</div>
|
||||
</a>
|
||||
</div>
|
|
@ -0,0 +1,11 @@
|
|||
<a href="https://github.com/borgbackup/borg"><img style="position: fixed; top: 0; right: 0; border: 0;"
|
||||
src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png" alt="Fork me on GitHub"></a>
|
||||
|
||||
<h3>Useful Links</h3>
|
||||
<ul>
|
||||
<li><a href="https://borgbackup.github.io/">Main Web Site</a></li>
|
||||
<li><a href="https://pypi.python.org/pypi/borgbackup">PyPI packages</a></li>
|
||||
<li><a href="https://github.com/borgbackup/borg">GitHub</a></li>
|
||||
<li><a href="https://github.com/borgbackup/borg/issues">Issue Tracker</a></li>
|
||||
<li><a href="http://librelist.com/browser/borgbackup/">Mailing List</a></li>
|
||||
</ul>
|
|
@ -1,12 +1,14 @@
|
|||
@import url("basic.css");
|
||||
@import url(//fonts.googleapis.com/css?family=Black+Ops+One);
|
||||
|
||||
body {
|
||||
font-family: Helvetica;
|
||||
background-color: white;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
background-color: black;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
div.related {
|
||||
display: none;
|
||||
background-color: black;
|
||||
|
@ -14,10 +16,12 @@ div.related {
|
|||
width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
div.related a {
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
div.document {
|
||||
width: 1030px;
|
||||
margin: 0 auto;
|
||||
|
@ -27,114 +31,144 @@ div.documentwrapper {
|
|||
float: right;
|
||||
width: 760px;
|
||||
padding: 0 20px 20px 20px;
|
||||
background-color: #f3f3f3;
|
||||
color: #00aa00;
|
||||
background-color: #000000;
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
margin-left: 0;
|
||||
parring-right: 20px;
|
||||
padding-right: 20px;
|
||||
width: 230px;
|
||||
background: #e9e9e9;
|
||||
background: #081008;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
h1, h2, h3 {
|
||||
font-family: "Oswald";
|
||||
font-weight: normal;
|
||||
color: #333;
|
||||
color: #33dd33;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: .8em 0 .5em;
|
||||
font-size: 200%;
|
||||
}
|
||||
h2, h3 {
|
||||
|
||||
h2 {
|
||||
margin: 1.2em 0 .6em;
|
||||
font-size: 140%;
|
||||
}
|
||||
h1 { font-size: 200%;}
|
||||
h2 { font-size: 140%;}
|
||||
h3 { font-size: 110%;}
|
||||
|
||||
h3 {
|
||||
margin: 1.2em 0 .6em;
|
||||
font-size: 110%;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding-left: 1.2em;
|
||||
margin-bottom: .3em;
|
||||
}
|
||||
|
||||
ul ul {
|
||||
font-size: 95%;
|
||||
}
|
||||
|
||||
li {
|
||||
margin: .1em 0;
|
||||
}
|
||||
a:link, a:visited {
|
||||
color: #00608f;
|
||||
|
||||
a:link {
|
||||
color: #dddd00;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #990000;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #00B0E4;
|
||||
border-bottom: 1px dotted #00B0E4;
|
||||
color: #dd0000;
|
||||
border-bottom: 1px dotted #dd0000;
|
||||
}
|
||||
|
||||
div.sphinxsidebar a:link, div.sphinxsidebar a:visited {
|
||||
color: #555;
|
||||
border-bottom: 1px dotted #555;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
color: #00aa00;
|
||||
background: 0000000;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input {
|
||||
border: 1px solid #ccc;
|
||||
color: #00cc00;
|
||||
background: 0000000;
|
||||
border: 1px solid #444444;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 10px 20px;
|
||||
background: white;
|
||||
color: #222;
|
||||
background: #101010;
|
||||
color: #22cc22;
|
||||
line-height: 1.5em;
|
||||
border-bottom: 2px solid black;
|
||||
font-family: "Inconsolata";
|
||||
}
|
||||
|
||||
pre a:link,
|
||||
pre a:visited {
|
||||
color: #00B0E4;
|
||||
color: #00b0e4;
|
||||
}
|
||||
|
||||
div.sidebarlogo .title {
|
||||
font-family: "Oswald";
|
||||
font-family: 'Black Ops One', cursive;
|
||||
font-size: 500%;
|
||||
}
|
||||
|
||||
div.sidebarlogo a {
|
||||
color: #00dd00;
|
||||
}
|
||||
|
||||
div.sidebarlogo .subtitle {
|
||||
font-style: italic;
|
||||
color: #777;
|
||||
}
|
||||
|
||||
tt span.pre {
|
||||
font-size: 110%;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-family: "Oswald";
|
||||
font-size: 95%;
|
||||
}
|
||||
|
||||
div.admonition p.admonition-title + p {
|
||||
display: inline;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
div.admonition p {
|
||||
margin-bottom: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
p.admonition-title {
|
||||
display: inline;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
p.admonition-title:after {
|
||||
content: ":";
|
||||
content: ":";
|
||||
}
|
||||
|
||||
div.note {
|
||||
background-color: #ff5;
|
||||
background-color: #0f5;
|
||||
border-bottom: 2px solid #d22;
|
||||
}
|
||||
|
||||
div.seealso {
|
||||
background-color: #ffe;
|
||||
border: 1px solid #ff6;
|
||||
background-color: #0fe;
|
||||
border: 1px solid #0f6;
|
||||
border-radius: .4em;
|
||||
box-shadow: 2px 2px #dd6;
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
[theme]
|
||||
inherit = basic
|
||||
stylesheet = attic.css
|
||||
stylesheet = local.css
|
||||
pygments_style = tango
|
||||
|
||||
[options]
|
23
docs/conf.py
23
docs/conf.py
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Attic documentation build configuration file, created by
|
||||
# documentation build configuration file, created by
|
||||
# sphinx-quickstart on Sat Sep 10 18:18:25 2011.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its containing dir.
|
||||
|
@ -40,7 +40,7 @@ source_suffix = '.rst'
|
|||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = 'Attic - Deduplicating Archiver'
|
||||
project = 'Borg - Deduplicating Archiver'
|
||||
copyright = '2010-2014, Jonas Borgström'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
|
@ -91,7 +91,7 @@ pygments_style = 'sphinx'
|
|||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'attic'
|
||||
html_theme = 'local'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
|
@ -166,7 +166,7 @@ html_show_copyright = False
|
|||
#html_file_suffix = None
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'atticdoc'
|
||||
htmlhelp_basename = 'borgdoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output --------------------------------------------------
|
||||
|
@ -180,8 +180,8 @@ htmlhelp_basename = 'atticdoc'
|
|||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
('index', 'Attic.tex', 'Attic Documentation',
|
||||
'Jonas Borgström', 'manual'),
|
||||
('index', 'Borg.tex', 'Borg Documentation',
|
||||
'see "AUTHORS" file', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
|
@ -213,14 +213,13 @@ latex_documents = [
|
|||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
#man_pages = [
|
||||
# ('man', 'attic', 'Attic',
|
||||
# ['Jonas Borgström'], 1)
|
||||
# ('man', 'borg', 'Borg',
|
||||
# ['see "AUTHORS" file'], 1)
|
||||
#]
|
||||
|
||||
extensions = ['sphinx.ext.extlinks']
|
||||
|
||||
extlinks = {
|
||||
'issue': ('https://github.com/jborg/attic/issues/%s', '#'),
|
||||
'targz_url': ('https://pypi.python.org/packages/source/A/Attic/%%s-%s.tar.gz' % version, None),
|
||||
'artifacts': ('https://attic-backup.org/downloads/releases/%s/%%s' % version, '')
|
||||
}
|
||||
'issue': ('https://github.com/borgbackup/borg/issues/%s', '#'),
|
||||
'targz_url': ('https://pypi.python.org/packages/source/b/borgbackup/%%s-%s.tar.gz' % version, None),
|
||||
}
|
||||
|
|
10
docs/faq.rst
10
docs/faq.rst
|
@ -13,16 +13,16 @@ Can I backup VM disk images?
|
|||
makes sure only the modified parts of the file are stored.
|
||||
|
||||
Can I backup from multiple servers into a single repository?
|
||||
Yes, but in order for the deduplication used by Attic to work, it
|
||||
Yes, but in order for the deduplication used by Borg to work, it
|
||||
needs to keep a local cache containing checksums of all file
|
||||
chunks already stored in the repository. This cache is stored in
|
||||
``~/.cache/attic/``. If Attic detects that a repository has been
|
||||
``~/.cache/borg/``. If Borg detects that a repository has been
|
||||
modified since the local cache was updated it will need to rebuild
|
||||
the cache. This rebuild can be quite time consuming.
|
||||
|
||||
So, yes it's possible. But it will be most efficient if a single
|
||||
repository is only modified from one place. Also keep in mind that
|
||||
Attic will keep an exclusive lock on the repository while creating
|
||||
Borg will keep an exclusive lock on the repository while creating
|
||||
or deleting archives, which may make *simultaneous* backups fail.
|
||||
|
||||
Which file attributes are preserved?
|
||||
|
@ -41,7 +41,7 @@ Which file attributes are preserved?
|
|||
|
||||
How can I specify the encryption passphrase programmatically?
|
||||
The encryption passphrase can be specified programmatically using the
|
||||
`ATTIC_PASSPHRASE` environment variable. This is convenient when setting up
|
||||
`BORG_PASSPHRASE` environment variable. This is convenient when setting up
|
||||
automated encrypted backups. Another option is to use
|
||||
key file based encryption with a blank passphrase. See
|
||||
:ref:`encrypted_repos` for more details.
|
||||
|
@ -49,7 +49,7 @@ How can I specify the encryption passphrase programmatically?
|
|||
When backing up to remote servers, is data encrypted before leaving the local machine, or do I have to trust that the remote server isn't malicious?
|
||||
Yes, everything is encrypted before leaving the local machine.
|
||||
|
||||
If a backup stops mid-way, does the already-backed-up data stay there? I.e. does Attic resume backups?
|
||||
If a backup stops mid-way, does the already-backed-up data stay there? I.e. does Borg resume backups?
|
||||
Yes, during a backup a special checkpoint archive named ``<archive-name>.checkpoint`` is saved every 5 minutes
|
||||
containing all the data backed-up until that point. This means that at most 5 minutes worth of data needs to be
|
||||
retransmitted if a backup needs to be restarted.
|
||||
|
|
|
@ -26,7 +26,7 @@ Off-site backups
|
|||
long as |project_name| is installed.
|
||||
|
||||
Backups mountable as filesystems
|
||||
Backup archives are :ref:`mountable <attic_mount>` as
|
||||
Backup archives are :ref:`mountable <borg_mount>` as
|
||||
`userspace filesystems`_ for easy backup verification and restores.
|
||||
|
||||
|
||||
|
@ -53,8 +53,8 @@ Repository
|
|||
A repository is a filesystem directory storing data from zero or more
|
||||
archives. The data in a repository is both deduplicated and
|
||||
optionally encrypted making it both efficient and safe. Repositories are
|
||||
created using :ref:`attic_init` and the contents can be listed using
|
||||
:ref:`attic_list`.
|
||||
created using :ref:`borg_init` and the contents can be listed using
|
||||
:ref:`borg_list`.
|
||||
|
||||
Key file
|
||||
When a repository is initialized a key file containing a password
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
.. highlight:: bash
|
||||
.. |project_name| replace:: ``Attic``
|
||||
.. |package_dirname| replace:: Attic-|version|
|
||||
.. |project_name| replace:: ``Borg``
|
||||
.. |package_dirname| replace:: borgbackup-|version|
|
||||
.. |package_filename| replace:: |package_dirname|.tar.gz
|
||||
.. |package_url| replace:: https://pypi.python.org/packages/source/A/Attic/|package_filename|
|
||||
.. |git_url| replace:: https://github.com/jborg/attic.git
|
||||
.. |package_url| replace:: https://pypi.python.org/packages/source/b/borgbackup/|package_filename|
|
||||
.. |git_url| replace:: https://github.com/borgbackup/borg.git
|
||||
.. _github: https://github.com/borgbackup/borg
|
||||
.. _issue tracker: https://github.com/borgbackup/borg/issues
|
||||
.. _deduplication: https://en.wikipedia.org/wiki/Data_deduplication
|
||||
.. _AES: https://en.wikipedia.org/wiki/Advanced_Encryption_Standard
|
||||
.. _HMAC-SHA256: http://en.wikipedia.org/wiki/HMAC
|
||||
|
@ -11,7 +13,6 @@
|
|||
.. _PBKDF2: https://en.wikipedia.org/wiki/PBKDF2
|
||||
.. _ACL: https://en.wikipedia.org/wiki/Access_control_list
|
||||
.. _libacl: http://savannah.nongnu.org/projects/acl/
|
||||
.. _github: https://github.com/jborg/attic
|
||||
.. _OpenSSL: https://www.openssl.org/
|
||||
.. _Python: http://www.python.org/
|
||||
.. _Buzhash: https://en.wikipedia.org/wiki/Buzhash
|
||||
|
@ -19,13 +20,8 @@
|
|||
.. _`msgpack-python`: https://pypi.python.org/pypi/msgpack-python/
|
||||
.. _llfuse: https://pypi.python.org/pypi/llfuse/
|
||||
.. _homebrew: http://mxcl.github.io/homebrew/
|
||||
.. _issue tracker: https://github.com/jborg/attic/issues
|
||||
.. _userspace filesystems: https://en.wikipedia.org/wiki/Filesystem_in_Userspace
|
||||
.. _librelist: http://librelist.com/
|
||||
.. _Debian: http://packages.debian.org/attic
|
||||
.. _Ubuntu: http://packages.ubuntu.com/attic
|
||||
.. _Arch Linux: https://aur.archlinux.org/packages/attic/
|
||||
.. _Slackware: http://slackbuilds.org/result/?search=Attic
|
||||
.. _Cython: http://cython.org/
|
||||
.. _virtualenv: https://pypi.python.org/pypi/virtualenv/
|
||||
.. _mailing list discussion about internals: http://librelist.com/browser/attic/2014/5/6/questions-and-suggestions-about-inner-working-of-attic>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.. include:: global.rst.inc
|
||||
|
||||
Welcome to Attic
|
||||
Welcome to Borg
|
||||
================
|
||||
|project_name| is a deduplicating backup program written in Python.
|
||||
The main goal of |project_name| is to provide an efficient and secure way
|
||||
|
@ -13,9 +13,9 @@ Easy to use
|
|||
Initialize a new backup :ref:`repository <repository_def>` and create your
|
||||
first backup :ref:`archive <archive_def>` in two lines::
|
||||
|
||||
$ attic init /somewhere/my-repository.attic
|
||||
$ attic create /somewhere/my-repository.attic::Monday ~/Documents
|
||||
$ attic create --stats /somewhere/my-repository.attic::Tuesday ~/Documents
|
||||
$ borg init /somewhere/my-repository.borg
|
||||
$ borg create /somewhere/my-repository.borg::Monday ~/Documents
|
||||
$ borg create --stats /somewhere/my-repository.borg::Tuesday ~/Documents
|
||||
Archive name: Tuesday
|
||||
Archive fingerprint: 387a5e3f9b0e792e91ce87134b0f4bfe17677d9248cb5337f3fbf3a8e157942a
|
||||
Start time: Tue Mar 25 12:00:10 2014
|
||||
|
@ -32,10 +32,7 @@ Easy installation
|
|||
-----------------
|
||||
You can use pip to install |project_name| quickly and easily::
|
||||
|
||||
$ pip3 install attic
|
||||
|
||||
|project_name| is also part of the Debian_, Ubuntu_, `Arch Linux`_ and Slackware_
|
||||
distributions of GNU/Linux.
|
||||
$ pip3 install borgbackup
|
||||
|
||||
Need more help with installing? See :ref:`installation`.
|
||||
|
||||
|
@ -59,13 +56,18 @@ If you've found a bug or have a concrete feature request, you can add your bug
|
|||
report or feature request directly to the project's `issue tracker`_. For more
|
||||
general questions or discussions, a post to the mailing list is preferred.
|
||||
|
||||
IRC
|
||||
---
|
||||
Join us on channel ##borgbackup on chat.freenode.net. As usual on IRC, just
|
||||
ask or tell directly and then patiently wait for replies. Stay connected.
|
||||
|
||||
Mailing list
|
||||
------------
|
||||
|
||||
There is a mailing list for Attic on librelist_ that you can use for feature
|
||||
requests and general discussions about Attic. A mailing list archive is
|
||||
available `here <http://librelist.com/browser/attic/>`_.
|
||||
There is a mailing list for Borg on librelist_ that you can use for feature
|
||||
requests and general discussions about Borg. A mailing list archive is
|
||||
available `here <http://librelist.com/browser/borgbackup/>`_.
|
||||
|
||||
To subscribe to the list, send an email to attic@librelist.com and reply
|
||||
To subscribe to the list, send an email to borgbackup@librelist.com and reply
|
||||
to the confirmation mail. Likewise, to unsubscribe, send an email to
|
||||
attic-unsubscribe@librelist.com and reply to the confirmation mail.
|
||||
borgbackup-unsubscribe@librelist.com and reply to the confirmation mail.
|
||||
|
|
|
@ -36,11 +36,11 @@ Installing from PyPI using pip
|
|||
|
||||
To install |project_name| system-wide::
|
||||
|
||||
$ sudo pip3 install Attic
|
||||
$ sudo pip3 install borgbackup
|
||||
|
||||
To install it in a user-specific account::
|
||||
|
||||
$ pip3 install --user Attic
|
||||
$ pip3 install --user borgbackup
|
||||
|
||||
Then add ``$HOME/.library/bin`` to your ``$PATH``.
|
||||
|
||||
|
@ -48,7 +48,7 @@ Installing from source tarballs
|
|||
-------------------------------
|
||||
.. parsed-literal::
|
||||
|
||||
$ curl -O :targz_url:`Attic`
|
||||
$ curl -O :targz_url:`Borg`
|
||||
$ tar -xvzf |package_filename|
|
||||
$ cd |package_dirname|
|
||||
$ sudo python3 setup.py install
|
||||
|
@ -58,20 +58,8 @@ Installing from git
|
|||
.. parsed-literal::
|
||||
|
||||
$ git clone |git_url|
|
||||
$ cd attic
|
||||
$ cd borg
|
||||
$ sudo python3 setup.py install
|
||||
|
||||
Please note that when installing from git, Cython_ is required to generate some files that
|
||||
are normally bundled with the release tarball.
|
||||
|
||||
Packages
|
||||
--------
|
||||
|
||||
|project_name| is also part of the Debian_, Ubuntu_, `Arch Linux`_ and Slackware_
|
||||
distributions of GNU/Linux.
|
||||
|
||||
Standalone binaries
|
||||
-------------------
|
||||
|
||||
Prebuilt standalone binaries that work on
|
||||
most Linux systems can be found :artifacts:`here <>`.
|
||||
|
|
|
@ -251,14 +251,14 @@ security but limits the maximum repository capacity to only 295
|
|||
exabytes (2**64 * 16 bytes).
|
||||
|
||||
Encryption keys are either a passphrase, passed through the
|
||||
``ATTIC_PASSPHRASE`` environment or prompted on the commandline, or
|
||||
``BORG_PASSPHRASE`` environment or prompted on the commandline, or
|
||||
stored in automatically generated key files.
|
||||
|
||||
Key files
|
||||
---------
|
||||
|
||||
When initialized with the ``init -e keyfile`` command, |project_name|
|
||||
needs an associated file in ``$HOME/.attic/keys`` to read and write
|
||||
needs an associated file in ``$HOME/.borg/keys`` to read and write
|
||||
the repository. The format is based on msgpack_, base64 encoding and
|
||||
PBKDF2_ SHA256 hashing, which is then encoded again in a msgpack_.
|
||||
|
||||
|
@ -312,6 +312,6 @@ data
|
|||
described above
|
||||
|
||||
The resulting msgpack_ is then encoded using base64 and written to the
|
||||
key file, wrapped using the standard ``textwrap`` module with a
|
||||
header. The header is a single line with the string ``ATTIC_KEY``, a
|
||||
space and a hexadecimal representation of the repository id.
|
||||
key file, wrapped using the standard ``textwrap`` module with a header.
|
||||
The header is a single line with a MAGIC string, a space and a hexadecimal
|
||||
representation of the repository id.
|
||||
|
|
|
@ -13,16 +13,16 @@ A step by step example
|
|||
|
||||
1. Before a backup can be made a repository has to be initialized::
|
||||
|
||||
$ attic init /somewhere/my-repository.attic
|
||||
$ borg init /somewhere/my-repository.borg
|
||||
|
||||
2. Backup the ``~/src`` and ``~/Documents`` directories into an archive called
|
||||
*Monday*::
|
||||
|
||||
$ attic create /somewhere/my-repository.attic::Monday ~/src ~/Documents
|
||||
$ borg create /somewhere/my-repository.borg::Monday ~/src ~/Documents
|
||||
|
||||
3. The next day create a new archive called *Tuesday*::
|
||||
|
||||
$ attic create --stats /somewhere/my-repository.attic::Tuesday ~/src ~/Documents
|
||||
$ borg create --stats /somewhere/my-repository.borg::Tuesday ~/src ~/Documents
|
||||
|
||||
This backup will be a lot quicker and a lot smaller since only new never
|
||||
before seen data is stored. The ``--stats`` option causes |project_name| to
|
||||
|
@ -42,27 +42,27 @@ A step by step example
|
|||
|
||||
4. List all archives in the repository::
|
||||
|
||||
$ attic list /somewhere/my-repository.attic
|
||||
$ borg list /somewhere/my-repository.borg
|
||||
Monday Mon Mar 24 11:59:35 2014
|
||||
Tuesday Tue Mar 25 12:00:10 2014
|
||||
|
||||
5. List the contents of the *Monday* archive::
|
||||
|
||||
$ attic list /somewhere/my-repository.attic::Monday
|
||||
$ borg list /somewhere/my-repository.borg::Monday
|
||||
drwxr-xr-x user group 0 Jan 06 15:22 home/user/Documents
|
||||
-rw-r--r-- user group 7961 Nov 17 2012 home/user/Documents/Important.doc
|
||||
...
|
||||
|
||||
6. Restore the *Monday* archive::
|
||||
|
||||
$ attic extract /somwhere/my-repository.attic::Monday
|
||||
$ borg extract /somwhere/my-repository.borg::Monday
|
||||
|
||||
7. Recover disk space by manually deleting the *Monday* archive::
|
||||
|
||||
$ attic delete /somwhere/my-backup.attic::Monday
|
||||
$ borg delete /somwhere/my-backup.borg::Monday
|
||||
|
||||
.. Note::
|
||||
Attic is quiet by default. Add the ``-v`` or ``--verbose`` option to
|
||||
Borg is quiet by default. Add the ``-v`` or ``--verbose`` option to
|
||||
get progress reporting during command execution.
|
||||
|
||||
Automating backups
|
||||
|
@ -70,15 +70,15 @@ Automating backups
|
|||
|
||||
The following example script backs up ``/home`` and
|
||||
``/var/www`` to a remote server. The script also uses the
|
||||
:ref:`attic_prune` subcommand to maintain a certain number
|
||||
:ref:`borg_prune` subcommand to maintain a certain number
|
||||
of old archives::
|
||||
|
||||
#!/bin/sh
|
||||
REPOSITORY=username@remoteserver.com:repository.attic
|
||||
REPOSITORY=username@remoteserver.com:repository.borg
|
||||
|
||||
# Backup all of /home and /var/www except a few
|
||||
# excluded directories
|
||||
attic create --stats \
|
||||
borg create --stats \
|
||||
$REPOSITORY::hostname-`date +%Y-%m-%d` \
|
||||
/home \
|
||||
/var/www \
|
||||
|
@ -88,7 +88,7 @@ of old archives::
|
|||
|
||||
# Use the `prune` subcommand to maintain 7 daily, 4 weekly
|
||||
# and 6 monthly archives.
|
||||
attic prune -v $REPOSITORY --keep-daily=7 --keep-weekly=4 --keep-monthly=6
|
||||
borg prune -v $REPOSITORY --keep-daily=7 --keep-weekly=4 --keep-monthly=6
|
||||
|
||||
.. _encrypted_repos:
|
||||
|
||||
|
@ -97,7 +97,7 @@ Repository encryption
|
|||
|
||||
Repository encryption is enabled at repository creation time::
|
||||
|
||||
$ attic init --encryption=passphrase|keyfile PATH
|
||||
$ borg init --encryption=passphrase|keyfile PATH
|
||||
|
||||
When repository encryption is enabled all data is encrypted using 256-bit AES_
|
||||
encryption and the integrity and authenticity is verified using `HMAC-SHA256`_.
|
||||
|
@ -116,11 +116,11 @@ Passphrase based encryption
|
|||
|
||||
.. Note::
|
||||
For automated backups the passphrase can be specified using the
|
||||
`ATTIC_PASSPHRASE` environment variable.
|
||||
`BORG_PASSPHRASE` environment variable.
|
||||
|
||||
Key file based encryption
|
||||
This method generates random keys at repository initialization time that
|
||||
are stored in a password protected file in the ``~/.attic/keys/`` directory.
|
||||
are stored in a password protected file in the ``~/.borg/keys/`` directory.
|
||||
The key file is a printable text file. This method is secure and suitable
|
||||
for automated backups.
|
||||
|
||||
|
@ -138,18 +138,18 @@ Remote repositories
|
|||
host is accessible using SSH. This is fastest and easiest when |project_name|
|
||||
is installed on the remote host, in which case the following syntax is used::
|
||||
|
||||
$ attic init user@hostname:repository.attic
|
||||
$ borg init user@hostname:repository.borg
|
||||
|
||||
or::
|
||||
|
||||
$ attic init ssh://user@hostname:port/repository.attic
|
||||
$ borg init ssh://user@hostname:port/repository.borg
|
||||
|
||||
If it is not possible to install |project_name| on the remote host,
|
||||
it is still possible to use the remote host to store a repository by
|
||||
mounting the remote filesystem, for example, using sshfs::
|
||||
|
||||
$ sshfs user@hostname:/path/to/folder /tmp/mymountpoint
|
||||
$ attic init /tmp/mymountpoint/repository.attic
|
||||
$ borg init /tmp/mymountpoint/repository.borg
|
||||
$ fusermount -u /tmp/mymountpoint
|
||||
|
||||
However, be aware that sshfs doesn't fully implement POSIX locks, so
|
||||
|
|
|
@ -4,10 +4,10 @@ if [ ! -d usage ]; then
|
|||
fi
|
||||
for cmd in change-passphrase check create delete extract info init list mount prune; do
|
||||
FILENAME="usage/$cmd.rst.inc"
|
||||
LINE=`echo -n attic $cmd | tr 'a-z- ' '-'`
|
||||
echo -e ".. _attic_$cmd:\n" > $FILENAME
|
||||
echo -e "attic $cmd\n$LINE\n::\n\n" >> $FILENAME
|
||||
attic help $cmd --usage-only | sed -e 's/^/ /' >> $FILENAME
|
||||
LINE=`echo -n borg $cmd | tr 'a-z- ' '-'`
|
||||
echo -e ".. _borg_$cmd:\n" > $FILENAME
|
||||
echo -e "borg $cmd\n$LINE\n::\n\n" >> $FILENAME
|
||||
borg help $cmd --usage-only | sed -e 's/^/ /' >> $FILENAME
|
||||
echo -e "\nDescription\n~~~~~~~~~~~\n" >> $FILENAME
|
||||
attic help $cmd --epilog-only >> $FILENAME
|
||||
borg help $cmd --epilog-only >> $FILENAME
|
||||
done
|
||||
|
|
|
@ -22,13 +22,13 @@ Examples
|
|||
::
|
||||
|
||||
# Local repository
|
||||
$ attic init /data/mybackuprepo.attic
|
||||
$ borg init /data/mybackuprepo.borg
|
||||
|
||||
# Remote repository
|
||||
$ attic init user@hostname:mybackuprepo.attic
|
||||
$ borg init user@hostname:mybackuprepo.borg
|
||||
|
||||
# Encrypted remote repository
|
||||
$ attic init --encryption=passphrase user@hostname:mybackuprepo.attic
|
||||
$ borg init --encryption=passphrase user@hostname:mybackuprepo.borg
|
||||
|
||||
|
||||
.. include:: usage/create.rst.inc
|
||||
|
@ -38,17 +38,17 @@ Examples
|
|||
::
|
||||
|
||||
# Backup ~/Documents into an archive named "my-documents"
|
||||
$ attic create /data/myrepo.attic::my-documents ~/Documents
|
||||
$ borg create /data/myrepo.borg::my-documents ~/Documents
|
||||
|
||||
# Backup ~/Documents and ~/src but exclude pyc files
|
||||
$ attic create /data/myrepo.attic::my-files \
|
||||
$ borg create /data/myrepo.borg::my-files \
|
||||
~/Documents \
|
||||
~/src \
|
||||
--exclude '*.pyc'
|
||||
|
||||
# Backup the root filesystem into an archive named "root-YYYY-MM-DD"
|
||||
NAME="root-`date +%Y-%m-%d`"
|
||||
$ attic create /data/myrepo.attic::$NAME / --do-not-cross-mountpoints
|
||||
$ borg create /data/myrepo.borg::$NAME / --do-not-cross-mountpoints
|
||||
|
||||
|
||||
.. include:: usage/extract.rst.inc
|
||||
|
@ -58,16 +58,16 @@ Examples
|
|||
::
|
||||
|
||||
# Extract entire archive
|
||||
$ attic extract /data/myrepo::my-files
|
||||
$ borg extract /data/myrepo::my-files
|
||||
|
||||
# Extract entire archive and list files while processing
|
||||
$ attic extract -v /data/myrepo::my-files
|
||||
$ borg extract -v /data/myrepo::my-files
|
||||
|
||||
# Extract the "src" directory
|
||||
$ attic extract /data/myrepo::my-files home/USERNAME/src
|
||||
$ borg extract /data/myrepo::my-files home/USERNAME/src
|
||||
|
||||
# Extract the "src" directory but exclude object files
|
||||
$ attic extract /data/myrepo::my-files home/USERNAME/src --exclude '*.o'
|
||||
$ borg extract /data/myrepo::my-files home/USERNAME/src --exclude '*.o'
|
||||
|
||||
.. include:: usage/check.rst.inc
|
||||
|
||||
|
@ -79,14 +79,14 @@ Examples
|
|||
~~~~~~~~
|
||||
::
|
||||
|
||||
$ attic list /data/myrepo
|
||||
$ borg list /data/myrepo
|
||||
my-files Thu Aug 1 23:33:22 2013
|
||||
my-documents Thu Aug 1 23:35:43 2013
|
||||
root-2013-08-01 Thu Aug 1 23:43:55 2013
|
||||
root-2013-08-02 Fri Aug 2 15:18:17 2013
|
||||
...
|
||||
|
||||
$ attic list /data/myrepo::root-2013-08-02
|
||||
$ borg list /data/myrepo::root-2013-08-02
|
||||
drwxr-xr-x root root 0 Jun 05 12:06 .
|
||||
lrwxrwxrwx root root 0 May 31 20:40 bin -> usr/bin
|
||||
drwxr-xr-x root root 0 Aug 01 22:08 etc
|
||||
|
@ -102,18 +102,18 @@ Examples
|
|||
::
|
||||
|
||||
# Keep 7 end of day and 4 additional end of week archives:
|
||||
$ attic prune /data/myrepo --keep-daily=7 --keep-weekly=4
|
||||
$ borg prune /data/myrepo --keep-daily=7 --keep-weekly=4
|
||||
|
||||
# Same as above but only apply to archive names starting with "foo":
|
||||
$ attic prune /data/myrepo --keep-daily=7 --keep-weekly=4 --prefix=foo
|
||||
$ borg prune /data/myrepo --keep-daily=7 --keep-weekly=4 --prefix=foo
|
||||
|
||||
# Keep 7 end of day, 4 additional end of week archives,
|
||||
# and an end of month archive for every month:
|
||||
$ attic prune /data/myrepo --keep-daily=7 --keep-weekly=4 --monthly=-1
|
||||
$ borg prune /data/myrepo --keep-daily=7 --keep-weekly=4 --monthly=-1
|
||||
|
||||
# Keep all backups in the last 10 days, 4 additional end of week archives,
|
||||
# and an end of month archive for every month:
|
||||
$ attic prune /data/myrepo --keep-within=10d --keep-weekly=4 --monthly=-1
|
||||
$ borg prune /data/myrepo --keep-within=10d --keep-weekly=4 --monthly=-1
|
||||
|
||||
|
||||
.. include:: usage/info.rst.inc
|
||||
|
@ -122,13 +122,13 @@ Examples
|
|||
~~~~~~~~
|
||||
::
|
||||
|
||||
$ attic info /data/myrepo::root-2013-08-02
|
||||
$ borg info /data/myrepo::root-2013-08-02
|
||||
Name: root-2013-08-02
|
||||
Fingerprint: bc3902e2c79b6d25f5d769b335c5c49331e6537f324d8d3badcb9a0917536dbb
|
||||
Hostname: myhostname
|
||||
Username: root
|
||||
Time: Fri Aug 2 15:18:17 2013
|
||||
Command line: /usr/bin/attic create --stats /data/myrepo::root-2013-08-02 / --do-not-cross-mountpoints
|
||||
Command line: /usr/bin/borg create --stats /data/myrepo::root-2013-08-02 / --do-not-cross-mountpoints
|
||||
Number of files: 147429
|
||||
Original size: 5344169493 (4.98 GB)
|
||||
Compressed size: 1748189642 (1.63 GB)
|
||||
|
@ -141,7 +141,7 @@ Examples
|
|||
~~~~~~~~
|
||||
::
|
||||
|
||||
$ attic mount /data/myrepo::root-2013-08-02 /tmp/mymountpoint
|
||||
$ borg mount /data/myrepo::root-2013-08-02 /tmp/mymountpoint
|
||||
$ ls /tmp/mymountpoint
|
||||
bin boot etc lib lib64 mnt opt root sbin srv usr var
|
||||
$ fusermount -u /tmp/mymountpoint
|
||||
|
@ -154,16 +154,16 @@ Examples
|
|||
::
|
||||
|
||||
# Create a key file protected repository
|
||||
$ attic init --encryption=keyfile /tmp/encrypted-repo
|
||||
$ borg init --encryption=keyfile /tmp/encrypted-repo
|
||||
Initializing repository at "/tmp/encrypted-repo"
|
||||
Enter passphrase (empty for no passphrase):
|
||||
Enter same passphrase again:
|
||||
Key file "/home/USER/.attic/keys/tmp_encrypted_repo" created.
|
||||
Key file "/home/USER/.borg/keys/tmp_encrypted_repo" created.
|
||||
Keep this file safe. Your data will be inaccessible without it.
|
||||
|
||||
# Change key file passphrase
|
||||
$ attic change-passphrase /tmp/encrypted-repo
|
||||
Enter passphrase for key file /home/USER/.attic/keys/tmp_encrypted_repo:
|
||||
$ borg change-passphrase /tmp/encrypted-repo
|
||||
Enter passphrase for key file /home/USER/.borg/keys/tmp_encrypted_repo:
|
||||
New passphrase:
|
||||
Enter same passphrase again:
|
||||
Key file "/home/USER/.attic/keys/tmp_encrypted_repo" updated
|
||||
Key file "/home/USER/.borg/keys/tmp_encrypted_repo" updated
|
||||
|
|
22
setup.py
22
setup.py
|
@ -7,11 +7,11 @@ import versioneer
|
|||
versioneer.versionfile_source = 'attic/_version.py'
|
||||
versioneer.versionfile_build = 'attic/_version.py'
|
||||
versioneer.tag_prefix = ''
|
||||
versioneer.parentdir_prefix = 'Attic-' # dirname like 'myproject-1.2.0'
|
||||
versioneer.parentdir_prefix = 'borgbackup-' # dirname like 'myproject-1.2.0'
|
||||
|
||||
min_python = (3, 2)
|
||||
if sys.version_info < min_python:
|
||||
print("Attic requires Python %d.%d or later" % min_python)
|
||||
print("Borg requires Python %d.%d or later" % min_python)
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
|
@ -54,7 +54,7 @@ except ImportError:
|
|||
platform_darwin_source = platform_darwin_source.replace('.pyx', '.c')
|
||||
from distutils.command.build_ext import build_ext
|
||||
if not all(os.path.exists(path) for path in [crypto_source, chunker_source, hashindex_source, platform_linux_source, platform_freebsd_source]):
|
||||
raise ImportError('The GIT version of Attic needs Cython. Install Cython or use a released version')
|
||||
raise ImportError('The GIT version of Borg needs Cython. Install Cython or use a released version')
|
||||
|
||||
|
||||
def detect_openssl(prefixes):
|
||||
|
@ -67,8 +67,8 @@ def detect_openssl(prefixes):
|
|||
|
||||
|
||||
possible_openssl_prefixes = ['/usr', '/usr/local', '/usr/local/opt/openssl', '/usr/local/ssl', '/usr/local/openssl', '/usr/local/attic', '/opt/local']
|
||||
if os.environ.get('ATTIC_OPENSSL_PREFIX'):
|
||||
possible_openssl_prefixes.insert(0, os.environ.get('ATTIC_OPENSSL_PREFIX'))
|
||||
if os.environ.get('BORG_OPENSSL_PREFIX'):
|
||||
possible_openssl_prefixes.insert(0, os.environ.get('BORG_OPENSSL_PREFIX'))
|
||||
ssl_prefix = detect_openssl(possible_openssl_prefixes)
|
||||
if not ssl_prefix:
|
||||
raise Exception('Unable to find OpenSSL >= 1.0 headers. (Looked here: {})'.format(', '.join(possible_openssl_prefixes)))
|
||||
|
@ -95,12 +95,12 @@ elif sys.platform == 'darwin':
|
|||
ext_modules.append(Extension('attic.platform_darwin', [platform_darwin_source]))
|
||||
|
||||
setup(
|
||||
name='Attic',
|
||||
name='borgbackup',
|
||||
version=versioneer.get_version(),
|
||||
author='Jonas Borgstrom',
|
||||
author_email='jonas@borgstrom.se',
|
||||
url='https://attic-backup.org/',
|
||||
description='Deduplicated backups',
|
||||
author='The Borg Collective (see AUTHORS file)',
|
||||
author_email='borgbackup@librelist.com',
|
||||
url='https://borgbackup.github.io/',
|
||||
description='Deduplicated, encrypted, authenticated and compressed backups',
|
||||
long_description=long_description,
|
||||
license='BSD',
|
||||
platforms=['Linux', 'MacOS X'],
|
||||
|
@ -117,7 +117,7 @@ setup(
|
|||
'Topic :: System :: Archiving :: Backup',
|
||||
],
|
||||
packages=['attic', 'attic.testsuite'],
|
||||
scripts=['scripts/attic'],
|
||||
scripts=['scripts/borg'],
|
||||
cmdclass=cmdclass,
|
||||
ext_modules=ext_modules,
|
||||
# msgpack pure python data corruption was fixed in 0.4.6.
|
||||
|
|
Loading…
Reference in New Issue