Dump files to native FS more consistently

Specifically:

- A data fork dump file will always exist
- A resource fork dump file will exist iff there are any bytes in that
  fork (but this dump file may be empty)
- A Finder info dump will exist if there are any nonzero bytes in the
  type or creator code
This commit is contained in:
Elliot Nunn 2019-02-22 15:49:47 +08:00
parent 51a0f8e68e
commit fb493a154f

View File

@ -15,6 +15,12 @@ def _fuss_if_unsyncable(name):
if _unsyncability(name): if _unsyncability(name):
raise ValueError('Unsyncable name: %r' % name) raise ValueError('Unsyncable name: %r' % name)
def _try_delete(name):
try:
os.remove(name)
except FileNotFoundError:
pass
class AbstractFolder(MutableMapping): class AbstractFolder(MutableMapping):
def __init__(self, from_dict=()): def __init__(self, from_dict=()):
@ -234,34 +240,35 @@ class AbstractFolder(MutableMapping):
continue continue
nativepath = path.join(folder_path, *(comp.replace(path.sep, ':') for comp in p)) nativepath = path.join(folder_path, *(comp.replace(path.sep, ':') for comp in p))
info_path = nativepath + '.idump'
rsrc_path = nativepath + '.rdump'
if isinstance(obj, Folder): if isinstance(obj, Folder):
os.makedirs(nativepath, exist_ok=True) os.makedirs(nativepath, exist_ok=True)
elif obj.mddate != obj.bkdate or not any_exists(nativepath): elif obj.mddate != obj.bkdate or not any_exists(nativepath):
# always write the data fork
data = obj.data data = obj.data
if obj.type in TEXT_TYPES: if obj.type in TEXT_TYPES:
data = data.decode('mac_roman').replace('\r', os.linesep).encode('utf8') data = data.decode('mac_roman').replace('\r', os.linesep).encode('utf8')
with open(nativepath, 'wb') as f:
f.write(data)
rsrc = obj.rsrc # write a resource dump iff that fork has any bytes (dump may still be empty)
if rsrc: if obj.rsrc:
rsrc = parse_file(rsrc) with open(rsrc_path, 'wb') as f:
rsrc = make_rez_code(rsrc, ascii_clean=True) rdump = make_rez_code(parse_file(obj.rsrc), ascii_clean=True)
f.write(rdump)
info = obj.type + obj.creator else:
if info == b'????????': info = b'' _try_delete(rsrc_path)
for thing, suffix in ((data, ''), (rsrc, '.rdump'), (info, '.idump')): # write an info dump iff either field is non-null
wholepath = nativepath + suffix idump = obj.type + obj.creator
if thing or (suffix == '' and not rsrc): if any(idump):
written.append(wholepath) with open(info_path, 'wb') as f:
with open(written[-1], 'wb') as f: f.write(idump)
f.write(thing) else:
else: _try_delete(info_path)
try:
os.remove(wholepath)
except FileNotFoundError:
pass
if written: if written:
t = path.getmtime(written[-1]) t = path.getmtime(written[-1])