#!/usr/bin/env bash # vim:expandtab:ts=4:sw=4:fdm=marker:fmr={{{,}}} # To Inspect the code use vim, modelines and folds!!!! ######################################################################### # This Scripts is inspired by Morlenxus' easy_e17.sh # # and also a tiny bit of code is taken form it. # # The easy_e17.sh script can be found at: # # http://omicron.homeip.net/projects/#easy_e17.sh # # # # License: BSD licence # # Get the latest version at: https://github.com/ObiWahn/git_e17 # # Coded by Jan Christoph Uhde - linux (a) obiwahn dot org # ######################################################################### (( $BASH_VERSINFO < 4 )) && echo -e "\nThis Script requires at least bash version >= 4\n" && exit 1 ### global variable definitions {{{ ## TODO ## Convert package list strings to arrays!!! basic_lib="efl e_dbus azy elementary" basic_bin="e evas_generic_loaders terminology exchange" themes="dark 23oz b_and_w darkness detourious efenniht" modules_lib="libeweather etrophy" modules_bin="emprint --exalt" modules_extra="alarm comp-scale cpu deskshow diskio drawer eektool elfe" modules_extra+=" empris engage eooorg everything-aspell everything-mpris" modules_extra+=" everything-pidgin everything-places everything-shotgun everything-skeleton" modules_extra+=" everything-tracker everything-wallpaper everything-websearch eweather --exalt-client" modules_extra+=" exebuf execwatch flame forecasts iiirk itask mail mem moon mpdule net news penguins" modules_extra+=" photo places quickaccess rain screenshot skel slideshow snow taskbar tclock uptime" modules_extra+=" weather winlist-ng winselector wlan" extra_lib="imlib2 enlil --libast python-evas python-ecore python-e_dbusi" extra_lib+=" python-edje python-emotion python-elementary shellementary" extra_bin=" --clouseau --e_cho --e-type e_phys --eblock --econcentration editje eenvader.fractal --emote empower" extra_bin+=" --enjoy enki entrance ephoto eskiss --Eterm --expedite exquisite eyelight rage" declare -A packages_msg packages_msg[__basic_lib]="\nenlightenment foundation libraries:" packages_msg[__basic_bin]="\nbasic binaries:" packages_msg[__themes]="themes:\n" packages_basic="__basic_lib $basic_lib __basic_bin $basic_bin __themes $themes" packages_msg[__modules_lib]="\nmodule libraries:" packages_msg[__modules_bin]="\nmodule binaries:" packages_msg[__modules_extra]="\nmodule extras" packages_half="$packages_basic __modules_lib $modules_lib __modules_bin $modules_bin __modules_extra $modules_extra" packages_msg[__extra_lib]="\nextra libraries:" packages_msg[__extra_bin]="\nextra binaries:" packages_full="$packages_half __extra_lib $extra_lib __extra_bin $extra_bin" declare -A conf declare -A g_old_conf packages="" packages_failed="" g_current_commit="" g_current_branch="" g_old_commit="" # signals return status of some operations as # we lack proper return values g_current_failed=false g_clean_phase=false conf[dev]=false conf[verbose]=false conf[debug]=false conf[debug_level]=10 conf[animate]=false conf[clean]=false conf[distclean]=false conf[uninstall]=false conf[vmake]=false #for use in errors e="\n " bold=$(tput bold) boldoff=$(tput sgr0) c_red=$(tput setaf 1) c_green=$(tput setaf 2) c_norm=$(tput setaf 7) green="${bold}${c_green}" red="${bold}${c_red}" norm="${c_norm}${boldoff}" ok="${bold}${c_green}OK${c_norm}${boldoff}" fail="${bold}${c_red}FAILED${c_norm}${boldoff}" error="${bold}${c_red}Error:${c_norm}${boldoff}" conf[git_repo]="git://git.enlightenment.fr/vcs/svn.git" ###end global vars }}} #### main function {{{ main(){ debug 1 "$FUNCNAME() $*" ## interpret command line get_opts "$@" ## configuration get_git_e17_path_from_global_cfg read_local_cfg read_global_cfg assign_defaults interpret_action check_cfg ## uninstall distcheck ## source get_src git_fetch_reset git_pull ## package management if ! [[ "$packages" ]]; then echo -e "\n${bold}No packages to build!${boldoff}\n" exit 0 fi ## finding changes calculate_updates add_failed ignore_pkgs ## set_env build_main noob_info } #### end main function }}} ##### functions used in main {{{ ### display help - help(), devhelp() {{{ help(){ debug 1 "$FUNCNAME() $*" # # This functions displays the help file # printf '%b\n' \ "git_e17 - simple script for building enlightenment 17" \ "" \ "./git_e17 [options] ${green}action${norm} [(only|plugin) ]" \ "" \ "actions:" \ " ${green}build${norm}" \ " build and install" \ " ${green}update${norm}" \ " update your e17 to the latest version" \ " list" \ " list all available packages" \ " uninstall" \ " uninstall e17" \ "" \ "only:" \ " use only named packages" \ "" \ "plugin:" \ " call plugin hook on named plugins" \ "" \ "options:" \ " -h | --help" \ " show this page" \ " ${green}--git-e17-path${norm}" \ " workdir for this script. It will contain the source, config and log" \ " files and dirs in which e17 is build. The default git_e17_path should" \ " be ${green}set in ~/.git_e17${norm}" \ " -i | --ignore pkg1,pkg2,pkg2" \ " -s | --skip-errors" \ " skip non fatal errors" \ " ${bold}--dev-help${boldoff}" \ " developer help will give you more actions and options" \ "" } devhelp(){ debug 1 "$FUNCNAME() $*" # # This functions displays the developer help file # printf '%b\n' \ "" \ "${red}Enable devmode with --dev on command line or dev=true in a configuration file.${norm}" \ "" \ "changed actions: (when in dev mode actions do not enforce additional options) " \ " build" \ " build and install" \ " update" \ " update source, build and install" \ "extra actions:" \ " fromscratch" \ " delete e17 installation and install e17 from scratch" \ " ATTENTION: this will rm -fr $install_path" \ " do not do is if you installed to /usr/local" \ " check" \ " check if your system is ready to install e17" \ " (In dev mode the check is not done on every run.) "\ "" \ "extra options:" \ " --dev" \ " options: sets noob_info=false" \ " avoids system checks" \ " there will be the time that you want it in you conf" \ " ${bold}-v | --verbose${boldoff}" \ " be more verbose during the build" \ " --conf " \ " config file - especially useful if you want multiple installs" \ " ONLY CONF NAME - NO FULL PATHS!!!" \ " --cflags flags" \ " --ldflags flags" \ " you need the quotes!!" \ " -b | --branch " \ " branch, tag or commit to use" \ " -r | --remote " \ " select remote pull/fetch" \ " -p | --pull" \ " does a git pull --no-commit" \ " -f | --fetch-reset-hard" \ " ATTENTION: this will delete your local changes!!!!" \ " fetches update from remote, finds out your current branch" \ " and will do a git reset --hard remote/currentbrach" \ "" \ " --clean / --distclean / --uninstall" \ " make clean / distclean / uninstall before building" \ " --vmake" \ " more verbose make (V=1)" \ " --conf_args" \ " extra configure args - for all packages" \ " -d | --debug" \ " enable script debugging mode" \ " -a | --animate" } ### end help }}} ### parse command line get_opts(){ #{{{ debug 1 "$FUNCNAME() $*" section " reading command " # # This function reads the command line arguments # # in: # $@ - ARGV # # out: # sets: conf, branch, debug, verbose or calls help # TODO - idiot proof checking of arguments # copy_cfg while : do case $1 in --git-e17-path) conf[git_e17_path]="$2" echo "found option: --git-e17-path $2" shift 2 ;; -c|--conf) conf[config_file]="$2" echo "found option: --conf $2" shift 2 ;; -b|--branch) conf[branch]="$2" echo "found option: --branch $2" shift 2 ;; -r|--remote) conf[remote]="$2" echo "found option: --remote $2" shift 2 ;; -p|--pull) conf[pull]=true echo "found option: --pull" shift ;; -f|--fetch-reset-hard) conf[fetch]=true echo "found option: --fetch-reset-hard" shift ;; -s|--skip-errors) conf[on_error]=skip echo "found option: --skip-errors" shift ;; -a|--animate) conf[animate]=true conf[debug]=false conf[verbose]=false echo "found option: --animate" shift ;; -d|--debug) conf[debug]=true conf[animate]=false conf[debug_level]=4 echo "found option: --debug" shift ;; -v|--verbose) conf[verbose]=true conf[animate]=false echo "found option: --verbose" shift ;; --cflags) conf[cflags]="$2" echo "found option: --cflags $2" shift 2 ;; --ldflags) conf[ldflags]="$2" echo "found option: --ldflags $2" shift 2 ;; --clean) conf[clean]=true echo "found option: --clean" shift ;; --distclean) conf[distclean]=true echo "found option: --distclean" shift ;; --uninstall) conf[uninstall]=true echo "found option: --uninstall" shift ;; -i | --ignore) conf[ignore]="$2" echo "found option: --ignore '$2'" shift 2 ;; -d | --dev) conf[dev]="true" echo "found option: --dev '$2'" shift 1 ;; --vmake) echo "found option: --vmake" conf[vmake]="true" shift 1 ;; --dev-help) echo "found option: --dev-help" { help; devhelp; } | less -R exit 0 ;; -h|--help) echo "found option: --help" help exit 0 ;; *) #no more options beakb break ;; esac done #parse action parameter debug 1 "action: $1" if [[ "$1" == @(build|update|devupdate|devbuild|fromscratch|list|uninstall|quick|check) ]]; then conf[action]="$1" echo "selected action is ${conf[action]}" shift else cmd_error fi if ! [[ "$1" ]]; then debug 1 "commandline actions are ok - options are not checked here" elif [[ "$1" == only ]]; then shift packages="$@" echo "only: $packages" elif [[ "$1" == plugin ]]; then shift packages="${@:-all}" echo "plugins: $packages" plugin exit else cmd_error fi echo print_cfg debug_cfg } #}}} ### get git_e17_path form ~/.git_e17 || create the file get_git_e17_path_from_global_cfg(){ #{{{ debug 1 "$FUNCNAME() $*" section " reading global configuration in ~/.git_e17 " # # This function tries to read the global configuration file # or creates it. If the file exists two important config # items are read when they are not set by command line # # out: # sets: conf[git_e17_path], conf[config_file] # copy_cfg local conf_file="$HOME/.git_e17" debug 1 "git e17 path: $1" if [[ ! -f "$conf_file" ]]; then #create config echo "$(default_global_cfg)" > "$conf_file" || ferr "Unable to create $conf_file" if [[ ! ${conf[git_e17_path]} ]]; then echo -e "\nPlease edit your fresh created ~/.git_e17." echo "Set the git_e17_path this dir will be the scripts working dir." echo "It will contain logs, soure and build dir, configuration files" echo "and other things." fi fi #read config values git_e17_path and config_file while IFS='=' read -r item value; do if [[ "$item" == @(git_e17_path|config_file) ]]; then conf["$item"]=${conf["$item"]:-"$value"} debug 3 "conf[$item]=$value" fi done <<< "$(grep -v ^# "$conf_file" | grep -v ^$ )" #final check if path is set debug 2 "The git e17 path must be set by now!! git_e17_path=${conf[git_e17_path]}" if [[ ! ${conf[git_e17_path]} ]]; then ferr -e "git_e17_path is not set:(\n${e}please set it via commandline or ~/.git_e17" fi #remove trailing slash from git_e17_path conf[git_e17_path]=${conf[git_e17_path]%/} echo "git e17 path set to ${conf[git_e17_path]}" echo "config file set to ${conf[config_file]}" #check if git_e17_path exists if ! [[ -d "${conf[git_e17_path]}" && -w "${conf[git_e17_path]}" ]]; then if ! mkdir -p "${conf[git_e17_path]}"; then ferr -e "unable to create or access ${conf[git_e17_path]}" fi fi echo print_cfg } #}}} ### read configuration in git e17 directory read_local_cfg(){ #{{{ debug 1 "$FUNCNAME() $*" section " reading git-e17-path configuration file (${conf[config_file]}) " # # This function checks if the config exists. If it does not the file is created. # Then the configuration file is read and the values are put into the conf array. # In case the file was newly created the user is asked if he wants to continue. # # out: # sets: ... a lot items in conf ... # copy_cfg local new_cfg=false local conf_file="${conf[git_e17_path]}/${conf[config_file]}" if [[ ! -f "$conf_file" ]]; then echo "$(default_local_cfg)" > "$conf_file" || ferr "Unable to create $conf_file" new_cfg=true fi # read config config="$(grep -v ^# < "$conf_file" | grep -v ^$)" debug 3 "$config" while IFS='=' read -r item value; do conf["$item"]=${conf["$item"]:-"$value"} done <<< "$config" print_cfg if $new_cfg; then echo -e "\nEnlightenment 17 will be install to: ${bold} ${conf[install_path]} ${boldoff}" echo -e "To change this or other settings you can edit:" echo -e "${bold}$conf_file${boldoff}\n" [[ $(ask_yn "Do you want to proceed with the installation using the defaults?") == "yes" ]] || exit 1 fi } #}}} ### read rest of ~/.git_e17 - sets only overwrite unset options read_global_cfg(){ #{{{ debug 1 "$FUNCNAME() $*" section " reading global cfg options " # # Read global configuration and copy items to conf # copy_cfg config="$(grep -v ^# < "$HOME/.git_e17" | grep -v ^$)" debug 3 "$config" while IFS='=' read -r item value; do conf["$item"]=${conf["$item"]:-"$value"} done <<< "$config" print_cfg } ### assign default values assign_defaults(){ debug 1 "$FUNCNAME() $*" section " assigning default vaules " conf[install_path]="${conf[install_path]:-"/opt/e17"}" #TODO - maybe the script should fail if the build path is not set conf[build_path]="${conf[build_path]:-"${conf[git_e17_path]}/build"}" conf[log_path]="${conf[log_path]:-"${conf[git_e17_path]}/log"}" conf[packagelist]="${conf[packagelist]:-"full"}" conf[on_error]="${conf[on_error]:-"ask"}" conf[nice]="${conf[nice]:-"19"}" conf[pull]=${conf[pull]:-false} conf[fetch]=${conf[fetch]:-false} conf[remote]="${conf[remote]:-"origin"}" conf[noob_info]="${conf[noob_info]:-"true"}" conf[dev]="${conf[dev]:-"false"}" if [[ ! $packages ]]; then case "${conf[packagelist]}" in full) packages="$packages_full" ;; half) packages="$packages_half" ;; basic) packages="$packages_basic" ;; *) ferr "No valid package list packagelist=full|half|basic" ;; esac fi print_cfg } #}}} interpret_action(){ #{{{ debug 1 "$FUNCNAME() $*" section " interpret action " # # Function interprets action and sets options # # out: # sets: some options in conf so that they fit the selected action # copy_cfg local action="${conf[action]}" if ${conf[dev]}; then conf[noob_info]=false #we dont want no noobinfo at then end: case "$action" in build|devbuild) conf[action]="build" ;; update|devupdate) conf[action]="update" ;; quick) conf[action]="build" conf[animate]=true conf[debug]=false conf[verbose]=false conf[on_error]="skip" ;; esac else case "$action" in build) conf[action]="build" conf[fetch]=false conf[pull]=false conf[animate]=true conf[debug]=false conf[verbose]=false conf[on_error]="skip" ;; update|quick) conf[action]="update" conf[branch]="master" conf[remote]="origin" conf[fetch]=true conf[pull]=false conf[animate]=true conf[debug]=false conf[verbose]=false conf[on_error]="skip" ;; devbuild) conf[action]="build" ;; devupdate) conf[action]="update" ;; esac fi case "$action" in fromscratch) (( $(id -u) == 0 )) && echo "idiot!!! Don't do this as root!!!" && exit 666 rm -fr "${conf[install_path]}" rm -fr "${conf[build_path]}" rm -fr "${conf[src_path]}/trunk" conf[fetch]=true conf[action]="build" ;; list) #TODO list exit 1 ;; check) conf[dev]=false #required otherwise distcheck will exit immediately distcheck exit 0 ;; esac echo "These changes are forces by options" print_cfg } #}}} ### check for missing options and unwritable paths check_cfg(){ #{{{ debug 1 "$FUNCNAME() $*" section " checking configuration " # # check configuration # ## FIXME ## conf[theme_path]="$HOME/.e/e/themes" ## FIX-FOR-A-THEME local paths="theme_path install_path git_e17_path log_path build_path log_path" local output="debug debug_level dev verbose animate" local conf_items="$paths src_path $output action config_file packagelist nice on_error" for item in $conf_items; do if [[ -z "${conf["$item"]}" ]]; then ferr "Value for $item is not set - please edit your config file" fi done # check if directories are writeable for path in $paths; do if [[ ! -d "${conf[$path]}" ]]; then mkdir -p "${conf[$path]}" && continue ferr "Unable to create the directory ${conf[$path]} - create it!" elif [[ ! -w "${conf[$path]}" ]]; then ferr "The directory ${conf[$path]} is not writeable for you:( - change that!" fi done #translate strings to bool for key in ${!conf[@]}; do case ${conf[key]} in true|yes) conf[key]=true ;; false|no) conf[key]=false ;; *) continue ;; esac done echo "Configuration passed all checks." debug_cfg } #}}} ### uninstall e17 uninstall(){ #{{{ debug 1 "$FUNCNAME() $*" [[ ${conf[action]} == uninstall ]] || return section " uninstalling e17 " # # This functions uninstalls e17 # # # ok this is is frigging ugly:P - but it works :E # #enter build dir cd "${conf[build_path]}" || { echo "uninstall failed"; exit 1; } #visit all subdirs - they should match the package names for dir in * ; do #change dir if ! cd "$dir" &>/dev/null ; then echo "failed to uninstall $dir" continue fi #test for makefile if [[ -e Makefile || -e makefile ]]; then write_name "$dir" #uninstall - try to run make uninstall nice -n "${conf[nice]}" bash -c "make uninstall" &>>"${conf[log_path]}/uninstall.log" & rotate $! "" "${conf[log_path]}/uninstall.log" wait echo "$ok" else echo "$fail" fi cd .. done exit 0 } #}}} ### functions that scan source code and select packages to be build get_src(){ #{{{ debug 1 "$FUNCNAME() $*" section " getting source code " # # Clone Repository if it does not exist and change into to it's directory # # out: # sets: g_current_branch, g_old_commit # g_current_failed=false local src_path="${conf[src_path]}" local git="${conf[git_repo]}" local remote="${conf[remote]}" #delete log file rm -fr "${conf[git_e17_path]}/git.log" # # TODO - check and double check that this is a reop or exit # #does the repo exist if [[ ! -d ${conf[src_path]} ]]; then #create it echo "cloning ${conf[git_repo]}" for i in {0..10}; do echo "trying to clone git repository" if git clone -v --progress "${conf[git_repo]}" "$src_path"; then repo_cloned=true echo "successfully cloned git repo" break else echo "failed to clone repository" fi done $repo_cloned || ferr "unable to clone repository" fi #change to repo echo "changing into $src_path" cd "$src_path" || ferr "failed to cd in $src_path" #get name of branch g_current_branch="$(git symbolic-ref HEAD)" g_current_branch="${g_current_branch##*/}" [[ -n "$g_current_branch" ]] || ferr "You are not on any branch - Fix your repo!!!" echo "Your current branch is $g_current_branch" #get hash of current HEAD g_current_commit="$(git log -1 --format="%H")" g_old_commit="$(git log -1 --format="%H")" echo "You are at commit $g_old_commit" } #}}} ### fetch changes and reset repo to fetched head git_fetch_reset(){ #{{{ debug 1 "$FUNCNAME() $*" ${conf[fetch]} || return section " git fetch && git reset --hard " # # fetches latest # local remote="${conf[remote]}" local branch="${conf[branch]:-"$g_current_branch"}" #select right branch echo "checking out $branch so that you local $branch matches the remote branch" echo "i think this is a good default for people that are not messing with the code" if [[ -n "$branch" && "$branch" != "$g_current_branch" ]]; then if ! git checkout ${conf[branch]}; then ferr "unable to checkout selected branch - fix your repository" fi fi echo "git fetch $remote" git fetch $remote &> >( tee -a "${conf[git_e17_path]}/git.log" ) || nerr "git fetch failed" echo "git clean -f -d" git clean -f -d &> /dev/null echo "git reset --hard $remote/$branch" git reset --hard "$remote/$branch" &> >( tee -a "${conf[git_e17_path]}/git.log" ) \ || nerr "git reset --hard failed" } #}}} ### pull changes into repo git_pull(){ #{{{ debug 1 "$FUNCNAME() $*" ${conf[pull]} || return section " git pull --no-commit " # # pull updates into branch # section " dear god we all hope there are no conflicts " git pull --no-commit $remote &> >( tee -a "${conf[git_e17_path]}/git.log" ) || nerr "git pull failed" } #}}} ### calculate updates calculate_updates(){ #{{{ debug 1 "$FUNCNAME() $*" [[ "${conf[action]}" == "update" ]] || return section " calculating changes " # # Calculates changes to packages du to to fetch / pull operations # g_current_commit="$(git log -1 --format="%H")" ## Speed this up write_name "building path map" local -A path_map for pkg in $packages; do find_local_path "$pkg" "${conf[src_path]}" "/trunk" local path="${conf[current_package_path]}" if [[ -n "$path" ]]; then path=${path##"$src_path"} path_map["$pkg"]="trunk/$path/" debug 3 "map $pkg: ${path_map[$pkg]}" else debug 3 "unable to map $pkg to source location" fi done #rotate does not work here #rotate $! "" "no_file" #wait echo -e "$ok \n" packages_new="" echo "checking packages for changes: " echo "package name .............. update status - (install status)" echo for pkg in $packages; do if [[ $pkg == __* ]]; then packages_new+="$pkg " continue fi debug 3 "map $pkg: ${path_map[$pkg]}" if [[ -n "${path_map[$pkg]}" ]]; then write_name "$pkg" # calulate the new dir per package #find the last successful install/build local succ_build="$(grep "^$pkg" "${conf[build_path]}/git_e17_status")" if [[ -z "$succ_build" ]]; then #build it because we have no info packages_new+="$pkg " echo "never build" continue fi local stat try succ_commit fail IFS=: read -r _ stat try succ_commit fail <<< "$succ_build" if [[ "$succ_commit" == "na" ]]; then #build it because it was never build successfully packages_new+="$pkg " echo "never build" continue fi debug 3 "last successfully bulid commit: $succ_commit" #get files that differ form last successfully build commit new_files="$(git diff --name-only "$succ_commit" -- "${path_map[$pkg]}" 2>/dev/null)" if [[ $? -ne 0 ]]; then #build it because git diff failed. packages_new+="$pkg " #echo "git diff --name-only $succ_commit -- ${path_map[$pkg]} failed" echo "git diff failed" continue fi debug 4 "new files for $pkg: $new_files" local new_dirs="$( while read -r line; do echo "${line%/*}/" done <<< "$new_files" )" local new_dirs_uniq="$( echo "$new_dirs" | sort | uniq 2>/dev/null)" debug 4 sleep "new_dirs: $new_dirs_uniq" #build it because there are changes in the path if echo $new_dirs_uniq | grep -q -E "${path_map[$pkg]}.*" ; then echo "changed - ($stat)" packages_new+="$pkg " else echo "unchanged - ($stat)" fi fi done packages="$packages_new" if [[ "$packages" ]]; then echo -e "The following packages are not up to date: \n" echo_long "$packages" else echo -e "All packages are up to date! There is no need to update!!\n" exit 0 fi } #}}} ### add failed packags to rebuild list add_failed(){ #{{{ debug 1 "$FUNCNAME() $*" section " looking for failed packages " # # add failed packages to packages that should be build # echo "not implemented" } #}}} ### mark package as failed pkg_failed(){ #{{{ debug 1 "$FUNCNAME() $*" # # add to failed # msg -e " - Adding $1 to failed list of failed packages\n" local status_file="${conf[build_path]}/git_e17_status" status_content="$(cat "$status_file")" local name stat try succ fail while IFS=: read -r name stat try succ fail; do if [[ "$pkg" == "$name" ]]; then echo "$name:failed:$try:$succ:$g_current_commit" else echo "$name:$stat:$try:$succ:$fail" fi done <<< "$status_content" > "$status_file" packages_failed+="$pkg " } #}}} ### mark package as successfully build pkg_success(){ #{{{ debug 1 "$FUNCNAME() $*" # # remove from failed # local status_file="${conf[build_path]}/git_e17_status" local name stat try succ fail status_content="$(cat "$status_file")" while IFS=: read -r name stat try succ fail; do if [[ "$pkg" == "$name" ]]; then echo "$name:success:$try:$g_current_commit:$fail" else echo "$name:$stat:$try:$succ:$fail" fi done <<< "$status_content" > "$status_file" } #}}} ### ignore_pkgs(){ #{{{ debug 1 "$FUNCNAME() $*" [[ "${conf[ignore]}" ]] || return section " ignore packages " # # remove packages to ignore to from packages # local ignore=${conf[ignore]//,/ } echo "ignoring packages $ignore" packages="$(sub_lists "$packages" "$ignore")" } #}}} ### set up the build environment set_env(){ #{{{ debug 1 "$FUNCNAME() $*" local install_path="${conf[install_path]}" section " setting environment variables " export PATH="$install_path/bin:$PATH" echo "PATH=$PATH" export ACLOCAL_FLAGS="-I $install_path/share/aclocal $ACLOCAL_FLAGS" echo "ACLOCAL_FLAGS=$ACLOCAL_FLAGS" export LD_LIBRARY_PATH="$install_path/lib:$LD_LIBRARY_PATH" echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH" export PKG_CONFIG_PATH="$install_path/lib/pkgconfig:$PKG_CONFIG_PATH" echo "PKG_CONFIG_PATH=$PKG_CONFIG_PATH" export CPPFLAGS="$CPPFLAGS -I$install_path/include" echo "CPPFLAGS=$CPPFLAGS" export LDFLAGS="$LDFLAGS -L$install_path/lib ${conf[ldflags]}" echo "LDFLAGS=$LDFLAGS" export LD_RUN_PATH="$install_path/lib" echo "LD_RUN_PATH=$LD_RUN_PATH" export CFLAGS="$CFLAGS ${conf[cflags]}" echo "CFLAGS=$CFLAGS" export PYTHONPATH="$($pythoncmd -c "import distutils.sysconfig; print distutils.sysconfig.get_python_lib(prefix='$install_path')" 2>/dev/null)" echo "PYTHONPATH=$PYTHONPATH" export PYTHONINCLUDE="$($pythoncmd -c "import distutils.sysconfig; print distutils.sysconfig.get_python_inc(prefix='$install_path')" 2>/dev/null)" echo "PYTHONINCLUDE=$PYTHONINCLUDE" export NOCONFIGURE="true" echo "NOCONFIGURE=$NOCONFIGURE" export V=1 echo "V=$V" echo if ${conf[verbose]}; then sleep 5 fi echo 'checking existence of $install_path/share/aclocal $PYTHONPATH $PYTHONINCLUDE ... ' local failed=false for dir in "$install_path/share/aclocal" "$PYTHONPATH" "$PYTHONINCLUDE"; do if [[ ! -w "$dir" ]]; then if ! mkdir -p "$dir"; then echo echo "please create the $dir as root and allow you user to wirte to it" echo "sudo mkdir -p $dir" echo "sudo chown $USER:$USER $dir" failed=true fi fi done ## TODO ## OUTPUT $failed && ferr "can not access all required directories" } #}}} #calls build in main script build_main(){ #{{{ section " entering build phase " echo -e "The following packages will be build:\n" echo_long "$packages" echo build "${conf[src_path]}" "/trunk" "${conf[build_path]}" } #}}}} ### build ### calls: find_local_path, compile build(){ #{{{ debug 1 "$FUNCNAME() $*" # # This functions should find the # local repo_path="$1" local trunk="$2" local build_path="$3" local status_file="${conf[build_path]}/git_e17_status" [[ -e "$status_file" ]] || touch "$status_file" for pkg in $packages; do # # please use only # msg - for normal and verbose mode messages or # msg_ani - for animation mode messages # within this loop for output # if [[ $pkg == __* ]]; then echo -e "${bold}${packages_msg["$pkg"]}${norm}" continue fi #skip-packages if [[ $pkg == --* ]]; then continue fi # TODO - ormaaj suggests to use temp files here - I was too lazy ... status_content="$(cat "$status_file")" #BAD STYLE local name_found=false local name stat try succ failed while IFS=: read -r name stat try succ failed; do if [[ "$pkg" == $name ]]; then echo "$name:$stat:$g_current_commit:$succ:$failed" name_found=true else if [[ -n "$name" ]]; then echo "$name:$stat:$try:$succ:$failed" fi fi done <<< "$status_content" > "$status_file" #BAD STYLE if ! $name_found; then echo "$pkg:x:$g_current_commit:na:na" >> "$status_file" fi msg "- trying to build $pkg ..." #initialize vars debug 2 "init vars" g_current_failed=false conf[current_package_path]="" #find src find_local_path "$pkg" "$repo_path" "$trunk" local cpath="${repo_path}${trunk}/${conf[current_package_path]}" local bpath="${conf[build_path]}/$pkg" if [[ -z "$cpath" ]]; then nerr "source path of of package $pkg not found" msg_ani "SKIP" continue else #for animation ${conf[animate]} && write_name "$pkg" fix_pkg "$pkg" "$cpath" "$bpath" ###compile it! declare -g g_retry=true while $g_retry; do g_retry=false compile "$pkg" "$cpath" "$bpath" if ${conf[animate]} && $g_current_failed; then ## BEGIN ANIMATION MODE OUTPUT # this is the place for extra information in # animation mode - it is shown when a building step failed msg_ani "$fail" pkg_err "$pkg" $g_retry && write_name "$pkg" fi done #### #### management of failed / successful packages if $g_current_failed; then # # ADD PKG TO FAILED pkg_failed "$pkg" else #for animation msg_ani "$ok" if [[ $pkg == e ]] && ! ${conf[dev]}; then echo -e "${bold}E17 is installed :) The rest is optional!!\nDo not bug me or people in #e if other packages fail!${norm}" fi # REMOVE PKG FROM FAILED pkg_success "$pkg" fi fi done [[ $packages_failed ]] && echo -e "\n${bold}The following packages failed to build:\n${red}$packages_failed${norm}" } #}}} ### find the source code of a package find_local_path (){ #{{{ debug 1 "$FUNCNAME() $*" # # Function that should find the source path to the current package # # in: # $1 - package name # $2 - path to repo # $3 - trunk # out: # sets: conf[current_package_path] # local name="$1" local repo_path="$2" local trunk="$3" local path="" local src_path="${repo_path}${trunk}" conf[current_package_path]="$path" #prune dirs to ignore local prune="" for dir in devs DOCS E16 EXAMPLES TEST web packaging; do prune="-o -path $src_path/$dir $prune" done prune=${prune#-o} #use find to get possible dirs #debug-x dirs="$(find "$src_path" -maxdepth 3 -type d \( $prune \) -prune -o -type d -name "$name" -printf "%P\n" )" #debug+x debug 5 "$dirs" #pick the one with the shortest path local path_len=666 while read -r path ;do if [[ -d "$src_path/$path" ]] && (( ${#path} < $path_len )); then conf[current_package_path]="$path" path_len=${#path} fi done <<< "$dirs" debug 5 "path selected for $pkg: $src_path/${conf[current_package_path]}" if [[ -z "${conf[current_package_path]}" ]] ; then debug 1 "Source path for $pkg was not found!" fi } #}}} ### sets up configure parameters ### calls: run_cmd compile(){ #{{{ debug 1 "$FUNCNAME() $*" # # # local pkg="$1" debug 1 "package: $pkg" local src_path="$2" debug 1 "srcpath: $src_path" local build_path="$3" debug 1 "build_path: $build_path" g_current_failed=false local install_path="${conf[install_path]}" local pkg_conf_args="${conf["${pkg}_conf_args"]}" local build_type="" local log_file="${conf[log_path]}/$pkg.log" [[ -e "$log_file" ]] && rm "$log_file" # find type of build process if [ -e "$src_path/CMakeLists.txt" ]; then build_type="cmake" elif [ -e "$src_path/autogen.sh" ]; then build_type="autogen" elif [ -e "$src_path/bootstrap" ]; then build_type="bootstrap" elif [ -e "$src_path/Makefile.PL" ]; then build_type="perl" elif [ -e "$src_path/Makefile" ]; then build_type="make" export PREFIX="${conf[install_path]}" elif [ -e "$src_path/setup.py" ]; then build_type="python" elif [ -e "$src_path/configure" ]; then build_type="configure" else export PREFIX="" fi debug 1 "Type of build system $build_type" declare -g g_clean_phase=true case "$build_type" in autogen|bootstrap|cmake|configure) ${conf[uninstall]} && run_cmd "$pkg" "$src_path" "$build_path" "make uninstall" "make uninstall" g_current_failed=false ${conf[clean]} && run_cmd "$pkg" "$src_path" "$build_path" "make clean" "make clean" g_current_failed=false ${conf[distclean]} && run_cmd "$pkg" "$src_path" "$build_path" "make distclean" "make distclean" g_current_failed=false ;;& make|perl) ${conf[uninstall]} && run_cmd "$pkg" "$src_path" "" "make uninstall" "make uninstall" g_current_failed=false ${conf[clean]} && run_cmd "$pkg" "$src_path" "" "make clean" "make clean" g_current_failed=false ;; *) : ;; esac g_clean_phase=false g_current_failed=false #use the power of ;;& - muahahh #UGLY HACK!! case "$build_type" in autogen) run_cmd "$pkg" "$src_path" "" "autogen" "./autogen.sh" ;;& cmake) run_cmd "$pkg" "$src_path" "" "cmake" "cmake -DCMAKE_INSTALL_PREFIX=$install_path $pkg_conf_args $src_path" ;;& bootstrap) run_cmd "$pkg" "$src_path" "" "boostrap" "./bootstrap" ;;& perl) run_cmd "$pkg" "$src_path" "$build_path" "perlmake" "perl $src_path/Makefile.PL prefix=$install_path" ;;& autogen|bootstrap|configure) #configure $g_current_failed || run_cmd "$pkg" "$src_path" "$build_path" "configure" "$src_path/configure --prefix=$install_path $pkg_conf_args" ;;& autogen|cmake|bootstrap|perl|configure) # make && make install $g_current_failed || run_cmd "$pkg" "$src_path" "$build_path" "make" "make -j ${conf[threads]}" $g_current_failed || run_cmd "$pkg" "$src_path" "$build_path" "install" "make install" ;; make) # make && make install run_cmd "$pkg" "$src_path" "" "make" "$make_extra make -j ${conf[threads]}" $g_current_failed || run_cmd "$pkg" "$src_path" "" "install" "make install" ;; python) run_cmd "$pkg" "$src_path" "" "setup.py-build" "python setup.py build build_ext --include-dirs=$PYTHONINCLUDE $pkg_conf_args" $g_current_failed || run_cmd "$pkg" "$src_path" "" "setup-py-install" "$pythoncmd setup.py install --prefix=$install_path install_headers --install-dir=$PYTHONINCLUDE" ;; *) msg " - no build system ... $fail" g_current_failed=true return esac } #}}} ### runs the commands that are actually used to build the code ### calls: rotate run_cmd(){ #{{{ debug 1 "$FUNCNAME() $*" # # in: # $1 - pkg - package name # $2 - src - source path # $3 - build - path in which configure will be run # $4 - title - titel of the displayed action while the command is running # $@ - the command to be run # # out: # compiles the code and sets g_current_failed in case of failure # # FUNCTION NEEDS TO BE REWRITTEN - it is UGLY and STUIP # a better way than writing $@ to call the command would be nice # # the 3 different calls might be handled in another way # maybe it is better to write a separate run_animated function # local pkg="$1" local src="$2" local build_path="$3" local title="$4" shift 4 if [[ -n "$build_path" ]]; then #clean it whatever it means mkdir -p "$build_path" || on_error "unable to create $build_path" cd "$build_path" || on_error "unable to cd into $build_path" else cd "$src" || on_error "unable to cd into $src" fi ## check if makefile is available if [[ $title == "make"* ]]; then if ! [[ -e Makefile || -e makefile ]]; then #TODO - elif check source dir and cd into it g_current_failed=true #We will not fail in clean_phase # make sure animation mode is not interrupted ${conf[animate]} && return # BEGIN NORMAL OUTPUT msg -n " - $title ... " if $g_clean_phase; then msg "$fail - make may fail during clean phase" else msg "$fail" msg "no Makefile :(" pkg_err "$pkg" fi # BEGIN NORMAL OUTPUT return fi fi log_file="${conf[log_path]}/$pkg.log" debug 1 "running in path: $(pwd)" echo -e "\n\n" >>"$log_file" echo -e "git_e17 - $title\n" >>"$log_file" echo -e "command: $* " >>"$log_file" echo -e "dir: $(pwd)" >>"$log_file" echo -e "revision: $g_current_commit \n\n" >>"$log_file" #run only if pre checks did not fail if ! $g_current_failed; then #if animation mode is used if ${conf[animate]}; then #call nice -n "${conf[nice]}" bash -c "$@" &>>"$log_file" & #get pid pid="$!" #start animation ( rotate "$pid" "${title}: " "$log_file" ) & #wait for command to finish and check exit status if ! wait $pid; then g_current_failed=true else #check log for errors if tail -n 20 "$log_file" | grep -q -i error &> /dev/null; then g_current_failed=true fi fi #wait for animation - is that necessary? wait # success #return here and now do not go any further - HACK!!! return #if a more verbose mode is used elif ${conf[verbose]} ; then echo -e " - RUNNING: ${bold}$@${boldoff} ... " echo -e " IN: $(pwd)\n" sleep 2 if ! nice -n "${conf[nice]}" bash -c "$@" &> >(tee -a "$log_file"); then g_current_failed=true else if tail -n 20 "$log_file" | grep -q -i error &> /dev/null; then g_current_failed=true else echo return fi fi #if normal mode is used else msg -n " - $title ... " if ! nice -n "${conf[nice]}" bash -c "$@" &>>"$log_file"; then g_current_failed=true else if tail -n 20 "$log_file" | grep -q -i error &> /dev/null; then g_current_failed=true else msg "$ok" return fi fi fi msg "$fail" # # NORMAL AND VERBOSE MODE OUTPUT HERE !!!!!! # echo tail -n 30 "$log_file" echo $g_clean_phase || pkg_err $pkg : fi #end of pre checks of } #}}} ### fix packages fix_pkg(){ #{{{ debug 1 "$FUNCNAME() $*" # # fix packages # local pkg="$1" local cpath="$2" local bpath="$3" case $pkg in drawer|itask|winlist-ng|enlil|enki) msg -n " - fixing ... " rsync -av "$cpath/" "$bpath/" &>/dev/null msg "PRAY!" ;; evas) #delete old svg loader instead of unistalling evas rm -fr "${conf[install_path]}/lib/evas/modules/loaders/svg" 2>/dev/null ;; esac } #}}} ##### functions used in main }}} #### distcheck functions {{{ distcheck(){ #{{{ #echo -e "${bold}checking distribution ...${boldoff}" debug 1 "$FUNCNAME() $*" section " distribution setting and checks " #allow distros to set their own python command # TODO - this should probably go into conf[] # or up to the other global vars. on the other hand # people are more likely to find it here pythoncmd="python" # Default binaries and libs to check. # Can be overriden by distribution (See Arch) deps_bin="git make automake byacc g++ gcc libtool pkg-config" deps_dev="dbus-1 fontconfig freetype GL jpeg lua5.1 png udev xml2 X11 Xext Xrandr xcb" #find distribution if [ -e "/etc/debian_version" ]; then echo "found distribution debian" ! ${conf[dev]} || return debian_check elif [ -e "/etc/arch-release" ] ; then echo "found distribution arch" deps_bin="${deps_bin/byacc/yacc}" deps_dev="${deps_dev/lua5.1/lua}" pythoncmd="python2" ! ${conf[dev]} || return archlinux_check elif [ -e "/etc/fedora-release" ]; then echo "found distribution fedora" deps_dev="${deps_dev/lua5.1/lua}" ! ${conf[dev]} || return fedora_check unsupported_dist_note elif [ -e "/etc/gentoo-release" ]; then echo "found distribution gentoo" ! ${conf[dev]} || return unsupported_dist_note elif [ -e "/etc/redhat-release" ]; then echo "found distribution redhat" ! ${conf[dev]} || return unsupported_dist_note elif [ -e "/etc/SuSE-release" ]; then echo "found distribution Suse" ! ${conf[dev]} || return unsupported_dist_note else echo "did not find your distribution" ! ${conf[dev]} || return unsupported_dist_note fi # # general check # echo -e "${bold}proceeding with general checks\n${boldoff}" local failed=false echo -e "checking commands:" for bin in $deps_bin; do write_name "$bin" if ! type $bin &> /dev/null; then failed=true echo "$fail - missing" else echo "$ok " fi done echo -e "\nchecking includes:" compfile="/tmp/include_test.c" echo "main(){}" >$compfile for dep in $deps_dev; do write_name "$dep" if ! gcc -o /dev/null $compfile -l$dep &>/dev/null; then failed=true echo "$fail - include missing" else echo "$ok" fi done $failed && ferr "Please install the missing build dependencies" } #}}} ## debian specific stuff debian_check(){ #{{{ debug 1 "$FUNCNAME() $*" #must be tested for stable local deps_debian_common="git autoconf automake1.9 autotools-dev autoconf-archive gettext libtool libfreetype6-dev " deps_debian_common+="libpng12-dev libtiff4-dev libgif-dev libbz2-dev libltdl-dev pkg-config libxine-dev build-essential flex bison byacc " deps_debian_common+="libxcursor-dev libtag1-dev sqlite libxml2-dev libsqlite3-dev libxslt1.1 libxslt1-dev giblib1 " deps_debian_common+="giblib-dev libtool libtagc0-dev libmpd1 libmpd-dev libxcomposite-dev libxcomposite1 libxdamage-dev " deps_debian_common+="libxdamage1 libxkbfile-dev libxkbfile1 libxkbfile-dev libxkbfile1 libdbus-1-dev libtheora-dev libpopt-dev " deps_debian_common+="libglib2.0-dev libfontconfig1-dev libxrandr-dev libasound2-dev libxinerama-dev cvs automake libgstreamer0.10-dev menu " deps_debian_common+="menu-xdg xdg-utils liblua5.1-0-dev dbus-x11 libexif-dev mesa-common-dev libudev-dev cython " deps_debian_common+="libxcb-shape0-dev python-dev libcanberra-dev libtuxcap-dev chipmunk-dev autopoint libpoppler-private-dev " deps_debian_common+="libxcb-keysyms1-dev x11proto-print-dev libxp-dev libxtst-dev libfribidi-dev libxss-dev libmount-dev " deps_debian_common+="libblkid-dev check libsndfile1-dev libgstreamer-plugins-base0.10-dev" ##TODO finish the lists local stable="libpam-dev libiptcdata-dev libcurl4-gnutls-dev libsdl-dev " local sid="libpam0g-dev libiptcdata0-dev libcurl4-openssl-dev libsdl1.2-dev" ## use this for now local deps_debian_sid="$deps_debian_common $sid" local pkg_list="$(dpkg -l)" local missing="" echo -e "\n ### This check should work for Debian wheezy/sid and Ubuntu precise ###" echo -e "\ndependences:" echo_long "${deps_debian_sid}\n" write_name "checking packages" for dep in $deps_debian_sid; do if ! echo "$pkg_list" | grep -q -E "^ii\s*$dep" &>/dev/null ; then missing+="$dep " fi wait done if [[ $missing ]]; then echo -e "${fail}\n\nThe following packages are missing:\n${missing}\n" if (( $(id -u) == 0 )); then if [[ $(ask_yn "do you want to install the missing packages?") == "yes" ]]; then apt-get install $missing || exit 1 fi else ask_to_cont "Do you want to proceed with the installation ?" fi else echo -e "${ok} \n" fi } #}}} archlinux_check(){ local deps_arch="git autoconf automake binutils bison fakeroot flex gcc libtool m4 make patch pkg-config " deps_arch+="dbus fontconfig freetype2 libjpeg-turbo lua libpng libxml2 libx11 libxext libxrandr libxcb libxp" local missing="" echo -e "\n ### Checking Deps... ###" for dep in $deps_arch; do if ! pacman -Qs $dep | grep -q -E "^local/$dep " &>/dev/null ; then missing+="$dep " fi wait done if [[ $missing ]]; then echo -e "${fail}\n\nThe following packages are missing: \n${missing}\n" if (( $(id -u) == 0 )); then if [[ $(ask_yn "do you want to install the missing packages?") == "yes" ]]; then pacman -S $missing || exit 1 fi else ask_to_cont "Do you want to proceed with the installation ?" fi else echo -e "${ok} \n" fi } fedora_check(){ echo "the following packages should be installed:" echo echo "git subversion automake autoconf libtool libtool-ltdl libtool-ltdl-devel gcc" echo "libX11-devel libpng-devel libjpeg-devel giflib-devel libtiff-devel bzip2-devel" echo "libid3tag libid3tag-devel id3lib-devel id3lib fontconfig-devel libXext-devel2" echo "libXrender-devel libXcomposite-devel libXdamage-devel libXrandr-devel" echo "libXcursor-devel libXinerama-devel openssl-devel curl-devel pam-devel" echo "freetype-devel texinfo gettext-devel xine-lib-devel flex bison libxml2-devel" echo "libxslt-devel taglib-devel sqlite-devel giblib-devel libxkbfile-devel" echo "librsvg2-devel libmpd libmpd-devel gcc-c++ libogg-devel libtheora-devel" echo "dbus-devel cvs libudev-devel lua-devel libXp-devel pulseaudio-libs-devel " echo "libsndfile-devel libmount-devel bullet-devel xcb-util-keysyms-devel" echo } unsupported_dist_note(){ echo "there are currently no checks for you distribution / OS available" echo "please send me a patch or tell me which packages are required" echo "and how to check their presence" } #### distcheck functions }}} #### Helper functions {{{ inter_lists(){ #intersect list $1 and $2 local result="" for list1_item in $1; do for list2_item in $2; do if [[ "$list1_item" == "$list2_item" ]]; then result+="$list1_item " fi done done } # subtract 2nd list from first sub_lists(){ local result="" for list1_item in $1; do for list2_item in $2; do if ! [[ "$list1_item" == "$list2_item" ]]; then result+="$list1_item " fi done done } sort_as_full(){ #bring items in $@ in the same order as in $packages_full inter_lists "$packages_full" "$@" } ## OUTPUT write_bold(){ tput bold; echo "$@"; tput sgr0; } msg(){ ${conf[animate]} || echo "$@"; } #normal mode message - only when not animated verbose(){ ${conf[verbose]} && echo -e "$@";} #verbose message msg_ani(){ ${conf[animate]} && echo "$@"; } #animation mode message # print scetion banner section(){ local fill_symbol="-" local title="$@" local width=80 local fill=$(( width-${#title} )) local rest=$(( fill % 2 )) fill=$(( fill / 2)) #printf "$fill_symbol%.0s" {1..$(( fill + rem ))} - fuck no for (( n=1 ; n <= fill ; n++ )); do echo -n "$fill_symbol" ; done tput bold echo -n "$title" tput sgr0 for (( n=1 ; n <= (fill+rest) ; n++ )); do echo -n "$fill_symbol" ; done echo } ## print configuration copy_cfg(){ unset g_old_conf declare -g -A g_old_conf for key in "${!conf[@]}"; do g_old_conf["$key"]="${conf["$key"]}" done } print_cfg(){ local changed=false local changes="$( for item in "${!conf[@]}"; do if [[ "${conf["$item"]}" != "${g_old_conf["$item"]}" ]]; then echo "$item=${conf["$item"]}" changed=true fi done)" if [[ "$changes" ]]; then echo "The following Configuration items changed:" echo "$changes" else echo "The configuration did not Change!" fi } echo_padd(){ local len="$1" local padd="$2" local args= shift 2 ## get aditional arguments while : ; do if [[ $1 == @(-n|-e|-ne) ]]; then args+=$1 shift else break fi done msg="$@ " #fill with padd while (( ${#msg} < len-1 )); do msg+="$padd" done msg+=" " #print echo $args "$msg" } echo_long(){ # breaks a long line in single lines that fit width # if the first argument is -f the second is inseted # in the beginning of the lines local fill="" if [[ "$1" == "-f" ]]; then fill="$2" shift 2 fi # break output at width local line_out="$fill" local width=75 for item in $@; do if (( (${#line_out} + ${#item}) > width )); then echo -ne "${line_out}\n" line_out="${fill}" else line_out+="$item " fi done echo -ne "${line_out}\n" } print_array(){ #call: print_array array[@] declare -a array=("${!1}") for item in "${array[@]}"; do echo "$item" done } ## ERROR err(){ echo; echo -n "$error "; echo "$@"; } #fatal error ferr(){ err "$@"; exit 1; } #non fatal error nerr(){ debug 1 "$FUNCNAME() $*" [[ ${conf[on_error]} == "skip" ]] && return g_current_failed=true err "$@" case ${conf[on_error]} in exit) exit 1 ;; ask) local rv="$(ask_yn "The Program encountered an error - do you want to continue?")"; [[ "$rv" == "no" ]] && exit 1 ;; esac } # ask to continue on error ask_yn(){ while true; do read -p "$@ (y/n) " yn case "$yn" in [Yy]*) echo "yes"; break ;; [Nn]*) echo "no" ; break ;; *) echo "Please answer with yes or no." 1>&2 ;; esac done } ask_to_cont(){ [[ $(ask_yn "$1") == "yes" ]] || exit 1 } pkg_err(){ debug 1 "$FUNCNAME() $*" [[ ${conf[on_error]} == "skip" ]] && return g_current_failed=true local pkg="$1" shift err "The installation of package $pkg failed!" case ${conf[on_error]} in exit) # # ADD PGK TO FAILED pkg_failed "$pkg" exit ;; ask) while true; do read -p " Do you want to continue, retry or quit? (${bold}Y${boldoff}es/${bold}R${boldoff}etry/${bold}Q${boldoff}uit) " yrq case "$yrq" in [Rr]*) declare -g g_retry=true break 1 ;; [Yy]*) break ;; [Qq]*) # # ADD PKG TO FAILED pkg_failed "$pkg" exit 1 ;; *) echo "Please answer with yes, no, retry." 1>&2 ;; esac done echo ;; *) ;; esac } cmd_error(){ #section "" err -e "No vaild command! See --help for usage.\n" echo -e " Or try: ./git_e17 --git-e17-path ~/path/to/work-dir build\n" exit 1 } ## helper debuging debug(){ # # This function displays debug information # when the debug level set via command line # is greater or equal the level passed to # the function # # In: # $1 - level # $2 - message # ${conf[debug]} || return local action="" local level="$1" shift if [[ "$1" == @(ask|sleep) ]]; then action="$1" shift fi msg="$@" if (( level <= ${conf[debug_level]} )); then while read -r debug_line <&13; do printf '%q\n' "debug $level: $debug_line" 1>&2 done 13<<< "$msg" fi [[ "$action" == "sleep" ]] && sleep 5 [[ "$action" == "ask" ]] && read -p "press key to continue" -n 1 } debug-x(){ ${conf[debug]} && set -x; } debug+x(){ ${conf[debug]} && set +x; } ## debug configuration debug_cfg(){ ${conf[debug]} || return echo debug 4 "current configuration:" for item in ${!conf[@]}; do debug 4 "$item=${conf["$item"]}" done echo } ### fancy output functions ### taken from easy e17.sh - the code ist mostly unrevised:( del_word(){ cnt=0 max=${#1} while (( cnt < max )); do echo -n -e "\b \b" (( cnt++ )) done } ## TODO - rewrite rotate () { local pid=$1 local name="$2" local log_file=$3 local animation_state=1 local log_line="" echo -n "$name" echo -n " " while [[ "$(ps -p $pid -o comm=)" ]]; do [[ $log_file == "no_file" ]] || last_line=$(tail -1 "$log_file") if [[ $log_file == "no_file" ]] || [[ "$log_line" != "$last_line" ]]; then echo -e -n "\b\b\b\b\b" case $animation_state in 1) echo -n "[" echo -n -e "\033[1m" echo -n "\\o\\" echo -n -e "\033[0m" echo -n "]" animation_state=2 ;; 2) echo -n "[" echo -n -e "\033[1m|o|\033[0m" echo -n "]" animation_state=3 ;; 3) echo -n "[" echo -n -e "\033[1m/o/\033[0m" echo -n "]" animation_state=4 ;; 4) echo -n "[" echo -n -e "\033[1m|o|\033[0m" echo -n "]" animation_state=5 ;; 5) echo -n "[" echo -n -e "\033[1m" echo -n "\\o/" echo -n -e "\033[0m" echo -n "]" animation_state=6 ;; 6) echo -n "[" echo -n -e "\033[1m|o|\033[0m" echo -n "]" animation_state=1 ;; esac log_line=$last_line fi sleep 1 done del_word "$name[|-|]" } write_name(){ echo_padd 28 . -n "$@" } ### END HELPER FUNCTIONS }}} list(){ #{{{ debug 1 "$FUNCNAME() $*" [[ ${conf[action]} == list ]] || return section " list of available enlightenment packages " echo echo "not implemented" echo exit 0 } #}}} plugin(){ #{{{ debug 1 "$FUNCNAME() $*" # # plugins will be called form here # get_git_e17_path_from_global_cfg read_local_cfg read_global_cfg assign_defaults interpret_action check_cfg distcheck set_env section " installing plugins " # TODO add to config pushd ${PWD} &>/dev/null cd "${conf[src_path]}" || ferr "unable to cahnge to build path" g_current_commit="$(git log -1 --format="%H")" || ferr "unable to get current commit" popd &>/dev/null local plugin_path="${BASH_SOURCE%/*}" echo "slected plugins: $packages" if [[ $packages == "all"* ]]; then cd "$plugin_path" || ferr "unable to cd into plugin path" local plugins="" for plugin in git_e17-plugin-*; do plugins+=${plugin#git_e17-plugin-} done else local plugins="$packages" fi #backup configuration local -A conf_backup for key in ${!conf[@]}; do conf_backup[$key]=${conf[$key]} done for plugin in $plugins; do section " installing $plugin plugin " #source plugin local plugin_path="$plugin_path/git_e17-plugin-$plugin" echo "sourcing: $plugin_path" . "$plugin_path" || ferr "failed to source: $plugin_path" #run plugin plugin_build $plugin #restore configuration for key in ${!conf_backup[@]}; do conf[$key]=${conf_backup[$key]} done done ## exit when finished ## do not delete the exit exit } #}}} default_global_cfg(){ #{{{ # # default content of ~/.git_e17 # printf '%b\n' \ "# git_e17 - global configuration file" \ "#" \ "# INFO:" \ "# - local configurations and command line options override this file" \ "# - lines starting with # are ignored" \ "# - make sure your user has write access to all chosen paths" \ "# - you are able to set the path outside the git e17 path" \ "" \ "# item=val - NO SPACES - NO QUOTES" \ "" \ "# default git_e17_path" \ "# THIS IS THE PATH TO THE SCRIPTS WORKING DIR - PLEASE SET IT" \ "git_e17_path=${conf[git_e17_path]%/}" \ "# default config file" \ "config_file=default.conf" \ "" \ "# enable developer mode" \ "#dev=true" \ "# disable noob info" \ "#noob_info=false" } #}}} default_local_cfg(){ #{{{ printf '%b\n' \ "# git_e17 - local configuration file" \ "#" \ "# INFO:" \ "# - lines starting with # are ignored" \ "# - make sure your user has write access to all chosen paths" \ "# - you are able to set the paths outside the git e17 directory" \ "" \ "# item=val - NO SPACES - NO QUOTES" \ "" \ "# this is the target dir of your installation" \ "install_path=/opt/e17" \ "# git repoistory directory" \ "src_path=${conf[git_e17_path]}/e.org.git" \ "# dir in which the" \ "build_path=${conf[git_e17_path]}/build" \ "log_path=${conf[git_e17_path]}/log" \ "" \ "# enable developer mode" \ "#dev=true" \ "# disable noob info" \ "#noob_info=false" \ "# additional CFLAGS" \ "cflags=-g" \ "# additional LDFLAGS" \ "#ldflags=" \ "# clean " \ "#clean=false " \ "# packagelist to use basic, full" \ "packagelist=full" \ "# branch to checkout" \ "#branch=master" \ "# remote to pull from" \ "#remote=origin" \ "" \ "# on on compile error action: ask,exit,continue" \ "on_error=ask" \ "# number ot threads" \ "threads=8" \ "#niceness level" \ "nice=19" \ "#create documentation" \ "doc=false" \ "" \ "## extra configure flags" \ "evas_conf_args=--enable-gl-x11" } #}}} noob_info(){ #{{{ ${conf[noob_info]} || return #test if e was installed install_e=false for pkg in $packages; do if [[ $pkg == e ]]; then install_e=true fi done $install_e || { echo; exit 0; } section " info " for pkg in $packages_failed; do if [[ $pkg == e ]]; then echo "Enlightenment failed to install or update :(" echo "Please check your logs at: ${conf[log_path]}" exit 1 fi done printf '%b\n' \ "Your installation of Enlightenment is successful! " \ "" \ "You can rebuild failed packages with ${bold}./git_e17 build only names of failed. ${norm}" \ "To update you installation use ${bold}./git_e17 update${norm}" \ "You ${red}need${norm} to add the following lines to your ${green}~/.profile${norm} or shells profile file:" \ "$green" \ " # Make e17 bins like enlightenment_start available from any location" \ " export PATH=\"${conf[install_path]}/bin:\$PATH\"" \ "" \ " # Add new python2 libs to PYTHONPATH" \ " export PYTHONPATH=\"${conf[install_path]}/$($pythoncmd -c "import distutils.sysconfig; print distutils.sysconfig.get_python_lib(prefix='$install_path')" 2>/dev/null):\$PYTHONPATH\"" \ "" \ " # Add e17 libs to your users linker search path " \ " # Doing it like this is considered harmful by some people and most programs" \ " # are compiled with RPATH anyway - Read on LD_LIBRARY_PATH!!!" \ " #export LD_LIBRARY_PATH=\"${conf[install_path]}/bin:\$LD_LIBRARY_PATH\"" \ "$norm" \ "In order to use enlightenment with ${bold}gdm, kdm, xdm ... ${norm} as root you ${red}need${norm} to:" \ "${green}ln -s ${conf[install_path]}/share/xessions/enlightenment.desktop /usr/share/xsessions/$norm" \ "If it does not work ask for an ${red}equivalent${norm} of ${red}/usr/share/xessions${norm}" \ "at ${green}your distribution's$norm website or (freenode) IRC channel." } #}}} ### program starts here # make sure main program ist not run as root as it cause serious damage # i like to be sloppy - if you override this don't blame me:P if (( $(id -u) == 0 )); then ferr "${red}You should not run scripts as root!${norm}" fi main "$@"