def test_sync_nocase_with_checksums_ok(self):
        # self._set_basic_subdir_files()
        checksums = self.basic_checksums.copy()

        self._add_torrent_file_only('dir1\\case1')
        self._add_real_file_only('dir1\\Case1', force_keep_it=True, content='tralala')
        checksums[TOP_DIR + '\\dir1\\case1'] = hashlib.sha1('tralala').digest()

        self._add_torrent_file_only('dir1\\Case2')
        self._add_real_file_only('dir1\\case2', force_keep_it=True, content='tralala2')
        checksums[TOP_DIR + '\\dir1\\Case2'] = hashlib.sha1('tralala2').digest()

        self._add_torrent_file_only('dir5\\subdir1\\case5')
        self._add_real_file_only('Dir5\\Subdir1\\Case5', force_keep_it=True, content='tralala3')
        checksums[TOP_DIR + '\\dir5\\subdir1\\case5'] = hashlib.sha1('tralala3').digest()

        self._add_torrent_file_only('Dir6\\Subdir2\\case6')
        self._add_real_file_only('dir6\\subdir2\\Case6', force_keep_it=True, content='tralala4')
        checksums[TOP_DIR + '\\Dir6\\Subdir2\\case6'] = hashlib.sha1('tralala4').digest()

        retval = integrity.check_mod_directories(self.file_paths,
                                                 BASE_DIR, check_subdir='', on_superfluous='remove',
                                                 checksums=checksums)

        self.assertEqual(retval, True, "check_mod_directories should return true")
    def test_sync_subdir(self):
        self._set_basic_subdir_files()
        retval = integrity.check_mod_directories(self.file_paths,
                                                 base_directory='c:\\teamspeak\\plugins',
                                                 check_subdir='top_dir\\ts\\plugins',
                                                 on_superfluous='warn')

        self.assertEqual(retval, True, "check_mod_directories should return true")
    def _test_sync_missing_dir(self):
        '''Test invalid because checking empty dirs from torrents not yet implemented.'''
        self._add_torrent_file_only('dir1\\dir6', content=DIRECTORY)

        retval = integrity.check_mod_directories(self.file_paths,
                                                 BASE_DIR, check_subdir='', on_superfluous='ignore')

        self.assertEqual(retval, False, "check_mod_directories should return true")
    def test_sync_superfluous_dir_on_warn(self):
        self._add_real_file_only('dir1\\dir6', force_keep_it=True, content=DIRECTORY)
        self.assertTrue(os.path.isdir(os.path.join(BASE_DIR, TOP_DIR, 'dir1\\dir6')), 'File is not a dir!')

        retval = integrity.check_mod_directories(self.file_paths,
                                                 BASE_DIR, check_subdir='', on_superfluous='warn')

        self.assertEqual(retval, False, "check_mod_directories should return false")
    def test_sync_subdir_missing(self):
        self._set_basic_subdir_files()
        self._add_file('ts\\plugins\\tsdir1\\tsfile4')
        retval = integrity.check_mod_directories(self.file_paths,
                                                 base_directory='c:\\teamspeak\\plugins',
                                                 check_subdir='top_dir\\ts\\plugins',
                                                 on_superfluous='warn')

        self.assertEqual(retval, False, "check_mod_directories should return false")
    def test_sync_whitelisted_entries_from_torrent_removed(self):
        self._add_torrent_file_only('dir1\\tfr.ts3_plugin')
        self._add_torrent_file_only('tfr.ts3_plugin\\somefile')
        self._add_torrent_file_only('tfr.ts3_plugin\\otherfile')
        self._add_torrent_file_only('.synqinfo\\file1')
        self._add_torrent_file_only('.synqinfo\\file2')

        retval = integrity.check_mod_directories(self.file_paths,
                                                 BASE_DIR, check_subdir='', on_superfluous='remove')

        self.assertEqual(retval, True, "check_mod_directories should return true")
    def test_sync_keep_whitelisted_physical_entries_on_warn(self):
        self._add_real_file_only('dir1\\tfr.ts3_plugin', force_keep_it=True)
        self._add_real_file_only('tfr.ts3_plugin\\somefile', force_keep_it=True)
        self._add_real_file_only('tfr.ts3_plugin\\otherfile', force_keep_it=True)
        self._add_real_file_only('.synqinfo\\file1', force_keep_it=True)
        self._add_real_file_only('.synqinfo\\file2', force_keep_it=True)

        retval = integrity.check_mod_directories(self.file_paths,
                                                 BASE_DIR, check_subdir='', on_superfluous='warn')

        self.assertEqual(retval, True, "check_mod_directories should return true")
    def test_sync_entries_in_other_top_dirs(self):
        self._add_real_file_only('dir1\\file6', top_dir='other', force_keep_it=True)
        self._add_real_file_only('dir2\\file1', top_dir='other', force_keep_it=True)
        self._add_real_file_only('dir2\\dire1', top_dir='other2', force_keep_it=True, content=DIRECTORY)
        self._add_real_file_only('somefile', top_dir='', base_dir='c:\\', force_keep_it=True)
        self._add_real_file_only('otherfile', top_dir='', base_dir=BASE_DIR, force_keep_it=True)

        retval = integrity.check_mod_directories(self.file_paths,
                                                 BASE_DIR, check_subdir='', on_superfluous='remove')

        self.assertEqual(retval, True, "check_mod_directories should return true")
    def test_sync_superfluous_entries_but_ignore(self):
        self._add_real_file_only('dir1\\file6', force_keep_it=True)
        self._add_real_file_only('dir1\\dir6', force_keep_it=True, content=DIRECTORY)
        self._add_real_file_only('dir1\\żółw', force_keep_it=True)
        self._add_real_file_only('żółw\\dir6', force_keep_it=True, content=DIRECTORY)
        self.assertTrue(os.path.isdir(os.path.join(BASE_DIR, TOP_DIR, 'dir1\\dir6')), 'File is not a dir!')
        self.assertTrue(os.path.isdir(os.path.join(BASE_DIR, TOP_DIR, 'żółw\\dir6')), 'File is not a dir!')

        retval = integrity.check_mod_directories(self.file_paths,
                                                 BASE_DIR, check_subdir='', on_superfluous='ignore')

        self.assertEqual(retval, True, "check_mod_directories should return true")
