def __init__(self, owner=None): super(Widget, self).__init__(owner) # make up a doc self.t = DirectoryScanner() if Platform.isMac: self.t.addPathsForScanning(['/Applications']) else: self.t.addPathsForScanning(['C:\\Program Files']) self.p = PersistentScanningState("demo.sqlite", echo_sql=False) self.initialScan() self.mergeScan() print "Info Is:", self.p.scanInfo() self.mapper = MergeScanMapper(self.p) self.ui = Ui_CustomTreeWidget() self.ui.setupUi(self) self.ui.treeView.setModel( MergeScanTreeModel(self.p, self.mapper, self.p.roots(), self)) self.ui.treeView.expandToDepth(1) model = self.ui.treeView.model() header = self.ui.treeView.header() header.setResizeMode(MergeScanTreeModel.COL_CHECKED, QHeaderView.ResizeToContents) header.setResizeMode(MergeScanTreeModel.COL_PERMISSIONS, QHeaderView.ResizeToContents) self.ui.treeView.setAttribute(Qt.WA_MacShowFocusRect, False)
class PersistTestCase(unittest.TestCase): """ Proves that the scan results can be persisted to a storage form, and re-constituted with the same data. """ def setUp(self): self.p = PersistentScanningState("test.sqlite", echo_sql=False) def tearDown(self): del self.p os.remove("test.sqlite") def test_scan_is_stored(self): t = DirectoryScanner() t.addPathsForScanning([good_app_path()]) # since its an iterable, force its execution for x in self.p.storeFilesystemSnapshot(t): pass # and the dir count contains something values = self.p.session.query(FileSystemSnapshot).all() self.assertTrue(len(values) > 0) self.assertTrue(DocumentStorage.deleteDocumentNamed('test.sqlite')) def test_scan_paths_being_scanned(self): self.p.storePathsBeingScanned(['one_path', 'two_path']) # open up the DB and check... paths = [ p.abs_path for p in self.p.pathsBeingScanned() ] logger.info("paths are: {0}".format(paths)) self.assertTrue( "one_path" in paths ) self.assertTrue( "two_path" in paths )
class PersistTestCase(unittest.TestCase): """ Proves that the scan results can be persisted to a storage form, and re-constituted with the same data. """ def setUp(self): self.p = PersistentScanningState("test.sqlite", echo_sql=False) def tearDown(self): del self.p os.remove("test.sqlite") def test_scan_is_stored(self): t = DirectoryScanner() t.addPathsForScanning([good_app_path()]) # since its an iterable, force its execution for x in self.p.storeFilesystemSnapshot(t): pass # and the dir count contains something values = self.p.session.query(FileSystemSnapshot).all() self.assertTrue(len(values) > 0) self.assertTrue(DocumentStorage.deleteDocumentNamed('test.sqlite')) def test_scan_paths_being_scanned(self): self.p.storePathsBeingScanned(['one_path', 'two_path']) # open up the DB and check... paths = [p.abs_path for p in self.p.pathsBeingScanned()] logger.info("paths are: {0}".format(paths)) self.assertTrue("one_path" in paths) self.assertTrue("two_path" in paths)
def beginChangesScan(self, doc_name): """ Find the selected item, and use the directories inside to perform a scan, the merge the results of that with the existing document - forming a set of objects that have been added/changed/removed """ # now fetch the data model for that one to get the paths that need to be scanned self.storage = PersistentScanningState( DocumentStorage.documentFullPath(doc_name)) #return self.__beginChangesScanWithDocument() self.__beginChangesScanWithDocument()
def __init__(self, owner = None): super(Widget, self).__init__(owner) # make up a doc self.t = DirectoryScanner() if Platform.isMac: self.t.addPathsForScanning(['/Applications']) else: self.t.addPathsForScanning(['C:\\Program Files']) self.p = PersistentScanningState("demo.sqlite", echo_sql=False) self.initialScan() self.mergeScan() print "Info Is:", self.p.scanInfo() self.mapper = MergeScanMapper(self.p) self.ui = Ui_CustomTreeWidget() self.ui.setupUi(self) self.ui.treeView.setModel(MergeScanTreeModel(self.p, self.mapper, self.p.roots(), self)) self.ui.treeView.expandToDepth(1) model = self.ui.treeView.model() header = self.ui.treeView.header() header.setResizeMode(MergeScanTreeModel.COL_CHECKED, QHeaderView.ResizeToContents) header.setResizeMode(MergeScanTreeModel.COL_PERMISSIONS, QHeaderView.ResizeToContents) self.ui.treeView.setAttribute(Qt.WA_MacShowFocusRect, False)
def setUp(self): self.t = DirectoryScanner() self.builder = DirectoryTreeBuilder() # construct a known directory structure, suitable for testing - it includes files, directories, ACL's, etc self.contents_path = self.builder.make_dir("BB/TextEdit.app/Contents", 0755) self.builder.make_dir("BB/TextEdit.app/Contents/Resources", 0755) self.builder.make_dir("BB/TextEdit.app/Contents/Frameworks", 0755) self.builder.create_file("BB/TextEdit.app/Contents/Stupid.txt", 0755, 425) # produce a single scan of the fake file-system entries self.p = PersistentScanningState("tree-tests.sqlite") self.t.addPathsForScanning([self.builder.rootDir]) self.initialScan() self.mergeScan()
def beginInitialScan(self, scan_paths, doc_name=None): # construct an initial scan, based on the selected items within the model... # workflow: scan to produce a persistent model, monitor/rescan, re-integrate changes into initial model (changed, deleted, added etc) scanner = DirectoryScanner() scanner.addPathsForScanning(scan_paths) # we want to store the results too - so build a storage device, its all being run via iterables # so its easy to chain these together. doc_path = DocumentStorage.getDocumentPathForName(doc_name, scan_paths) self.storage = PersistentScanningState(doc_path) self.storage.storePathsBeingScanned(scanner.paths_to_scan) self.storage.scanningStateChanged.connect( lambda x: self.scanStateChanged.emit(x)) self.isScanning = True self.scanStarted.emit(doc_path) # this one line performs a recursive disk scan on multiple folders, obtains file/dir info, persists # this to the DB and then finally exposes [idx, f] so the UI can display progress. Long live iterables... (and C++, you can die in a fire) total_found = 0 for idx, f in enumerate(self.storage.storeFilesystemSnapshot(scanner)): total_found = idx if not (idx % 100): self.scanProgress.emit(idx, f.abs_path) if not self.isScanning: break registryScanner = RegistryScanner() totalRegistry = 0 for idx, r in enumerate( self.storage.storeRegistryEntrySnapshot(registryScanner)): totalRegistry = idx if not (idx % 100): self.scanProgress.emit(idx, r.key_name) if not self.isScanning: break self.stopScanning() # complete the scan... self.scanFinished.emit(total_found) self.storage = None
def beginChangesScan(self, doc_name): """ Find the selected item, and use the directories inside to perform a scan, the merge the results of that with the existing document - forming a set of objects that have been added/changed/removed """ # now fetch the data model for that one to get the paths that need to be scanned self.storage = PersistentScanningState(DocumentStorage.documentFullPath(doc_name)) #return self.__beginChangesScanWithDocument() self.__beginChangesScanWithDocument()
def setUp(self): self.t = DirectoryScanner() self.builder = DirectoryTreeBuilder() # construct a known directory structure, suitable for testing - it includes files, directories, ACL's, etc self.contents_path = self.builder.make_dir("AA/TextEdit.app/Contents", 0755) self.builder.make_dir("AA/TextEdit.app/Contents/Resources", 0755) self.builder.make_dir("AA/TextEdit.app/Contents/Frameworks", 0755) self.dbName = "find-diffs.sqlite" self.removeDB() # produce a single scan of the fake file-system entries self.p = PersistentScanningState(self.dbName) self.t.addPathsForScanning([self.builder.rootDir]) self.initialScan()
def initializePage(self): name_of_file = self.wizard().documentName() self.__refreshResultsUsingDocument( PersistentScanningState( DocumentStorage.documentFullPath(name_of_file))) self.wizard().removePage(WizardPage.CREATE_NEW) self.wizard().removePage(WizardPage.FIRST_SCAN_PROGRESS) self.wizard().removePage(WizardPage.SECOND_SCAN_PROGRESS) self.wizard().removePage(WizardPage.SCANNING_COMPLETE_INSTALL_NOW) self.wizard().reinsertCreateScanPage()
def initializePage(self): model = QStandardItemModel() # using a document model, we can obtain all the documents to list inside this view... all_docs = DocumentStorage.documents() for doc_filename in all_docs: # find out the last scan date, number of files, etc document = PersistentScanningState(doc_filename) logger.debug("found info: {0}".format(document.info)) creation_date_str = str(document.info.date_created) last_date = str(document.info.date_last_scanned) num_scanned = "{0:,}".format(document.info.files_scanned) num_merged = "{0:,}".format(document.info.files_merged) is_merged = document.info.merge_complete if not is_merged: last_date_str = "" else: last_date_str = last_date doc = os.path.split(doc_filename)[1][:-len('.sqlite')] items = [ QStandardItem(doc), QStandardItem(str(num_scanned)), QStandardItem(creation_date_str), QStandardItem(str(num_merged)), QStandardItem(last_date_str), ] items[1].setData(Qt.AlignRight, Qt.TextAlignmentRole) items[3].setData(Qt.AlignRight, Qt.TextAlignmentRole) model.invisibleRootItem().appendRow(items) self.ui.treeView.setModel(model) header = self.ui.treeView.header() model.setHeaderData(0, Qt.Horizontal, "Name") model.setHeaderData(1, Qt.Horizontal, "# First Scan") model.setHeaderData(2, Qt.Horizontal, "Date Created") model.setHeaderData(3, Qt.Horizontal, "# Second Scan") model.setHeaderData(4, Qt.Horizontal, "Date Scanned") header.setResizeMode(0, QHeaderView.ResizeToContents) header.setResizeMode(1, QHeaderView.ResizeToContents) header.setResizeMode(2, QHeaderView.ResizeToContents) header.setResizeMode(3, QHeaderView.ResizeToContents) header.setResizeMode(4, QHeaderView.ResizeToContents) self.ui.treeView.selectionModel().currentRowChanged.connect( self.__onSelectionChanged)
def isComplete(self): done = self.document_name is not None if done: # if the second scan completed OK, we can skip the second scan fullpath_doc_name = DocumentStorage.documentFullPath( self.document_name) logger.debug("going with full path of document: {0}".format( fullpath_doc_name)) persist_doc = PersistentScanningState(fullpath_doc_name) self.setField("secondScanComplete", persist_doc.info.merge_complete) self.wizard().setDocumentName(self.document_name) self.wizard().setWindowFilePath(fullpath_doc_name) return done
def beginInitialScan(self, scan_paths, doc_name = None): # construct an initial scan, based on the selected items within the model... # workflow: scan to produce a persistent model, monitor/rescan, re-integrate changes into initial model (changed, deleted, added etc) scanner = DirectoryScanner() scanner.addPathsForScanning(scan_paths) # we want to store the results too - so build a storage device, its all being run via iterables # so its easy to chain these together. doc_path = DocumentStorage.getDocumentPathForName(doc_name, scan_paths) self.storage = PersistentScanningState(doc_path) self.storage.storePathsBeingScanned(scanner.paths_to_scan) self.storage.scanningStateChanged.connect(lambda x: self.scanStateChanged.emit(x)) self.isScanning = True self.scanStarted.emit(doc_path) # this one line performs a recursive disk scan on multiple folders, obtains file/dir info, persists # this to the DB and then finally exposes [idx, f] so the UI can display progress. Long live iterables... (and C++, you can die in a fire) total_found = 0 for idx, f in enumerate(self.storage.storeFilesystemSnapshot(scanner)): total_found = idx if not (idx % 100): self.scanProgress.emit(idx, f.abs_path) if not self.isScanning: break registryScanner = RegistryScanner() totalRegistry = 0 for idx ,r in enumerate(self.storage.storeRegistryEntrySnapshot(registryScanner)): totalRegistry = idx if not (idx % 100): self.scanProgress.emit(idx, r.key_name) if not self.isScanning: break self.stopScanning() # complete the scan... self.scanFinished.emit(total_found) self.storage = None
def initializePage(self): """ Find and load the persistent document, create the export UI and insert it into the 'container'. This method assumes that the wizard has a documentName set. """ self.container = QWidget(self) if self.plugin is not None: self.plugin.ui.setParent(None) self.gridLayout.removeWidget(self.plugin.ui) self.plugin.ui = None self.plugin = None name_of_file = self.wizard().documentName() document = PersistentScanningState( DocumentStorage.documentFullPath(name_of_file)) self.plugin = self.__createPluginNamed( self.field("exportType").toString()) ui = self.__createExportUI(document, self.container) self.gridLayout.addWidget(ui) self.changed()
class MacTestBuildTreeModel(unittest.TestCase): """ Tests how a tree model is built in different path/scan situations, and with different input data - esp. between the mac and windows implementations. """ def setUp(self): self.t = DirectoryScanner() self.builder = DirectoryTreeBuilder() # construct a known directory structure, suitable for testing - it includes files, directories, ACL's, etc self.contents_path = self.builder.make_dir("BB/TextEdit.app/Contents", 0755) self.builder.make_dir("BB/TextEdit.app/Contents/Resources", 0755) self.builder.make_dir("BB/TextEdit.app/Contents/Frameworks", 0755) self.builder.create_file("BB/TextEdit.app/Contents/Stupid.txt", 0755, 425) # produce a single scan of the fake file-system entries self.p = PersistentScanningState("tree-tests.sqlite") self.t.addPathsForScanning([self.builder.rootDir]) self.initialScan() self.mergeScan() def initialScan(self): for value in self.p.storeFilesystemSnapshot(self.t.performScan()): pass self.assertTrue(self.p.numberOfScannedFiles() > 0) def mergeScan(self): for value in self.p.storeSecondScan(self.t.performScan()): pass self.assertTrue(self.p.numberOfMergedFiles() > 0) def test_simple_tree_model(self): # grab a fake scan of something we know the content of, e.g. one directory containing one file builder = FileSystemTreeModelBuilder(self.p) builder.buildModel() topLevel = builder.itemRootedAtPath(self.builder.rootDir) itemBB = builder.childOfItem(topLevel, "BB") self.assertTrue(itemBB is not None) self.assertEqual(itemBB.data().toString(), "BB") self.assertEqual(itemBB.rowCount(), 1) # fetch something that doesn't exist - should bring me back None self.assertEqual(None, builder.childOfItem(itemBB, "Not Here")) self.assertEqual(None, builder.itemRootedAtPath(os.path.join(self.builder.rootDir, "WOOT"))) itemTextEdit = builder.childOfItem(itemBB, "TextEdit.app") self.assertTrue(itemTextEdit is not None) self.assertEqual(itemTextEdit.data().toString(), "TextEdit.app") self.assertEqual(itemTextEdit.rowCount(), 1) itemContents = builder.childOfItem(itemTextEdit, "Contents") self.assertTrue(itemContents is not None) self.assertEqual(itemContents.data().toString(), "Contents") self.assertEqual(itemContents.rowCount(), 2) # go grab both - they should be the frameworks and resources items = builder.childrenOfItem(itemContents, ["Resources", "Frameworks"]) self.assertEqual(items["Resources"].data().toString(), "Resources") self.assertEqual(items["Frameworks"].data().toString(), "Frameworks")
def setUp(self): self.p = PersistentScanningState("test.sqlite", echo_sql=False)
class ScanningController(QObject): scanStarted = pyqtSignal(str) scanProgress = pyqtSignal(int, str) scanStateChanged = pyqtSignal(int) scanFinished = pyqtSignal(int) mergeCompleted = pyqtSignal() def __init__(self): super(QObject, self).__init__() self.document = None self.isScanning = True self.storage = None def stopScanning(self): self.isScanning = False if self.storage is not None: self.storage.isScanning = False def beginInitialScan(self, scan_paths, doc_name = None): # construct an initial scan, based on the selected items within the model... # workflow: scan to produce a persistent model, monitor/rescan, re-integrate changes into initial model (changed, deleted, added etc) scanner = DirectoryScanner() scanner.addPathsForScanning(scan_paths) # we want to store the results too - so build a storage device, its all being run via iterables # so its easy to chain these together. doc_path = DocumentStorage.getDocumentPathForName(doc_name, scan_paths) self.storage = PersistentScanningState(doc_path) self.storage.storePathsBeingScanned(scanner.paths_to_scan) self.storage.scanningStateChanged.connect(lambda x: self.scanStateChanged.emit(x)) self.isScanning = True self.scanStarted.emit(doc_path) # this one line performs a recursive disk scan on multiple folders, obtains file/dir info, persists # this to the DB and then finally exposes [idx, f] so the UI can display progress. Long live iterables... (and C++, you can die in a fire) total_found = 0 for idx, f in enumerate(self.storage.storeFilesystemSnapshot(scanner)): total_found = idx if not (idx % 100): self.scanProgress.emit(idx, f.abs_path) if not self.isScanning: break registryScanner = RegistryScanner() totalRegistry = 0 for idx ,r in enumerate(self.storage.storeRegistryEntrySnapshot(registryScanner)): totalRegistry = idx if not (idx % 100): self.scanProgress.emit(idx, r.key_name) if not self.isScanning: break self.stopScanning() # complete the scan... self.scanFinished.emit(total_found) self.storage = None def beginChangesScan(self, doc_name): """ Find the selected item, and use the directories inside to perform a scan, the merge the results of that with the existing document - forming a set of objects that have been added/changed/removed """ # now fetch the data model for that one to get the paths that need to be scanned self.storage = PersistentScanningState(DocumentStorage.documentFullPath(doc_name)) #return self.__beginChangesScanWithDocument() self.__beginChangesScanWithDocument() def __beginChangesScanWithDocument(self): scan_paths = [ p.abs_path for p in self.storage.pathsBeingScanned() ] # kick off another scan scan = DirectoryScanner() scan.addPathsForScanning(scan_paths) self.scanStarted.emit(self.storage.filename) # now re-scan, we'll use a 'merge' facility from the persistent scanning state, it automatically # creates the required set of (added, modified, deleted) files. total_found = 0 merge = self.storage.storeSecondScan(scan) for idx, f in enumerate(merge): total_found = idx #yield idx, f if not (idx % 100): self.scanProgress.emit(idx, ensure_unicode(f.abs_path)) if not self.isScanning: break total_found = 0 registryScanner = RegistryScanner() for idx, r in enumerate(self.storage.storeSecondRegistryScan(registryScanner)): total_found = idx if not (idx % 100): self.scanProgress.emit(idx, ensure_unicode(r.key)) if not self.isScanning: break self.scanFinished.emit(total_found) self.mergeCompleted.emit() self.stopScanning() self.storage = None
class FindDifferencesTestCase(TestCase): def setUp(self): self.t = DirectoryScanner() self.builder = DirectoryTreeBuilder() # construct a known directory structure, suitable for testing - it includes files, directories, ACL's, etc self.contents_path = self.builder.make_dir("AA/TextEdit.app/Contents", 0755) self.builder.make_dir("AA/TextEdit.app/Contents/Resources", 0755) self.builder.make_dir("AA/TextEdit.app/Contents/Frameworks", 0755) self.dbName = "find-diffs.sqlite" self.removeDB() # produce a single scan of the fake file-system entries self.p = PersistentScanningState(self.dbName) self.t.addPathsForScanning([self.builder.rootDir]) self.initialScan() def tearDown(self): self.p = None self.t = None self.builder = None self.removeDB() def removeDB(self): try: if os.path.exists(self.dbName): os.unlink(self.dbName) except Exception: logger.critical("all bets are off - could not delete {0}".format( self.dbName)) def initialScan(self): for value in self.p.storeFilesystemSnapshot(self.t): pass self.assertTrue(self.p.scanInfo().files_scanned > 0) self.assertEqual(0, self.p.scanInfo().files_merged) def mergeScan(self): for value in self.p.storeSecondScan(self.t): pass self.assertTrue(self.p.scanInfo().files_merged > 0) def test_parent_child_relationships_in_file_system(self): # fetch the root FileSystemSnapshot object, grab its children path = FileSystemHelper.convertedPath('%AA/TextEdit.app/Contents') root = self.p.session.query(FileSystemSnapshot).filter( FileSystemSnapshot.abs_path.like(path)).one() self.assertTrue(root is not None) children = root.children for child in children: logger.info("{0}".format(child)) def test_find_new_directory(self): self.builder.make_dir("AA/NewDirectory", 0777) self.mergeScan() ms = self.p.session.query(FileSystemMerge).filter( FileSystemMerge.abs_path.like('%NewDirectory')).one() logger.info("row, after add: {0}".format(ms.abs_path)) self.assertEqual(Qt.Checked, ms.checked) self.assertEqual(PersistentScanningState.ITEM_ADDED, ms.flags) # now find AA, it should be partial because NewDirectory is well, new, and other stuff is marked as Qt.Unchecked fs_parent = self.p.session.query(FileSystemSnapshot).get( ms.parent.abs_path) self.assertTrue(fs_parent is not None) has_parent_changed = fs_parent.path_info != ms.parent.path_info if has_parent_changed: self.assertEqual(Qt.PartiallyChecked, ms.parent.checked) self.assertEqual(PersistentScanningState.ITEM_MODIFIED, ms.parent.flags) else: self.assertEqual(PersistentScanningState.ITEM_UNCHANGED, ms.parent.flags) def test_find_deleted_directory(self): self.builder.del_dir("AA/TextEdit.app/Contents/Frameworks") self.mergeScan() ms = self.p.session.query(FileSystemMerge).filter( FileSystemMerge.abs_path.like('%Frameworks')).one() self.assertTrue( ms.abs_path.endswith( FileSystemHelper.convertedPath( "AA/TextEdit.app/Contents/Frameworks"))) self.assertEqual(PersistentScanningState.ITEM_DELETED, ms.flags) self.assertEqual(Qt.Unchecked, ms.checked) @skipIf(Platform.isWindows, "POSIX tests cannot run on Windows") def test_modified_directory_owner(self): self.builder.change_posix("AA/TextEdit.app/Contents", 0500) self.mergeScan() query = self.p.session.query("ct", "flags", "checked").from_statement( "SELECT count(*) as ct, flags, checked FROM file_system_merge WHERE abs_path LIKE '%Contents'" ).one() count = query.ct flags = query.flags checked = query.checked # even though the two folders UNDER this one are unchanged, the fact that this folder is modified takes precedence self.assertEqual(count, 1) self.assertEqual(flags, PersistentScanningState.ITEM_MODIFIED) self.assertEqual(checked, Qt.Checked) def test_root_scan_paths_are_in_persistent_document(self): paths = self.p.pathsBeingScanned() self.assertEqual(paths[0].abs_path, self.builder.rootDir) # run a merge scan to produce content in the FileSystemMerge table self.mergeScan() # and that this path is explicitly available from the FileSystemMerge model... root_path = self.p.session.query(FileSystemMerge).filter( FileSystemMerge.abs_path == self.builder.rootDir).one() self.assertTrue(root_path is not None) self.assertEqual(root_path.abs_path, self.builder.rootDir) def test_find_modified_directories_and_files(self): pass
class ScanningController(QObject): scanStarted = pyqtSignal(str) scanProgress = pyqtSignal(int, str) scanStateChanged = pyqtSignal(int) scanFinished = pyqtSignal(int) mergeCompleted = pyqtSignal() def __init__(self): super(QObject, self).__init__() self.document = None self.isScanning = True self.storage = None def stopScanning(self): self.isScanning = False if self.storage is not None: self.storage.isScanning = False def beginInitialScan(self, scan_paths, doc_name=None): # construct an initial scan, based on the selected items within the model... # workflow: scan to produce a persistent model, monitor/rescan, re-integrate changes into initial model (changed, deleted, added etc) scanner = DirectoryScanner() scanner.addPathsForScanning(scan_paths) # we want to store the results too - so build a storage device, its all being run via iterables # so its easy to chain these together. doc_path = DocumentStorage.getDocumentPathForName(doc_name, scan_paths) self.storage = PersistentScanningState(doc_path) self.storage.storePathsBeingScanned(scanner.paths_to_scan) self.storage.scanningStateChanged.connect( lambda x: self.scanStateChanged.emit(x)) self.isScanning = True self.scanStarted.emit(doc_path) # this one line performs a recursive disk scan on multiple folders, obtains file/dir info, persists # this to the DB and then finally exposes [idx, f] so the UI can display progress. Long live iterables... (and C++, you can die in a fire) total_found = 0 for idx, f in enumerate(self.storage.storeFilesystemSnapshot(scanner)): total_found = idx if not (idx % 100): self.scanProgress.emit(idx, f.abs_path) if not self.isScanning: break registryScanner = RegistryScanner() totalRegistry = 0 for idx, r in enumerate( self.storage.storeRegistryEntrySnapshot(registryScanner)): totalRegistry = idx if not (idx % 100): self.scanProgress.emit(idx, r.key_name) if not self.isScanning: break self.stopScanning() # complete the scan... self.scanFinished.emit(total_found) self.storage = None def beginChangesScan(self, doc_name): """ Find the selected item, and use the directories inside to perform a scan, the merge the results of that with the existing document - forming a set of objects that have been added/changed/removed """ # now fetch the data model for that one to get the paths that need to be scanned self.storage = PersistentScanningState( DocumentStorage.documentFullPath(doc_name)) #return self.__beginChangesScanWithDocument() self.__beginChangesScanWithDocument() def __beginChangesScanWithDocument(self): scan_paths = [p.abs_path for p in self.storage.pathsBeingScanned()] # kick off another scan scan = DirectoryScanner() scan.addPathsForScanning(scan_paths) self.scanStarted.emit(self.storage.filename) # now re-scan, we'll use a 'merge' facility from the persistent scanning state, it automatically # creates the required set of (added, modified, deleted) files. total_found = 0 merge = self.storage.storeSecondScan(scan) for idx, f in enumerate(merge): total_found = idx #yield idx, f if not (idx % 100): self.scanProgress.emit(idx, ensure_unicode(f.abs_path)) if not self.isScanning: break total_found = 0 registryScanner = RegistryScanner() for idx, r in enumerate( self.storage.storeSecondRegistryScan(registryScanner)): total_found = idx if not (idx % 100): self.scanProgress.emit(idx, ensure_unicode(r.key)) if not self.isScanning: break self.scanFinished.emit(total_found) self.mergeCompleted.emit() self.stopScanning() self.storage = None