def getCachedSize(self): fetcher = Fetcher() localdir = os.path.join(sysconf.get("data-dir"), "packages/") fetcher.setLocalDir(localdir, mangle=False) total = 0 for pkg in self.install: for loader in pkg.loaders: if not loader.getInstalled(): break else: continue info = loader.getInfo(pkg) for url in info.getURLs(): mirror = fetcher.getMirrorSystem().get(url) item = FetchItem(fetcher, url, mirror) path = fetcher.getLocalPath(item) if os.path.exists(path): total += os.path.getsize(path) return total
class Control(object): def __init__(self, confpath=None, forcelocks=False): self._confpath = None self._channels = {} # alias -> Channel() self._sysconfchannels = {} # alias -> data dict self._dynamicchannels = {} # alias -> Channel() self._pathlocks = PathLocks(forcelocks) self._cache = Cache() self.loadSysConf(confpath) self._fetcher = Fetcher() self._mediaset = self._fetcher.getMediaSet() self._achanset = AvailableChannelSet(self._fetcher) self._cachechanged = False def getChannels(self): return self._channels.values() def removeChannel(self, alias): channel = self._channels[alias] if isinstance(channel, PackageChannel): channel.removeLoaders() del self._channels[alias] if alias in self._sysconfchannels: del self._sysconfchannels[alias] if alias in self._dynamicchannels: del self._dynamicchannels[alias] def getFileChannels(self): return [ x for x in self._channels.values() if isinstance(x, FileChannel) ] def checkPackageFile(self, arg): if os.path.exists(arg): if filter(None, hooks.call("check-package-file", arg)): return True if (os.path.isfile(arg) and os.path.getsize(arg) > 0 and tarfile.is_tarfile(arg)): return True return False def addFileChannel(self, filename): if not self._sysconfchannels: # Give a chance for backends to register # themselves on FileChannel hooks. self.rebuildSysConfChannels() found = False for channel in hooks.call("create-file-channel", filename): if channel: if channel.getAlias() in self._channels: raise Error, _("There's another channel with alias '%s'") \ % channel.getAlias() self._channels[channel.getAlias()] = channel found = True if not found and tarfile.is_tarfile(filename): tempdir = tempfile.mkdtemp() iface.debug("Extracting from %s to %s" % (filename, tempdir)) tarball = tarfile.open(filename, 'r') names = tarball.getnames() for name in names: tarball.extract(name, path=tempdir) tarball.close() files = os.listdir(tempdir) for file in files: path = os.path.join(tempdir, file) if os.path.isdir(path) and file == "RPMS": for rpm in os.listdir(path): files.append(os.path.join(path, rpm)) if os.path.isfile(path) and self.checkPackageFile(path): self.addFileChannel(path) found = True if not found: raise Error, _("Unable to create channel for file: %s") % filename def removeFileChannel(self, filename): filename = os.path.abspath(filename) for channel in self._channels.values(): if (isinstance(channel, FileChannel) and channel.getFileName() == filename): channel.removeLoaders() break else: raise Error, _("Channel not found for '%s'") % filename def askForRemovableChannels(self, channels): removable = [(str(x), x) for x in channels if x.isRemovable()] if not removable: return True removable.sort() removable = [x for name, x in removable] self._mediaset.umountAll() if not iface.insertRemovableChannels(removable): return False self._mediaset.mountAll() return True def getCache(self): return self._cache def getFetcher(self): return self._fetcher def getMediaSet(self): return self._mediaset def restoreMediaState(self): self._mediaset.restoreState() __stateversion__ = 2 def loadSysConf(self, confpath=None): datadir = sysconf.get("data-dir") if confpath: confpath = os.path.expanduser(confpath) if not os.path.isfile(confpath): raise Error, _("Configuration file not found: %s") % confpath sysconf.load(confpath) else: confpath = os.path.join(datadir, CONFFILE) if os.path.isfile(confpath): sysconf.load(confpath) self._confpath = confpath if os.path.isdir(datadir): writable = os.access(datadir, os.W_OK) else: try: os.makedirs(datadir) writable = True except OSError: raise Error, _("Can't create datadir at %s") % datadir if writable and not self._pathlocks.lock(datadir, exclusive=True): writable = False sysconf.setReadOnly(not writable) def saveSysConf(self, confpath=None): msys = self._fetcher.getMirrorSystem() if msys.getHistoryChanged() and not sysconf.getReadOnly(): sysconf.set("mirrors-history", msys.getHistory()) if confpath: confpath = os.path.expanduser(confpath) else: if sysconf.getReadOnly(): return if self._cachechanged: cachepath = os.path.join(sysconf.get("data-dir"), "cache") if sysconf.get("disk-cache", True): iface.showStatus(_("Saving cache...")) cachefile = open(cachepath + ".new", "w") state = (self.__stateversion__, self._cache, self._channels, self._sysconfchannels) cPickle.dump(state, cachefile, 2) cachefile.close() os.rename(cachepath + ".new", cachepath) iface.hideStatus() elif os.path.isfile(cachepath): os.unlink(cachepath) if not sysconf.getModified(): return sysconf.resetModified() confpath = self._confpath sysconf.save(confpath) def reloadMirrors(self): mirrors = sysconf.get("mirrors", {}) for channel in self._channels.values(): if isinstance(channel, MirrorsChannel): cmirrors = channel.getMirrors() if cmirrors: for origin in cmirrors: set = dict.fromkeys(cmirrors[origin]) set.update(dict.fromkeys(mirrors.get(origin, []))) mirrors[origin] = set.keys() msys = self._fetcher.getMirrorSystem() msys.setMirrors(mirrors) if not msys.getHistory(): msys.setHistory(sysconf.get("mirrors-history", [])) def rebuildSysConfChannels(self): channels = sysconf.get("channels", ()) forcechannels = sysconf.get("force-channels", "") if forcechannels: forcechannels = forcechannels.split(",") def isEnabled(alias, data): if forcechannels: return alias in forcechannels return not data.get("disabled") if channels and not self._channels: cachepath = os.path.join(sysconf.get("data-dir"), "cache") if os.path.isfile(cachepath) and sysconf.get("disk-cache", True): iface.showStatus(_("Loading cache...")) cachefile = open(cachepath) try: state = cPickle.load(cachefile) if state[0] != self.__stateversion__: raise StateVersionError except: if sysconf.get("log-level") == DEBUG: import traceback traceback.print_exc() if os.access(os.path.dirname(cachepath), os.W_OK): os.unlink(cachepath) else: (__stateversion__, self._cache, self._channels, self._sysconfchannels) = state for alias in self._channels.keys(): if (alias not in channels or not isEnabled(alias, channels[alias])): self.removeChannel(alias) cachefile.close() iface.hideStatus() for alias in channels: data = channels[alias] if not isEnabled(alias, data): continue if alias in self._sysconfchannels.keys(): if self._sysconfchannels[alias] == data: continue else: channel = self._channels[alias] if isinstance(channel, PackageChannel): channel.removeLoaders() del self._channels[alias] del self._sysconfchannels[alias] channel = createChannel(alias, data) self._sysconfchannels[alias] = data self._channels[alias] = channel for alias in self._sysconfchannels.keys(): if alias not in channels or channels[alias].get("disabled"): self.removeChannel(alias) def rebuildDynamicChannels(self): for alias in self._dynamicchannels.keys(): self.removeChannel(alias) newchannels = {} for channels in hooks.call("rebuild-dynamic-channels"): if channels: for channel in channels: alias = channel.getAlias() if alias in self._channels: raise Error, _("There's another channel with " "alias '%s'") % alias newchannels[alias] = channel self._channels.update(newchannels) self._dynamicchannels.update(newchannels) def reloadChannels(self, channels=None, caching=ALWAYS): if channels is None: manual = False self.rebuildSysConfChannels() self.rebuildDynamicChannels() channels = self._channels.values() hooks.call("reload-channels", channels) else: manual = True # Get channels directory and check the necessary locks. channelsdir = os.path.join(sysconf.get("data-dir"), "channels/") userchannelsdir = os.path.join(sysconf.get("user-data-dir"), "channels/") if not os.path.isdir(channelsdir): try: os.makedirs(channelsdir) except OSError: raise Error, _("Unable to create channel directory.") if caching is ALWAYS: if sysconf.getReadOnly() and os.access(channelsdir, os.W_OK): iface.warning( _("The Smart library is already in use by " "another process.")) iface.warning(_("Configuration is in readonly mode!")) if not self._pathlocks.lock(channelsdir): raise Error, _("Channel information is locked for writing.") elif sysconf.getReadOnly(): raise Error, _("Can't update channels in readonly mode.") elif not self._pathlocks.lock(channelsdir, exclusive=True): raise Error, _("Can't update channels with active readers.") self._fetcher.setLocalDir(channelsdir, mangle=True) # Prepare progress. If we're reading from the cache, we don't want # too much information being shown. Otherwise, ask for a full-blown # progress for the interface, and build information of currently # available packages to compare later. if caching is ALWAYS: progress = Progress() else: progress = iface.getProgress(self._fetcher, True) oldpkgs = {} for pkg in self._cache.getPackages(): oldpkgs[(pkg.name, pkg.version)] = True progress.start() steps = 0 for channel in channels: steps += channel.getFetchSteps() progress.set(0, steps) # Rebuild mirror information. self.reloadMirrors() self._fetcher.setForceMountedCopy(True) self._cache.reset() # Do the real work. result = True for channel in channels: digest = channel.getDigest() if not manual and channel.hasManualUpdate(): self._fetcher.setCaching(ALWAYS) else: self._fetcher.setCaching(caching) if channel.getFetchSteps() > 0: progress.setTopic( _("Fetching information for '%s'...") % (channel.getName() or channel.getAlias())) progress.show() self._fetcher.setForceCopy(channel.isRemovable()) self._fetcher.setLocalPathPrefix(channel.getAlias() + "%%") try: if not channel.fetch(self._fetcher, progress): iface.debug(_("Failed fetching channel '%s'") % channel) result = False except Error, e: iface.error(unicode(e)) iface.debug(_("Failed fetching channel '%s'") % channel) result = False if (channel.getDigest() != digest and isinstance(channel, PackageChannel)): channel.addLoaders(self._cache) if channel.getAlias() in self._sysconfchannels: self._cachechanged = True if result and caching is not ALWAYS: sysconf.set("last-update", time.time()) self._fetcher.setForceMountedCopy(False) self._fetcher.setForceCopy(False) self._fetcher.setLocalPathPrefix(None) # Finish progress. progress.setStopped() progress.show() progress.stop() # Build cache with the new information. self._cache.load() # Compare new packages with what we had available, and mark # new packages. if caching is not ALWAYS: pkgconf.clearFlag("new") for pkg in self._cache.getPackages(): if (pkg.name, pkg.version) not in oldpkgs: pkgconf.setFlag("new", pkg.name, "=", pkg.version) # Remove unused files from channels directory. for dir in (channelsdir, userchannelsdir): if os.access(dir, os.W_OK): aliases = self._channels.copy() aliases.update(dict.fromkeys(sysconf.get("channels", ()))) for entry in os.listdir(dir): sep = entry.find("%%") if sep == -1 or entry[:sep] not in aliases: os.unlink(os.path.join(dir, entry)) # Change back to a shared lock. self._pathlocks.lock(channelsdir) return result
class Control(object): def __init__(self, confpath=None, forcelocks=False): self._confpath = None self._channels = {} # alias -> Channel() self._sysconfchannels = {} # alias -> data dict self._dynamicchannels = {} # alias -> Channel() self._pathlocks = PathLocks(forcelocks) self._cache = Cache() self.loadSysConf(confpath) self._fetcher = Fetcher() self._mediaset = self._fetcher.getMediaSet() self._achanset = AvailableChannelSet(self._fetcher) self._cachechanged = False def getChannels(self): return self._channels.values() def removeChannel(self, alias): channel = self._channels[alias] if isinstance(channel, PackageChannel): channel.removeLoaders() del self._channels[alias] if alias in self._sysconfchannels: del self._sysconfchannels[alias] if alias in self._dynamicchannels: del self._dynamicchannels[alias] def getFileChannels(self): return [x for x in self._channels.values() if isinstance(x, FileChannel)] def addFileChannel(self, filename): if not self._sysconfchannels: # Give a chance for backends to register # themselves on FileChannel hooks. self.rebuildSysConfChannels() found = False for channel in hooks.call("create-file-channel", filename): if channel: if channel.getAlias() in self._channels: raise Error, _("There's another channel with alias '%s'") \ % channel.getAlias() self._channels[channel.getAlias()] = channel found = True if not found: raise Error, _("Unable to create channel for file: %s") % filename def removeFileChannel(self, filename): filename = os.path.abspath(filename) for channel in self._channels.values(): if (isinstance(channel, FileChannel) and channel.getFileName() == filename): channel.removeLoaders() break else: raise Error, _("Channel not found for '%s'") % filename def askForRemovableChannels(self, channels): removable = [(str(x), x) for x in channels if x.isRemovable()] if not removable: return True removable.sort() removable = [x for name, x in removable] self._mediaset.umountAll() if not iface.insertRemovableChannels(removable): return False self._mediaset.mountAll() return True def getCache(self): return self._cache def getFetcher(self): return self._fetcher def getMediaSet(self): return self._mediaset def restoreMediaState(self): self._mediaset.restoreState() __stateversion__ = 2 def loadSysConf(self, confpath=None): datadir = sysconf.get("data-dir") if confpath: confpath = os.path.expanduser(confpath) if not os.path.isfile(confpath): raise Error, _("Configuration file not found: %s") % confpath sysconf.load(confpath) else: confpath = os.path.join(datadir, CONFFILE) if os.path.isfile(confpath): sysconf.load(confpath) self._confpath = confpath if os.path.isdir(datadir): writable = os.access(datadir, os.W_OK) else: try: os.makedirs(datadir) writable = True except OSError: raise Error, _("Can't create datadir at %s") % datadir if writable and not self._pathlocks.lock(datadir, exclusive=True): writable = False sysconf.setReadOnly(not writable) def saveSysConf(self, confpath=None): msys = self._fetcher.getMirrorSystem() if msys.getHistoryChanged() and not sysconf.getReadOnly(): sysconf.set("mirrors-history", msys.getHistory()) if confpath: confpath = os.path.expanduser(confpath) else: if sysconf.getReadOnly(): return if self._cachechanged: cachepath = os.path.join(sysconf.get("data-dir"), "cache") if sysconf.get("disk-cache", True): iface.showStatus(_("Saving cache...")) cachefile = open(cachepath+".new", "w") state = (self.__stateversion__, self._cache, self._channels, self._sysconfchannels) cPickle.dump(state, cachefile, 2) if os.name == 'nt': os.close(cachefile.fileno()) else: # 'posix' cachefile.close() os.rename(cachepath+".new", cachepath) iface.hideStatus() elif os.path.isfile(cachepath): os.unlink(cachepath) if not sysconf.getModified(): return sysconf.resetModified() confpath = self._confpath sysconf.save(confpath) def reloadMirrors(self): mirrors = sysconf.get("mirrors", {}) for channel in self._channels.values(): if isinstance(channel, MirrorsChannel): cmirrors = channel.getMirrors() if cmirrors: for origin in cmirrors: set = dict.fromkeys(cmirrors[origin]) set.update(dict.fromkeys(mirrors.get(origin, []))) mirrors[origin] = set.keys() msys = self._fetcher.getMirrorSystem() msys.setMirrors(mirrors) if not msys.getHistory(): msys.setHistory(sysconf.get("mirrors-history", [])) def rebuildSysConfChannels(self): channels = sysconf.get("channels", ()) forcechannels = sysconf.get("force-channels", "") if forcechannels: forcechannels = forcechannels.split(",") def isEnabled(alias, data): if forcechannels: return alias in forcechannels return not data.get("disabled") if channels and not self._channels: cachepath = os.path.join(sysconf.get("data-dir"), "cache") if os.path.isfile(cachepath) and sysconf.get("disk-cache", True): iface.showStatus(_("Loading cache...")) cachefile = open(cachepath) try: state = cPickle.load(cachefile) if state[0] != self.__stateversion__: raise StateVersionError except: if sysconf.get("log-level") == DEBUG: import traceback traceback.print_exc() if os.access(os.path.dirname(cachepath), os.W_OK): if os.name == 'nt': os.close(cachefile.fileno()) else: # 'posix' cachefile.close() os.unlink(cachepath) else: (__stateversion__, self._cache, self._channels, self._sysconfchannels) = state for alias in self._channels.keys(): if (alias not in channels or not isEnabled(alias, channels[alias])): self.removeChannel(alias) cachefile.close() iface.hideStatus() for alias in channels: data = channels[alias] if not isEnabled(alias, data): continue if alias in self._sysconfchannels.keys(): if self._sysconfchannels[alias] == data: continue else: channel = self._channels[alias] if isinstance(channel, PackageChannel): channel.removeLoaders() del self._channels[alias] del self._sysconfchannels[alias] channel = createChannel(alias, data) self._sysconfchannels[alias] = data self._channels[alias] = channel for alias in self._sysconfchannels.keys(): if alias not in channels or channels[alias].get("disabled"): self.removeChannel(alias) def rebuildDynamicChannels(self): for alias in self._dynamicchannels.keys(): self.removeChannel(alias) newchannels = {} for channels in hooks.call("rebuild-dynamic-channels"): if channels: for channel in channels: alias = channel.getAlias() if alias in self._channels: raise Error, _("There's another channel with " "alias '%s'") % alias newchannels[alias] = channel self._channels.update(newchannels) self._dynamicchannels.update(newchannels) def reloadChannels(self, channels=None, caching=ALWAYS): if channels is None: manual = False self.rebuildSysConfChannels() self.rebuildDynamicChannels() channels = self._channels.values() hooks.call("reload-channels", channels) else: manual = True # Get channels directory and check the necessary locks. channelsdir = os.path.join(sysconf.get("data-dir"), "channels/") userchannelsdir = os.path.join(sysconf.get("user-data-dir"), "channels/") if not os.path.isdir(channelsdir): try: os.makedirs(channelsdir) except OSError: raise Error, _("Unable to create channel directory.") if caching is ALWAYS: if sysconf.getReadOnly() and os.access(channelsdir, os.W_OK): iface.warning(_("The Smart library is already in use by " "another process.")) iface.warning(_("Configuration is in readonly mode!")) if not self._pathlocks.lock(channelsdir): raise Error, _("Channel information is locked for writing.") elif sysconf.getReadOnly(): raise Error, _("Can't update channels in readonly mode.") elif not self._pathlocks.lock(channelsdir, exclusive=True): raise Error, _("Can't update channels with active readers.") self._fetcher.setLocalDir(channelsdir, mangle=True) # Prepare progress. If we're reading from the cache, we don't want # too much information being shown. Otherwise, ask for a full-blown # progress for the interface, and build information of currently # available packages to compare later. if caching is ALWAYS: progress = Progress() else: progress = iface.getProgress(self._fetcher, True) oldpkgs = {} for pkg in self._cache.getPackages(): oldpkgs[(pkg.name, pkg.version)] = True progress.start() steps = 0 for channel in channels: steps += channel.getFetchSteps() progress.set(0, steps) # Rebuild mirror information. self.reloadMirrors() self._fetcher.setForceMountedCopy(True) self._cache.reset() # Do the real work. result = True for channel in channels: digest = channel.getDigest() if not manual and channel.hasManualUpdate(): self._fetcher.setCaching(ALWAYS) else: self._fetcher.setCaching(caching) if channel.getFetchSteps() > 0: progress.setTopic(_("Fetching information for '%s'...") % (channel.getName() or channel.getAlias())) progress.show() self._fetcher.setForceCopy(channel.isRemovable()) self._fetcher.setLocalPathPrefix(channel.getAlias()+"%%") try: if not channel.fetch(self._fetcher, progress): iface.debug(_("Failed fetching channel '%s'") % channel) result = False except Error, e: iface.error(unicode(e)) iface.debug(_("Failed fetching channel '%s'") % channel) result = False if (channel.getDigest() != digest and isinstance(channel, PackageChannel)): channel.addLoaders(self._cache) if channel.getAlias() in self._sysconfchannels: self._cachechanged = True if result and caching is not ALWAYS: sysconf.set("last-update", time.time()) self._fetcher.setForceMountedCopy(False) self._fetcher.setForceCopy(False) self._fetcher.setLocalPathPrefix(None) # Finish progress. progress.setStopped() progress.show() progress.stop() # Build cache with the new information. self._cache.load() # Compare new packages with what we had available, and mark # new packages. if caching is not ALWAYS: pkgconf.clearFlag("new") for pkg in self._cache.getPackages(): if (pkg.name, pkg.version) not in oldpkgs: pkgconf.setFlag("new", pkg.name, "=", pkg.version) # Remove unused files from channels directory. for dir in (channelsdir, userchannelsdir): if os.access(dir, os.W_OK): aliases = self._channels.copy() aliases.update(dict.fromkeys(sysconf.get("channels", ()))) for entry in os.listdir(dir): sep = entry.find("%%") if sep == -1 or entry[:sep] not in aliases: os.unlink(os.path.join(dir, entry)) # Change back to a shared lock. self._pathlocks.lock(channelsdir) return result