def update(self, known_only=False): """Update our set of dropboxes to represent the latest state on disk @param known_only if True will not actually search for new dropboxes, but only check if existing dropboxes have had their configuration changed or were removed @return self""" def update_stat(dbpath, stat, db): try: new_stat = dbpath.stat() except OSError: del self.dropboxes[dbpath] self._dropbox_removed(db) else: if new_stat.st_size != stat.st_size or new_stat.st_mtime != stat.st_mtime: self.dropboxes[dbpath] = (new_stat, db) self._dropbox_changed(stat, new_stat, db) # end handle change # end handle dropbox doesn't exist # end utility to test stat if known_only: for dbpath, (stat, db) in self.dropboxes.iteritems(): update_stat(dbpath, stat, db) # end for each stat, db else: seen_paths = set() for search_base in self.paths: if search_base.endswith(os.path.sep): search_base = Path(search_base[:-1]) # end assure we don't end with slash if not search_base.isdir(): log.warn("Skipping unaccessible search base at '%s'", search_base) continue # end log.debug("Searching for dropboxes under '%s' (depth=%i, glob='%s')", search_base, self.max_depth, self.config_file_glob) num_dropboxes = 0 # Amount of dropboxes found for this search base for root, dirs, files in os.walk(search_base): if root[len(search_base):].count(os.path.sep) == self.max_depth - 1: del dirs[:] # end handle aborting recursion for match in (f for f in files if fnmatch(f, self.config_file_glob)): dbpath = Path(root) / match seen_paths.add(dbpath) num_dropboxes += 1 if dbpath in self.dropboxes: # check for change stat, db = self.dropboxes[dbpath] update_stat(dbpath, stat, db) else: # handle new dropbox try: stat = dbpath.stat() except OSError: log.error("Couldn't stat dropbox configuration at '%s' even though it was found during search", dbpath) else: dropbox = self.DropboxType(dbpath) self.dropboxes[dbpath] = (stat, dropbox) self._dropbox_added(stat, dropbox) # end handle inaccessible config file (invalid ACL ?) # end handle update or new # end handle each match # end for each root, dir, files if num_dropboxes == 0: log.warn("Didn't find a single dropbox in search base '%s'", search_base) # end info log # end for each search_base # Check for deleted for deleted_db_path in (set(self.dropboxes.keys()) - seen_paths): stat, db = self.dropboxes[deleted_db_path] del self.dropboxes[deleted_db_path] self._dropbox_removed(stat, db) # end for each deleted # end handle known only return self