Ejemplo n.º 1
0
 def _analyze_local_item(self, local_item_name):
     """
     Analyze what to do with a local item that isn't found remotely. Assume that the item passes ignore list.
     :param str local_item_name: Name of the local item.
     """
     q = self.items_store.get_items_by_id(item_name=local_item_name, parent_path=self.remote_path)
     p = self.local_path + '/' + local_item_name
     is_dir = os.path.isdir(p)
     if len(q) > 0:
         # The item was on the server before, but now seems gone.
         item_id, item = _unpack_first_item(q)
         if item.is_folder and is_dir:
             # Type matched. Delete local entry.
             self._send_path_to_trash(local_item_name, p)
         else:
             # The record is obsolete. Upload local entry.
             self.items_store.delete_item(item_name=local_item_name, parent_path=self.remote_path)
             self._create_upload_task(local_item_name, is_dir)
     else:
         # The item has no record before. Probably new so upload it.
         # TODO: This can be made a little smarter by examining hash.
         self._create_upload_task(local_item_name, is_dir)
Ejemplo n.º 2
0
 def _analyze_local_item(self, local_item_name):
     """
     Analyze what to do with a local item that isn't found remotely. Assume that the item passes ignore list.
     :param str local_item_name: Name of the local item.
     """
     q = self.items_store.get_items_by_id(item_name=local_item_name,
                                          parent_path=self.remote_path)
     p = self.local_path + '/' + local_item_name
     is_dir = os.path.isdir(p)
     if len(q) > 0:
         # The item was on the server before, but now seems gone.
         item_id, item = _unpack_first_item(q)
         if item.is_folder and is_dir:
             # Type matched. Delete local entry.
             self._send_path_to_trash(local_item_name, p)
         else:
             # The record is obsolete. Upload local entry.
             self.items_store.delete_item(item_name=local_item_name,
                                          parent_path=self.remote_path)
             self._create_upload_task(local_item_name, is_dir)
     else:
         # The item has no record before. Probably new so upload it.
         # TODO: This can be made a little smarter by examining hash.
         self._create_upload_task(local_item_name, is_dir)
Ejemplo n.º 3
0
 def _analyze_remote_item(self, remote_item, all_local_items):
     """
     Analyze what to do with a remote item. Assume that this item passes ignore list.
     This function is the core algorithm and probably the ugliest code I've written so far.
     :param onedrived.api.items.OneDriveItem remote_item: The remote item object.
     :param [str] all_local_items: All remaining untouched local items.
     """
     item_local_path = self.local_path + '/' + remote_item.name
     q = self.items_store.get_items_by_id(parent_path=self.remote_path, item_name=remote_item.name)
     exists = os.path.exists(item_local_path)
     has_record = len(q) > 0
     if not has_record and not exists:
         # There is no record in database. The item is not present. Probably a new file.
         self._create_download_task(item_local_path, remote_item)
     elif has_record and not exists:
         # There is record but the file is gone.
         item_id, item_record = _unpack_first_item(q)
         if item_id == remote_item.id and remote_item.c_tag == item_record.c_tag \
                 and remote_item.e_tag == item_record.e_tag:
             # Same record. The file is probably deleted when daemon is off.
             self._create_delete_item_task(item_local_path, remote_item)
         else:
             # The record differs. For safety we download it.
             self.logger.info('Cannot determine actions for "%s". Non-existent and records differ.', item_local_path)
             self._create_download_task(item_local_path, remote_item)
     else:
         # The entry exists locally.
         # First solve possible type conflict.
         is_dir = os.path.isdir(item_local_path)
         if is_dir != remote_item.is_folder:
             self.logger.info('Type conflict on path "%s". One side is file and the other is dir.', item_local_path)
             self._move_existing_and_download(item_local_path, remote_item, all_local_items, q)
         elif is_dir:
             # Both sides are directories. Just update the record and sync if needed.
             if has_record:
                 item_id, item_record = _unpack_first_item(q)
                 has_record = item_id == remote_item.id
             if not has_record:
                 self.logger.info('Fix database record for directory "%s".', item_local_path)
                 self.items_store.update_item(remote_item, ItemRecordStatuses.OK)
             else:
                 self.logger.debug('Directory "%s" has intact record.', item_local_path)
         else:
             # Both sides are files. Examine file attributes.
             file_size, file_mtime = stat_file(item_local_path)
             if file_size == remote_item.size \
                     and compare_timestamps(file_mtime, datetime_to_timestamp(remote_item.modified_time)) == 0:
                 # Same file name. Same size. Same mtime. Guess they are the same for laziness.
                 # Just update the record.
                 need_update = not has_record
                 if has_record:
                     item_id, item_record = _unpack_first_item(q)
                     need_update = item_record.c_tag != remote_item.c_tag or item_record.e_tag != remote_item.e_tag
                 if need_update:
                     self.logger.info('Fix database record for file "%s" based on file size and mtime.',
                                      item_local_path)
                     self.items_store.update_item(remote_item, ItemRecordStatuses.OK)
                 else:
                     self.logger.debug('File "%s" seems fine.', item_local_path)
             else:
                 if has_record:
                     item_id, item_record = _unpack_first_item(q)
                     if item_id == remote_item.id and item_record.c_tag == remote_item.c_tag \
                             or item_record.e_tag == remote_item.e_tag:
                         # The remote item did not change since last update, but LOCAL file changed since then.
                         self.logger.info('File "%s" changed locally since last sync. Upload.', item_local_path)
                         self._create_upload_task(local_item_name=remote_item.name, is_dir=False)
                     elif file_size == item_record.size and compare_timestamps(
                             file_mtime, datetime_to_timestamp(item_record.modified_time)) == 0:
                         # The local item did not change since last update, but REMOTE file changed since then.
                         self.logger.info('File "%s" changed remotely since last sync. Download.', item_local_path)
                         self._create_download_task(item_local_path, remote_item)
                     else:
                         # Three ends mismatch. Keep both.
                         self.logger.info('Cannot determine file "%s". All information differ. Keep both.',
                                          item_local_path)
                         self._move_existing_and_download(item_local_path, remote_item, all_local_items, q)
                 else:
                     # Examine file hash.
                     if _have_equal_hash(item_local_path, remote_item):
                         # Same hash means that they are the same file. Update local timestamp and database record.
                         self._update_attr_when_hash_equal(item_local_path, remote_item)
                     else:
                         self.logger.info('Cannot determine file "%s". Rename and keep both.', item_local_path)
                         self._move_existing_and_download(item_local_path, remote_item, all_local_items, q)