Ejemplo n.º 10
0
    def torrent_finished_hook(self, mod):
        """Hook that is called when a torrent has been successfully and fully downloaded.
        This hook then removes any superfluous files in the directory and updates
        the metadata file.

        Return whether then mod has been synced successfully and no superfluous
        files are present in the directory.
        """
        if not mod.torrent_handle.has_metadata():
            Logger.error('Finished_hook: torrent {} has no metadata!'.format(
                mod.foldername))
            return False

        metadata_file = MetadataFile(mod.foldername)
        metadata_file.read_data(ignore_open_errors=False)

        # Remove unused files
        torrent_info = mod.torrent_handle.get_torrent_info()
        files_list = [
            entry.path.decode('utf-8') for entry in torrent_info.files()
        ]
        cleanup_successful = check_mod_directories(files_list,
                                                   mod.parent_location,
                                                   on_superfluous='remove')

        # Workaround. This should be moved to some kind of Mod class method or something...
        mod.files_list = files_list
        '''
        # Removed for now because we already have the original torrent file downloaded
        # and we don't need to artificially recreate it.

        # Recreate the torrent file and store it in the metadata file for future checks
        recreated_torrent = libtorrent.create_torrent(torrent_info)
        bencoded_recreated_torrent = libtorrent.bencode(recreated_torrent.generate())
        metadata_file.set_torrent_content(bencoded_recreated_torrent)
        '''

        if not cleanup_successful:
            Logger.info(
                "Could not perform mod {} cleanup. Marking torrent as dirty.".
                format(mod.foldername))
            metadata_file.set_dirty(True)
            metadata_file.write_data()

            return False
        else:
            metadata_file.set_dirty(False)
            metadata_file.write_data()

        return True
    def test_sync_nocase(self):
        self._set_basic_subdir_files()

        self._add_torrent_file_only('dir1\\case1')
        self._add_real_file_only('dir1\\Case1', force_keep_it=True)
        self._add_torrent_file_only('dir1\\Case2')
        self._add_real_file_only('dir1\\case2', force_keep_it=True)

        self._add_torrent_file_only('dir3\\case3')
        self._add_real_file_only('Dir3\\Case3', force_keep_it=True)
        self._add_torrent_file_only('Dir4\\case4')
        self._add_real_file_only('dir4\\Case4', force_keep_it=True)

        self._add_torrent_file_only('dir5\\subdir1\\case5')
        self._add_real_file_only('Dir5\\Subdir1\\Case5', force_keep_it=True)
        self._add_torrent_file_only('Dir6\\Subdir2\\case6')
        self._add_real_file_only('dir6\\subdir2\\Case6', force_keep_it=True)

        retval = integrity.check_mod_directories(self.file_paths,
                                                 BASE_DIR, check_subdir='', on_superfluous='remove')

        self.assertEqual(retval, True, "check_mod_directories should return true")
