More robust installer with ability to save install preferences

pull/126/head
Mike Thornton 2012-05-07 15:41:41 -05:00
parent fe815f170d
commit 907446f97f
1 changed files with 215 additions and 79 deletions

View File

@ -1,88 +1,224 @@
#!/usr/bin/env bash
BASH_IT="$HOME/.bash_it"
#!/usr/bin/env python
import os
import sys
import shutil
from os import path
from optparse import OptionParser
import ConfigParser
from glob import glob
cp $HOME/.bash_profile $HOME/.bash_profile.bak
HOME=os.getenv('HOME')
BASH_IT=path.join(HOME, '.bash_it')
BASH_PROFILE = path.join(HOME, '.bash_profile')
echo "Your original .bash_profile has been backed up to .bash_profile.bak"
def confirm(prompt=None, default=False):
"""
Prompt the user for yes or no input.
cp $HOME/.bash_it/template/bash_profile.template.bash $HOME/.bash_profile
Returns True or False
"""
if prompt is None:
prompt = 'Confirm'
echo "Copied the template .bash_profile into ~/.bash_profile, edit this file to customize bash-it"
if default:
prompt = '%s [%s/%s]: ' % (prompt, 'Y', 'n')
else:
prompt = '%s [%s/%s]: ' % (prompt, 'y', 'N')
while True:
ans = raw_input(prompt)
if not ans:
return default
elif ans.lower() == 'y':
return True
elif ans.lower() == 'n':
return False
else:
print 'Please enter y or n.'
continue
while true
do
read -p "Do you use Jekyll? (If you don't know what Jekyll is, answer 'n') [Y/N] " RESP
def ask(prompt, values, default=None):
for i, v in enumerate(values):
prompt += '\n %d. %s' % (i + 1, v)
case $RESP
in
[yY])
cp $HOME/.bash_it/template/jekyllconfig.template.bash $HOME/.jekyllconfig
echo "Copied the template .jekyllconfig into your home directory. Edit this file to customize bash-it for using the Jekyll plugins"
break
;;
[nN])
break
;;
*)
echo "Please enter Y or N"
esac
done
prompt += '\n Choice #?'
function load_all() {
file_type=$1
[ ! -d "$BASH_IT/$file_type/enabled" ] && mkdir "$BASH_IT/${file_type}/enabled"
ln -s $BASH_IT/${file_type}/[^_]available/* "${BASH_IT}/${file_type}/enabled"
}
if default:
prompt += ' [%s]' % default
function load_some() {
file_type=$1
for file in `ls $BASH_IT/${file_type}/available/[^_]*`
do
if [ ! -d "$BASH_IT/$file_type/enabled" ]
then
mkdir "$BASH_IT/$file_type/enabled"
fi
while true
do
read -p "Would you like to enable the ${file%.*.*} $file_type? [Y/N] " RESP
case $RESP in
[yY])
ln -s "$BASH_IT/$file_type/available/$file" "$BASH_IT/$file_type/enabled"
break
;;
[nN])
break
;;
*)
echo "Please choose y or n."
;;
esac
done
done
}
prompt += ': '
for type in "aliases" "plugins" "completion"
do
while true
do
read -p "Would you like to enable all, some, or no $type? Some of these may make bash slower to start up (especially completion). (all/some/none) " RESP
case $RESP
in
some)
load_some $type
break
;;
all)
load_all $type
break
;;
none)
break
;;
*)
echo "Unknown choice. Please enter some, all, or none"
continue
;;
esac
done
done
min = 1
max = len(values)
options = range(min, max + 1)
while True:
ans = raw_input(prompt)
if not ans:
return default
try:
ans = int(ans)
except ValueError:
print('Please enter a number %d-%d' % (min, max))
prompt = '#?: '
continue
if ans in options:
return values[ans - 1]
else:
print('Please enter a number %d-%d' % (min, max))
prompt = '#?: '
def is_bash_it_installed():
if path.exists(BASH_PROFILE):
f = open(BASH_PROFILE, 'r')
installed = '$BASH_IT' in f.read()
f.close()
return installed
return False
class Configurator(object):
def __init__(self, config, prompt):
self.config = config
self.prompt = prompt
def getbool(self, key, default=False):
section, key = key.split('.', 1)
if self.config.has_option(section, key):
val = self.config.getboolean(section, key)
else:
val = default
return val
def get(self, key, default=None):
section, key = key.split('.', 1)
if self.config.has_option(section, key):
val = self.config.get(section, key)
else:
val = default
return val
def set(self, key, value):
section, key = key.split('.', 1)
if not self.config.has_section(section):
self.config.add_section(section)
self.config.set(section, key, value)
def confirm(self, key, question, default=False):
val = self.getbool(key, default)
if self.prompt:
val = confirm(question, val)
if val:
self.set(key, 'yes')
else:
self.set(key, 'no')
return val
def ask(self, key, question, values, default=None):
val = self.get(key, default)
if self.prompt:
val = ask(question, values, val)
self.set(key, val)
return val
def main(configfile=None, prompt=True):
config = ConfigParser.RawConfigParser()
if configfile:
config.read(configfile)
conf = Configurator(config, prompt)
if is_bash_it_installed():
print('Bash-it already installed, running configurator...')
else:
profile_name = path.basename(BASH_PROFILE)
if conf.confirm('bash-it.install', 'Do you want to install bash-it into your %s?' % profile_name):
print('Installing bash-it into %s...' % profile_name)
if path.exists(BASH_PROFILE) and conf.confirm('bash-it.backup', 'Do you want to back up your %s?' % profile_name, True):
shutil.copy(BASH_PROFILE, BASH_PROFILE + '.bak')
print("Your original .bash_profile has been backed up to %s.bak" % profile_name)
shutil.copyfile(path.join(BASH_IT, 'template/bash_profile.template.bash'), BASH_PROFILE)
print("Copied the template .bash_profile into %s, edit this file to customize bash-it" % BASH_PROFILE)
jekyll_config = path.join(HOME, '.jekyllconfig')
if path.exists(jekyll_config):
print('Jekyll config already installed.')
elif conf.confirm('jekyll.install', 'Do you use Jekyll? (If you don\'t know what Jekyll is, answer "n")'):
shutil.copyfile(path.join(BASH_IT, 'template/jekyllconfig.template.bash'), jekyll_config)
print("Copied the template .jekyllconfig to %s. Edit this file to customize bash-it for using the Jekyll plugins" % jekyll_config)
for name, type in [('alias', 'aliases'), ('plugin', 'plugins'), ('completion', 'completion')]:
resp = conf.ask('%s.install' % type, 'Would you like to enable all, some, or no %s? Some of these may make bash slower to start up (especially completion)' % type, values=['all', 'some', 'none'], default='all')
install_dir = path.join(BASH_IT, type, 'enabled')
if resp in ['all', 'some'] and not path.exists(install_dir):
os.makedirs(install_dir)
if resp in ['all', 'none']:
config.remove_section(type)
conf.set(type + '.install', resp)
for filename in glob(path.join(BASH_IT, type, 'available', '*')):
plugin_filename = path.basename(filename)
if plugin_filename.startswith('_'):
continue
plugin_name, _ = plugin_filename.split('.', 1)
install_file = path.join(install_dir, plugin_filename)
conf_key = '.'.join([type, plugin_name])
if resp == 'all' or (resp == 'some' and
conf.confirm(conf_key, 'Would you like to enable the %s %s' % (plugin_name, name))):
if path.exists(install_file):
os.remove(install_file)
os.symlink(filename, install_file)
print(' Installed %s %s' % (plugin_name, name))
elif path.exists(install_file):
os.remove(install_file)
print(' Removed %s %s' % (plugin_name, name))
if conf.prompt:
if confirm('Would you like to save your install preferences?'):
filename = configfile or 'pref.ini'
ans = raw_input('Where would you like to save to? [%s]:' % filename)
if not ans:
ans = filename
ans = path.join(BASH_IT, ans)
f = open(ans, 'w')
config.write(f)
f.close()
print('Saved preferences to %s' % ans)
if __name__ == '__main__':
parser = OptionParser()
parser.add_option('-c', '--config', dest='config',
help='Config file to use', metavar="FILE")
parser.add_option('-n', '--no-prompt', dest='no_prompt', action='store_true',
help='Install without prompting.')
(options, args) = parser.parse_args()
if options.no_prompt and not options.config:
parser.abort('You must supply a config to use without prompting.')
try:
main(options.config, not options.no_prompt)
except KeyboardInterrupt:
print('\nCancelled by keyboard.')