You are not logged in.

#1 2011-10-07 19:50:30

utdemir
Member
Registered: 2009-06-10
Posts: 23

pachorizon - Sort your pacman mirrorlist by distance

I'm behind a stupid firewall, and can't use ping, so can't use tools like rankmirrors.  So I wrote a python script for sorting mirrors with nearest countries.
Usage:

Usage:   pachorizon.py <country> <mirrorlist>
         pachorizon.py list
         pachorizon.py help
Example: pachorizon.py "Great Britain" /etc/pacman.d/mirrorlist

Example output:

$ ./pachorizon.py "Great Britain" /etc/pacman.d/mirrorlist 
## Pacman mirrorlist generated for Great Britain

## Great Britain
# Server = http://mirror.lividpenguin.com/pub/archlinux/$repo/os/$arch
# Server = http://mirror.cinosure.com/archlinux/$repo/os/$arch
# Server = http://archlinux.mirrors.uk2.net/$repo/os/$arch

## Ireland
# Server = http://ftp.heanet.ie/mirrors/ftp.archlinux.org/$repo/os/$arch

## Netherlands
# Server = http://mirror.nl.leaseweb.net/archlinux/$repo/os/$arch
# Server = http://ftp.nluug.nl/pub/os/Linux/distr/archlinux/$repo/os/$arch

## Belgium
# Server = http://archlinux.mirror.kangaroot.net/$repo/os/$arch

## Luxembourg
# Server = http://archlinux.mirror.root.lu/$repo/os/$arch
.....

Script:

#!/usr/bin/env python3

import sys
import math
import functools
import collections 

coords= {'Australia': (-27.0, 133.0),
         'Belarus': (53.0, 28.0),
         'Belgium': (50.5, 4.0),
         'Brazil': (-10.0, -55.0),
         'Canada': (60.0, -95.0),
         'Chile': (-30.0, -71.0),
         'China': (35.0, 105.0),
         'Colombia': (4.0, -72.0),
         'Czech Republic': (49.45, 15.3),
         'Denmark': (56.0, 10.0),
         'Estonia': (59.0, 26.0),
         'Finland': (64.0, 26.0),
         'France': (46.0, 2.0),
         'Germany': (51.0, 9.0),
         'Great Britain': (54.0, -2.0),
         'Greece': (39.0, 22.0),
         'Hungary': (47.0, 20.0),
         'India': (20.0, 77.0),
         'Indonesia': (-5.0, 120.0),
         'Ireland': (53.0, -8.0),
         'Israel': (31.3, 34.45),
         'Italy': (42.5, 12.5),
         'Japan': (36.0, 138.0),
         'Kazakhstan': (48.0, 68.0),
         'Korea': (40.0, 127.0),
         'Latvia': (57.0, 25.0),
         'Luxembourg': (49.45, 6.1),
         'Moldova': (47.0, 29.0),
         'Netherlands': (52.3, 5.45),
         'New Caledonia': (-21.3, 165.3),
         'Norway': (62.0, 10.0),
         'Poland': (52.0, 20.0),
         'Portugal': (39.3, -8.0),
         'Romania': (46.0, 25.0),
         'Russia': (60.0, 100.0),
         'Singapore': (1.22, 103.48),
         'South Korea': (40.0, 127.0),
         'Spain': (40.0, -4.0),
         'Sweden': (62.0, 15.0),
         'Switzerland': (47.0, 8.0),
         'Taiwan': (23.3, 121.0),
         'Turkey': (39.0, 35.0),
         'USA': (38.0, -97.0),
         'Ukraine': (49.0, 32.0),
         'United States': (38.0, -97.0),
         'Uzbekistan': (41.0, 64.0)}

def distance_between_coords(coord1, coord2):
    """Recipe From:
    http://www.johndcook.com/python_longitude_latitude.html"""
    
    lat1, long1 = coord1
    lat2, long2 = coord2

    # Convert latitude and longitude to 
    # spherical coordinates in radians.
    degrees_to_radians = math.pi/180.0
        
    # phi = 90 - latitude
    phi1 = (90.0 - lat1)*degrees_to_radians
    phi2 = (90.0 - lat2)*degrees_to_radians
        
    # theta = longitude
    theta1 = long1*degrees_to_radians
    theta2 = long2*degrees_to_radians
        
    # Compute spherical distance from spherical coordinates.
        
    # For two locations in spherical coordinates 
    # (1, theta, phi) and (1, theta, phi)
    # cosine( arc length ) = 
    #    sin phi sin phi' cos(theta-theta') + cos phi cos phi'
    # distance = rho * arc length
    
    cos = (math.sin(phi1)*math.sin(phi2)*math.cos(theta1 - theta2) + 
           math.cos(phi1)*math.cos(phi2))
    arc = math.acos( cos )

    return arc * 6373 #for kilometers

def distance_between_countries(c1, c2):
    return distance_between_coords(coords[c1], coords[c2])

my_location = sys.argv[1]

if my_location == "help":
    print("Usage:   pachorizon.py <country> <mirrorlist>")
    print("         pachorizon.py list")
    print("         pachorizon.py help")
    
    print("Example: pachorizon.py \"Great Britain\" /etc/pacman.d/mirrorlist")

    exit()
elif my_location == "list":
    print("Possible countries:" )
    print(", ".join(c for c in coords.keys()))
    exit()
mirrorlist = open(sys.argv[2]).readlines()

urls = [("Any", [])]

for line in mirrorlist:
    line = line.strip("# \n")
    
    if line in coords.keys():
        urls.append((line, []))
    elif line.startswith("Server ="):
        urls[-1][-1].append(line.split("Server =", 1)[1].strip())

locationless, *urls = urls

get_distance = functools.partial(distance_between_countries, my_location)

sorted_urls = collections.OrderedDict(sorted(
    urls,
    key = lambda i: get_distance(i[0]),
    ))

sorted_urls["Any"] = locationless[1]
sorted_urls.move_to_end("Any", last=False)

print("## Pacman mirrorlist generated for " + my_location + "\n")

for country, servers in sorted_urls.items():
    if not servers:
        continue
        
    print("## " + country)
    for server in servers:
        print("# Server = " + server)
    print()

I hope you like it smile.

Offline

Board footer

Powered by FluxBB