diff --git a/docs/man/activator.pod b/docs/man/activator.pod index 098924428..417303b5a 100644 --- a/docs/man/activator.pod +++ b/docs/man/activator.pod @@ -122,6 +122,20 @@ sync all the configured repositories =back +=item B + +clean unavaiable packages from mirrors + +=over + + +=item B<--days=> + +expiration days [default is: 0] + +=back + + =item B lock the current repository database (server-side) diff --git a/docs/man/man1/activator.1 b/docs/man/man1/activator.1 index 2c5e1a729..6cc5c62cb 100644 --- a/docs/man/man1/activator.1 +++ b/docs/man/man1/activator.1 @@ -216,6 +216,16 @@ sync all the configured repositories .RE .RS 4 .RE +.IP "\fBvacuum\fR" 4 +.IX Item "vacuum" +clean unavaiable packages from mirrors +.RS 4 +.IP "\fB\-\-days=" 4 +.IX Item "--days=" +expiration days [default is: 0] +.RE +.RS 4 +.RE .IP "\fBlock\fR" 4 .IX Item "lock" lock the current repository database (server-side) @@ -272,6 +282,6 @@ Fabio Erculiani .SH "POD ERRORS" .IX Header "POD ERRORS" Hey! \fBThe above document had some coding errors, which are explained below:\fR -.IP "Around line 170:" 4 -.IX Item "Around line 170:" +.IP "Around line 184:" 4 +.IX Item "Around line 184:" You forgot a '=back' before '=head1' diff --git a/libraries/entropy/server/interfaces/mirrors.py b/libraries/entropy/server/interfaces/mirrors.py index fc290d47a..206d75c04 100644 --- a/libraries/entropy/server/interfaces/mirrors.py +++ b/libraries/entropy/server/interfaces/mirrors.py @@ -17,7 +17,7 @@ import time from entropy.exceptions import EntropyPackageException from entropy.output import red, darkgreen, bold, brown, blue, darkred, \ darkblue, purple, teal -from entropy.const import etpConst +from entropy.const import etpConst, const_get_int from entropy.cache import EntropyCacher from entropy.i18n import _ from entropy.misc import RSS @@ -1880,7 +1880,7 @@ class Server(object): if os.path.isfile(dest_expiration): os.remove(dest_expiration) - def _is_package_expired(self, repository_id, package_rel): + def _is_package_expired(self, repository_id, package_rel, days): pkg_path = self._entropy.complete_local_package_path(package_rel, repository_id) @@ -1888,10 +1888,8 @@ class Server(object): if not os.path.isfile(pkg_path): return False - srv_set = self._settings[Server.SYSTEM_SETTINGS_PLG_ID]['server'] mtime = os.path.getmtime(pkg_path) - days = srv_set['packages_expiration_days'] - delta = int(days)*24*3600 + delta = days*24*3600 currmtime = time.time() file_delta = currmtime - mtime @@ -1930,7 +1928,8 @@ class Server(object): return repo_bins - def tidy_mirrors(self, repository_id, ask = True, pretend = False): + def tidy_mirrors(self, repository_id, ask = True, pretend = False, + expiration_days = None): """ Cleanup package mirrors for given repository from outdated package files. A package file is considered outdated if the corresponding @@ -1944,10 +1943,21 @@ class Server(object): @type ask: bool @keyword pretend: just execute without effectively change anything on mirrors + @keyword expiration_days: days after a package is considered expired + @type: int @type pretend: bool @return: True, if tidy went successful, False if not @rtype: bool """ + if expiration_days is None: + srv_set = self._settings[Server.SYSTEM_SETTINGS_PLG_ID]['server'] + expiration_days = srv_set['packages_expiration_days'] + else: + if not isinstance(expiration_days, const_get_int()): + raise AttributeError("invalid expiration_days") + if expiration_days < 0: + raise AttributeError("invalid expiration_days") + self._entropy.output( "[%s|%s|%s] %s" % ( brown(repository_id), @@ -1997,7 +2007,8 @@ class Server(object): removal = [] for package_rel in expiring_packages: - expired = self._is_package_expired(repository_id, package_rel) + expired = self._is_package_expired(repository_id, package_rel, + expiration_days) if expired: removal.append(package_rel) else: diff --git a/server/activator.py b/server/activator.py index 3bdf6fb5c..29eaf7738 100644 --- a/server/activator.py +++ b/server/activator.py @@ -63,6 +63,8 @@ help_opts = [ (1, 'repo', 1, _('repository handling functions')), (2, 'sync', 3, _('sync the current repository database across primary mirrors')), (3, '--syncall', 1, _('sync all the configured repositories')), + (2, 'vacuum', 3, _('clean unavaiable packages from mirrors')), + (3, '--days=', 1, _('expiration days [default is: 0, dangerous!]')), (2, 'lock', 3, _('lock the current repository database (server-side)')), (2, 'unlock', 3, _('unlock the current repository database (server-side)')), (2, 'download-lock', 2, _('lock the current repository database (client-side)')), diff --git a/server/server_activator.py b/server/server_activator.py index 7fe785c8d..7b253165e 100644 --- a/server/server_activator.py +++ b/server/server_activator.py @@ -14,7 +14,8 @@ import tempfile import subprocess from entropy.const import etpConst, etpUi from entropy.output import red, green, print_info, bold, darkgreen, blue, \ - darkred, brown, print_error, readtext, print_generic + darkred, brown, purple, teal, print_error, print_warning, readtext, \ + print_generic from entropy.server.interfaces import Server from entropy.server.interfaces.rss import ServerRssMetadata from entropy.transceivers import EntropyTransceiver @@ -404,13 +405,10 @@ def repo(options): def _repo(entropy_server, options): - cmd = options[0] - sync_all = False - for opt in options: - if opt == "--syncall": - sync_all = True - elif opt.startswith("--"): - return -10 + if not options: + return -10 + + cmd, args = options[0], options[1:] repository_id = entropy_server.repository() @@ -495,7 +493,7 @@ def _repo(entropy_server, options): elif cmd == "sync": repos = [repository_id] - if sync_all: + if "--syncall" in args: repos = entropy_server.repositories() rc = 0 @@ -514,6 +512,34 @@ def _repo(entropy_server, options): return rc + elif cmd == "vacuum": + + days = 0 + for arg in args: + if arg.startswith("--days="): + s_days = arg[len("--days="):] + try: + days = int(s_days) + if days < 0: + raise ValueError() + except ValueError: + return -10 + break + else: + return -10 + + print_info(green(" * ")+darkgreen("%s ..." % ( + _("Cleaning unavailable packages from repository"),) )) + print_warning(teal(" * ") + \ + purple(_("Removing unavailable packages, overriding Entropy defaults is generally bad."))) + print_warning(teal(" * ") + \ + purple(_("Users with outdated repositories, won't be able to find package files remotely."))) + sts = entropy_server.Mirrors.tidy_mirrors(repository_id, ask = True, + pretend = etpUi['pretend'], expiration_days = days) + if sts: + return 0 + return 1 + return -10 def sync_remote_databases():