Ejemplo n.º 12
0
def is_complete_quick(mod):
    """Performs a quick check to see if the mod *seems* to be correctly installed.
    This check assumes no external changes have been made to the mods.

    1. Check if metadata file exists and can be opened (instant)
    1a. WORKAROUND: Check if the file has just been created so it must be complete
    2. Check if torrent is not dirty [download completed successfully] (instant)
    3. Check if torrent url matches (instant)
    4. Check if files have the right size and modification time (very quick)
    5. Check if there are no superfluous files in the directory (very quick)"""

    Logger.info('Is_complete: Checking mod {} for completeness...'.format(
        mod.foldername))

    metadata_file = MetadataFile(mod.foldername)

    # (1) Check if metadata can be opened
    try:
        metadata_file.read_data(ignore_open_errors=False)
    except (IOError, ValueError):
        Logger.info(
            'Is_complete: Metadata file could not be read successfully. Marking as not complete'
        )
        return False

    # Workaround
    if metadata_file.get_force_creator_complete():
        Logger.info(
            'Is_complete: Torrent marked as (forced) complete by the creator. Treating as complete'
        )
        return True

    # (2)
    if metadata_file.get_dirty():
        Logger.info(
            'Is_complete: Torrent marked as dirty (not completed successfully). Marking as not complete'
        )
        return False

    # (3)
    if metadata_file.get_torrent_url() != mod.torrent_url:
        Logger.info(
            'Is_complete: Torrent urls differ. Marking as not complete')
        return False

    # Get data required for (4) and (5)
    torrent_content = metadata_file.get_torrent_content()
    if not torrent_content:
        Logger.info(
            'Is_complete: Could not get torrent file content. Marking as not complete'
        )
        return False

    try:
        torrent_info = get_torrent_info_from_bytestring(torrent_content)
    except RuntimeError:
        Logger.info(
            'Is_complete: Could not parse torrent file content. Marking as not complete'
        )
        return False

    resume_data_bencoded = metadata_file.get_torrent_resume_data()
    if not resume_data_bencoded:
        Logger.info(
            'Is_complete: Could not get resume data. Marking as not complete')
        return False
    resume_data = libtorrent.bdecode(resume_data_bencoded)

    # (4)
    file_sizes = resume_data['file sizes']
    files = torrent_info.files()
    # file_path, size, mtime
    files_data = map(lambda x, y: (y.path.decode('utf-8'), x[0], x[1]),
                     file_sizes, files)

    if not check_files_mtime_correct(mod.parent_location, files_data):
        Logger.info(
            'Is_complete: Some files seem to have been modified in the meantime. Marking as not complete'
        )
        return False

    # (5) Check if there are no additional files in the directory
    # TODO: Check if these checksums are even needed now
    checksums = dict([(entry.path.decode('utf-8'), entry.filehash.to_bytes())
                      for entry in torrent_info.files()])
    files_list = checksums.keys()
    if not check_mod_directories(
            files_list, mod.parent_location, on_superfluous='warn'):
        Logger.info(
            'Is_complete: Superfluous files in mod directory. Marking as not complete'
        )
        return False

    if not are_ts_plugins_installed(mod.parent_location, files_list):
        Logger.info('Is_complete: TS plugin out of date or not installed.')
        return False

    return True
    def test_sync_unicode(self):
        self._add_file('test\\żółw')
        retval = integrity.check_mod_directories(self.file_paths,
                                                 BASE_DIR, check_subdir='', on_superfluous='remove')

        self.assertEqual(retval, True, "check_mod_directories should return true")
    def test_sync_missing_unicode_file(self):
        self._add_torrent_file_only('dir1\\żółw')
        retval = integrity.check_mod_directories(self.file_paths,
                                                 BASE_DIR, check_subdir='', on_superfluous='ignore')

        self.assertEqual(retval, False, "check_mod_directories should return false")
    def test_sync_already_synced(self):
        retval = integrity.check_mod_directories(self.file_paths,
                                                 BASE_DIR, check_subdir='', on_superfluous='remove')

        self.assertEqual(retval, True, "check_mod_directories should return true")