diff options
author | 2009-06-17 18:45:31 +0100 | |
---|---|---|
committer | 2009-06-17 18:45:31 +0100 | |
commit | 5e561c1bb476977119fb947a4e21fe6dd4e3c314 (patch) | |
tree | edc9261465523b884f869145aa97a0b7dd9ccd2b | |
download | uselect-5e561c1bb476977119fb947a4e21fe6dd4e3c314.tar.gz uselect-5e561c1bb476977119fb947a4e21fe6dd4e3c314.tar.bz2 uselect-5e561c1bb476977119fb947a4e21fe6dd4e3c314.zip |
Initial Universal Select Tool Commit
-rw-r--r-- | install.sh | 11 | ||||
-rw-r--r-- | modules/env.uselect | 325 | ||||
-rw-r--r-- | modules/gcc.uselect | 41 | ||||
-rw-r--r-- | modules/kernel.uselect | 24 | ||||
-rw-r--r-- | modules/one.uselect | 44 | ||||
-rw-r--r-- | modules/python.uselect | 21 | ||||
-rw-r--r-- | uio.py | 253 | ||||
-rw-r--r-- | umodule.py | 274 | ||||
-rwxr-xr-x | uselect.py | 99 |
9 files changed, 1092 insertions, 0 deletions
diff --git a/install.sh b/install.sh new file mode 100644 index 0000000..326f761 --- /dev/null +++ b/install.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# +# Uselect Temporary installer +# + +PWD=`pwd` + +rm -f /usr/bin/uselect +rm -f /usr/share/uselect +ln -s $PWD/uselect.py /usr/bin/uselect +ln -s $PWD /usr/share/uselect diff --git a/modules/env.uselect b/modules/env.uselect new file mode 100644 index 0000000..effed56 --- /dev/null +++ b/modules/env.uselect @@ -0,0 +1,325 @@ +# Copyright 1999-2009 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# env.uselect mephx.x@gmail.com + +module env { + description "Manage environment variables set in /etc/env.d/" + version "0.1" + author "mephx.x@gmail.com" +} env + + +user action update + description "Collect environment variables from all scripts in /etc/env.d/" + parameters "<makelinks> <noldconfig>" + options { + "makelinks : Specify \"makelinks\" to force updating of links" + "noldconfig : Do not alter the ld.so cache or configuration." + } + type runnable + + file env-update.bash { + #!/bin/bash + # Classes of env-vars + + source /usr/share/eselect/libs/tests.bash + source /usr/share/eselect/libs/core.bash + source /usr/share/eselect/libs/path-manipulation.bash + + source /usr/share/eselect/libs/config.bash + source /usr/share/eselect/libs/multilib.bash + + SPACE_CLASS="CONFIG_PROTECT + CONFIG_PROTECT_MASK" + PATH_CLASS="ADA_INCLUDE_PATH + ADA_OBJECT_PATH + CLASSPATH + INFODIR + INFOPATH + KDEDIRS + LDPATH + MANPATH + PATH + PKG_CONFIG_PATH + PRELINK_PATH + PRELINK_PATH_MASK + PYTHONPATH + ROOTPATH" + + # Recognized file formats: + MIME_WHITELIST="text/plain text/x-makefile" + + # Configuration files + ENVPROFILE="${ROOT}/etc/profile.env" + LDCONFIG="${ROOT}/etc/ld.so.conf" + PRELINK="${ROOT}/etc/prelink.conf" + LDMTIMEDB="${ROOT}/var/lib/eselect/env/ld-mtimedb" + + # Keep all stored LDPATHS + ESELECT_LDPATH=( ) + + # is_envd_file() + # Return successfuly when file can be sourced. + is_envfile() { + local mime envfile=${1} + + # Make sure it is a file and no backup file + [[ -f ${envfile} ]] || return 1 + [[ -n ${envfile##*~} ]] || return 1 + [[ ${envfile##*.} != bak ]] || return 1 + + mime=$(POSIXLY_CORRECT=1 file -i ${envfile} \ + | cut -d ' ' -f 2 | sed -e 's/;$//') + if ! has ${mime} ${MIME_WHITELIST} ; then + echo "Skipping non-text file ${envfile}." + return 1 + fi + + return 0 + } + + # update_envvar_classes() + # Update the contents of *_CLASS based on env,d files. + update_envvar_classes() { + local -a envfiles + local value + envfiles=( ${ROOT}/etc/env.d/* ) + + for envfile in ${envfiles[@]} ; do + is_envfile ${envfile} || continue + + value=$(load_config ${envfile} COLON_SEPARATED) + for x in ${value} ; do + has ${x} ${PATH_CLASS} && continue + PATH_CLASS="${PATH_CLASS} ${x}" + done + + value=$(load_config ${envfile} SPACE_SEPARATED) + for x in ${value} ; do + has ${x} ${SPACE_CLASS} && continue + SPACE_CLASS="${SPACE_CLASS} ${x}" + done + done + } + + # create_profile_env() + # Create profile.env file + create_profile_env() { + local -a envfiles + local vars store items tmpprofile + envfiles=( ${ROOT}/etc/env.d/* ) + + # Blank the file first! + tmpprofile="$(mktemp ${ROOT}/tmp/profile.XXXXXX)" + [[ $? = 0 ]] || die "Couldn't create temporary file!" + + # Gather ye classes while ye may! + update_envvar_classes + + # Parse all files in env.d + for envfile in ${envfiles[@]} ; do + is_envfile ${envfile} || continue + + # Which vars are to be loaded? + # TODO: Change to bash magic? + vars=$(sed \ + -e '/^#/d' -e '/^\s*$/d' -e '/^.*=/s/^\([^=]*\)=.*/\1/' \ + ${envfile}) + [[ -z ${vars} ]] && continue + for var in ${vars} ; do + # Colon separated?... + if has ${var} ${PATH_CLASS} ; then + store=$(load_config ${tmpprofile} ${var}) + if [[ -z ${store} ]] ; then + store=$(load_config ${envfile} ${var}) + else + items="$(load_config ${envfile} ${var})" + items=( ${items//:/ } ) + for item in ${items[@]} ; do + has ${item} ${store//:/ } && continue + store="${store}:${item}" + done + fi + store_config ${tmpprofile} ${var} "${store#:}" + continue + fi + # Space separated!... + if has ${var} ${SPACE_CLASS} ; then + store=( $(load_config ${tmpprofile} ${var}) ) + if [[ -z ${store[@]} ]] ; then + store=( $(load_config ${envfile} ${var}) ) + else + items=( $(load_config ${envfile} ${var}) ) + for item in ${items[@]} ; do + has ${item} ${store[@]} && continue + store=( ${store[@]} ${item} ) + done + fi + store_config ${tmpprofile} ${var} "${store[@]}" + continue + fi + # Ok, just a non-cummultative var. + store_config \ + ${tmpprofile} \ + ${var} \ + "$(load_config ${envfile} ${var})" + done + + has LDPATH ${vars} || continue + # Store LDPATH for later processing + items=$(load_config ${envfile} LDPATH) + items=( ${items//:/ } ) + for item in ${items[@]} ; do + has ${item} ${LDPATH[@]} && continue + ESELECT_LDPATH=( ${ESELECT_LDPATH[@]} ${item} ) + done + done + + # Move new file onto old one + ENVPROFILE=$(canonicalise ${ENVPROFILE}) + chmod a+r ${tmpprofile} + mv ${tmpprofile} ${ENVPROFILE} \ + || die "Couldn't move ${tmpprofile} to ${ENVPROFILE}!\n + Original profile.env remains unchanged." + } + + # create_ld_so_conf() + # Create ld.so.conf file based upon gathered LDPATHs + create_ld_so_conf() { + [[ -z ${ESELECT_LDPATH[@]} ]] && die -q 'No LDPATHs found in ${ROOT}/etc/env.d/*' + + local str + str="# ld.so.conf autogenerated by eselect\n" + str="${str}# Make all changes to /etc/env.d files\n" + for x in ${ESELECT_LDPATH[@]} ; do + str="${str}${x}\n" + done + echo -e "${str}" > $(canonicalise ${LDCONFIG}) + } + + # create_prelink_conf() + # Create prelink.conf file based upon existing profile.env + create_prelink_conf() { + [[ -z ${ESELECT_LDPATH[@]} ]] && die -q 'No LDPATHs found in ${ROOT}/etc/env.d/*' + local str + str="# prelink.conf autogenerated by eselect\n" + str="${str}# Make all changes to /etc/env.d files\n" + # Add default items + for x in /bin /sbin /usr/bin /usr/sbin ; do + str="${str}-l ${x}\n" + done + for x in $(list_libdirs) ; do + [[ -e ${ROOT}/${x} ]] && str="${str}-l /${x}\n" + [[ -e ${ROOT}/usr/${x} ]] && str="${str}-l /usr/${x}\n" + done + prelink_mask=$(load_config ${ENVPROFILE} PRELINK_PATH_MASK) + prelink_mask=( ${prelink_mask//:/ } ) + prelink="$(load_config ${ENVPROFILE} PATH)" + prelink="${prelink} $(load_config ${ENVPROFILE} PRELINK_PATH)" + prelink=( ${prelink//:/ } ${ESELECT_LDPATH[@]} ) + for x in ${prelink[@]} ; do + has ${x} ${prelink_mask} && continue + [[ -z ${x##*/} ]] || x="${x}/" + str="${str}-h ${x}\n" + done + for x in ${prelink_mask[@]} ; do + str="${str}-b ${x}\n" + done + echo -e "${str}" > $(canonicalise ${PRELINK}) + } + + # need_links() + # Returns true if any item of ${LDPATH} has been modified. + need_links() { + local ret=1 + for x in ${ESELECT_LDPATH[@]} ; do + y=${x//\//_} + y=${y//-/_} + y=${y//./_} + y=${y//+/_} + oldmtime=$(load_config ${LDMTIMEDB} "mtime${y}") + newmtime=$(stat -c %Y ${x} 2> /dev/null) + if [[ ${oldmtime} != ${newmtime} ]] ; then + ret=0 + store_config ${LDMTIMEDB} "mtime${y}" ${newmtime} + fi + done + return ${ret} + } + + # update_ldcache() + # Update ld.so.cache using ldconfig + update_ldcache() { + case $(uname -s) in + FreeBSD | DragonFly) + echo "Regenerating ${ROOT}/var/run/ld-elf.so.hints..." + ( + cd / + ldconfig -elf -i -f "${ROOT:-/}var/run/ld-elf.so.hints" \ + "${ROOT:-/}etc/ld.so.conf" + ) + ;; + *) + echo "Regenerating ${ROOT}/etc/ld.so.cache..." + ( + cd / + ldconfig ${1} -r ${ROOT:-/} + ) + ;; + esac + } + + ### update action + + + + + do_update() { + local makelinks ldconfig=1 + while [[ ${#@} -gt 0 ]] ; do + case ${1} in + makelinks) + makelinks="-X" + ;; + noldconfig) + ldconfig=0 + ;; + *) + die -q "Unknown option '${1}'" + ;; + esac + shift + done + + if [[ -e ${ROOT}/etc/profile.env ]] ; then + [[ -w ${ROOT}/etc/profile.env ]] \ + || die -q "You need to be root!" + else + touch ${ROOT}/etc/profile.env + fi + + # Create configuration files + create_profile_env + if [[ ${ldconfig} == 1 ]] ; then + create_ld_so_conf + [[ -e ${ROOT}/usr/sbin/prelink ]] && create_prelink_conf + need_links && makelinks="-X" + update_ldcache ${makelinks} + fi + + # fix up ${ENVPROFILE} + cp ${ENVPROFILE} ${ENVPROFILE/.env/.csh} + sed -i \ + -e "s/^\(.*\)=\"\(.*\)\"/export \1='\2'/" \ + $(canonicalise ${ENVPROFILE}) + sed -i \ + -e "s/^\(.*\)=\"\(.*\)\"/setenv \1 '\2'/" \ + $(canonicalise ${ENVPROFILE/.env/.csh}) + } + + do_update $@ + + } env-update.bash +} update + +# vim: ft=eselect diff --git a/modules/gcc.uselect b/modules/gcc.uselect new file mode 100644 index 0000000..10a1fad --- /dev/null +++ b/modules/gcc.uselect @@ -0,0 +1,41 @@ +module gcc{ + description "GCC Version Switcher" + version "0.1" + author "mephx.x@gmail.com" +} gcc + +system action profile { + description "Change GCC's /usr/bin/gcc Version" + type runnable + parameters "<target>" + usage "<target> Target GCC profile." + file moo.bash { + #!/bin/bash + do_moo() { + if [ -z $1 ] + then + gcc-config -l + else + gcc-config $@ + fi + } + do_moo $@ + } moo.bash +} profile + +system action bin { + description "Print path where binaries of the given/current profile are located." + type runnable + file moo.bash { + #!/bin/bash + do_moo() { + if [ -z $1 ] + then + gcc-config -B + else + gcc-config -B + fi + } + do_moo $@ + } moo.bash +} bin diff --git a/modules/kernel.uselect b/modules/kernel.uselect new file mode 100644 index 0000000..646730a --- /dev/null +++ b/modules/kernel.uselect @@ -0,0 +1,24 @@ +# Copyright 1999-2009 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# kernel.uselect mephx.x@gmail.com + +module kernel { + description "Kernel Switcher" + version "0.1" + author "mephx.x@gmail.com" +} kernel + +system action src { + description "Change current kernel source target" + type sym + sym linux /usr/src/linux /usr/src/ (.*)-(.*$) * +} src + +system action boot { + description "Change current kernel boot target" + type sym + sym vmlinuz /boot/vmlinuz /boot/ vmlinuz-(.*$) * +} boot + + + diff --git a/modules/one.uselect b/modules/one.uselect new file mode 100644 index 0000000..91e3709 --- /dev/null +++ b/modules/one.uselect @@ -0,0 +1,44 @@ +# Copyright 1999-2009 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# one.uselect mephx.x@gmail.com + +module one { + description "Example Module description" + version "0.2" + author "mephx.x@gmail.com" +} one + +user action moo { + description "Example Module will moo for any user" + parameters "<integer>" + usage "<integer> - number of moos" + type runnable + file moo.bash { + #!/bin/bash + do_moo() { + if [ -z $1 ] + then + # print options + echo "1 - moo one time" + echo "2 - moo two times" + echo "3 - moo three times" + echo "x - moo x times" + else + for((i=0;$i<$1;i=$(($i+1))));do + echo moo + done + fi + } + do_moo $@ + } moo.bash +} moo + +system action foo { + description "Example Simple symlinking Action" + usage "moo <option>" + type sym + sym /usr/moo /usr/share/ moo-(\w+) /bin/moo +} foo + + + diff --git a/modules/python.uselect b/modules/python.uselect new file mode 100644 index 0000000..79df588 --- /dev/null +++ b/modules/python.uselect @@ -0,0 +1,21 @@ +# Copyright 1999-2009 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# python.uselect mephx.x@gmail.com + +module python { + description "Python Version Switcher" + version "0.1" + author "mephx.x@gmail.com" +} python + +user action bin { + description "Change Python's Version" + type sym + sym python /usr/bin/python /usr/bin/ python([0-9]+\.[0-9]+$) * +} bin + +system action config { + description "Change Python's /usr/bin/python-config Version" + type sym + sym python /usr/bin/python-config /usr/bin/ python([0-9]+\.[0-9]+)-config($) * +} config @@ -0,0 +1,253 @@ +#!/usr/bin/env python +# Copyright 1999-2009 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# Universal Select Tool +# Uselect Input/Output Module +# uio.py mephx.x@gmail.com + +import os +import pwd +import stat + +# Aligning +space = ' ' +right = '\t' + +# Globals +bold = lime = red = reset = yellow = notice = '' +error = warning = bullet = ok = highlight = '' + +verbose = False + +class FileSystem: + """ FileSystem Class """ + def __init__(self): + """ FileSystem Contructor """ + self.home = os.getenv('HOME') + self.uid = pwd.getpwuid(os.getuid())[0] + self.environment = self.home + '/.uselect/' + if not os.path.exists(self.environment): + os.mkdir(self.environment) + self.environment += 'bin/' + if not os.path.exists(self.environment): + os.mkdir(self.environment) + + def read_file(self, path): + """ Reads a File and returns lines[] """ + file = open(path,'r') + lines = file.readlines() + file.close + return lines + + def write_file(self, path ,lines): + """ Writes "lines[]" in File "path" """ + if os.path.exists(path): + raise Exception("File in " + path + " already Exists!") + return + file = open(path,'w') + for line in lines: + file.writelines(line + '\n') + file.close + return lines + + def execute_cmd(self, cmd, args): + """ Executes "cmd" and returns output """ + if not os.path.exists(cmd): + raise Exception('File "' + path + '" not found!') + return + for arg in args: + cmd += ' ' + arg + return os.popen(cmd).readlines() + + def delete_file(self, path): + """ Deletes file in "path" """ + if os.path.exists(path): + os.unlink(path) + + def make_exec_file(self, path): + """ Makes file in path u+rwx """ + if not os.path.exists(path): + raise Exception('File "' + path + '" not found!') + return + os.chmod(path, stat.S_IXUSR + stat.S_IRUSR + stat.S_IWUSR) + + def create_symlink(self, source, destination): + self.delete_file(destination) + os.symlink(source, destination) + + def list_dir(self, path): + """ Lists path directory """ + if not os.path.exists(path): + raise Exception("File " + path + " not found!") + return + else: + return os.listdir(path) + def path_exists(self, path): + return os.path.exists(path) + def real_path(self, path): + return os.path.realpath(path) + +class PrintSystem: + """ PrintSystem Class """ + + def __init__(self): + """ PrintSystem Constructor """ + return + + def verbose(self): + global verbose + verbose = True + return + + def use_colors(self, usecolors): + global bold, lime, red, reset, yellow, error, warning, bullet,\ + ok, highlight, notice + if usecolors: + # Text Colors + bold = '\033[1m' + lime = '\033[32m' + red = '\033[31m' + reset = '\033[0m' + yellow = '\033[1;33m' + blue = '\033[1;34m' + # Bullets + else: + bold = lime = red = reset = yellow = '' + + error = bold + '(' + red + '!' + reset + bold + ')' + reset + warning = bold + '(' + yellow + '!' + reset + bold + ')' + reset + bullet = bold + '(' + lime + '*' + reset + bold + ')' + reset + notice = bold + '(' + blue + '*' + reset + bold + ')' + reset + ok = bold + '(' + lime + '>' + reset + bold + ')' + reset + highlight = lime + bold + # Glocal Print Functions + def print_line(self, line, _verbose = False): + """ Prints line with type""" + global verbose + if _verbose and not verbose: + return + print line + return + + def print_table(self,list, _verbose = False): + """ Prints Lists of the form list[[a,b]] """ + global verbose + if _verbose and not verbose: + return + for item in list: + print(' ' + item[0] + reset + '\r' + 3 * right + item[1]) + return + + def print_exception(self, exception, iswarning = False): + """ Prints Exceptions in a standart way """ + if iswarning: + type = warning + ' Warning! ' + else: + type = error + ' Error! ' + self.print_line('\n' + type + str(exception) + '\n') + + def format_action(self, action): + table = [] + if action.parameters != '': + for line in action.usage: + table.append([line,'']) + table.append(['','']) + count = 1 + for option in action.options: + table.append([option[1] + space + \ + eval(option[0]),'']) + count += 1 + + return table + # Screen Functions + def print_ui(self, module = None, modules = None, \ + action = None, args = None): + if module == None: + # uselect Usage + # uselect Options + self.print_usage() + self.print_line('') + self.print_options() + self.print_line('') + self.print_modules(modules) + self.print_line('') + elif action == None: + # Modules Usage + self.print_usage(module) + self.print_line('') + self.print_module(module) + self.print_line('') + # Modules Actions + self.print_actions(module) + self.print_line('') + elif args == None: + # Actions Usage + self.print_usage(module, action) + self.print_line('') + # Action + self.print_action(module, action) + self.print_line('') + else: + # This means Action Done + for line in action.output: + print(line) + return + + def print_module(self, module): + self.print_line(bold + lime + 'Module' + space + reset \ + + bold +module.name + lime + ':' + reset) + module.get_actions() + self.print_line('Author:' + space + module.author + space \ + + 'Version:' + space + module.version) + + def print_modules(self, modules): + self.print_line(lime + bold + 'Modules:' + reset) + list = [] + for module in modules: + list.append([bold + module.name, bullet + space + module.description]) + self.print_table(list) + + def print_actions(self, module): + self.print_line(highlight + 'Actions:' + reset) + if len(module.actions) == 0: + print ' Module ' + module.name + \ + ' has no actions!' + return + list = [] + for action in module.actions: + self.print_table([[bold + action.name + reset, \ + action.description]]) + + def print_action(self, module, action): + self.print_table([[bold + action.description + reset, '']]) + self.print_line('') + self.print_table(self.format_action(action)) + + def print_version(self, version): + self.print_line(bold + 'Universal Select Tool - ' \ + + lime + 'uselect' + reset) + self.print_line(bold + 'Version ' + reset + version + '\n') + + def print_usage(self, module = None, action = None): + """ General Usage Printer """ + if module != None: + module_name = module.name + else: + module_name = '<module>' + if action != None: + action_name = action.name + options = action.parameters + else: + action_name = '<action>' + options = '<options>' + self.print_line(bold + lime + 'Usage:' + reset + ' uselect <options> ' + module_name \ + + space + action_name + space + options) + + def print_options(self): + self.print_line(highlight + space + 'Options:' + reset) + self.print_table([ \ + [bold + '-v', bullet + space + 'Verbose Mode'], \ + [bold + '-nc', bullet + space + 'No Colors'], \ + # [bold + '-profile', bullet + space + 'Profile Mode'], \ + [bold + '-version', bullet + space + 'Version Information']]) + diff --git a/umodule.py b/umodule.py new file mode 100644 index 0000000..11bbf35 --- /dev/null +++ b/umodule.py @@ -0,0 +1,274 @@ +#!/usr/bin/env python +# Copyright 1999-2009 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# Universal Select Tool +# Uselect Modules/Actions Module +# umodule.py mephx.x@gmail.com + +import re +import os + +modules_dir = '/usr/share/uselect/modules/' + +class Action: + + + def __init__(self, name, lines, _filesystem): + + self.filesystem = _filesystem + self.name = name + self.lines = lines + self.output = [] + self.usage = [] + self.options = [] + + for line in self.lines: + match = re.match('description "(.*)"', line.lstrip()) + if match: + self.description = match.group(1) + continue + match = re.match('type (.*)', line.lstrip()) + if match: + type = match.group(1) + continue + + if type == 'runnable': + self.__class__ = Runnable + elif type == 'sym': + if filesystem.uid != 'root': + self.__class__ = Path + else: + self.__class__ = Sym + self.build() + +class Runnable(Action): + + def do_action(self, args): + path = '/tmp/' + self.filename + self.filesystem.write_file(path, self.code) + self.filesystem.make_exec_file(path) + for line in self.filesystem.execute_cmd(path,args): + self.output.append(line[:-1]) + self.filesystem.delete_file(path) + for line in self.output: + self.options.append(['bold', line]) + + def get_code(self): + i = 0 + for line in self.lines: + match = re.match('file (.*) {', line.lstrip()) + if match: + ident = 1 + for char in line: + if char == '\t': + ident += 1 + self.filename = match.group(1) + for line in self.lines[i+1:]: + line = line.rstrip() + line = line.replace('\t', '', ident) + match = re.match('} ' + self.filename, line) + if match: + self.code.append('') + break + self.code.append(line) + i += 1 + + def build(self): + self.code = [] + self.get_code() + for line in self.lines: + match = re.match('parameters "(.*)"', line.lstrip()) + if match: + self.parameters = match.group(1) + continue + match = re.match('usage "(.*)"', line.lstrip()) + if match: + self.usage.append(match.group(1)) + continue + +class Link: + + def __init__(self, name, source_dir, source_regexp, source_target, \ + destination, _filesystem): + + self.name = name + self.destination = destination + self.targets = [] + self.status = [] + self.filesystem = _filesystem + + for dir in self.filesystem.list_dir(source_dir): + match = re.match(source_regexp, dir) + if match: + source = source_dir + match.group(0) + source_target + self.targets.append(source) + if self.filesystem.path_exists(destination): + if self.filesystem.real_path( \ + self.filesystem.environment + self.name) == \ + source: + self.status.append('notice') + elif self.filesystem.real_path(destination) == source: + self.status.append('ok') + else: + self.status.append('warning') + + else: + self.status.append('error') + return + +class Sym(Action): + + + def get_links(self): + for line in self.lines: + match = re.match('sym (.*) (.*) (.*) (.*) (.*)', line.lstrip()) + if match: + name = match.group(1) + source_dir = match.group(3) + source_regexp = match.group(4) + if match.group(5) == '*': + source_target = '' + else: + source_target = match.group(5) + destination = match.group(2) + self.links.append(Link(name, source_dir, source_regexp,\ + source_target, destination, self.filesystem)) + + def do_action(self, args): + + if len(args) != 0: + if args[0] == 'clear': + for link in self.links: + self.filesystem.delete_file(link.destination) + elif len(args) >= 1: + targets = [] + option = int(args[0]) -1 + for link in self.links: + for i in range(len(link.targets)): + targets.append([link.targets[i], \ + link.destination]) + if option >= 0 and option < len(targets): + self.filesystem.create_symlink(targets[option][0], \ + targets[option][1]) + self.output.append('Setting ' + targets[option][0] \ + + ' success!') + else: + raise UserWarning('Invalid Option "' \ + + args[0] + '"!') + else: + raise UserWarning('Invalid Option "' + args[0] \ + + '"!') + else: + for link in self.links: + for i in range(len(link.targets)): + self.options.append([link.status[i],str(i+1) + ' - ' + \ + link.targets[i]]) + self.parameters = '<target>' + self.usage.append('Available ' + self.name + ' targets:' ) + + def build(self): + self.links = [] + self.get_links() + +class Path(Action, Sym): + + def do_action(self, args): + if len(args) != 0: + if args[0] == 'clear': + home = self.filesystem.get_home() + for link in self.links: + self.filesystem.delete_file(home + '.uselect/bin/' \ + + link.name) + elif len(args) >= 1: + options = [] + choice = int(args[0]) - 1 + for link in self.links: + for i in range(len(link.targets)): + options.append([link.targets[i], \ + link.destination]) + if choice >= 0 and choice < len(options): + self.filesystem.create_symlink( \ + options[choice][0], + self.filesystem.environment + \ + link.name) + self.output.append('Setting ' + options[choice][0] \ + + ' success!') + else: + raise UserWarning('Invalid Option "' \ + + args[0] + '"!') + else: + raise UserWarning('Invalid Option "' + args[0] \ + + '"!') + else: + for link in self.links: + for i in range(len(link.targets)): + self.options.append([link.status[i],str(i+1) + ' - ' + \ + link.targets[i]]) + self.parameters = '<target>' + self.usage.append('Available ' + self.name + ' targets:' ) + return + +class Module(): + + def __init__(self, name, _filesystem): + global filesystem + filesystem = _filesystem + self.name = name + self.version = 'Unknown' + self.author = 'Anonymous' + self.description = name + ' has no description! ' + self.path = modules_dir + self.name + '.uselect' + self.lines = filesystem.read_file(self.path) + self.parse_module(name) + self.actions = [] + + def parse_module(self, name): + for line in self.lines: + line = line.lstrip() + match = re.match('description "(.*)"', line) + if match: + self.description = match.group(1) + continue + match = re.match('version "(.*)"', line) + if match: + self.version = match.group(1) + continue + match = re.match('author "(.*)"', line) + if match: + self.author = match.group(1) + continue + match = re.match('} ' + name, line) + if match: + break + + def get_action(self, name): + i = 0 + self.get_actions() + for action in self.actions: + if action.name == name: + return action + raise Exception('No such action "' + name + '"!') + + def get_actions(self): + i = 0 + for line in self.lines: + match = re.match('(\w*) action (\w*)', line.lstrip()) + if match: + wideness = match.group(1) + if wideness == "system" and filesystem.uid != "root": + continue + name = match.group(2) + u = 0 + for line in self.lines[i:]: + match = re.match('} ' + name + '\w*', line) + if match: + lines = self.lines[i:i+u+1] + action = Action(name, lines, filesystem) + self.actions.append(action) + break + u += 1 + if name == '(\w*)': + break + i += 1 + + diff --git a/uselect.py b/uselect.py new file mode 100755 index 0000000..4938176 --- /dev/null +++ b/uselect.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python +# Copyright 1999-2009 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# Universal Select Tool +# Base Module +# umodule.py mephx.x@gmail.com + +import os +import re +import sys +import stat +import string +import traceback + +from umodule import Module +from uio import PrintSystem +from uio import FileSystem + +verbose = False + +version = '0.2' +modules_dir = '/usr/share/uselect/modules/' + +class UniversalSelectTool: + + printsystem = PrintSystem() + filesystem = FileSystem() + + def __init__(self): + return + + def get_modules(self): + list = self.filesystem.list_dir(modules_dir) + self.modules = [] + for file in list: + match = re.match('(.*).uselect', file) + if match: + self.modules.append(Module(match.group(1), self.filesystem)) + + def get_module(self, name): + if not os.path.exists(modules_dir + name + '.uselect'): + raise Exception('Module ' + name + ' not found!') + return + else: + module = Module(name, self.filesystem) + return module + + def parse_argv(self, argv): + global profile, verbose, version + module = None + modules = None + action = None + args = None + self.printsystem.use_colors(True) + for arg in argv: + if arg == '-v': + verbose = True + self.printsystem.verbose() + argv = argv[1:] + elif arg == '-nc': + self.printsystem.use_colors(False) + argv = argv[1:] + elif arg == '-version': + self.printsystem.print_version(version) + argv = argv[1:] + if len(argv) < 1: + self.get_modules() + modules = self.modules + elif len(argv) == 1: + module = self.get_module(argv[0]) + elif len(argv) >= 2: + module = self.get_module(argv[0]) + action = module.get_action(argv[1]) + action.do_action(argv[2:]) + if len(argv) == 2: + argv = None + else: + argv = argv[2:] + + return [module, modules, argv, action] + + +def main(): + uselect = UniversalSelectTool() + try: + list = uselect.parse_argv(sys.argv[1:]) + uselect.printsystem.print_ui(module = list[0], \ + modules = list[1], args = list[2], action = list[3]) + except UserWarning, warning: + uselect.printsystem.print_exception(warning, True) + except Exception, exception: + uselect.printsystem.print_exception(exception) + if verbose: + traceback.print_exc() + printsystem.print_line('') + exit(1) + exit(0) + +if __name__ == '__main__': main() |