def check_for_edited_media_files(self): # Regular media files. new_hashes = {} for sql_res in self.con.execute("select filename, _hash from media"): filename, hash = normalise_path(sql_res[0]), sql_res[1] if not os.path.exists(expand_path(filename, self.media_dir())): continue new_hash = self._media_hash(filename) if hash != new_hash: new_hashes[filename] = new_hash for filename, new_hash in new_hashes.items(): self.con.execute("update media set _hash=? where filename=?", (new_hash, filename)) self.log().edited_media_file(filename)
def media_filenames_to_sync_for(self, partner): """Determine which media files need to be sent across during the sync. Obviously, this only includes existing media files, not deleted ones. """ _id = self.last_log_index_synced_for(partner) filenames = set() for filename in [cursor[0] for cursor in self.con.execute(\ """select object_id from log where _id>? and (event_type=? or event_type=?)""", (_id, EventTypes.ADDED_MEDIA_FILE, EventTypes.EDITED_MEDIA_FILE))]: if os.path.exists(\ normalise_path(expand_path(filename, self.media_dir()))): filenames.add(filename) return filenames
def add_media_file(self, log_entry): """ADDED_MEDIA_FILE events get created in several places: database._process_media, database.check_for_edited_media_files, latex, ... . In order to make sure that all of these are treated in the same way, we generate an ADDED_MEDIA_FILE event here, and prevent _process_media from generating this event through self.syncing = True. """ filename = log_entry["fname"] full_path = normalise_path(expand_path(filename, self.media_dir())) if os.path.exists(full_path): self.con.execute( """insert or replace into media(filename, _hash) values(?,?)""", (filename, self._media_hash(filename))) self.log().added_media_file(filename)
def _media_hash(self, filename): """A hash function that will be used to determine whether or not a media file has been modified outside of Mnemosyne. 'filename' is a relative path inside the media dir. In principle, you could have different hash implementations on different systems, as the hash is considered something internal and is not sent across during sync e.g.. """ filename = normalise_path(os.path.join(self.media_dir(), filename)) if not os.path.exists(filename): return "0" media_file = open(filename, "rb") hasher = md5() while True: buffer = media_file.read(8096) if not buffer: break hasher.update(buffer) return hasher.hexdigest()