The other tricky thing is that for some reason Windows has relative paths with
drive parts, like `C:some/path'. This is what `joinpath' does with `C:', so
we need to manually add a separator to ensure the resulting path actually
- points to an ADS.
+ points to an ADS. This makes the path absolute, but that's okay because there
+ doesn't seem to be any way to get an ADS on a relative path with a drive.
"""
def get_ads(self, name):
full_name = self.name + ':' + name
VersionInfo = namedtuple('ParseResult', ['bb_id', 'version'])
-VersionInfo.with_version = lambda self, v: VersionInfo(self.bb_id, v)
+VersionInfo.next = lambda self, v: VersionInfo(self.bb_id, self.version + 1)
def _extract_version(path):
except json.decoder.JSONDecodeError:
pass
else:
- bb_id = metadata.get('bbId')
+ bb_id = metadata.get('contentId')
version = metadata.get('version')
version_typecheck = lambda v: isinstance(v, int) if path.is_file() else v is None
if isinstance(bb_id, str) and version_typecheck(version):
from collections import defaultdict
results = defaultdict(set)
- for path in path.iterdir():
- info = _extract_version(path)
+ for child in path.iterdir():
+ info = _extract_version(child)
if info:
- results[info].add(path)
+ results[info].add(child)
return results
# https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file
-def sanitize(seg):
+def _sanitize(seg):
bad = {*map(chr, range(0, 31 + 1)), *r'<>:"/\|?*'}
return seg.translate({ch: '!' for ch in bad})
[child_path] = ver_map[info]
return child_path
else:
- return set_up_new_dir(
- path,
- content_doc['title'],
+ new_path = get_new_path(path, content_doc['title'])
+ write_metadata(
+ new_path,
VersionInfo(bb_id = content_doc['id'], version = None),
)
+ return new_path
-def set_up_new_file(*args):
- return _set_up_new_path(
- *args,
- creator = lambda path: path.open('x').close()
- )
-
-def set_up_new_dir(*args):
- return _set_up_new_path(*args, creator = pathlib.Path.mkdir)
-
-def _set_up_new_path(parent, base_name, version_info, creator):
+def get_new_path(parent, base_name):
import itertools
- sanitized = sanitize(base_name)
+ sanitized = _sanitize(base_name)
(stem, exts) = _split_name(sanitized)
def path_for(ordinal):
if ordinal is None:
seg = sanitized
else:
seg = '{stem}({ordinal}){exts}'.format(stem=stem, ordinal=ordinal, exts=exts)
- assert seg == sanitize(seg)
+ assert seg == _sanitize(seg)
return parent.joinpath(seg)
- path = next(
+ return next(
path
for path in map(path_for, itertools.chain([None], itertools.count()))
if not path.exists()
)
- creator(path)
+
+def write_metadata(path, version_info):
with WinPath(path).get_ads(BB_META_STREAM_NAME).open('x') as f:
- json.dump({'bbId': version_info.bb_id, 'version': version_info.version}, f)
- return path
+ json.dump({'contentId': version_info.bb_id, 'version': version_info.version}, f)
tmp_path.unlink()
else:
if match is False:
- new_version = latest.with_version(latest.version + 1)
+ new_version = latest.next()
LOGGER.info(" Found new revision ({})".format(new_version.version))
else:
new_version = fs.VersionInfo(att_id, 0)
LOGGER.info(" Storing initial revision")
- dest = fs.set_up_new_file(local_path, attachment_doc['fileName'], new_version)
+ dest = fs.get_new_path(local_path, attachment_doc['fileName'])
LOGGER.info(" Destination: {}".format(dest))
tmp_path.replace(dest)
+ fs.write_metadata(dest, new_version)