better attic create -v output

Added a indicator character to the left for (A)dded, (M)odified, (U)nchanged status
of regular files. Lowercase indicators are for special files.

You may or may not want to use grep to filter out U and d.
This commit is contained in:
Thomas Waldmann 2015-03-08 19:18:21 +01:00
parent 4ab4ecc7af
commit 9841af5542
2 changed files with 35 additions and 5 deletions

View File

@ -374,14 +374,22 @@ class Archive:
item = {b'path': make_path_safe(path), b'rdev': st.st_rdev}
item.update(self.stat_attrs(st, path))
self.add_item(item)
if stat.S_ISCHR(st.st_mode):
status = 'c' # char device
elif stat.S_ISBLK(st.st_mode):
status = 'b' # block device
return status
def process_symlink(self, path, st):
source = os.readlink(path)
item = {b'path': make_path_safe(path), b'source': source}
item.update(self.stat_attrs(st, path))
self.add_item(item)
status = 's' # symlink
return status
def process_file(self, path, st, cache):
status = None
safe_path = make_path_safe(path)
# Is it a hard link?
if st.st_nlink > 1:
@ -390,7 +398,8 @@ class Archive:
item = self.stat_attrs(st, path)
item.update({b'path': safe_path, b'source': source})
self.add_item(item)
return
status = 'h' # regular file, hardlink (to already seen inodes)
return status
else:
self.hard_links[st.st_ino, st.st_dev] = safe_path
path_hash = self.key.id_hash(os.path.join(self.cwd, path).encode('utf-8', 'surrogateescape'))
@ -403,6 +412,9 @@ class Archive:
break
else:
chunks = [cache.chunk_incref(id_, self.stats) for id_ in ids]
status = 'U' # regular file, unchanged
else:
status = 'A' # regular file, added
# Only chunkify the file if needed
if chunks is None:
with Archive._open_rb(path, st) as fd:
@ -410,10 +422,12 @@ class Archive:
for chunk in self.chunker.chunkify(fd):
chunks.append(cache.add_chunk(self.key.id_hash(chunk), chunk, self.stats))
cache.memorize_file(path_hash, st, [c[0] for c in chunks])
status = status or 'M' # regular file, modified (if not 'A' already)
item = {b'path': safe_path, b'chunks': chunks}
item.update(self.stat_attrs(st, path))
self.stats.nfiles += 1
self.add_item(item)
return status
@staticmethod
def list_archives(repository, key, manifest, cache=None):

View File

@ -157,16 +157,17 @@ Type "Yes I am sure" if you understand this and want to continue.\n""")
# Ignore unix sockets
if stat.S_ISSOCK(st.st_mode):
return
self.print_verbose(remove_surrogates(path))
status = None
if stat.S_ISREG(st.st_mode):
try:
archive.process_file(path, st, cache)
status = archive.process_file(path, st, cache)
except IOError as e:
self.print_error('%s: %s', path, e)
elif stat.S_ISDIR(st.st_mode):
if exclude_caches and is_cachedir(path):
return
archive.process_item(path, st)
status = 'd' # directory
try:
entries = os.listdir(path)
except OSError as e:
@ -176,13 +177,28 @@ Type "Yes I am sure" if you understand this and want to continue.\n""")
self._process(archive, cache, excludes, exclude_caches, skip_inodes,
os.path.join(path, filename), restrict_dev)
elif stat.S_ISLNK(st.st_mode):
archive.process_symlink(path, st)
status = archive.process_symlink(path, st)
elif stat.S_ISFIFO(st.st_mode):
archive.process_item(path, st)
status = 'f' # fifo
elif stat.S_ISCHR(st.st_mode) or stat.S_ISBLK(st.st_mode):
archive.process_dev(path, st)
status = archive.process_dev(path, st)
else:
self.print_error('Unknown file type: %s', path)
return
# Status output
# A lowercase character means a file type other than a regular file,
# attic 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.
# Note: A/M/U is relative to the "files" cache, not to the repo.
# This would be an issue if the files cache is not used.
if status is None:
status = '?' # need to add a status code somewhere
# output ALL the stuff - it can be easily filtered using grep.
# even stuff considered unchanged might be interesting.
self.print_verbose("%1s %s", status, remove_surrogates(path))
def do_extract(self, args):
"""Extract archive contents"""