From: Daira Hopwood Date: Tue, 25 Aug 2015 15:02:36 +0000 (+0100) Subject: Add Downloader._write_downloaded_file. refs ticket:2489 X-Git-Url: https://git.rkrishnan.org/%3C?a=commitdiff_plain;h=9594343b304edc7418fcc279299e7e8746a52c46;p=tahoe-lafs%2Ftahoe-lafs.git Add Downloader._write_downloaded_file. refs ticket:2489 Signed-off-by: Daira Hopwood --- diff --git a/src/allmydata/frontends/magic_folder.py b/src/allmydata/frontends/magic_folder.py index e6cf18c1..4131c501 100644 --- a/src/allmydata/frontends/magic_folder.py +++ b/src/allmydata/frontends/magic_folder.py @@ -541,5 +541,36 @@ class Downloader(QueueMixin): d.addBoth(remove_from_pending) return d - def _write_downloaded_file(self, name, file_contents): - fileutil.write(name, file_contents) + FUDGE_SECONDS = 10.0 + + @classmethod + def _write_downloaded_file(cls, path, file_contents, is_conflict=False, now=None): + # 1. Write a temporary file, say .foo.tmp. + # 2. is_conflict determines whether this is an overwrite or a conflict. + # 3. Set the mtime of the replacement file to be T seconds before the + # current local time. + # 4. Perform a file replacement with backup filename foo.backup, + # replaced file foo, and replacement file .foo.tmp. If any step of + # this operation fails, reclassify as a conflict and stop. + + precondition(isinstance(path, unicode), path=path) + + replacement_path = path + u".tmp" # FIXME more unique + backup_path = path + u".backup" + if now is None: + now = time.time() + + fileutil.write(replacement_path, file_contents) + os.utimes(replacement_path, (now, now - cls.FUDGE_SECONDS)) + if is_conflict: + cls._rename_conflicted_file(path, replacement_path) + else: + try: + fileutil.replace_file(path, replacement_path, backup_path) + except fileutil.ConflictError: + cls._rename_conflicted_file(path, replacement_path) + + @classmethod + def _rename_conflicted_file(self, path, replacement_path): + conflict_path = path + u".conflict" + fileutil.rename_no_overwrite(replacement_path, conflict_path) \ No newline at end of file