-
- #!/usr/bin/env python
- # -*- coding: utf-8 -*-
- '''Build a list of mirrors for pacman'''
-
- # Release : 1.5.1
- # Date : 28 March 2014
- # Authors : Esclapion, philm
-
- import argparse, datetime, getopt, os, signal, sys, time, urllib.request
- from sys import *
- path.append("/usr/lib/pacman-mirrors")
- from operator import itemgetter
- from decimal import *
- import os
-
-
- # Global initializations
- # ======================
- path_conf = "/etc/pacman-mirrors.conf"
- datenow = datetime.datetime.utcnow()
- serverList = []
- nbServer = 0 # Global count of servers available
- nbServerResp = 0 # Number of servers responding
- nbServerGood = 0 # Number of servers sinced < 4h
-
- generate = False # Generate new mirrorlist
- interactive = False # Use the gui for custom mirrorlist
- method = "rank" # Use generation method
- branch = "stable" # Use branch name
- onlyCountry=[] # Use only mirrors from country[,country,...]
- mirrorlistsDir="/etc/pacman.d/mirrors" # Use path as mirrorlist directory
- outputMirrorList = "/etc/pacman.d/mirrorlist" # Specify output file
- maxWaitTime = 2 # Server maximum waiting time (seconds)
-
- arch = os.uname().machine # i686 or X86_64
-
- def alarm_handler(signum, frame):
- raise TimeoutError("Ici")
- def timeOut(timeout):
- signal.signal(signal.SIGALRM, alarm_handler)
- signal.alarm(timeout) # produce SIGALRM in `timeout` seconds
-
-
- # Parse the file "pacman-mirrors.conf"
- # ====================================
- try :
- fi = open(path_conf, "r")
- except :
- print("\n Error : cannot open file", path_conf, "\n")
- exit(1)
- while 1 :
- line = fi.readline()
- if line == "" :
- break
- line = line.strip()
- if line == "" :
- continue
- if line[0] == '#' or line[0] == '\n' :
- continue
- i = line.find("=")
- if i == -1 :
- continue
- snom = line[0:i]
- i = i + 1
- j = len(line)
- if line[i] == '"' :
- i = i + 1
- if line[j -1] == '"' :
- j = j - 1
- sval = line[i:j]
- if snom == "Branch" : # Branch Pacman should use
- branch=sval
- elif snom == "OnlyCountry" : # Specify to use only mirrors from specific countries
- onlyCountry = sval.split(',')
- elif snom == "MirrorlistsDir" : # Input mirrorlist directory
- pathMirrors = sval + "/"
- elif snom == "OutputMirrorlist" : # Output mirrorlist
- outputMirrorList = sval
-
-
- #
- # Read the arguments of the command line
- # ======================================
-
- parser = argparse.ArgumentParser()
- parser.add_argument("-g", "--generate", help="generate new mirrorlist",
- action="store_true")
- parser.add_argument("-m", "--method", help="use generation method",
- type=str, choices=["rank", "random"])
- parser.add_argument("-b", "--branch", help="use branch name",
- type=str, choices=["stable", "testing", "unstable"])
- parser.add_argument("-c", "--country", help="use only mirrors from country[,country,...]",
- type=str)
- parser.add_argument("-d", "--mirror_dir", help="use path as mirrorlist directory",
- type=str)
- parser.add_argument("-o", "--output", help="specify output file",
- type=str)
- parser.add_argument("-t", "--timeout", help="server maximum waiting time (seconds)",
- type=int)
- if os.path.exists('/usr/lib/python3.4/site-packages/gi/overrides/Gtk.py') :
- parser.add_argument("-i", "--interactive", help="interactively generate a custom mirrorlist",
- action="store_true")
- parser.add_argument("-v", "--version", help="print the pacman-mirrors version",
- action="store_true")
- args = parser.parse_args()
- if len(sys.argv) == 1 :
- parser.print_help()
- exit(0)
- if args.generate :
- generate = args.generate
- if args.method :
- method = args.method
- if args.branch :
- branch = args.branch
- if args.country :
- onlyCountry = args.country.split(",")
- if onlyCountry == ["all"] :
- path = "/etc/pacman-mirrors.conf"
- try :
- fconf = open(path, "r")
- except :
- print("\n^GError : can't open file {0}.\n".format(path))
- exit(1)
- buf = fconf.read().split('\n')
- fconf.close()
- while buf[-1:] == [''] :
- del buf[-1:]
- try :
- fconf = open(path, "w")
- except :
- print("\n^GError : can't open file {0}.\n".format(path))
- exit(1)
- for line in buf :
- if "OnlyCountry" in line :
- fconf.write("#OnlyCountry=Custom\n")
- else :
- fconf.write(line + "\n")
- fconf.close
- try :
- os.remove(mirrorlistsDir + "/Custom")
- except :
- pass
- onlyCountry = []
-
- if args.mirror_dir :
- mirrorlistsDir = args.mirror_dir
- if args.output :
- if args.output[0] == '/' :
- outputMirrorList = args.output
- else :
- outputMirrorList = os.getcwd() + "/" + args.output
- if os.path.exists('/usr/lib/python3.4/site-packages/gi/overrides/Gtk.py') :
- if args.interactive :
- interactive = args.interactive
- else :
- interactive = False
- if args.timeout :
- maxWaitTime = args.timeout
- if args.version :
- print("pacman-mirrors 1.5")
- exit(0)
-
-
- try :
- os.chdir(mirrorlistsDir)
- except :
- print("\nError : Cannot change directory to", mirrorlistsDir, "\n")
- exit(1)
- listeDir = os.listdir(mirrorlistsDir)
- listeDir.sort()
- for i in onlyCountry :
- if i not in listeDir :
- print("\nError : unknown country", i)
- print("\nAvailable countries are :", listeDir, "\n")
- exit(1)
-
- if os.getuid() != 0 :
- print("\nError : must be root.\n")
- exit(1)
-
-
- # Main loop
- # =========
- if method == "rank" :
- print(":: Querying servers, this may take some time...")
- listeSer=[]
- for country in listeDir :
- if len(onlyCountry) != 0 and country not in onlyCountry :
- continue
- print(country)
- curCountry = country
- fi = open(country, "r")
- while 1 :
- s = fi.readline()
- if s == '' :
- break
- if s[0] == '[' :
- curCountry = s[1:-2]
- continue
- if s[0] != 'S' :
- continue
- urlServer = s[9:-1]
- urlServer = urlServer.replace("$branch", branch)
- # Add the server to the list, also if bad
- serverList.append([curCountry, "99.99", "99:99", urlServer, 0, False])
- # Country, response time, last sync, url, quality level
- nbServer = nbServer + 1
- if method == "random" :
- print("->", urlServer)
- continue
- print("-> .....", urlServer, end='')
- sys.stdout.flush()
- j = urlServer.find(branch)
- url = urlServer[0:j] + "state"
- start = time.time()
- try :
- furl = urllib.request.urlopen(url, timeout=maxWaitTime)
- except :
- print("\r-> Error!")
- continue
- timeOut(maxWaitTime)
- try :
- resp = furl.read()
- d = resp.find(b"date=")
- signal.alarm(0) # cancel alarm
- except :
- print("\r-> Error2!")
- furl.close()
- continue
- elapsed = round((time.time() - start), 3)
- nbServerResp = nbServerResp + 1 # The server responds ..
- date = resp[d+5:d+24].decode('utf-8')
- selapsed = "{:6.4}".format(Decimal(elapsed).quantize(Decimal('.001')))
- print("\r->", selapsed, sep="")
- sys.stdout.flush()
- serverList[nbServer - 1][1] = selapsed # - response time
- serverList[nbServer - 1][4] = 1
- try :
- date2 = datetime.datetime.strptime(date, "%Y-%m-%dT%H:%M:%S" )
- except :
- print('Wrong date format in "state" file. Server skipped.')
- continue
- sec = (datenow - date2).seconds
- min = int(sec / 60)
- hr = int (min /60)
- min = min - hr * 60
- if hr < 4 :
- nbServerGood = nbServerGood + 1 # ...and was recently synced (< 4h)
- serverList[nbServer - 1][4] = 2
- datesync = '{}:{}'.format(hr, str(min).zfill(2))
- serverList[nbServer - 1][2] = datesync # - last sync
- furl.close()
- fi.close()
- # break
-
-
- #
- # Build the file "mirrorlist"
- # ===========================
- serverList = sorted(serverList, key=itemgetter(1))
- if interactive :
- from pacman_mirrors_gui import chooseMirrors
- finished = False
- for item in serverList :
- item[3] = item[3].replace("/" + branch + "/", "/$branch/")
- while not finished :
- chooseMirrors(True, serverList)
- customList = []
- for elem in serverList :
- if elem[5] :
- customList.append(elem)
- if len(customList) == 0 :
- continue
- finished = chooseMirrors(False, customList)
-
- path = mirrorlistsDir + "/Custom"
- try :
- fcust = open(path, "w")
- except :
- print("\n^GError : can't create file {0}.\n".format(path))
- exit(1)
- fcust.write("##\n")
- fcust.write("## Pacman Mirrorlist\n")
- fcust.write("##\n\n")
- for elem in customList :
- fcust.write("[" + elem[0] + "]\n")
- fcust.write("Server = " + elem[3] + "\n")
- fcust.close()
- path = "/etc/pacman-mirrors.conf"
- try :
- fconf = open(path, "r")
- except :
- print("\n^GError : can't open file {0}.\n".format(path))
- exit(1)
- buf = fconf.read().split('\n')
- fconf.close()
- while buf[-1:] == [''] :
- del buf[-1:]
- try :
- fconf = open(path, "w")
- except :
- print("\n^GError : can't open file {0}.\n".format(path))
- exit(1)
- for line in buf :
- if "OnlyCountry" in line :
- fconf.write("OnlyCountry=Custom\n")
- else :
- fconf.write(line + "\n")
- fconf.close
- try :
- fo = open(outputMirrorList, "w")
- except :
- print("\nError : cannot create", outputMirrorList)
- exit(1)
- fo.write("##\n")
- fo.write("## Manjaro Linux repository mirrorlist\n")
- fo.write("## Generated on ")
- fo.write(datetime.datetime.now().strftime("%d %B %Y %H:%M"))
- fo.write("\n##\n")
- fo.write("## Use pacman-mirrors to modify\n")
- fo.write("##\n\n")
- print("\nCustom List")
- print("-----------\n")
- for server in customList :
- server[3] = server[3].replace("$branch", branch)
- print("-> {0} :".format(server[0]), server[3])
- fo.write("\n## Location : ")
- fo.write(server[0])
- if method == "rank" :
- fo.write("\n## Time :")
- fo.write(server[1])
- fo.write("\n## Last Sync : ")
- fo.write(server[2])
- fo.write("\nServer = ")
- fo.write(server[3])
- fo.write("\n")
- print("\n:: Generated and saved '{}' Custom list.".format(outputMirrorList))
-
-
- else :
- try :
- fo = open(outputMirrorList, "w")
- except :
- print("\nError : cannot create", outputMirrorList)
- exit(1)
- fo.write("##\n")
- fo.write("## Manjaro Linux repository mirrorlist\n")
- fo.write("## Generated on ")
- fo.write(datetime.datetime.now().strftime("%d %B %Y %H:%M"))
- fo.write("\n##\n")
- fo.write("## Use pacman-mirrors to modify\n")
- fo.write("##\n\n")
- if nbServerGood >= 3 : # Avoid an empty mirrorlist
- level = 2
- elif nbServerResp >= 3 :
- level = 1
- else :
- level = 0
- if nbServer == 0 :
- print("\nError : no server available !\n")
- for server in serverList :
- if server[4] < level :
- continue
- fo.write("\n## Location : ")
- fo.write(server[0])
- if method == "rank" :
- fo.write("\n## Time :")
- fo.write(server[1])
- fo.write("\n## Last Sync : ")
- fo.write(server[2])
- fo.write("\nServer = ")
- fo.write(server[3])
- fo.write("\n")
- print(":: Generated and saved '{}' mirrorlist.".format(outputMirrorList))
-
-