Ejemplo n.º 4
0
 def _analyze_remote_item(self, remote_item, all_local_items):
     """
     Analyze what to do with a remote item. Assume that this item passes ignore list.
     This function is the core algorithm and probably the ugliest code I've written so far.
     :param onedrived.api.items.OneDriveItem remote_item: The remote item object.
     :param [str] all_local_items: All remaining untouched local items.
     """
     item_local_path = self.local_path + '/' + remote_item.name
     q = self.items_store.get_items_by_id(parent_path=self.remote_path,
                                          item_name=remote_item.name)
     exists = os.path.exists(item_local_path)
     has_record = len(q) > 0
     if not has_record and not exists:
         # There is no record in database. The item is not present. Probably a new file.
         self._create_download_task(item_local_path, remote_item)
     elif has_record and not exists:
         # There is record but the file is gone.
         item_id, item_record = _unpack_first_item(q)
         if item_id == remote_item.id and remote_item.c_tag == item_record.c_tag \
                 and remote_item.e_tag == item_record.e_tag:
             # Same record. The file is probably deleted when daemon is off.
             self._create_delete_item_task(item_local_path, remote_item)
         else:
             # The record differs. For safety we download it.
             self.logger.info(
                 'Cannot determine actions for "%s". Non-existent and records differ.',
                 item_local_path)
             self._create_download_task(item_local_path, remote_item)
     else:
         # The entry exists locally.
         # First solve possible type conflict.
         is_dir = os.path.isdir(item_local_path)
         if is_dir != remote_item.is_folder:
             self.logger.info(
                 'Type conflict on path "%s". One side is file and the other is dir.',
                 item_local_path)
             self._move_existing_and_download(item_local_path, remote_item,
                                              all_local_items, q)
         elif is_dir:
             # Both sides are directories. Just update the record and sync if needed.
             if has_record:
                 item_id, item_record = _unpack_first_item(q)
                 has_record = item_id == remote_item.id
             if not has_record:
                 self.logger.info('Fix database record for directory "%s".',
                                  item_local_path)
                 self.items_store.update_item(remote_item,
                                              ItemRecordStatuses.OK)
             else:
                 self.logger.debug('Directory "%s" has intact record.',
                                   item_local_path)
         else:
             # Both sides are files. Examine file attributes.
             file_size, file_mtime = stat_file(item_local_path)
             if file_size == remote_item.size \
                     and compare_timestamps(file_mtime, datetime_to_timestamp(remote_item.modified_time)) == 0:
                 # Same file name. Same size. Same mtime. Guess they are the same for laziness.
                 # Just update the record.
                 need_update = not has_record
                 if has_record:
                     item_id, item_record = _unpack_first_item(q)
                     need_update = item_record.c_tag != remote_item.c_tag or item_record.e_tag != remote_item.e_tag
                 if need_update:
                     self.logger.info(
                         'Fix database record for file "%s" based on file size and mtime.',
                         item_local_path)
                     self.items_store.update_item(remote_item,
                                                  ItemRecordStatuses.OK)
                 else:
                     self.logger.debug('File "%s" seems fine.',
                                       item_local_path)
             else:
                 if has_record:
                     item_id, item_record = _unpack_first_item(q)
                     if item_id == remote_item.id and item_record.c_tag == remote_item.c_tag \
                             or item_record.e_tag == remote_item.e_tag:
                         # The remote item did not change since last update, but LOCAL file changed since then.
                         self.logger.info(
                             'File "%s" changed locally since last sync. Upload.',
                             item_local_path)
                         self._create_upload_task(
                             local_item_name=remote_item.name, is_dir=False)
                     elif file_size == item_record.size and compare_timestamps(
                             file_mtime,
                             datetime_to_timestamp(
                                 item_record.modified_time)) == 0:
                         # The local item did not change since last update, but REMOTE file changed since then.
                         self.logger.info(
                             'File "%s" changed remotely since last sync. Download.',
                             item_local_path)
                         self._create_download_task(item_local_path,
                                                    remote_item)
                     else:
                         # Three ends mismatch. Keep both.
                         self.logger.info(
                             'Cannot determine file "%s". All information differ. Keep both.',
                             item_local_path)
                         self._move_existing_and_download(
                             item_local_path, remote_item, all_local_items,
                             q)
                 else:
                     # Examine file hash.
                     if _have_equal_hash(item_local_path, remote_item):
                         # Same hash means that they are the same file. Update local timestamp and database record.
                         self._update_attr_when_hash_equal(
                             item_local_path, remote_item)
                     else:
                         self.logger.info(
                             'Cannot determine file "%s". Rename and keep both.',
                             item_local_path)
                         self._move_existing_and_download(
                             item_local_path, remote_item, all_local_items,
                             q)