Viewing file:
mirror.py (10.67 KB) -rw-r--r--Select action/file-type:

(
+) |

(
+) |

(
+) |
Code (
+) |
Session (
+) |

(
+) |
SDB (
+) |

(
+) |

(
+) |

(
+) |

(
+) |

(
+) |
#
# Copyright (c) 2004 Conectiva, Inc.
#
# Written by Gustavo Niemeyer <niemeyer@conectiva.com>
#
# This file is part of Smart Package Manager.
#
# Smart Package Manager is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation; either version 2 of the License, or (at
# your option) any later version.
#
# Smart Package Manager is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Smart Package Manager; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
from smart.option import OptionParser, append_all
from smart.util.filetools import getFileDigest
from smart.channel import *
from smart import *
import textwrap
import tempfile
import sys, os
USAGE=_("smart mirror [options]")
DESCRIPTION=_("""
This command allows one to manipulate mirrors. Mirrors are URLs
that supposedly provide the same contents as are available in
other URLs, named origins in this help text. There is no internal
restriction on the kind of information which is mirrored. Once
an origin URL is provided, and one or more mirror URLs are
provided, these mirrors will be considered for any file which
is going to be fetched from an URL starting with the origin URL.
Whether the mirror will be chosen or not will depend on the
history of downloads from this mirror and from other mirrors for
the same URL, since mirrors are automatically balanced so that
the fastest mirror and with less errors is chosen. When errors
occur, the next mirror is tried.
For instance, if a mirror "http://mirror.url/path/" is provided
for the origin "ftp://origin.url/other/path/", and a file in
"ftp://origin.url/other/path/subpath/somefile" is going to be
fetched, the mirror will be considered for being used, and the
URL "http://mirror.url/path/subpath/somefile" will be used if
the mirror is chosen. Notice that strings are compared and
replaced without any pre-processing, so that it's possible to
use URLs ending in prefixes of directory entries.
""")
EXAMPLES=_("""
smart mirror --show
smart mirror --add ftp://origin.url/some/path/ http://mirror.url/path/
smart mirror --remove ftp://origin.url/some/path/ http://mirror.url/path/
smart mirror --add http://some.url/path/to/mirrors.txt
smart mirror --sync http://some.url/path/to/mirrors.txt
smart mirror --clear-history ftp://origin.url/some/path/
smart mirror --clear-history ftp://mirror.url/path/
smart mirror --clear-history
""")
EDITEXAMPLE=_("""\
#
# Example:
#
# http://origin.url/some/path/
# http://mirror.url/another/path/
# http://some.mirror.url/to/the/same/content/
#
# http://another.origin.url/another/path/
# http://another.mirror.url/yet/another/path/
#
""")
def option_parser():
parser = OptionParser(usage=USAGE,
description=DESCRIPTION,
examples=EXAMPLES)
parser.defaults["add"] = []
parser.defaults["remove"] = []
parser.defaults["remove_all"] = []
parser.defaults["clear_history"] = None
parser.add_option("--show", action="store_true",
help=_("show current mirrors"))
parser.add_option("--yaml", action="store_true",
help=_("show current mirrors in YAML format"))
parser.add_option("--add", action="callback", callback=append_all,
help=_("add to the given origin URL the given mirror "
"URL, provided either in pairs, or in a given "
"file/url in the format used by --show"))
parser.add_option("--remove", action="callback", callback=append_all,
help=_("remove from the given origin URL the given "
"mirror URL, provided either in pairs, or in a "
"given file/url in the format used by --show"))
parser.add_option("--remove-all", action="callback", callback=append_all,
help=_("remove all mirrors for the given origin URLs"))
parser.add_option("--sync", action="store", metavar="FILE",
help=_("synchronize mirrors from the given file/url, "
"so that origins in the given file will have "
"exactly the specified mirrors"))
parser.add_option("--edit", action="store_true",
help=_("edit mirrors in editor set by $EDITOR"))
parser.add_option("--clear-history", action="callback", callback=append_all,
help=_("clear history for the given origins/mirrors, or "
"for all mirrors"))
parser.add_option("--show-penalities", action="store_true",
help=_("show current penalities for origins/mirrors, "
"based on the history information"))
return parser
def parse_options(argv):
parser = option_parser()
opts, args = parser.parse_args(argv)
opts.args = args
return opts
def read_mirrors(ctrl, filename):
fetched = False
if ":/" in filename:
url = filename
succ, fail = ctrl.downloadURLs([url], _("mirror descriptions"))
if fail:
raise Error, _("Failed to download mirror descriptions:\n") + \
"\n".join([" %s: %s" % (url, fail[url])
for url in fail])
filename = succ[url]
fetched = True
elif not os.path.isfile(filename):
raise Error, _("File not found: %s") % filename
try:
result = []
origin = None
mirror = None
for line in open(filename):
url = line.strip()
if not url or url[0] == "#":
continue
if line[0].isspace():
mirror = url
else:
if origin and mirror is None:
result.append(origin)
result.append(None)
origin = url
mirror = None
continue
if not origin:
raise Error, _("Invalid mirrors file")
result.append(origin)
result.append(mirror)
if origin and mirror is None:
result.append(origin)
result.append(None)
finally:
if fetched and filename.startswith(sysconf.get("data-dir")):
os.unlink(filename)
return result
def main(ctrl, opts):
if opts.add:
if len(opts.add) == 1:
opts.add = read_mirrors(ctrl, opts.add[0])
if len(opts.add) % 2 != 0:
raise Error, _("Invalid arguments for --add")
for i in range(0,len(opts.add),2):
origin, mirror = opts.add[i:i+2]
if mirror:
sysconf.add(("mirrors", origin), mirror, unique=True)
if opts.remove:
if len(opts.remove) == 1:
opts.remove = read_mirrors(ctrl, opts.remove[0])
if len(opts.remove) % 2 != 0:
raise Error, _("Invalid arguments for --remove")
for i in range(0,len(opts.remove),2):
origin, mirror = opts.remove[i:i+2]
if not sysconf.has(("mirrors", origin)):
iface.warning(_("Origin not found: %s") % origin)
if not sysconf.remove(("mirrors", origin), mirror):
iface.warning(_("Mirror not found: %s") % mirror)
if opts.remove_all:
for origin in opts.remove_all:
if not sysconf.remove(("mirrors", origin)):
iface.warning(_("Origin not found: %s") % origin)
if opts.sync:
reset = {}
lst = read_mirrors(ctrl, opts.sync)
for i in range(0,len(lst),2):
origin, mirror = lst[i:i+2]
if origin not in reset:
reset[origin] = True
sysconf.remove(("mirrors", origin))
if mirror:
sysconf.add(("mirrors", origin), mirror, unique=True)
if opts.clear_history is not None:
if opts.clear_history:
history = sysconf.get("mirrors-history", [])
history[:] = [x for x in history if x[0] not in opts.clear_history]
sysconf.set("mirrors-history", history)
else:
history = sysconf.remove("mirrors-history")
if opts.show:
mirrors = sysconf.get("mirrors", ())
for origin in mirrors:
print origin
for mirror in mirrors[origin]:
print " ", mirror
print
if opts.yaml:
import yaml
yamlmirrors = {}
mirrors = sysconf.get("mirrors", ())
for origin in mirrors:
yamlmirrors[origin] = mirrors[origin]
print yaml.dump(yamlmirrors)
if opts.edit:
sysconf.assertWritable()
fd, name = tempfile.mkstemp(".txt")
file = os.fdopen(fd, "w")
print >>file, EDITEXAMPLE
origins = sysconf.keys("mirrors")
origins.sort()
for origin in origins:
print >>file, origin
mirrors = sysconf.get(("mirrors", origin))
for mirror in mirrors:
print >>file, " ", mirror
print >>file
file.close()
editor = os.environ.get("EDITOR", "vi")
olddigest = getFileDigest(name)
while True:
os.system("%s %s" % (editor, name))
newdigest = getFileDigest(name)
if newdigest == olddigest:
break
try:
lst = read_mirrors(ctrl, name)
except Error, e:
iface.error(unicode(e))
if not iface.askYesNo(_("Continue?"), True):
break
else:continue
newmirrors = {}
for i in range(0,len(lst),2):
origin, mirror = lst[i:i+2]
newmirrors.setdefault(origin, []).append(mirror)
sysconf.set("mirrors", newmirrors)
break
os.unlink(name)
if opts.show_penalities:
ctrl.reloadMirrors()
mirrorsystem = ctrl.getFetcher().getMirrorSystem()
penalities = mirrorsystem.getPenalities().copy()
mirrors = sysconf.get("mirrors", ())
for origin in mirrors:
if origin not in penalities:
penalities[origin] = 0
for mirror in mirrors[origin]:
if mirror not in penalities:
penalities[origin] = 0
penalities = [(y, x) for x, y in penalities.items()]
penalities.sort()
for penality, url in penalities:
print "%s %d" % (url, penality)
# vim:ts=4:sw=4:et