mirror of
https://github.com/borgbackup/borg.git
synced 2026-05-28 04:03:21 -04:00
Merge branch 'master' into merge
This commit is contained in:
commit
354b3d34e3
8 changed files with 50 additions and 28 deletions
8
CHANGES
8
CHANGES
|
|
@ -3,6 +3,14 @@ Attic Changelog
|
|||
|
||||
Here you can see the full list of changes between each Attic release.
|
||||
|
||||
Version 0.16
|
||||
------------
|
||||
|
||||
(bugfix release, released on X)
|
||||
- Fix "All archives" output for attic info. (#183)
|
||||
- More user friendly error message when repository key file is not found (#236)
|
||||
- Fix parsing of iso 8601 timestamps with zero microseconds (#282)
|
||||
|
||||
Version 0.15
|
||||
------------
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from datetime import datetime, timedelta, timezone
|
||||
from datetime import datetime
|
||||
from getpass import getuser
|
||||
from itertools import groupby
|
||||
import errno
|
||||
|
|
@ -17,7 +17,7 @@ from attic import xattr
|
|||
from attic.platform import acl_get, acl_set
|
||||
from attic.chunker import Chunker
|
||||
from attic.hashindex import ChunkIndex
|
||||
from attic.helpers import Error, uid2user, user2uid, gid2group, group2gid, \
|
||||
from attic.helpers import parse_timestamp, Error, uid2user, user2uid, gid2group, group2gid, \
|
||||
Manifest, Statistics, decode_dict, st_mtime_ns, make_path_safe, StableDict, int_to_bigint, bigint_to_int
|
||||
|
||||
ITEMS_BUFFER = 1024 * 1024
|
||||
|
|
@ -172,11 +172,7 @@ class Archive:
|
|||
@property
|
||||
def ts(self):
|
||||
"""Timestamp of archive creation in UTC"""
|
||||
t = self.metadata[b'time'].split('.', 1)
|
||||
dt = datetime.strptime(t[0], '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc)
|
||||
if len(t) > 1:
|
||||
dt += timedelta(seconds=float('.' + t[1]))
|
||||
return dt
|
||||
return parse_timestamp(self.metadata[b'time'])
|
||||
|
||||
def __repr__(self):
|
||||
return 'Archive(%r)' % self.name
|
||||
|
|
@ -225,9 +221,9 @@ class Archive:
|
|||
|
||||
def calc_stats(self, cache):
|
||||
def add(id):
|
||||
count, size, csize = self.cache.chunks[id]
|
||||
count, size, csize = cache.chunks[id]
|
||||
stats.update(size, csize, count == 1)
|
||||
self.cache.chunks[id] = count - 1, size, csize
|
||||
cache.chunks[id] = count - 1, size, csize
|
||||
def add_file_chunks(chunks):
|
||||
for id, _, _ in chunks:
|
||||
add(id)
|
||||
|
|
|
|||
|
|
@ -103,11 +103,7 @@ class Cache:
|
|||
os.remove(os.path.join(self.path, 'config')) # kill config first
|
||||
shutil.rmtree(self.path)
|
||||
|
||||
def open(self):
|
||||
if not os.path.isdir(self.path):
|
||||
raise Exception('%s Does not look like an Attic cache' % self.path)
|
||||
self.lock = UpgradableLock(os.path.join(self.path, 'config'), exclusive=True)
|
||||
self.rollback()
|
||||
def _do_open(self):
|
||||
self.config = RawConfigParser()
|
||||
self.config.read(os.path.join(self.path, 'config'))
|
||||
if self.config.getint('cache', 'version') != 1:
|
||||
|
|
@ -120,6 +116,12 @@ class Cache:
|
|||
self.chunks = ChunkIndex.read(os.path.join(self.path, 'chunks').encode('utf-8'))
|
||||
self.files = None
|
||||
|
||||
def open(self):
|
||||
if not os.path.isdir(self.path):
|
||||
raise Exception('%s Does not look like an Attic cache' % self.path)
|
||||
self.lock = UpgradableLock(os.path.join(self.path, 'config'), exclusive=True)
|
||||
self.rollback()
|
||||
|
||||
def close(self):
|
||||
if self.lock:
|
||||
self.lock.release()
|
||||
|
|
@ -192,6 +194,7 @@ class Cache:
|
|||
if os.path.exists(os.path.join(self.path, 'txn.tmp')):
|
||||
shutil.rmtree(os.path.join(self.path, 'txn.tmp'))
|
||||
self.txn_active = False
|
||||
self._do_open()
|
||||
|
||||
def sync(self):
|
||||
"""Initializes cache by fetching and reading all archive indicies
|
||||
|
|
|
|||
|
|
@ -197,6 +197,14 @@ def to_localtime(ts):
|
|||
return datetime(*time.localtime((ts - datetime(1970, 1, 1, tzinfo=timezone.utc)).total_seconds())[:6])
|
||||
|
||||
|
||||
def parse_timestamp(timestamp):
|
||||
"""Parse a ISO 8601 timestamp string"""
|
||||
if '.' in timestamp: # microseconds might not be pressent
|
||||
return datetime.strptime(timestamp, '%Y-%m-%dT%H:%M:%S.%f').replace(tzinfo=timezone.utc)
|
||||
else:
|
||||
return datetime.strptime(timestamp, '%Y-%m-%dT%H:%M:%S').replace(tzinfo=timezone.utc)
|
||||
|
||||
|
||||
def update_excludes(args):
|
||||
"""Merge exclude patterns from files with those on command line.
|
||||
Empty lines and lines starting with '#' are ignored, but whitespace
|
||||
|
|
|
|||
|
|
@ -17,6 +17,10 @@ class UnsupportedPayloadError(Error):
|
|||
"""Unsupported payload type {}. A newer version is required to access this repository.
|
||||
"""
|
||||
|
||||
class KeyfileNotFoundError(Error):
|
||||
"""No key file for repository {} found in {}.
|
||||
"""
|
||||
|
||||
|
||||
class HMAC(hmac.HMAC):
|
||||
"""Workaround a bug in Python < 3.4 Where HMAC does not accept memoryviews
|
||||
|
|
@ -228,7 +232,7 @@ class KeyfileKey(AESKeyBase):
|
|||
line = fd.readline().strip()
|
||||
if line and line.startswith(cls.FILE_ID) and line[10:] == id:
|
||||
return filename
|
||||
raise Exception('Key file for repository with ID %s not found' % id)
|
||||
raise KeyfileNotFoundError(repository._location.canonical_path(), get_keys_dir())
|
||||
|
||||
def load(self, filename, passphrase):
|
||||
with open(filename, 'r') as fd:
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
import os
|
||||
import sys
|
||||
|
||||
platform = os.uname()[0]
|
||||
|
||||
if platform == 'Linux':
|
||||
if sys.platform.startswith('linux'):
|
||||
from attic.platform_linux import acl_get, acl_set, API_VERSION
|
||||
elif platform == 'FreeBSD':
|
||||
elif sys.platform.startswith('freebsd'):
|
||||
from attic.platform_freebsd import acl_get, acl_set, API_VERSION
|
||||
elif platform == 'Darwin':
|
||||
elif sys.platform == 'darwin':
|
||||
from attic.platform_darwin import acl_get, acl_set, API_VERSION
|
||||
else:
|
||||
API_VERSION = 2
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ from datetime import datetime, timezone, timedelta
|
|||
import os
|
||||
import tempfile
|
||||
import unittest
|
||||
from attic.helpers import adjust_patterns, exclude_path, Location, format_timedelta, ExcludePattern, make_path_safe, UpgradableLock, prune_within, prune_split, \
|
||||
StableDict, int_to_bigint, bigint_to_int
|
||||
from attic.helpers import adjust_patterns, exclude_path, Location, format_timedelta, IncludePattern, ExcludePattern, make_path_safe, UpgradableLock, prune_within, prune_split, to_localtime, \
|
||||
StableDict, int_to_bigint, bigint_to_int, parse_timestamp
|
||||
from attic.testsuite import AtticTestCase
|
||||
import msgpack
|
||||
|
||||
|
|
@ -209,3 +209,10 @@ class StableDictTestCase(AtticTestCase):
|
|||
d = StableDict(foo=1, bar=2, boo=3, baz=4)
|
||||
self.assert_equal(list(d.items()), [('bar', 2), ('baz', 4), ('boo', 3), ('foo', 1)])
|
||||
self.assert_equal(hashlib.md5(msgpack.packb(d)).hexdigest(), 'fc78df42cd60691b3ac3dd2a2b39903f')
|
||||
|
||||
|
||||
class TestParseTimestamp(AtticTestCase):
|
||||
|
||||
def test(self):
|
||||
self.assert_equal(parse_timestamp('2015-04-19T20:25:00.226410'), datetime(2015, 4, 19, 20, 25, 0, 226410, timezone.utc))
|
||||
self.assert_equal(parse_timestamp('2015-04-19T20:25:00'), datetime(2015, 4, 19, 20, 25, 0, 0, timezone.utc))
|
||||
|
|
|
|||
8
setup.py
8
setup.py
|
|
@ -9,8 +9,6 @@ versioneer.versionfile_build = 'attic/_version.py'
|
|||
versioneer.tag_prefix = ''
|
||||
versioneer.parentdir_prefix = 'Attic-' # dirname like 'myproject-1.2.0'
|
||||
|
||||
platform = os.uname()[0]
|
||||
|
||||
min_python = (3, 2)
|
||||
if sys.version_info < min_python:
|
||||
print("Attic requires Python %d.%d or later" % min_python)
|
||||
|
|
@ -89,11 +87,11 @@ ext_modules = [
|
|||
Extension('attic.chunker', [chunker_source]),
|
||||
Extension('attic.hashindex', [hashindex_source])
|
||||
]
|
||||
if platform == 'Linux':
|
||||
if sys.platform.startswith('linux'):
|
||||
ext_modules.append(Extension('attic.platform_linux', [platform_linux_source], libraries=['acl']))
|
||||
elif platform == 'FreeBSD':
|
||||
elif sys.platform.startswith('freebsd'):
|
||||
ext_modules.append(Extension('attic.platform_freebsd', [platform_freebsd_source]))
|
||||
elif platform == 'Darwin':
|
||||
elif sys.platform == 'darwin':
|
||||
ext_modules.append(Extension('attic.platform_darwin', [platform_darwin_source]))
|
||||
|
||||
setup(
|
||||
|
|
|
|||
Loading…
Reference in a new issue