#!/usr/bin/env python # $Id$ # Scans apps dir for current core client and application versions and updates # the database as appropriate. class Project: def __init__(self, **kwargs): self.__dict__.update(kwargs) PROJECTS_ROOT = '~/projects/' URL_ROOT = 'http://setiboinc.ssl.berkeley.edu/' # syntax: (directory_name, db_name, url_name, [('AppName','app_exe_name')]) PROJECTS = [ Project(directory_name ='AstroPulse_Beta', db_name ='ap', url_name ='ap', applications =[Project(appname='AstroPulse', exe_prefix='ap')]), Project(directory_name ='client_test', db_name ='boinc_client_test', url_name ='client_test', applications =[]) ] APPS_DIR = '../apps' KEY_DIR = '~/keys/' DUPLICATE_PLATFORM_EXECUTABLES = {'sparc-sun-solaris2.8':'sparc-sun-solaris2.7'} BoincCoreApp = Project(appname='BOINC Core Client') # Note: treat Darwin (CLI) as Unix (independent of MacOSX GUI) platform_name_windows = 'windows_intelx86' platform_name_macosx = 'MacOSX' import sys, os, glob, re def get_download_dir(directory_name): return os.path.join(PROJECTS_ROOT,directory_name,'download') def get_download_url(url_name): return os.path.join(URL_ROOT,url_name,'download') program_path = os.path.realpath(os.path.dirname(sys.argv[0])) sys.path[0:0] = ['../py', os.path.realpath(os.path.join(program_path, '../py'))] from version import * def xsort(list): newlist = list[:] newlist.sort() return newlist def query_yesno(msg): '''Query y/n; default Y''' print msg, "[Y/n]? ", return not raw_input().lower().startswith('n') def map_dupes(dict): for (platform_name,target_platform_name) in DUPLICATE_PLATFORM_EXECUTABLES.items(): if target_platform_name in dict and not platform_name in dict: dict[platform_name] = dict[target_platform_name] def glob_app(pattern): return pattern and glob.glob(os.path.join(APPS_DIR,pattern)) or [] # unix_pattern can include others also def get_clients(app, unix_pattern, windows_pattern='', mac_pattern=''): unix_clients, windows_clients, mac_clients = \ map(glob_app, [unix_pattern, windows_pattern, mac_pattern]) client_map = {} for client in windows_clients: client_map[platform_name_windows] = client for client in mac_clients: client_map[platform_name_macosx] = client for client in unix_clients: platform_name = re.sub('.*_','',client).replace('.gz','').replace('.exe','') if platform_name == 'win': platform_name = platform_name_windows elif platform_name == 'os_x': platform_name = platform_name_macosx client_map[platform_name] = client map_dupes(client_map) app.client_versions = client_map show_clients(app) def show_clients(app): client_map = app.client_versions if not client_map: print "No clients found for", app.appname, "version %s in %s!"%(version_string,APPS_DIR) return print "Clients found for", app.appname, "version", version_string, ":" for platform_name in xsort(client_map.keys()): print ' ', platform_name.ljust(20), client_map[platform_name] tried_apps_dirs = [ APPS_DIR ] if not os.path.isdir(APPS_DIR): APPS_DIR = os.path.join(program_path, APPS_DIR) tried_apps_dirs.append(APPS_DIR) if not os.path.isdir(APPS_DIR): raise SystemExit("Couldn't find apps dir in %s"%tried_apps_dirs) APPS_DIR = os.path.realpath(APPS_DIR) PROJECTS_ROOT = os.path.realpath(os.path.expanduser(PROJECTS_ROOT)) KEY_DIR = os.path.realpath(os.path.expanduser(KEY_DIR)) version_num = MAJOR_VERSION * 100 + MINOR_VERSION version_string = "%d.%02d"%(MAJOR_VERSION, MINOR_VERSION) get_clients(BoincCoreApp, unix_pattern='boinc_'+version_string+'*.gz', windows_pattern='BOINC_'+version_string+'*.exe', mac_pattern='boinc_'+version_string+'*.sit') for project in PROJECTS: for app in project.applications: get_clients(app, app.exe_prefix+'_'+version_string+'*') for project in PROJECTS: directory_name = project.directory_name db_name = project.db_name url_name = project.url_name print "--- database", db_name, " ---" existing_count = int(os.popen("""echo 'select count(*) from core_version where version_num=%d'|mysql %s"""%(version_num, db_name)).readlines()[-1].strip() or 0) if existing_count: if not query_yesno(" Delete %d existing version %s clients?"%(existing_count, version_string)): print " Skipping", db_name continue print " Deleting from core_version" os.system("""echo 'delete from core_version where version_num=%d' | mysql %s"""%(version_num, db_name)) code_sign_file = os.path.join(KEY_DIR, 'code_sign_private') client_map = BoincCoreApp.client_versions for platform_name in xsort(client_map.keys()): exec_file = os.path.split(client_map[platform_name])[1] download_dir = get_download_dir(directory_name) download_url = get_download_url(url_name) print " Adding ", platform_name.ljust(20), os.path.join(download_dir,exec_file) os.system(""" add core_version -db_name %(db_name)s \ -app_name 'core client' \ -platform_name %(platform_name)s \ -download_dir %(download_dir)s \ -download_url %(download_url)s \ -code_sign_keyfile %(code_sign_file)s \ -exec_dir %(APPS_DIR)s \ -version %(version_num)d \ -exec_files %(exec_file)s """ %locals()) for app in project.applications: appname = app.appname client_map = app.client_versions for platform_name in xsort(client_map.keys()): exec_file = os.path.split(client_map[platform_name])[1] download_dir = get_download_dir(directory_name) download_url = get_download_url(url_name) print " Adding ", platform_name.ljust(20), os.path.join(download_dir,exec_file) os.system(""" add core_version -db_name %(db_name)s \ -app_name '%(appname)s' \ -platform_name %(platform_name)s \ -download_dir %(download_dir)s \ -download_url %(download_url)s \ -code_sign_keyfile %(code_sign_file)s \ -exec_dir %(APPS_DIR)s \ -version %(version_num)d \ -exec_files %(exec_file)s """ %locals())