├── .gitignore ├── doc ├── README ├── AUTHORS └── FAQ ├── share ├── icons │ └── hicolor │ │ ├── 16x16 │ │ └── mimetypes │ │ │ ├── application-x-gobo-recipe.png │ │ │ └── text-x-gobo-recipe-source.png │ │ ├── 22x22 │ │ └── mimetypes │ │ │ ├── application-x-gobo-recipe.png │ │ │ └── text-x-gobo-recipe-source.png │ │ ├── 32x32 │ │ └── mimetypes │ │ │ ├── application-x-gobo-recipe.png │ │ │ └── text-x-gobo-recipe-source.png │ │ ├── 48x48 │ │ └── mimetypes │ │ │ ├── application-x-gobo-recipe.png │ │ │ └── text-x-gobo-recipe-source.png │ │ └── 64x64 │ │ └── mimetypes │ │ ├── application-x-gobo-recipe.png │ │ └── text-x-gobo-recipe-source.png ├── applications │ ├── Compile.desktop │ └── MakeRecipe.desktop ├── mime-info │ └── Compile.keys ├── mime │ └── packages │ │ └── Compile.xml └── mimelnk │ ├── text │ └── x-gobo-recipe-source.desktop │ └── application │ └── x-gobo-recipe.desktop ├── Functions ├── BuildType_meta ├── BuildType_makefile ├── BuildType_manifest ├── BuildType_xmkmf ├── BuildType_scons ├── BuildType_cmake ├── BuildType_meson ├── BuildType_waf ├── BuildType_cabal ├── BuildType_configure ├── UnionFS ├── BuildType_python ├── RecipeTools └── Compile ├── lib └── ruby │ └── site_ruby │ └── 1.8 │ ├── gobo │ ├── template.rb │ ├── commandapplication.rb │ ├── logconsole.rb │ └── parseconfig.rb │ └── gobo.rb ├── bin ├── ColorMake ├── GoboPath2Ruby ├── NoRecipe ├── GetRecipe ├── EditRecipe ├── ApplyVariables ├── UpdateRecipes ├── AutoPatch ├── PrepareProgram ├── FetchArchive ├── UnionSandbox ├── NewVersion ├── SandboxInstall ├── ContributeRecipe ├── MakeRecipe └── RecipeLint ├── Resources ├── Defaults │ └── Settings │ │ └── Compile │ │ └── Compile.conf └── Dependencies ├── Makefile └── examples ├── GoboSimpleExample.rb └── GoboBigExample.rb /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *~ 3 | Resources/MetaData 4 | share/man/ 5 | -------------------------------------------------------------------------------- /doc/README: -------------------------------------------------------------------------------- 1 | 2 | For documentation on supported options in recipes, see 3 | http://gobo.kundor.org/wiki/Recipe_format_specification 4 | 5 | -------------------------------------------------------------------------------- /share/icons/hicolor/16x16/mimetypes/application-x-gobo-recipe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gobolinux/Compile/HEAD/share/icons/hicolor/16x16/mimetypes/application-x-gobo-recipe.png -------------------------------------------------------------------------------- /share/icons/hicolor/16x16/mimetypes/text-x-gobo-recipe-source.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gobolinux/Compile/HEAD/share/icons/hicolor/16x16/mimetypes/text-x-gobo-recipe-source.png -------------------------------------------------------------------------------- /share/icons/hicolor/22x22/mimetypes/application-x-gobo-recipe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gobolinux/Compile/HEAD/share/icons/hicolor/22x22/mimetypes/application-x-gobo-recipe.png -------------------------------------------------------------------------------- /share/icons/hicolor/22x22/mimetypes/text-x-gobo-recipe-source.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gobolinux/Compile/HEAD/share/icons/hicolor/22x22/mimetypes/text-x-gobo-recipe-source.png -------------------------------------------------------------------------------- /share/icons/hicolor/32x32/mimetypes/application-x-gobo-recipe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gobolinux/Compile/HEAD/share/icons/hicolor/32x32/mimetypes/application-x-gobo-recipe.png -------------------------------------------------------------------------------- /share/icons/hicolor/32x32/mimetypes/text-x-gobo-recipe-source.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gobolinux/Compile/HEAD/share/icons/hicolor/32x32/mimetypes/text-x-gobo-recipe-source.png -------------------------------------------------------------------------------- /share/icons/hicolor/48x48/mimetypes/application-x-gobo-recipe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gobolinux/Compile/HEAD/share/icons/hicolor/48x48/mimetypes/application-x-gobo-recipe.png -------------------------------------------------------------------------------- /share/icons/hicolor/48x48/mimetypes/text-x-gobo-recipe-source.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gobolinux/Compile/HEAD/share/icons/hicolor/48x48/mimetypes/text-x-gobo-recipe-source.png -------------------------------------------------------------------------------- /share/icons/hicolor/64x64/mimetypes/application-x-gobo-recipe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gobolinux/Compile/HEAD/share/icons/hicolor/64x64/mimetypes/application-x-gobo-recipe.png -------------------------------------------------------------------------------- /share/icons/hicolor/64x64/mimetypes/text-x-gobo-recipe-source.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gobolinux/Compile/HEAD/share/icons/hicolor/64x64/mimetypes/text-x-gobo-recipe-source.png -------------------------------------------------------------------------------- /Functions/BuildType_meta: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | meta_do_install() { 4 | # All installation is performed by the recipes declared 5 | # in the include=() array. We just have to return success 6 | # to keep the caller happy. 7 | true 8 | } 9 | -------------------------------------------------------------------------------- /share/applications/Compile.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Encoding=UTF-8 3 | Version=1.0 4 | Name=Compile 5 | GenericName=Compilation tool 6 | Type=Application 7 | Comment=GoboLinux compilation tool 8 | Exec=Compile 9 | ShowOnlyIn= 10 | Terminal=true 11 | NoDisplay=true 12 | MultipleArgs=false 13 | InitialPreference=5 14 | MimeType=application/x-gobo-recipe; 15 | -------------------------------------------------------------------------------- /share/mime-info/Compile.keys: -------------------------------------------------------------------------------- 1 | application/x-gobo-recipe 2 | category=Archive 3 | description=GoboLinux recipe 4 | icon_filename=application-x-gobo-recipe 5 | open=Compile %f 6 | short_list_application_ids_for_novice_user_level=Compile 7 | short_list_application_ids_for_intermediate_user_level=Compile 8 | short_list_application_ids_for_advanced_user_level=Compile -------------------------------------------------------------------------------- /lib/ruby/site_ruby/1.8/gobo/template.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby (require) 2 | 3 | # GoboLinux template for creating Ruby classes/libraries 4 | 5 | class GoboFoo 6 | public # Public attributes 7 | private # Private instance/class variables 8 | public # Public methods 9 | def initialize() 10 | end 11 | protected # Protected methods 12 | private # Private methods 13 | end 14 | 15 | -------------------------------------------------------------------------------- /share/applications/MakeRecipe.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Encoding=UTF-8 3 | Version=1.0 4 | Name=MakeRecipe 5 | GenericName=Recipe creation tool 6 | Type=Application 7 | Comment=Tool to create a GoboLinux recipe 8 | Exec=MakeRecipe 9 | ShowOnlyIn= 10 | Terminal=true 11 | NoDisplay=true 12 | MultipleArgs=false 13 | InitialPreference=15 14 | MimeType=application/x-bzip2-compressed-tar;application/x-bzip;application/x-bzip-compressed-tar;application/x-gzip;application/x-tbz;application/x-bzip2;application/x-compressed-tar;application/x-tar;application/x-gzip; 15 | -------------------------------------------------------------------------------- /bin/ColorMake: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . ScriptFunctions 4 | Import File 5 | Import GoboLinux 6 | 7 | makecmd="$(which make)" 8 | 9 | for i in "$@" 10 | do 11 | if [ "$i" = "menuconfig" ] 12 | then exec $makecmd "$@" 13 | fi 14 | done 15 | 16 | if Quiet which mtail; then 17 | $makecmd "$@" 2>&1 | mtail --config="`Find_Conf ColorMake.mtailrc`" -q 18 | exit ${PIPESTATUS[0]} 19 | elif Quiet which ccze; then 20 | $makecmd "$@" 2>&1 | ccze --raw-ansi 21 | else 22 | Log_Terse "mtail not found. Unable to colorize output." 23 | $makecmd "$@" 24 | fi 25 | -------------------------------------------------------------------------------- /Functions/BuildType_makefile: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | makefile_do_configuration() { 4 | Add_Use_Flags_Options_To_Array buildmerged 5 | } 6 | 7 | makefile_do_build() { 8 | $make $build_target ${buildmerged:+"${buildmerged[@]}"} -f $makefile || wrap_fail "Build process failed." 9 | } 10 | 11 | makefile_do_install() { 12 | SandboxInstall $verbose ${unmanagedlist:+--unmanaged-files "${unmanagedlist}"} ${sandboxopts:+"${sandboxopts[@]}"} --make "$make" --makefile $makefile --target "$install_target" "$1" "$2" -- "${installmerged[@]}" || wrap_fail "Installation step failed." 13 | } 14 | -------------------------------------------------------------------------------- /Resources/Defaults/Settings/Compile/Compile.conf: -------------------------------------------------------------------------------- 1 | 2 | # Add your name here so that credit is added to recipes. 3 | #compileRecipeAuthor="" 4 | 5 | compileDir="${goboPrefix}/Data/Compile" 6 | compileArchivesDir="$compileDir/Archives" 7 | compileSourcesDir="$compileDir/Sources" 8 | compileRecipesDir="$compileDir/Recipes" 9 | 10 | # Main free software repositories 11 | ftpGnu=ftp://ftp.gnu.org/gnu 12 | ftpAlphaGnu=ftp://alpha.gnu.org/gnu 13 | httpSourceforge=https://downloads.sourceforge.net 14 | 15 | compileRecipesRepository=https://github.com/gobolinux/Recipes.git 16 | compileUpstreamBranch=master 17 | -------------------------------------------------------------------------------- /share/mime/packages/Compile.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | GoboLinux recipe 6 | 7 | 8 | 9 | 10 | GoboLinux recipe source file 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /bin/GoboPath2Ruby: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . GoboPath 4 | 5 | echo "Users = \"${goboUsers}\"" 6 | echo "Mount = \"${goboMount}\"" 7 | echo "Programs = \"${goboPrograms}\"" 8 | echo "System = \"${goboSystem}\"" 9 | echo "Links = \"${goboLinks}\"" 10 | echo "Scripts = \"${goboScripts}\"" 11 | echo "Variable = \"${goboVariable}\"" 12 | echo "Settings = \"${goboSettings}\"" 13 | echo "Executables = \"${goboExecutables}\"" 14 | echo "Libraries = \"${goboLibraries}\"" 15 | echo "Headers = \"${goboHeaders}\"" 16 | echo "Manuals = \"${goboManuals}\"" 17 | echo "Shared = \"${goboShared}\"" 18 | echo "Boot = \"${goboBoot}\"" 19 | echo "Temp = \"${goboTemp}\"" 20 | echo "Devices = \"${goboDevices}\"" 21 | echo "Status = \"${goboStatus}\"" 22 | echo "Environment = \"${goboEnvironment}\"" 23 | echo "UserSettings = \"${goboUserSettings}\"" 24 | 25 | -------------------------------------------------------------------------------- /Functions/BuildType_manifest: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | manifest_do_install() { 4 | for i in "${manifest[@]}" 5 | do 6 | src=`echo $i | cut -d: -f1` 7 | dst=`echo $i | cut -d: -f2-` 8 | if [ $(basename $(pwd)) != $(basename "${dir}") ] 9 | then 10 | fullsrc="${dir}/${src}" 11 | else 12 | fullsrc="${src}" 13 | fi 14 | fulldst="${installprefix}/${dst}" 15 | mkdir -p $(dirname "$fulldst") 16 | if Ends_With "/" "$fulldst" 17 | then 18 | mkdir -p "$fulldst" 19 | fi 20 | Log_Normal "Installing ${fullsrc} into ${fulldst}" 21 | if [ -d "${fullsrc}" -a -d "${fulldst}" ] 22 | then cp -Rv --no-preserve=ownership "${fullsrc}"/* "${fulldst}" 23 | else cp -Rv --no-preserve=ownership ${fullsrc} "${fulldst}" 24 | fi 25 | done 26 | } 27 | -------------------------------------------------------------------------------- /bin/NoRecipe: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | . ScriptFunctions 3 | Import GoboLinux 4 | Import RecipeTools 5 | 6 | Parse_Conf Compile.conf 7 | cat <= 3.0.0 # Meson build type 22 | Scripts > 2.9.8 23 | Sed 24 | Sudo 25 | Wget # used by FetchArchive script 26 | PIP3:meson # used by BuildType_meson 27 | PIP3:ninja # used by BuildType_cmake|meson 28 | -------------------------------------------------------------------------------- /Functions/BuildType_xmkmf: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | Import BuildType_makefile 4 | 5 | xmkmf_do_configuration() { 6 | xmkmf 7 | buildmerged=( 8 | "BINDIR=$target/bin" 9 | "LIBDIR=$target/lib" 10 | "LIBEXECDIR=$target/libexec" 11 | "INCDIR=$target/include" 12 | "IRULESRC=$goboLibraries/X11/config" 13 | "${buildmerged[@]}" 14 | ) 15 | installmerged=( 16 | "BINDIR=$installprefix/bin" 17 | "LIBDIR=$installprefix/lib" 18 | "LIBEXECDIR=$installprefix/libexec" 19 | "INCDIR=$installprefix/include" 20 | "IRULESRC=$goboLibraries/X11/config" 21 | "${installmerged[@]}" 22 | ) 23 | 24 | buildmerged=(`echo ${buildmerged[@]} | sed "s,$target,$goboIndex,g"`) 25 | installmerged=(`echo ${installmerged[@]} | sed "s,$target,$goboIndex,g"`) 26 | $make Makefiles "${buildmerged[@]}" 27 | } 28 | 29 | xmkmf_do_build() { 30 | makefile_do_build 31 | } 32 | 33 | xmkmf_do_install() { 34 | makefile_do_install "${1}" "${2}" 35 | } 36 | -------------------------------------------------------------------------------- /Functions/BuildType_scons: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | scons_sane_check() { 3 | Quiet scons --version || Die "This is a scons type recipe and you don't seem to have scons installed." 4 | } 5 | 6 | scons_init() { 7 | create_dirs_first="yes" 8 | scons="scons" 9 | } 10 | 11 | scons_do_build() { 12 | if [ ! "$override_default_options" = "yes" ] 13 | then 14 | scons_variables=( 15 | "${scons_variables[@]}" 16 | "PREFIX=$target" 17 | "prefix=$target" 18 | ) 19 | fi 20 | Add_Use_Flags_Options_To_Array scons_variables 21 | 22 | scons_variables=(`echo ${scons_variables[@]} | sed "s,$target,$goboIndex,g"`) 23 | $scons "${scons_variables[@]}" "${build_variables[@]}" $build_target || wrap_fail "Build failed." 24 | } 25 | 26 | scons_do_install() { 27 | SandboxInstall $verbose ${unmanagedlist:+--unmanaged-files "${unmanagedlist}"} ${sandboxopts:+"${sandboxopts[@]}"} -c $scons "$appname" "$versionnumber" -- "${scons_variables[@]}" "${install_variables[@]}" $install_target || wrap_fail "Installation failed" 28 | } 29 | -------------------------------------------------------------------------------- /doc/AUTHORS: -------------------------------------------------------------------------------- 1 | 2 | Compile development is led by Hisham Muhammad. 3 | See the --version option for authors of specific scripts. 4 | 5 | These are the people who contributed recipe entries, 6 | and help make Compile what it is today: 7 | 8 | Hisham Muhammad 9 | Giusepe Casagrande 10 | Guilherme Bedin 11 | Carlo Calica 12 | Jonatan Liljedahl 13 | Andre Detsch 14 | Jason Stubbs 15 | Jeremy Vernon 16 | Felix Breuer 17 | Fabio Mierlo 18 | Leandro Motta Barros 19 | Bill Burdick 20 | Mika Pesu 21 | Michael Homer 22 | Dave Dodge 23 | Lucas Correia Villa Real 24 | Maglan C. Diemer 25 | Thomas Krawczyk 26 | Taeber Rapczak 27 | Volker Wieban 28 | Julio Biason 29 | Rafael G. Jeffman 30 | Gen Wangden 31 | Peter Eriksen 32 | 33 | See the Recipe files in the various recipes for the 34 | specific authors. 35 | 36 | If your name is missing from this list, please contact 37 | me and I'll add you right away. 38 | 39 | Thanks to all! 40 | 41 | -- Hisham Muhammad, 13 may 2004. 42 | -- Lucas Lucas Correia Villa Real, 16 august 2004. 43 | -------------------------------------------------------------------------------- /lib/ruby/site_ruby/1.8/gobo/commandapplication.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | 3 | gobo/commandapplication.rb - GoboLinux CommandApplication Ruby Module 4 | 5 | Mostly stubs 6 | 7 | =end 8 | require 'gobo' 9 | 10 | class GoboCommandApplication < GoboApplication 11 | public # Public attributes 12 | private # Private instance/class variables 13 | public # Public methods 14 | def initialize() 15 | super() 16 | @commands = GoboCallbacks.new 17 | @descriptions = Hash.new 18 | end 19 | 20 | def addCommand(cmdName, description, aProc = nil) 21 | aProc = proc {|args| 22 | yield *args 23 | } if aProc == nil 24 | @commands.addCallback(cmdName, aProc) 25 | @descriptions[cmdName] = cmdDescription 26 | end 27 | 28 | def run() 29 | super() 30 | command = ARGV.shift 31 | if @commands[command] 32 | @commands[command].call() 33 | else 34 | puts "#{command} not a valid command" 35 | end 36 | end 37 | private # Private methods 38 | end 39 | -------------------------------------------------------------------------------- /bin/GetRecipe: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ################################################## 4 | # Imports 5 | ################################################## 6 | 7 | . ScriptFunctions 8 | Import OptionParser 9 | Import File 10 | Import GoboLinux 11 | Import Compile 12 | Import RecipeTools 13 | 14 | ################################################## 15 | # Options and configuration 16 | ################################################## 17 | 18 | Parse_Conf Compile.conf 19 | 20 | helpOnNoArguments=yes 21 | scriptDescription="Fetch a recipe and insert it in the recipes tree." 22 | scriptCredits="(C) 2003-2004 Carlo Calica et al. Released under the GNU GPL." 23 | scriptUsage=" [program-version]" 24 | Add_Option_Boolean "W" "no-web" "fully offline operation." 25 | 26 | Parse_Options "$@" 27 | 28 | ################################################## 29 | # Prepare Environment 30 | ################################################## 31 | 32 | cd $compileRecipesDir 33 | 34 | # sets 'recipedir', 'program' and 'version' 35 | # fails if recipe is not found 36 | Set_Recipe_Program_And_Version_From_Args $(Boolean "no-web" && echo none) 37 | 38 | echo "$recipedir" 39 | exit 0 40 | -------------------------------------------------------------------------------- /Functions/BuildType_cmake: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | Import BuildType_makefile 3 | 4 | cmake_sane_check() { 5 | Quiet cmake --version || Die "This is a CMake type recipe and you don't seem to have CMake installed." 6 | } 7 | 8 | cmake_init() { 9 | needs_build_directory="yes" 10 | } 11 | 12 | cmake_do_configuration(){ 13 | eval $(Combine_Arrays config cmake_options userconfigureoptions) 14 | Add_Use_Flags_Options_To_Array config 15 | # cmake always use its own build directory 16 | for i in "${cmake_variables[@]}" 17 | do 18 | var=`echo $i | cut -d= -f 1` 19 | val=`echo $i | cut -d= -f 2-` 20 | eval export $var=\'$val\' 21 | done 22 | cmake \ 23 | -DCMAKE_VERBOSE_MAKEFILE=ON \ 24 | -DCMAKE_INSTALL_PREFIX="${target}" \ 25 | -DCMAKE_INSTALL_SYSCONFDIR="${settings_target}" \ 26 | -DCMAKE_INSTALL_LOCALSTATEDIR="${variable_target}" \ 27 | -DCMAKE_INSTALL_MANDIR="${target}/man" \ 28 | -DCMAKE_INSTALL_LIBEXECDIR="${target}/libexec" \ 29 | -DSYSCONFDIR="${settings_target}" \ 30 | ${config[@]} "${sourcedir}" 31 | } 32 | 33 | cmake_do_build() { 34 | makefile_do_build 35 | } 36 | 37 | cmake_do_install() { 38 | makefile_do_install "${1}" "${2}" 39 | } 40 | -------------------------------------------------------------------------------- /Functions/BuildType_meson: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | meson_sane_check() { 4 | Quiet meson --help || Die "This is a meson type recipe and you don't seem to have meson installed." 5 | Quiet ninja --version || Die "This is a meson type recipe and you don't seem to have ninja installed." 6 | } 7 | 8 | meson_init() { 9 | needs_build_directory="yes" 10 | meson="meson" 11 | ninja="ninja" 12 | } 13 | 14 | meson_do_build() { 15 | # Unless the recipe author overrides it, set "--prefix=/usr" 16 | if [[ ! "$meson_options" == --prefix=* ]] 17 | then 18 | meson_options=( 19 | "${meson_options[@]}" 20 | "--prefix=$goboIndex" 21 | ) 22 | fi 23 | Add_Use_Flags_Options_To_Array meson_variables 24 | Add_Use_Flags_Options_To_Array ninja_variables 25 | 26 | $meson setup "${sourcedir}" "${meson_options[@]}" "${build_variables[@]}" $build_target || wrap_fail "Build failed." 27 | $ninja || wrap_fail "Build failed." 28 | } 29 | 30 | meson_do_install() { 31 | SandboxInstall $verbose ${unmanagedlist:+--unmanaged-files "${unmanagedlist}"} ${sandboxopts:+"${sandboxopts[@]}"} -c "$ninja install" "$appname" "$versionnumber" -- "${ninja_variables[@]}" "${install_variables[@]}" $install_target || wrap_fail "Installation failed" 32 | } 33 | -------------------------------------------------------------------------------- /Functions/BuildType_waf: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | waf_init() { 3 | waf="./waf" 4 | build_target="build" 5 | } 6 | 7 | 8 | waf_do_configuration() { 9 | if [ ! "$override_default_options" = "yes" ] 10 | then 11 | eval $(Combine_Arrays wafconfig waf_options userconfigureoptions) 12 | wafconfig=(configure --prefix="$target" "${wafconfig[@]}") 13 | else 14 | wafconfig=("${waf_options[@]}") 15 | fi 16 | Add_Use_Flags_Options_To_Array wafconfig 17 | 18 | [ -f "$waf" ] && chmod +x "$waf" 2>/dev/null 19 | ( 20 | for i in "${waf_variables[@]}" 21 | do 22 | var=`echo $i | cut -d= -f 1` 23 | val=`echo $i | cut -d= -f 2-` 24 | eval export $var=\'$val\' 25 | done 26 | 27 | $waf "${wafconfig[@]}" || return 1 28 | ) || return 1 29 | } 30 | 31 | waf_do_build() { 32 | waf_variables=(`echo ${waf_variables[@]} | sed "s,$target,$goboIndex,g"`) 33 | $waf "${waf_variables[@]}" "${build_variables[@]}" $build_target || wrap_fail "Build failed." 34 | } 35 | 36 | waf_do_install() { 37 | SandboxInstall $verbose ${unmanagedlist:+--unmanaged-files "${unmanagedlist}"} ${sandboxopts:+"${sandboxopts[@]}"} -c "$waf" "$appname" "$versionnumber" -- "${waf_variables[@]}" "${install_variables[@]}" $install_target || wrap_fail "Installation failed" 38 | } 39 | -------------------------------------------------------------------------------- /bin/EditRecipe: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ################################################## 4 | # Imports 5 | ################################################## 6 | 7 | . ScriptFunctions 8 | Import OptionParser 9 | Import File 10 | Import GoboLinux 11 | Import Compile 12 | Import RecipeTools 13 | 14 | ################################################## 15 | # Options and configuration 16 | ################################################## 17 | 18 | Parse_Conf Compile.conf 19 | 20 | helpOnNoArguments=yes 21 | scriptDescription="Fetch a recipe and place it in $compileRecipesDir, chopping its revision number. 22 | Calls a text editor on the Recipe file afterwards." 23 | scriptCredits="(C) 2006 Andre Detsch. Released under the GNU GPL." 24 | scriptUsage="[|| [program-version]]" 25 | Add_Option_Boolean "E" "no-edit" "Do not edit Recipe file, just place the recipe in $compileRecipesDir." 26 | Parse_Options "$@" 27 | 28 | ################################################## 29 | # Prepare Environment 30 | ################################################## 31 | 32 | recipe=`GetRecipe $(Arg 1) $(Arg 2)` || Die "Error while getting recipe." 33 | 34 | Set_Recipe_Program_And_Version_From_Args 35 | 36 | if Boolean "no-edit" 37 | then 38 | echo $recipedir 39 | else 40 | [ "$EDITOR" ] || Die 'Please set your $EDITOR variable using `export EDITOR='...'`.' 41 | $EDITOR "$recipedir/Recipe" 42 | fi 43 | -------------------------------------------------------------------------------- /lib/ruby/site_ruby/1.8/gobo/logconsole.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby (require) 2 | 3 | # This is a mixin for logging purposes. Dependent on @logLevel 4 | module GoboLogConsole 5 | LogLevelError=10 6 | LogLevelTerse=20 7 | LogLevelNormal=30 8 | LogLevelVerbose=40 9 | LogLevelDebug=50 10 | 11 | attr_reader :logLevel 12 | 13 | def setLogLevel(level) 14 | @logLevel = level 15 | end 16 | 17 | def logFunction(stream, message, color = "") 18 | stream.puts message 19 | stream.flush 20 | end 21 | 22 | def ask(message) 23 | $stdout << message 24 | $stdout.flush 25 | return $stdin.readline.chomp 26 | end # End of ask 27 | 28 | def askContinue(message = nil) 29 | return if @logLevel < LogLevelNormal 30 | puts message if message 31 | response = ask("Press Enter to continue or Ctrl-C to cancel.") 32 | stop if response.downcase == "n" 33 | end # End of askContinue 34 | 35 | def logError(message = "") 36 | logFunction($stderr, message) if @logLevel >= LogLevelError 37 | end 38 | def logTerse(message = "") 39 | logFunction($stdout, message) if @logLevel >= LogLevelTerse 40 | end 41 | def logNormal(message = "") 42 | logFunction($stdout, message) if @logLevel >= LogLevelNormal 43 | end 44 | def logVerbose(message = "") 45 | logFunction($stdout, message) if @logLevel >= LogLevelVerbose 46 | end 47 | def logDebug(message = "") 48 | logFunction($stderr, message) if @logLevel >= LogLevelDebug 49 | end 50 | 51 | 52 | end # End of module GoboLogConsole 53 | -------------------------------------------------------------------------------- /bin/ApplyVariables: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ### Imports ################################################################### 4 | 5 | source ScriptFunctions 6 | Import OptionParser 7 | 8 | ### Options ################################################################### 9 | 10 | helpOnNoArguments=yes 11 | scriptNotes="$scriptName processes a file replacing instances of variables marked 12 | with special indicators ('@%', '%@' by default) with the contents of equivalent 13 | environment variables." 14 | Add_Option_Entry "o" "open" "Opening mark." "@%" 15 | Add_Option_Entry "c" "close" "Closing mark." "%@" 16 | Add_Option_Entry "i" "identifier" "Add a prefix identifier in the form of '_' to the opening markup." 17 | Parse_Options "$@" 18 | 19 | ### Operation ################################################################# 20 | 21 | open=`Entry "open"` 22 | close=`Entry "close"` 23 | if Is_Entry "identifier" 24 | then 25 | open="${open}`Entry identifier`_" 26 | fi 27 | 28 | cat "$(Arg 1)" | python3 -c ' 29 | import os,sys,string 30 | 31 | op=sys.argv[1] 32 | cl=sys.argv[2] 33 | for line in sys.stdin.readlines(): 34 | while 1: 35 | op_index=line.find(op) 36 | if op_index == -1: 37 | break 38 | cl_index=line.find(cl) 39 | if cl_index == -1: 40 | break 41 | var = line[op_index + len(op):cl_index] 42 | try: 43 | val = os.environ[var] 44 | except: 45 | val = "" 46 | line = line.replace(op + var + cl, val) 47 | print(line, end=" ") 48 | ' "$open" "$close" 49 | -------------------------------------------------------------------------------- /lib/ruby/site_ruby/1.8/gobo/parseconfig.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby (require) 2 | 3 | # This class reads and parses shell script config file 4 | # copied from Michael Homer's Freshen 5 | 6 | require 'shellwords' 7 | 8 | class GoboParseConfig < Hash 9 | public # Public attributes 10 | private # Private instance/class variables 11 | public # Public methods 12 | def initialize(filename, inheritfrom=nil) 13 | super(inheritfrom) 14 | # if inheritfrom 15 | # self = inheritfrom.vars 16 | # else 17 | # self = Hash.new 18 | # end 19 | inarray = false 20 | thisarray = "" #look, I know these are dirty blah blah 21 | file = File.open(filename) 22 | file.readlines.each { 23 | |line| 24 | line.strip! 25 | if !line.empty? and line.slice(0,1) != "#" 26 | words = Shellwords.shellwords(line) 27 | words[0].gsub!(/\$([a-zA-Z]+)/) {self[$1]} 28 | words[0].gsub!(/\$\{([a-zA-Z]+)\}/) {self[$1]} 29 | spl = words[0].split("=", 2) 30 | if spl[1] == "(" 31 | inarray = true 32 | self.store spl[0], Array.new 33 | thisarray = spl[0] 34 | elsif inarray 35 | if words[0] == ")" 36 | inarray = false 37 | else 38 | self[thisarray].push words[0] 39 | end 40 | else 41 | self.store(spl[0], spl[1]) 42 | end 43 | end 44 | } 45 | end # End of initialize() 46 | # def [] (x) 47 | # @vars[x] 48 | # end # End of [](x) 49 | # def member? (x) 50 | # @vars.member?(x) 51 | # end # End of member? 52 | protected # Protected methods 53 | private # Private methods 54 | end 55 | 56 | -------------------------------------------------------------------------------- /Functions/BuildType_cabal: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cabal_sane_check() { 3 | Quiet ghc -V || Die "This is a cabal recipe and you don't seem to have GHC installed." 4 | } 5 | 6 | cabal_init() { 7 | create_dirs_first="yes" 8 | post_install_message="Package registered via ghc-pkg; manual update required on package changes (InstallPackage, RemoveProgram, etc.)" 9 | [ "$runhaskell" ] || runhaskell="runhaskell" 10 | } 11 | 12 | cabal_do_configuration(){ 13 | if [ ! "$override_default_options" = "yes" ] 14 | then 15 | cabal_options=( 16 | "${cabal_options[@]}" 17 | "--prefix=$target" 18 | ) 19 | fi 20 | Add_Use_Flags_Options_To_Array cabal_options 21 | cabal_options=(`echo ${cabal_options[@]} | sed "s,$target,$goboIndex,g"`) 22 | 23 | for f in Setup.lhs Setup.hs ; do 24 | [ -e ${sourcedir}/${f} ] && cabal_setup="$f"; 25 | done 26 | [ ! -z "$cabal_setup" ] || Die "Cabal Setup.hs or Setup.lhs not found" 27 | 28 | $runhaskell "$cabal_setup" configure "${cabal_options[@]}" || wrap_fail "Configure failed" 29 | } 30 | 31 | cabal_do_build() { 32 | $runhaskell "$cabal_setup" build "${build_variables[@]}" || wrap_fail "Build failed." 33 | } 34 | 35 | cabal_do_install() { 36 | # The package db should really be moved outside of ghc installation and functions should be added to Scripts to udpate the db 37 | pkg_dbloc=$(dirname `ghc-pkg list | head -n 1 | cut -f1 -d:`) 38 | SandboxInstall $verbose ${unmanagedlist:+--unmanaged-files "${unmanagedlist}"} ${sandboxopts:+"${sandboxopts[@]}"} -a $pkg_dbloc -c $runhaskell "$appname" "$versionnumber" -- "$cabal_setup" install "${install_variables[@]}" || wrap_fail "Installation failed." 39 | } 40 | 41 | -------------------------------------------------------------------------------- /Functions/BuildType_configure: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | Import BuildType_makefile 4 | 5 | configure_init() { 6 | [ -n "${configure}" ] || configure="./configure" 7 | [ -n "${autogen}" ] || autogen="autogen.sh" 8 | } 9 | 10 | configure_do_configuration() { 11 | eval $(Combine_Arrays config configure_options userconfigureoptions) 12 | Add_Use_Flags_Options_To_Array config 13 | [ "$needs_build_directory" = "yes" ] && configure="${sourcedir}/$configure" 14 | 15 | [ -f "$configure" ] && chmod +x "$configure" 2>/dev/null 16 | ( 17 | for i in "${configure_variables[@]}" 18 | do 19 | var=`echo $i | cut -d= -f 1` 20 | val=`echo $i | cut -d= -f 2-` 21 | eval export $var=\'$val\' 22 | done 23 | 24 | [ -e "./$autogen" ] && autogen="./$autogen" && chmod +x $autogen 25 | [ "$autogen_before_configure" = "yes" ] && yes "" | $autogen 26 | prepareoptions=( 27 | --verbose 28 | --configure $configure 29 | `[ "$override_default_options" = "yes" ] && echo "--no-default-options"` 30 | `[ "$build_in_programs" = "yes" ] && echo "--programs"` 31 | ) 32 | PrepareProgram $batch $keep ${prepareoptions[*]} "$appname" "$versionnumber" ${config:+"--" "${config[@]}"} || return 1 33 | ) || return 1 34 | } 35 | 36 | configure_do_build() { 37 | # Configure generates libtool with hardcoded linking behaviour, but we are using our own libtool. 38 | # If option --disable-static is present pass it explicitly: 39 | if Array_Contains config "--disable-static"; then 40 | export LIBTOOLFLAGS="--tag=disable-static" 41 | Log_Debug "Recognized configure option --disable-static, setting LIBTOOLFLAGS=--tag=disable-static" 42 | fi 43 | makefile_do_build 44 | } 45 | 46 | configure_do_install() { 47 | makefile_do_install "${1}" "${2}" 48 | } 49 | -------------------------------------------------------------------------------- /bin/UpdateRecipes: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ################################################## 4 | # Imports 5 | ################################################## 6 | 7 | . ScriptFunctions 8 | Import OptionParser 9 | Import File 10 | Import GoboLinux 11 | Import Compile 12 | 13 | ################################################## 14 | # Options and configuration 15 | ################################################## 16 | 17 | Parse_Conf Compile.conf 18 | 19 | scriptDescription="Update local recipe list from recipe stores." 20 | scriptCredits="(C) 2003-2004 Carlo Calica et al. Released under the GNU GPL." 21 | scriptUsage="[]" 22 | scriptNotes="When updating a single program, $scriptName will download "\ 23 | "all its available recipes. When no program is specified, $scriptName will "\ 24 | "fetch the recipe list and populate $compileRecipesDir with directory "\ 25 | "entries (and download the recipes only if --all is used)." 26 | Add_Option_Boolean "a" "all" "Download contents of updated recipes. "\ 27 | "By default, $scriptName will only fetch the recipe list and generate "\ 28 | "empty recipe directories (except when updating a single program)." 29 | Add_Option_Boolean "l" "all-latest" "Like --all, but only fetch the latest "\ 30 | "versions of each recipe." 31 | Add_Option_Boolean "t" "thorough" "Check all availabe mirrors for updates. "\ 32 | "By default, only the first working mirror (as configured in Compile.conf) is used." 33 | Parse_Options "$@" 34 | 35 | if Is_Writable "$compileRecipesDir" 36 | then sudo= 37 | else sudo="sudo -u #0" 38 | fi 39 | 40 | ################################################## 41 | # Prepare Environment 42 | ################################################## 43 | 44 | Check_Dir_Variable compileRecipesDir 45 | Check_Dir_Variable compileRecipesRepository 46 | 47 | if [ ! -d "${compileRecipesDir}/.git" ] 48 | then 49 | Log_Normal "Initializing recipes repository" 50 | git clone "${compileRecipesRepository}" "${compileRecipesDir}" 51 | else 52 | cd $compileRecipesDir 53 | git pull 54 | fi 55 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PROGRAM = Compile 2 | VERSION = git-$(shell date +%Y%m%d) 3 | goboPrograms ?= /Programs 4 | PREFIX ?= 5 | DESTDIR = $(PREFIX)/$(goboPrograms)/$(PROGRAM)/$(VERSION) 6 | INSTALL_DIR = install -d 7 | INSTALL_FILE = install 8 | man_files = $(shell grep -l Parse_Options bin/* | xargs -i echo {}.1) 9 | scripts = ApplyVariables Compile FetchArchive GoboPath2Ruby NewVersion PrepareProgram AutoPatch ContributeRecipe NoRecipe RecipeLint UnionSandbox ColorMake EditRecipe GetRecipe MakeRecipe SandboxInstall UpdateRecipes 10 | 11 | .PHONY: all clean install uninstall 12 | 13 | default: all 14 | 15 | manuals: $(man_files) 16 | 17 | $(man_files): %.1: % 18 | @echo "Generating man page $@" 19 | help2man --name=" " --source="GoboLinux" --no-info $< --output $@ 20 | 21 | clean_manuals: 22 | @echo "Cleaning man pages" 23 | echo $(man_files) | tr '\n' ' ' | xargs -d ' ' -n 1 rm -f 24 | 25 | clean_resources: 26 | rm -rf Resources/FileHash* 27 | 28 | clean: clean_manuals clean_resources 29 | 30 | install_manuals: manuals 31 | @$(INSTALL_DIR) -d -m 755 $(DESTDIR)/share/man/man1 32 | echo $(man_files) | tr '\n' ' ' | xargs -d ' ' -n 1 -i \ 33 | $(INSTALL_FILE) -m 644 {} $(DESTDIR)/share/man/man1 34 | 35 | install_scripts: 36 | @echo "Installing scripts" 37 | $(INSTALL_DIR) -d -m 755 $(DESTDIR)/bin 38 | echo $(scripts) | tr '\n' ' ' | xargs -d ' ' -n 1 -i \ 39 | $(INSTALL_FILE) -m 755 bin/{} $(DESTDIR)/bin 40 | 41 | install_lib: 42 | @echo "Installing lib" 43 | $(INSTALL_DIR) -d -m 755 $(DESTDIR) 44 | cp -r lib $(DESTDIR) 45 | 46 | install_resources: 47 | @echo "Installing Resources" 48 | cp -r Resources $(DESTDIR) 49 | 50 | install_share_data: 51 | @echo "Installing share data" 52 | cp -rf share $(DESTDIR) 53 | 54 | install_functions: 55 | @echo "Installing Functions" 56 | cp -rf Functions $(DESTDIR) 57 | 58 | install_docs: 59 | @echo "Installing docs" 60 | cp -rf doc $(DESTDIR) 61 | cp -rf examples $(DESTDIR)/doc 62 | 63 | prepare_install: 64 | @echo "Installing $(PROGRAM) into $(DESTDIR)" 65 | $(INSTALL_DIR) -d -m 755 $(DESTDIR) 66 | 67 | install: install_scripts install_manuals prepare_install install_lib install_resources install_share_data install_functions 68 | @echo "Installed $(PROGRAM) into $(DESTDIR)" 69 | -------------------------------------------------------------------------------- /Functions/UnionFS: -------------------------------------------------------------------------------- 1 | #!/bin/bash (source) 2 | 3 | # unionImplementation is defined in Scripts/Directories.conf 4 | 5 | function Union_Backend() { 6 | local union= 7 | for union in "${unionImplementations[@]}" 8 | do 9 | case "$union" in 10 | "funionfs") GetSupportedFilesystems | grep -q "fuse" && funionfs -V &> /dev/null ;; 11 | "overlayfs") GetSupportedFilesystems | grep -q "overlay" ;; 12 | "unionfs") GetSupportedFilesystems | grep -q "unionfs" ;; 13 | "unionfs-fuse") GetSupportedFilesystems | grep -q "fuse" && unionfs -V &> /dev/null ;; 14 | esac 15 | [ $? = 0 ] && echo "$union" && break 16 | done 17 | } 18 | 19 | function Union_Is_Supported() { 20 | local union=`Union_Backend` 21 | [ "$union" ] && return 0 || return 1 22 | } 23 | 24 | function Union_Mount() { 25 | local union="$1" 26 | local rw_ro=`echo $2 | sed 's/\(.*\)=rw:\(.*\)=ro:\(.*\)=tmp/\1=rw:\2=ro/g'` 27 | case "$union" in 28 | "funionfs") funionfs -o dirs="$rw_ro" -o nonempty none "$3" ;; 29 | "overlayfs") 30 | upper=`echo $2 | sed 's/\(.*\)=rw:\(.*\)=ro:\(.*\)=tmp/\1/g'` 31 | lower=`echo $2 | sed 's/\(.*\)=rw:\(.*\)=ro:\(.*\)=tmp/\2/g'` 32 | work=`echo $2 | sed 's/\(.*\)=rw:\(.*\)=ro:\(.*\)=tmp/\3/g'` 33 | mount -t overlay none -o "lowerdir=$lower,upperdir=$upper,workdir=$work" "$3" ;; 34 | "unionfs") mount -t unionfs -o dirs="$rw_ro" none "$3" ;; 35 | "unionfs-fuse") 36 | dirs=`echo "$rw_ro" | sed 's/=[^:]*//g'` 37 | unionfs -o cow -o nonempty "$rw_ro" "$3";; 38 | esac 39 | } 40 | 41 | function Union_Add() { 42 | local union="$1" 43 | case "$union" in 44 | "funionfs") false ;; 45 | "overlayfs") false ;; 46 | "unionfs") mount -t unionfs -o remount,add=:"$2" none "$3" ;; 47 | "unionfs-fuse") false ;; 48 | esac 49 | } 50 | 51 | function Union_Umount() { 52 | local mp= 53 | local union="$1" 54 | shift 55 | case "$union" in 56 | "funionfs") for mp in $@; do fusermount -u "$mp"; done ;; 57 | "overlayfs") for mp in $@; do umount "$mp"; done ;; 58 | "unionfs") for mp in $@; do umount "$mp"; done ;; 59 | "unionfs-fuse") for mp in $@; do fusermount -u "$mp"; done ;; 60 | esac 61 | } 62 | -------------------------------------------------------------------------------- /Functions/BuildType_python: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | python_sane_check() { 3 | Quiet python${python_major} -V || wrap_fail "This is a python type recipe and you don't seem to have python installed." 4 | } 5 | 6 | # Can be overridden by the recipe 7 | python_major=${python_major:-} 8 | 9 | set_python_vars() { 10 | python=python${python_major} 11 | pythonversion=$($python -V 2>&1 | sed 's,Python \([0-9]*\.[0-9]*\).*,\1,') 12 | sitepackages="${target}/lib/python${pythonversion}/site-packages" 13 | } 14 | 15 | python_init() { 16 | create_dirs_first="yes" 17 | build_target="build" 18 | set_python_vars 19 | } 20 | 21 | build_python_options() { 22 | # need to update python vars in case $python_major is overriden 23 | set_python_vars 24 | # should exist in other modes too (eg, configure) 25 | if [ "$override_default_options" = "yes" ] 26 | then default_python_options=() 27 | else 28 | case "$1" in 29 | build) 30 | default_python_options=() 31 | ;; 32 | build_ext) 33 | default_python_options=( 34 | "--build-lib $sitepackages" 35 | ) 36 | ;; 37 | install) 38 | default_python_options=( 39 | "--prefix $target" 40 | "--exec-prefix $target" 41 | ) 42 | ;; 43 | esac 44 | fi 45 | eval $(Combine_Arrays opts python_options default_python_options) 46 | Add_Use_Flags_Options_To_Array opts 47 | 48 | opts=(`echo ${opts[@]} | sed "s,$target,$goboIndex,g"`) 49 | 50 | # This must occur after the source is unpacked, so it can't go in _init. 51 | # We have to guard against build_script being set from the recipe, or 52 | # earlier in the compile process. 53 | if ! [ "${build_script}" ] 54 | then 55 | for i in setup.py configure.py build.py 56 | do [ -e "${sourcedir}/${i}" ] && build_script="$i" 57 | done 58 | fi 59 | } 60 | 61 | python_do_build() { 62 | mkdir -p "$sitepackages" 63 | build_python_options $build_target 64 | $python $build_script $build_target ${opts[*]} || wrap_fail "Build failed." 65 | } 66 | 67 | python_do_install() { 68 | build_python_options $install_target 69 | SandboxInstall $verbose ${unmanagedlist:+--unmanaged-files "${unmanagedlist}"} ${sandboxopts:+"${sandboxopts[@]}"} -c $python "$appname" "$versionnumber" -- $build_script $install_target --root / ${opts[*]} || wrap_fail "Installation failed" 70 | } 71 | -------------------------------------------------------------------------------- /examples/GoboSimpleExample.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | # Workaround lack of ruby Environment 4 | $: << "/System/Index/lib/ruby/site_ruby/1.8" 5 | 6 | require 'gobo' 7 | 8 | 9 | ### App Info ################################################################## 10 | # 11 | # Create a GoboApplication object and set 12 | app = GoboApplication.new() 13 | 14 | app.description = "Simple example showing GoboLinux's Ruby Framework." 15 | app.credits = "Released under the GNU GPL." 16 | app.usage = "" 17 | app.example = "foo bar baz" 18 | app.notes = <&2 11 | ) 12 | fi 13 | 14 | if ! echo $entry | grep -q / 15 | then 16 | entry=`ls "$compileRecipesDir" | grep -i "^$entry$"` 17 | [ "$entry" ] || return 1 18 | entry="$compileRecipesDir/$entry" 19 | else 20 | if [ -f "$entry/Recipe" ] 21 | then 22 | version=$(basename $entry) 23 | entry=$(dirname $entry) 24 | fi 25 | fi 26 | 27 | [ -d "$entry" ] || return 2 28 | 29 | program=`basename $entry` 30 | recipedir="$entry/$version" 31 | 32 | if ! [ "$version" ] 33 | then 34 | [ `ls "$entry" | wc -l` -eq 1 ] || { 35 | # pick latest 36 | version=$(GuessLatest $(ls "$compileRecipesDir/$program")) 37 | if [ "$version" ] 38 | then 39 | recipedir="$compileRecipesDir/$program/$version" 40 | return 0 41 | else 42 | return 3 43 | fi 44 | } 45 | version=`ls "$entry"` 46 | fi 47 | 48 | recipedir="$entry/$version" 49 | [ -d "$recipedir" ] || return 4 50 | 51 | return 0 52 | } 53 | 54 | # if you only want to know if where a recipe is without the side effects 55 | function Which_Recipe() { 56 | saverecipedir=$recipedir 57 | saveprogram=$program 58 | saveversion=$version 59 | 60 | Find_Recipe_Program_And_Version "$@" 61 | ret=$? 62 | if [ "$ret" = 0 ] 63 | then 64 | echo $recipedir 65 | fi 66 | 67 | recipedir=$saverecipedir 68 | program=$saveprogram 69 | version=$saveversion 70 | 71 | return $ret 72 | } 73 | 74 | # if you only want to know if a recipe exists without the side effects 75 | function Has_Recipe() { 76 | Which_Recipe "$@" &>/dev/null 77 | return $? 78 | } 79 | 80 | function Set_Recipe_Program_And_Version_From_Args() { 81 | action=$1 82 | [ "$action" ] || action=pull 83 | 84 | if file "$(Arg 1)" | grep -q bzip2 85 | then 86 | Die "Recipe files are not supported." 87 | fi 88 | 89 | Find_Recipe_Program_And_Version "$action" "$(Arg 1)" "$(Arg 2)" 90 | case $? in 91 | 1) Die "Could not find $(Arg 1) in $compileRecipesDir." 92 | ;; 93 | 2) Die "Could not read $(Arg 1)." 94 | ;; 95 | 3) Die "Could not find a version of $(Arg 1) in $compileRecipesDir." 96 | ;; 97 | 4) Die "Version $(Arg 2) does not exist for $(Arg 1). Available versions are:\n$(ls $recipedir/..)" 98 | ;; 99 | esac # esac is still ridiculous! 100 | 101 | return 0 102 | } 103 | -------------------------------------------------------------------------------- /bin/AutoPatch: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source ScriptFunctions 4 | Import OptionParser 5 | Import GoboLinux 6 | 7 | helpOnNoArguments=yes 8 | scriptDescription="Compile patch streamlining tool. Run it once, edit the sources and run it again." 9 | scriptCredits="Copyright (C) Hisham Muhammad, 2014 - Released under the GNU GPL." 10 | scriptUsage="" 11 | scriptExample="Bullet" 12 | Add_Option_Boolean "c" "clean" "Cleanup directories in Archives." 13 | Parse_Options "$@" 14 | 15 | Parse_Conf Compile.conf 16 | 17 | cd "$compileSourcesDir" 18 | 19 | if [ $(basename $(readlink -f .)) != "Sources" ] 20 | then 21 | echo "This is designed to run in the Sources directory." 22 | exit 1 23 | fi 24 | 25 | recipedir=`GetRecipe $(Arg 1) $(Arg 2)` 26 | source "$recipedir/Recipe" 27 | 28 | if [ -z "$dir" ] 29 | then 30 | dir=`basename "$url" .tar.gz` 31 | dir=`basename "$dir" .tar.bz2` 32 | dir=`basename "$dir" .tar.xz` 33 | dir=`basename "$dir" .tgz` 34 | dir=`basename "$dir" .tbz2` 35 | fi 36 | if [ -z "$file" ] 37 | then 38 | file=`basename "$url"` 39 | fi 40 | 41 | while Has_Substring "$dir" "/" 42 | do 43 | dir=`dirname "$dir"` 44 | done 45 | 46 | function cleanup() { 47 | if [ -d "$dir" -o -d "$dir.old" ] 48 | then 49 | Log_Question "Delete $dir and $dir.old? " 50 | read yn 51 | if [ "$yn" = "y" ] 52 | then 53 | rm -rf "$dir" 54 | rm -rf "$dir.old" 55 | else 56 | exit 1 57 | fi 58 | fi 59 | } 60 | 61 | # Step one: generate two clean directories 62 | # to start a diff. 63 | function step_one() { 64 | Log_Normal "Directory: $dir" 65 | cleanup 66 | Log_Normal "Extracting ../Archives/$file" 67 | aunpack "../Archives/$file" 68 | cp -a "$dir" "$dir.old" 69 | } 70 | 71 | function step_two() { 72 | 73 | packagename=`Get_Token "$recipedir" "/" "-2"` 74 | versionandrevision=`Get_Token "$recipedir" "/" "-1"` 75 | newrecipedir="$compileRecipesDir/$packagename/$versionandrevision" 76 | if [ "$recipedir" != "$newrecipedir" ] 77 | then 78 | Log_Normal "Copying recipe from $recipedir to $newrecipedir" 79 | mkdir -p "$compileRecipesDir/$packagename" 80 | cp -R "$recipedir" "$newrecipedir" 81 | recipedir="$newrecipedir" 82 | fi 83 | 84 | diff -Nur "$dir.old" "$dir" | mtail --config /System/Settings/Scripts/diff.mtailrc 85 | echo "*******************************************************************************" 86 | echo 87 | ls "$recipedir"/*.patch &> /dev/null && { 88 | echo "Existing patches:" 89 | ls "$recipedir"/*.patch 90 | echo 91 | } 92 | Log_Question "Enter patch name (without path or .patch extension): " 93 | read patchname 94 | if [ "$patchname" != "" ] 95 | then 96 | Log_Question "Please write a description: " 97 | read description 98 | for i in `seq -w 20` 99 | do 100 | ls "$recipedir/$i"*".patch" &> /dev/null || break 101 | done 102 | patchfilename="$recipedir/$i-$patchname.patch" 103 | Log_Normal "Writing $patchfilename ..." 104 | echo "$description" > "$patchfilename" 105 | echo >> "$patchfilename" 106 | diff -Nur "$dir.old" "$dir" >> "$patchfilename" 107 | fi 108 | cleanup 109 | } 110 | 111 | if Boolean "clean" 112 | then 113 | cleanup 114 | elif [ -e "$dir.old" ] 115 | then 116 | step_two 117 | else 118 | step_one 119 | fi 120 | 121 | -------------------------------------------------------------------------------- /doc/FAQ: -------------------------------------------------------------------------------- 1 | 2 | Compile FAQ 3 | maintained by Rafael Jeffman 4 | 5 | Questions 6 | 7 | 1. About Compile 8 | 9 | 1.1. What are Compile, Recipes and source packages? 10 | 1.2. Why should I use source packages instead of binary ones? 11 | 12 | 2. How to use Compile 13 | 14 | 2.1. How do I create a Recipe for a program based on GNU Autotools? 15 | 2.2. Does Compile support dependencies? 16 | 2.3. How do I create a program which is based of many source archives? 17 | 2.4. How do I make it download and use a file when the resulting file is not 18 | a part of the URL? 19 | 2.5. I've already downloaded the source URL. How do I use it? 20 | 21 | 1. About Compile 22 | 23 | 1.1. What are Compile, Recipes and source packages? 24 | 25 | Compile is the system used by GoboLinux to 26 | install programs using their source code distribution instead of a 27 | pre-compiled binary version. Altough inspired by Gentoo's Portage, it 28 | was built from scratch to reflect the philosophy of GoboLinux 29 | and to be easily integrated to it. 30 | 31 | Recipes are how the configuration files used by Compile are called. They 32 | contain a recipe on how to obtain and compile a program from its 33 | sources. A Recipe may also contain patches to be applied to the source 34 | code in order to make the program work properly. 35 | 36 | Source packages in GoboLinux differ a little from other distributions. 37 | Apart from possible patches that are released with a Recipe, the sources 38 | for a given program is obtained from the official distribution site. 39 | There is no "GoboLinux Repository" for sources. 40 | 41 | 1.2. Why should I use source packages instead of binary ones? 42 | 43 | There might be many reasons for installing software from the source 44 | code. The most common are: 45 | 46 | * *Optimization* Some software is very sensible to machine 47 | optimization. For these, compiling for a specific target may 48 | enhance its usage. A good example is MPlayer. 49 | * *Compilation Options/Dependencies* Most software has many 50 | compilation options that may alter its avaiable features, 51 | optimization parameters and runtime dependencies. Binary 52 | distributions are released with a pre-selected set of compilation 53 | options that may not be the optimal one neither the ones required 54 | in a specific usage scenario. 55 | * *Consistency* It is easier to keep the system consistency 56 | installing all software from source code. 57 | 58 | 2. How to use Compile 59 | 60 | 2.1. How do I create a Recipe for a program based on GNU Autotools? 61 | 62 | Most of the open source software available today, when installed from 63 | the source code uses the GNU Autotools for configuring its compile 64 | options and to generate system dependent code. Their installation is 65 | often performed by issuing three commands: configure, make and make 66 | install. For example, most - if not all - of the software avaiable at 67 | GNU.org can be installed this way. 68 | 69 | For what can be called "well behaved" programs, that is those programs 70 | that respect the configuration of installation paths, a Recipe would be 71 | like: 72 | 73 | url=ftp://ftp.gtk.org/pub/gtk/v2.0/pango-1.0.5.tar.bz2 74 | is_compileprogram=yes 75 | 76 | This Recipe tells Compile where this program (Pango--1.0.5) can be found 77 | using the *url* directive and that it can be compiled using standard GNU 78 | Autotools procedure by setting *is_compileprogram* to /yes/. 79 | *is_compileprogram* is derived from the old method for installing 80 | program from sources called CompileProgram. 81 | 82 | To select configure options set *configure_options*, as in the 83 | ImageMagick--5.5.7-10 Recipe: 84 | 85 | url=ftp://ftp.imagemagick.org/pub/ImageMagick/ImageMagick-5.5.7-10.tar.bz2 86 | dir=ImageMagick-5.5.7 87 | is_compileprogram=yes 88 | configure_options=( 89 | "--enable-shared" 90 | "--with-x" 91 | "--without-perl" 92 | ) 93 | 94 | 2.2. Does Compile support dependencies? 95 | 96 | Yes. It is the same as in the /Programs hierarchy: through a 97 | Resources/Dependencies file. In fact, the Resources/ directory inside, 98 | say, Recipes/Foo/1.0 is copied directly to /Programs/Foo/1.0 after 99 | compilation. This way you can set Environment variables, configuration 100 | Defaults, etc. The Compile program verifies the Dependencies file and, 101 | if there is a program which is not in /Programs and a recipe for it is 102 | available, it gets compiled first. 103 | 104 | 2.3. How do I create a program which is based of many source archives? 105 | 106 | You can use a meta-recipe. KDE and Enlightenment, for example, are done 107 | this way. Create a separate recipe for each component. Then, in the 108 | meta-recipe, specify the recipe type as is_meta=yes and list the recipes 109 | to be included in the include array. When you compile the meta-recipe, 110 | all subpackages will be built into the same /Programs entry. (For 111 | example, all components of KDE will be installed at /Programs/KDE , but 112 | if you don't use KDE and only want to build ARTS separately, you can 113 | just 'Compile ARTS' and it will get installed at /Programs/ARTS). 114 | 115 | 2.4. How do I make it download and use a file when the resulting file 116 | is not a part of the URL? 117 | 118 | Specify both the "url" variable and the "file" variable. 119 | 120 | 2.5. I've already downloaded the source URL. How do I use it? 121 | 122 | Put the file in the Archives directory. 123 | -------------------------------------------------------------------------------- /bin/PrepareProgram: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ### Imports ############################################################## 4 | 5 | source ScriptFunctions 6 | Import File 7 | Import GoboLinux 8 | Import Log 9 | Import OptionParser 10 | Import Directories 11 | Import Array 12 | Import String 13 | 14 | ### Options ############################################################## 15 | 16 | helpOnNoArguments=yes 17 | scriptDescription="prepares applications for instalation, running the 'configure' script." 18 | scriptCredits="Copyright (C) 2001-2005 Hisham Muhammad - Released under the GNU GPL." 19 | scriptUsage=" [ -- ]" 20 | scriptExample="KDE 2.2" 21 | scriptNotes="The directory hierarchy for the program is only created with --tree." 22 | 23 | # This option should be removed; there's no more interaction in this script. 24 | Add_Option_Boolean "b" "batch" "batch mode: no user interaction" 25 | 26 | Add_Option_Boolean "t" "tree" "Prepare directories only, do not attempt to run configure." 27 | Add_Option_Boolean "T" "tree-cleanup" "Like --tree, but instead of creating directories, remove empty ones" 28 | Add_Option_Boolean "k" "keep" "Keep the directory if it already exists in the directory hierarchy." 29 | Add_Option_Boolean "r" "remove" "Remove the directory if it already exists in the directory hierarchy." 30 | Add_Option_Entry "c" "configure" "Specify program to be used as 'configure' script." "./configure" 31 | Add_Option_Boolean "a" "autoconf" "Assume configure is based on autoconf, skipping detection." 32 | Add_Option_Boolean "A" "no-autoconf" "Assume configure is NOT based on autoconf, skipping detection." 33 | Add_Option_Boolean "D" "no-default-options" "Skip detection altogether, use only configure options passed on the command-line." 34 | Add_Option_Boolean "p" "programs" "Prepare for build directly in /Programs, not $goboIndex" 35 | 36 | Parse_Options "$@" 37 | 38 | Is_Entry "configure" && export PATH="$PATH:." 39 | 40 | ### Functions ############################################################ 41 | 42 | # TODO: this function is now in Compile and should probably disappear in the future 43 | function config_is_autoconf() { 44 | Boolean "autoconf" && return 0 45 | Boolean "no-autoconf" && return 1 46 | grep -i "Generated .* autoconf" "$configureprogram" &> /dev/null 47 | } 48 | 49 | function config_accepts_prefix() { 50 | grep -- "--prefix" "$configureprogram" &> /dev/null 51 | } 52 | 53 | function config_accepts_sysconfdir() { 54 | grep -- "--sysconfdir" "$configureprogram" &> /dev/null 55 | } 56 | 57 | function config_accepts_mandir() { 58 | grep -- "--mandir" "$configureprogram" &> /dev/null 59 | } 60 | 61 | function config_accepts_libexecdir() { 62 | grep -- "--libexecdir" "$configureprogram" &> /dev/null 63 | } 64 | 65 | function build_change() { 66 | echo "/-L/!s/"$1"/"$2"/g;" 67 | } 68 | 69 | ### Operation ############################################################# 70 | 71 | programname="$(Arg 1)" 72 | [ -z "$programname" ] && Die "Missing argument." 73 | Dir_Set Case && { 74 | # Respect capitalization passed, if any. 75 | if [ "$programname" = `echo "$programname" | tr '[:upper:]' '[:lower:]'` ] 76 | then programname=`GuessProgramCase "$programname"` 77 | fi 78 | } 79 | 80 | if [ "$(Arg 2)" ] 81 | then 82 | versionnumber="$(Arg 2)" 83 | else 84 | Die "Please specify version." 85 | fi 86 | 87 | programname=`NamingConventions "$programname"` 88 | 89 | baseprogramdir=`Get_Dir runtime "$programname" ''` 90 | programdir=`Get_Dir runtime "$programname" "$versionnumber"` 91 | settingsdir=`Get_Dir runtimeSettings "$programname" "$versionnumber"` 92 | variabledir=`Get_Dir runtimeVariable "$programname" "$versionnumber"` 93 | 94 | Dir_Set Install && installdir=`Get_Dir install "$programname" "$versionnumber"` 95 | 96 | if Boolean "tree" 97 | then 98 | Dir_Set Install && Create_Program_Tree "$installdir" || Create_Program_Tree "$programdir" 99 | exit $? 100 | elif Boolean "tree-cleanup" 101 | then 102 | Clean_Program_Tree "$programdir" 103 | exit $? 104 | fi 105 | 106 | configureprogram=`Entry "configure"` 107 | 108 | echo 109 | Log_Normal "Preparing..." 110 | rm -f config.cache 111 | 112 | Exists "$configureprogram" || Die "configure script "`[ $configureprogram != "./configure" ] && echo " ($configureprogram) "`"not found." 113 | 114 | if ! Boolean "programs" 115 | then 116 | configureprefix="$goboIndex" 117 | configuresettings="$goboSettings" 118 | configuremandir="${goboShared}/man" 119 | else 120 | configureprefix="$programdir" 121 | configuresettings="$settingsdir" 122 | configuremandir="${target}/Shared/man" 123 | fi 124 | configurevariable="$goboVariable" 125 | 126 | if Boolean "no-default-options" 127 | then 128 | configure_options=() 129 | elif config_is_autoconf 130 | then 131 | Log_Normal "Autoconf configure script detected." 132 | configure_options=( 133 | --prefix="$configureprefix" 134 | --sysconfdir="$configuresettings" 135 | --localstatedir="$configurevariable" 136 | --mandir="${configuremandir}" 137 | --libexecdir="${configureprefix}/lib/$(Downcase ${programname})" 138 | ) 139 | elif config_accepts_prefix 140 | then 141 | Log_Normal "Non-autoconf configure script detected (accepts --prefix)." 142 | configure_options=( 143 | --prefix="$configureprefix" 144 | ) 145 | if config_accepts_sysconfdir 146 | then 147 | configure_options=( 148 | "${configure_options[@]}" 149 | --sysconfdir="$configuresettings" 150 | ) 151 | fi 152 | if config_accepts_mandir 153 | then 154 | configure_options=( 155 | "${configure_options[@]}" 156 | --mandir="$configuremandir" 157 | ) 158 | fi 159 | if config_accepts_libexecdir 160 | then 161 | configure_options=( 162 | "${configure_options[@]}" 163 | --libexecdir="${configureprefix}/lib/$(Downcase ${programname})" 164 | ) 165 | fi 166 | else 167 | configure_options=() 168 | fi 169 | 170 | eval `Args_To_Array args 3` 171 | if [ -n "$args" ] 172 | then 173 | for a in "${args[@]}" 174 | do 175 | if echo "${a}" | grep -q "/Resources/Defaults/Settings" 176 | then 177 | tmpargs=( 178 | "${tmpargs[@]}" 179 | "$(echo "${a}")" 180 | ) 181 | else 182 | tmpargs=( 183 | "${tmpargs[@]}" 184 | "$(echo "${a}" | sed "s,$programdir,$goboIndex,g")" 185 | ) 186 | fi 187 | done 188 | args=("${tmpargs[@]}") 189 | fi 190 | 191 | "$configureprogram" ${configure_options:+"${configure_options[@]}"} ${args:+"${args[@]}"} 2>&1 | Color_Output configure >&$normalFD 192 | if [ "${PIPESTATUS[0]}" != 0 ] 193 | then Die "configure failed." 194 | fi 195 | 196 | exit 0 197 | -------------------------------------------------------------------------------- /bin/FetchArchive: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ################################################## 4 | # Imports 5 | ################################################## 6 | 7 | . ScriptFunctions 8 | Import OptionParser 9 | Import File 10 | Import Terminal 11 | Import GoboLinux 12 | Import Array 13 | 14 | ################################################## 15 | # Options and configuration 16 | ################################################## 17 | 18 | Parse_Conf Compile.conf 19 | Import Compile 20 | 21 | helpOnNoArguments=yes 22 | scriptDescription="Given a recipe, download the files required to compile it." 23 | scriptUsage=" [arch-recipe]" 24 | scriptExample="$compileRecipeDir/K3B/0.10/Recipe" 25 | Add_Option_Entry "d" "save-directory" "Rename the directory into which the archive is unpacked/files checked out." "" 26 | Add_Option_Entry "s" "save-to" "Save the files to the given directory" "$compileArchivesDir" 27 | Add_Option_Entry "P" "program" "Program name" "Bash" 28 | Add_Option_Entry "V" "version-number" "Version number with revision" "4.0-r1" 29 | Add_Option_Boolean "b" "batch" "Avoid asking questions." 30 | Add_Option_Boolean "" "no-check-certificate" "Do not check certificates when downloading files. NOTE: This can be dangerous!" 31 | Add_Option_Boolean "" "no-verify-files" "Do not verify downloaded files, this flag is normally passed when creating a new recipe" 32 | Parse_Options "$@" 33 | 34 | savedir=$(Entry "save-to") 35 | sourcedir=$(Entry "save-directory") 36 | programname=$(Entry "program") 37 | versionnumber=$(Entry "version-number") 38 | 39 | wget_bin="wget" 40 | git_bin="git" 41 | if Boolean "no-check-certificate" 42 | then 43 | Log_Normal "NOTE: Ignoring certificates when downloading sources" 44 | wget_bin="wget --no-check-certificate" 45 | git_bin="GIT_SSL_NO_VERIFY=true git" 46 | fi 47 | 48 | ################################################## 49 | # Fundamental variables 50 | ################################################## 51 | 52 | recipe="$(Arg 1)" 53 | [ "$recipe" ] || Die "Missing argument. Usage: $scriptName . See --help." 54 | [ -e "$recipe" ] || Die "File not found: $recipe" 55 | . "$recipe" 56 | 57 | archrecipe="$(Arg 2)" 58 | [ -e "$archrecipe" ] && source "$archrecipe" 59 | 60 | [ -z "${sourcedir}" ] && sourcedir="${dir%%/*}" 61 | 62 | ################################################## 63 | # Get sources 64 | ################################################## 65 | 66 | for var in url mirror_url file file_size file_md5 file_sha cvs cvs_module svn git bzr hg 67 | do 68 | eval ' 69 | if [ -n "$'$var'" -a ! -n "${'$var's[*]}" ] 70 | then '$var's=("$'$var'") 71 | fi 72 | ' 73 | done 74 | 75 | [ ! -w "${savedir}" -o ! -x "${savedir}" ] && chown `whoami` "${savedir}" 76 | 77 | savesourcedir="${sourcedir}" 78 | [ -z "${sourcedir}" ] && sourcedir="$(echo ${recipe} | sed 's,.*/\([^/]*\)/\([^/]*\)/Recipe,\1-\2,')" 79 | 80 | [ -d "${sourcedir}" ] && [ ! -w "${sourcedir}" -o ! -x "${sourcedir}" ] && chown -R `whoami` "${sourcedir}" 81 | 82 | cd "$savedir" 83 | 84 | if [ "${cvss[*]}" ] 85 | then 86 | for cvs in "${cvss[@]}" 87 | do 88 | if echo "$cvs" | grep -q " " 89 | then 90 | origcvs="$cvs" 91 | cvs="${origcvs% *}" 92 | cvs_modules=("${origcvs#* }") 93 | fi 94 | if [ "$cvs_password" ] 95 | then Log_Normal "When asked for a password, enter \"$cvs_password\"." 96 | else Log_Normal "If asked for a password, just press Enter." 97 | fi 98 | 99 | login_method=`echo ${cvs} | cut -b-5` 100 | [ "$cvs_rsh" ] && export CVS_RSH=$cvs_rsh || export CVS_RSH=ssh 101 | [ "$login_method" != ":ext:" ] && cvs -d${cvs} login || exit $? 102 | for cvs_module in "${cvs_modules[@]}" 103 | do 104 | checkout_dir=`basename "$sourcedir"` 105 | cvs -d${cvs} ${cvs_opts} ${cvs_options} checkout -d"$checkout_dir" ${cvs_checkout_options} ${cvs_module} || exit $? 106 | done 107 | done 108 | exit 0 109 | elif [ "${svns[*]}" ] 110 | then 111 | for svn in "${svns[@]}" 112 | do 113 | if [ "$svn_username" ] 114 | then svn checkout "${svn}" "${sourcedir}" --username "${svn_username}" --password "${svn_password}" || exit $? 115 | else svn checkout "${svn}" "${sourcedir}" || exit $? 116 | fi 117 | done 118 | exit 0 119 | elif [ "${gits[*]}" ] 120 | then 121 | for git in "${gits[@]}" 122 | do 123 | bflag="" 124 | if [ "${branch}" ] 125 | then bflag="-b ${branch}" 126 | elif [ "${tag}" ] 127 | then bflag="-b ${tag}" 128 | fi 129 | if [ ! -d "${sourcedir}" ] 130 | then 131 | $git_bin clone --depth=1 ${bflag} "${git}" "${sourcedir}" || exit $? 132 | cd "${sourcedir}" && $git_bin submodule update --init || true 133 | else cd "${sourcedir}" && $git_bin pull || exit $? 134 | fi 135 | done 136 | exit 0 137 | elif [ "${bzrs[*]}" ] 138 | then 139 | for bzr in "${bzrs[@]}" 140 | do 141 | if [ ! -d "${sourcedir}" ] 142 | then bzr branch "${bzr}" "${sourcedir}" || exit $? 143 | else cd "${sourcedir}" && bzr pull || exit $? 144 | fi 145 | done 146 | exit 0 147 | elif [ "${hgs[*]}" ] 148 | then 149 | for hg in "${hgs[@]}" 150 | do 151 | if [ ! -d "${sourcedir}" ] 152 | then hg clone ${hg} "${sourcedir}" || exit $? 153 | else cd "${sourcedir}" && hg update || exit $? 154 | fi 155 | done 156 | exit 0 157 | elif ! [ -n "${urls[*]}" ] 158 | then 159 | Die "Missing URL in recipe '$recipe'." 160 | else 161 | sourcedir="${savesourcedir}" 162 | fi 163 | 164 | if ! [ "${files[*]}" ] 165 | then files=(`Map basename "${urls[@]}"`) 166 | fi 167 | 168 | if [ ! -z ${file_shas} ]; 169 | then 170 | file_sums=${file_shas} 171 | use_sha=1 172 | else 173 | file_sums=${file_md5s} 174 | use_sha=0 175 | fi 176 | 177 | for url_index in `seq 0 $[${#urls[@]}-1]` 178 | do 179 | file="${files[url_index]}" 180 | [ -f "${file}" -a ! -w "${file}" ] && chown `whoami` "$file" 181 | # First verification to know if we need to download it again 182 | if Boolean "no-verify-files" 183 | then 184 | if [ -f "${file}" ] 185 | then result=2 # incomplete 186 | else result=3 # missing 187 | fi 188 | else 189 | Verify_Files "$file" "${file_sizes[url_index]}" "${file_sums[url_index]}" $use_sha 190 | result=$? 191 | fi 192 | # File was ok 193 | if [ "$result" = "0" ] 194 | then 195 | continue 196 | # File was corrupted, delete it 197 | elif [ "$result" = "1" ] 198 | then 199 | Log_Normal "File $file is corruped, downloading it again!" 200 | rm -f -- ${file} 201 | elif [ "$result" = "2" ] 202 | then 203 | if Boolean "batch" || { Log_Normal "File ${file} has been already downloaded"; Ask "Remove and download again?"; } 204 | then rm -f ${file} 205 | else continue 206 | fi 207 | fi 208 | 209 | function wget_url() { 210 | fileindex=$1 211 | mirrorlevel=$2 212 | urlcount="${#urls[@]}" 213 | if [ "$mirrorlevel" = 0 ] 214 | then fetch="${urls[fileindex]}" 215 | else fetch="${mirror_urls[(mirrorlevel-1)*urlcount+fileindex]}" 216 | fi 217 | if [ -z "$fetch" ] 218 | then 219 | # No more mirrors in recipe 220 | if [ -n "$programname" -a -n "$versionnumber" ] 221 | then 222 | version_no_rev="${versionnumber%-r*}" 223 | # Try gobolinux.org mirror 224 | $wget_bin -O "$file" -c --passive-ftp "https://gobolinux.org/mirror_url/$programname/$version_no_rev/$file" 225 | return $? 226 | else 227 | return 1 228 | fi 229 | fi 230 | local file="${files[fileindex]}" 231 | unset LANG LC_ALL # So that wget's output is not translated 232 | if [ -e "$file" ] 233 | then 234 | if Starts_With "http:" "$fetch" 235 | then 236 | expectedlength=`$wget_bin --spider "$fetch" 2>&1 | grep "Length:" | tr -d ".," | cut -d" " -f2` 237 | locallength=`wc -c "$file" | cut -d" " -f1` 238 | if [ "$expectedlength" = "$locallength" ] 239 | then 240 | Log_Verbose "$file is already fully retrieved." 241 | return 0 242 | fi 243 | fi 244 | fi 245 | $wget_bin -O "$file" -c --passive-ftp "$fetch" || { 246 | wget_url "$fileindex" "$[mirrorlevel+1]" 247 | } 248 | } 249 | 250 | # Note: calling this function modifies the value of $file! 251 | wget_url "$url_index" 0 || { 252 | Die "Could not fetch '$url'." 253 | } 254 | 255 | # Verify the new downloaded file 256 | # Since file variable has been modified by wget_url(!?) we need to 257 | # set it again 258 | if Boolean "no-verify-files" 259 | then 260 | result=0 261 | else 262 | file=${files[url_index]} 263 | Verify_Files "$file" "${file_sizes[url_index]}" "${file_sums[url_index]}" $use_sha 264 | result=$? 265 | fi 266 | case $result in 267 | 1) Die "File $file is corrupted. Exiting." ;; 268 | 2) Die "File $file is incomplete. Exiting." ;; 269 | 3) Die "Files $file is not available. Exiting." ;; 270 | esac 271 | done 272 | -------------------------------------------------------------------------------- /bin/UnionSandbox: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ### Imports ################################################################### 4 | 5 | source ScriptFunctions 6 | Import Array 7 | Import File 8 | Import GoboLinux 9 | Import Log 10 | Import OptionParser 11 | Import UnionFS 12 | 13 | ### Options ################################################################### 14 | 15 | scriptDescription="Run the program in a protected sandbox, as superuser, using unionfs" 16 | scriptCredits="Copyright (C) 2003. Released under the GNU GPL." 17 | helpOnNoArguments=yes 18 | scriptUsage="[] []" 19 | scriptExample="-r 0.0 -s '.:${goboPrograms}/NaughtyApp/Current' make install" 20 | scriptNotes=" 21 | To allow mobility within the sandbox, the '.' directory is mounted at 22 | a sandbox root (like $sandboxroot). For this reason, use of relative paths like '..' to reach 23 | directories higher in the hierarchy than '.' may produce unexpected results. 24 | It may also confuse symbolic links that flow through the sandbox. 25 | " 26 | 27 | Add_Option_Entry "w" "writedir" "The dir where writes outside sandbox are written." 28 | Add_Option_Entry "d" "directory" "The program should be run at . "\ 29 | "This path should be either absolute, or relative to the sandbox root." 30 | Add_Option_List "s" "sandbox" "Colon-separated list of areas where the restricted process has write access to." "." 31 | Add_Option_List "m" "map" "Colon-separated mapping (lhs=rhs) where writes to rhs are mapped to lhs." "" 32 | Parse_Options "$@" 33 | 34 | Parse_Conf Directories.conf 35 | 36 | Boolean "verbose" && verbose="--verbose" 37 | 38 | ### Operation ################################################################# 39 | 40 | Is_Writable "${goboPrograms}" || Die "Needs write access to ${goboPrograms}" 41 | 42 | [ "$1" ] || Die "Please specify a command to be executed inside the sandbox." 43 | Union_Is_Supported || Die "unionfs is unavailabe on this system." 44 | unionbackend=`Union_Backend` 45 | 46 | [ "${unionSandbox[0]}" = "" ] && Die "Please set unionSandbox in Settings/Scripts/Directories.conf" 47 | [ "$unionSandboxMP" = "" ] && Die "Please set unionSandboxMP in Settings/Scripts/Directories.conf" 48 | [ "$unionSandboxRW" = "" ] && Die "Please set unionSandboxRW in Settings/Scripts/Directories.conf" 49 | 50 | sandbox_mp=`mktemp -d "${unionSandboxMP}.tmp.XXXXXXXXXXX"` 2>/dev/null || Die "Unable to create UnionSandbox mount point at $unionSandboxMP" 51 | sandbox_rw=`mktemp -d "${unionSandboxRW}.tmp.XXXXXXXXXXX"` 2>/dev/null || Die "Unable to create UnionSandbox read/write mount point at $unionSandboxRW" 52 | sandbox_tmp=`mktemp -d "${unionSandboxRW}.tmp.XXXXXXXXXXX"` 2>/dev/null || Die "Unable to create UnionSandbox workdir mount point at $unionSandboxRW" 53 | chmod a+rx "$sandbox_mp" "$sandbox_rw" "$sandbox_tmp" 54 | 55 | function RealPath { 56 | readlink -f $@ 57 | } 58 | 59 | List_To_Array "sandbox" bindmounts 60 | bindmounts=(`Map RealPath "${bindmounts[@]}"`) 61 | List_To_Array "map" mapmounts 62 | 63 | # Preset cmd status 64 | result=0 65 | 66 | function symlinks_in_root() { 67 | # If we have a host running GoboLinux with gobohidden entries and a chroot environment 68 | # where packages are being compiled with no hidden entries, then the same directory can 69 | # be returned more than once. We use sort+uniq as a filter to workaround that problem. 70 | find `gobohide --list 2> /dev/null | tail -n +1 | grep "^/"` /* -maxdepth 0 -type l | sort -n | uniq 71 | } 72 | 73 | # Called at end of script and by signal handler 74 | function cleanup() { 75 | Log_Normal "Cleaning up." 76 | Quiet pushd ${unionfsPackageDir} 77 | find . -name "*__dir_opaque" | xargs rm -f 78 | Quiet popd 79 | 80 | # Remove wrapper 81 | rm -f -- "$sandbox_mp/.wrapper" 82 | 83 | # Clean up mountpoints 84 | 85 | # unionfs-fuse keeps a few programs busy, so we need to make sure all ocurrences created by us are finished 86 | for entry in $(ps xaw | awk {'print $1 " " $5'} | grep "unionfs" | grep ${sandbox_mp} | grep unionfs) 87 | do 88 | local pid=$(echo "$entry" | cut -d" " -f1) 89 | local unionapp=$(echo $entry | cut -d" " -f2) 90 | [ "$unionapp" = "unionfs" ] && Quiet kill -9 $pid 91 | done 92 | umount "$sandbox_mp/$goboStatus" 93 | umount "$sandbox_mp/$goboDevices" 94 | error=false 95 | For_Each_Reverse mapmounts ' 96 | rhs=$(echo $each | cut -d= -f2) 97 | umount ${sandbox_mp}$rhs || { echo "Error unmounting ${sandbox_mp}${rhs}"; error=true; } 98 | ' 99 | For_Each_Reverse bindmounts ' 100 | umount ${sandbox_mp}${each} || { echo "Error unmounting ${sandbox_mp}${each}"; error=true; } 101 | ' 102 | For_Each_Reverse unionSandbox ' 103 | Union_Umount ${unionbackend} ${sandbox_mp}${each} || { echo "Error unmounting ${sandbox_mp}${each}"; error=true; } 104 | Quiet rmdir ${sandbox_mp}${each} 105 | Quiet rmdir ${sandbox_rw}${each} 106 | Quiet rmdir ${sandbox_tmp}${each} 107 | ' 108 | # Do not attempt to 'rm -rf' if some unmount failed. 109 | [ "$error" = "true" ] && exit 1 110 | 111 | # Clean up legacy links 112 | rm -rf ${sandbox_mp}/usr 113 | rm `find ${sandbox_mp} -maxdepth 1 -type l` 114 | 115 | # Remove tmp dirs 116 | if Is_Entry_Set "writedir" 117 | then 118 | writedir=`Entry "writedir"` 119 | Log_Normal "Moving entries to: $writedir" 120 | Assert_Dir $writedir 121 | cp -ra --no-preserve=xattr $verbose "$sandbox_rw/." "$writedir" 122 | Quiet mv -v $sandbox_mp/* $writedir 123 | fi 124 | rm -rf $sandbox_rw $sandbox_tmp 125 | rmdir $sandbox_mp 126 | 127 | exit $result 128 | } 129 | 130 | function sandbox_die() { 131 | message=$1 132 | Log_Error $message 133 | result=1 134 | cleanup 135 | } 136 | 137 | function mount_union() { 138 | dir=$1 139 | Assert_Dir ${sandbox_mp}${dir} 140 | Assert_Dir ${sandbox_rw}${dir} 141 | Assert_Dir ${sandbox_tmp}${dir} 142 | uniondirs=`echo "${sandbox_rw}${dir}=rw:${dir}=ro:${sandbox_tmp}${dir}=tmp"` 143 | # Dev Note: 144 | # $unionfsPackageDir is empty in PostInstall which was causing sed to garble $uniondirs! 145 | # Upon further investigation, it turned out this sed operation is redundant. 146 | # See https://github.com/gobolinux/Compile/issues/67. 147 | # However this was tested only for the "unionImplementations" "overlayfs" and "unionfs-fuse". 148 | # I did not verify whether this sed operation is *possibly* useful for other implementations like "unionfs" or "funionfs." 149 | # ... therefore I am leaving it here but wrapped securely (sed only if $unionfsPackageDir is non-empty). 150 | if [[ -n "$unionfsPackageDir" ]] 151 | then 152 | uniondirs=`echo $uniondirs | sed "s,$unionfsPackageDir=ro,$unionfsPackageDir=rw,g"` 153 | fi 154 | Union_Mount "$unionbackend" "$uniondirs" "${sandbox_mp}${dir}" 155 | [ "$?" = "0" ] || sandbox_die "Unable to mount unionfs" 156 | } 157 | 158 | trap "sandbox_die 'Interrupted...'" SIGHUP SIGINT SIGTERM 159 | 160 | Log_Verbose "Preparing the sandbox..." 161 | 162 | # Mount unionfs 163 | 164 | unionSandbox=( ${unionSandbox[@]} "$goboIndex" ) 165 | For_Each unionSandbox 'mount_union $each' 166 | 167 | # Bind mount writable areas 168 | error=false 169 | For_Each bindmounts 'mkdir -p ${sandbox_mp}/${each}; mount -o bind $each ${sandbox_mp}/${each}; [ "$?" = "0" ] || error=true' 170 | [ "$error" = "false" ] || sandbox_die "Unable to mount writable areas in chroot" 171 | 172 | error=false 173 | For_Each mapmounts 'lhs=$(echo $each | cut -d= -f1) 174 | rhs=$(echo $each | cut -d= -f2) 175 | Assert_Dir $lhs 176 | Assert_Dir ${sandbox_mp}$rhs 177 | mount -o bind $lhs ${sandbox_mp}$rhs 178 | [ "$?" = "0" ] || error=true 179 | ' 180 | [ "$error" = "false" ] || sandbox_die "Unable to mount map areas in chroot" 181 | 182 | # Create legacy links and directories 183 | cp -a $verbose `symlinks_in_root` "$sandbox_mp" 184 | mkdir -p "${sandbox_mp}/run" 185 | 186 | # Create wrapper 187 | newpwd="$PWD" 188 | Is_Entry_Set "directory" && newpwd=`Entry "directory"` 189 | echo "#!/bin/bash" >"${sandbox_mp}/.wrapper" 190 | echo "cd $newpwd" >>"${sandbox_mp}/.wrapper" 191 | Args_To_Array command >> "${sandbox_mp}/.wrapper" 192 | if [ "$unionbackend" != "unionfs" ] 193 | then 194 | # delete entries in sandbox if they are legacy symlinks 195 | echo "[ -L $goboDevices ] && rm $goboDevices" >> "${sandbox_mp}/.wrapper" 196 | echo "[ -L $goboStatus ] && rm $goboStatus" >> "${sandbox_mp}/.wrapper" 197 | if grep -q devtmpfs "$goboStatus/filesystems" 198 | then devfs=devtmpfs 199 | else devfs=tmpfs 200 | fi 201 | echo "mkdir -p $goboDevices; mount -t $devfs none $goboDevices" >> "${sandbox_mp}/.wrapper" 202 | echo "mkdir -p $goboStatus; mount -t proc none $goboStatus" >> "${sandbox_mp}/.wrapper" 203 | echo "[ -e \"${goboLibraries}/udev/devices/\" ] && cp -aR \"${goboLibraries}/udev/devices/\"* $goboDevices" >> "${sandbox_mp}/.wrapper" 204 | 205 | # We check if udevadm is also available at runtime. This is needed when building Udev itself. 206 | if Executable_Exists_In_Path "udevadm" 207 | then echo "which udevadm >& /dev/null && udevadm trigger && udevadm settle --timeout=10" >> "${sandbox_mp}/.wrapper" 208 | else echo "which udevtrigger >& /dev/null && udevtrigger && udevsettle" >> "${sandbox_mp}/.wrapper" 209 | fi 210 | 211 | # The following line is a kludge in order to partially mitigate https://github.com/gobolinux/Compile/issues/51. 212 | # This should be fixed properly by running Pre_Installation_Preparation outside of Runner. 213 | echo "find /System/Index | RemoveBroken > /dev/null" >>"${sandbox_mp}/.wrapper" 214 | fi 215 | echo "\"\${command[@]}\"" >>"${sandbox_mp}/.wrapper" 216 | 217 | # Useful for debugging: 218 | #echo "res=\$?" >>"${sandbox_mp}/.wrapper" 219 | #echo "echo DEBUG SHELL; bash" >>"${sandbox_mp}/.wrapper" 220 | #echo "exit \$res" >>"${sandbox_mp}/.wrapper" 221 | 222 | chmod a+x "${sandbox_mp}/.wrapper" 223 | 224 | # Run program in chrooted sandbox 225 | chroot $sandbox_mp /.wrapper 226 | result=$? 227 | 228 | # Cleanup 229 | cleanup 230 | 231 | -------------------------------------------------------------------------------- /lib/ruby/site_ruby/1.8/gobo.rb: -------------------------------------------------------------------------------- 1 | ### Changelog ################################################################# 2 | 3 | # 30/08/2003 - Initial Version 4 | 5 | =begin 6 | 7 | gobo.rb - GoboLinux Ruby Module 8 | 9 | =end 10 | require 'getoptlong' 11 | require 'gobo/logconsole.rb' 12 | require "open3" 13 | #require 'process' 14 | 15 | def Dir.empty?(dir) 16 | begin 17 | return Dir.entries(dir).length == 2 18 | rescue Errno::ENOENT 19 | return true 20 | end 21 | end 22 | 23 | module Gobo 24 | DEFAULT_ARCH = "i686" 25 | def Gobo.RealPath (symLink) 26 | return `readlink -f #{symLink}`.chomp 27 | end 28 | 29 | def Gobo.goodLink?(symlink) 30 | return false unless FileTest.symlink?(symlink) 31 | return FileTest.exists?(File.readlink(symlink)) 32 | end 33 | 34 | def Gobo.brokenLink?(symlink) 35 | return false unless FileTest.symlink?(symlink) 36 | return ! FileTest.exists?(File.readlink(symlink)) 37 | end 38 | 39 | def Gobo.smartNumber(number) 40 | string = number.to_s 41 | return string unless string.include? "." 42 | string[0, string.index('.') + 3] 43 | end 44 | 45 | def Gobo.smartSize(size) 46 | return size.to_s + " bytes" if size > 0 and size < 1023.99 47 | return "#{smartNumber(size / 1024.to_f)} Kb (#{smartNumber(size)} bytes)" if size >= 1024 and size < 1048576 48 | return "#{smartNumber(size / 1048576.to_f)} Mb (#{smartNumber(size)} bytes)" if size >= 1048576 and size < 1073741824 49 | return "#{smartNumber(size / 1073741824.to_f)} Gb (#{smartNumber(size)} bytes)" if size >= 1073741824 and size < 1099511627776 50 | return "#{smartNumber(size / 1099511627776.to_f)} Tb (#{smartNumber(size)} bytes)" if size >= 1099511627776 and size < 1125899906842624 51 | return "#{smartNumber(size / 1125899906842624.to_f)} Pb (#{smartNumber(size)} bytes)" if size >= 1125899906842624 52 | end 53 | 54 | def Gobo.getUsername 55 | name = ENV['USER'] 56 | if Process.uid == 0 && (name == "gobo" || name == "root") 57 | if ENV["SUDO_USER"] 58 | name = ENV["SUDO_USER"] 59 | else 60 | puts "You are currently logged in as #{ENV['USER']}." 61 | puts "Please enter your regular user name so this devel version" 62 | $stdout.print "can be properly tagged: " 63 | $stdout.flush 64 | name = $stdin.gets 65 | end 66 | end 67 | return name 68 | end 69 | 70 | def Gobo.chdir(dir, &block) 71 | Dir.chdir(dir) { 72 | block.call 73 | } 74 | # begin 75 | # pwd = Dir.getwd 76 | # Dir.chdir(dir) 77 | # block.call(pwd) 78 | # rescue 79 | # raise 80 | # ensure 81 | # Dir.chdir(pwd) 82 | # end 83 | end # End of Gobo.chdir 84 | 85 | def Gobo.smartPOpen(cmd, txt, block = nil) 86 | $stdout << "exec:" << cmd << "\n" 87 | IO.popen(cmd, "r") { |io| 88 | io.each { |msg| 89 | block.call("STDOUT:#{txt}#{msg}") 90 | } 91 | } 92 | # stdin, stdout, stderr = Open3.popen3(cmd) 93 | # readers = Array[stdout, stderr, $stdin] 94 | # $stdout << readers.inspect << "\n" 95 | # $stdout << readers.inspect << "\n" 96 | # # (read, write, error) = select(readers,10) 97 | # select(readers,10) 98 | end # End of Gobo.smartPOpen 99 | 100 | def Gobo.parseConfig(filename) 101 | conf = Hash.new 102 | File.open(filename) { |file| 103 | data = file.read().chomp! 104 | data.gsub!(/\n(\s+)/, '\1') 105 | data.split(/\n/).each { |entry| 106 | (name, value) = entry.split(/: /) 107 | conf[name] = value 108 | } 109 | } 110 | return conf 111 | end # End of Gobo.parseConfig 112 | end # End of Module Gobo 113 | 114 | module GoboPath 115 | rubyblock = `GoboPath2Ruby` 116 | eval rubyblock 117 | end 118 | 119 | class GoboApplication 120 | include GoboLogConsole 121 | public 122 | attr_accessor :description, :credits, :usage, :example 123 | attr_accessor :notes, :helpOnNoArguments 124 | attr_reader :name, :version, :startDir 125 | 126 | public 127 | def initialize() 128 | # Add default switches 129 | @options = Hash.new 130 | addOptionBoolean("help", ["-h"], "Display this help") 131 | addOptionBoolean("version", ["-v"], "Show program version") 132 | addOptionBoolean("verbose", ["-V"], "Enable verbose mode") 133 | addOptionBoolean("debug", [], "Enable debug mode") 134 | 135 | @name = File.basename($0) 136 | @version = File.basename(File.dirname(File.dirname(Gobo.RealPath("#{$0}")))) 137 | @startDir = Dir.getwd 138 | $startDir = @startDir 139 | setLogLevel(LogLevelNormal) 140 | # setLogLevel(LogLevelDebug) 141 | end 142 | 143 | def start() 144 | # Save argument list 145 | @savedArgs = ARGV.clone 146 | # Fill getopts with array of arrays for GetoptLong 147 | getopts = Array.new 148 | @options.each do |key, value| 149 | if value["type"] == "entry" 150 | if value["value"] == nil 151 | flag = GetoptLong::REQUIRED_ARGUMENT 152 | else 153 | flag = GetoptLong::OPTIONAL_ARGUMENT 154 | end 155 | elsif value["type"] == "list" 156 | flag = GetoptLong::OPTIONAL_ARGUMENT 157 | else 158 | flag = GetoptLong::NO_ARGUMENT 159 | end 160 | getopts.push( ["--#{key}", value["switches"], flag].flatten) 161 | end 162 | 163 | # Process options 164 | begin 165 | opts = GetoptLong.new(*getopts) 166 | opts.quiet=true 167 | opts.each { |opt, arg| 168 | value = @options[opt[2..-1]] 169 | case value["type"] 170 | when "boolean" 171 | value["value"] = true 172 | when "entry" 173 | value["value"] = arg if arg.length > 0 174 | when "list" 175 | value["value"] = arg.split(":") 176 | end 177 | } 178 | rescue GetoptLong::InvalidOption =>msg 179 | logVerbose "Invalid option: #{msg}" 180 | end 181 | 182 | help if options("help") 183 | help if ARGV.size == 0 && helpOnNoArguments == true 184 | version if options("version") 185 | setLogLevel(LogLevelVerbose) if options("verbose") 186 | setLogLevel(LogLevelDebug) if options("debug") 187 | run() 188 | end 189 | 190 | def stop(msg = nil) 191 | logError "#{msg}" if msg 192 | exit(0) 193 | end 194 | 195 | def run() 196 | end 197 | 198 | def options(key) 199 | @options[key]["value"] 200 | end 201 | 202 | def setOption (name, value = true) 203 | @options[name]["value"] = value 204 | end 205 | 206 | def addOption (type, name, switches, description, default) 207 | # Make sure switches is an array 208 | switches = [switches] unless switches.is_a?(Array) 209 | @options[name] = {"switches" => switches, "type" => type, 210 | "description" => description, "value" => default} 211 | end 212 | def addOptionBoolean (name, switches, description) 213 | addOption("boolean", name, switches, description, false) 214 | end 215 | 216 | def addOptionEntry (name, switches, description, default = nil) 217 | addOption("entry", name, switches, description, default) 218 | end 219 | 220 | def addOptionList (name, switches, description, default = nil) 221 | addOption("list", name, switches, description, default) 222 | end 223 | 224 | def version() 225 | logNormal "#{@name} #{@version}" 226 | logNormal "" 227 | logNormal @credits if @credits 228 | stop() 229 | end 230 | 231 | def help() 232 | logNormal @description if @description 233 | logNormal "" 234 | logNormal "Usage: #{@name} #{@usage}" 235 | logNormal 236 | logNormal "Options:" 237 | @options.sort.each do |x| 238 | (key, value) = x 239 | case value["type"] 240 | when "boolean" 241 | logNormal " --#{key}, " << value["switches"].join(", ") 242 | logNormal " #{value["description"]}" 243 | when "entry" 244 | logNormal " --#{key}, " << value["switches"].join(", ") << "" 245 | logNormal " #{value["description"]}" 246 | logNormal " The default value is #{value["value"]}" if value["value"] 247 | when "list" 248 | logNormal " --#{key}, " << value["switches"].join(", ") << "[:...]" 249 | logNormal " #{value["description"]}" 250 | logNormal " The default value is #{value["value"]}" if value["value"] 251 | end 252 | end 253 | logNormal "\n\nNotes:\n #{@notes}\n" if @notes 254 | logNormal "Examples:\n #{@name} #{@example}" if @example 255 | stop() 256 | end 257 | 258 | def verifySuperuser 259 | if Process.uid != 0 260 | logVerbose "Running as superuser..." 261 | # Revalidate password for another 5 mins" 262 | system 'sudo -u "#0" -v' 263 | # Run with superuser's HOME. 264 | exec "sudo " << ["-u", "\"#0\"", "-H", $0, "#{@savedArgs.join(' ')}"].join(" ") 265 | end 266 | end # End of verifySuperuser 267 | 268 | end # End of GoboApplication 269 | 270 | class GoboCallbacks < Hash 271 | public 272 | def initialize() 273 | super() 274 | end 275 | 276 | def addCallback(callName, aProc = nil) 277 | if (aProc != nil) 278 | if aProc.respond_to? :call 279 | self[callName] = aProc 280 | else 281 | raise "#{callName} callback has no call method" 282 | end 283 | else 284 | self[callName] = proc { |args| 285 | yield *args 286 | } 287 | end 288 | end 289 | 290 | def call(callName, *args) 291 | self[callName].call(*args) if self[callName] 292 | end 293 | 294 | protected 295 | def []=(callName, aProc) 296 | if callName && (aProc.respond_to? :call) 297 | super 298 | else 299 | raise "#{callName} callback has no call method" 300 | end 301 | end 302 | private 303 | def checkSelf 304 | self.each { |callName, aProc| 305 | raise "#{callName} callback has no call method" if aProc.respond_to? :call 306 | } 307 | end 308 | end 309 | -------------------------------------------------------------------------------- /bin/NewVersion: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source ScriptFunctions 4 | Import File 5 | Import Log 6 | Import OptionParser 7 | Import GoboLinux 8 | Import Array 9 | 10 | ### Options ################################################################### 11 | 12 | scriptDescription="Update a recipe to a new version." 13 | scriptCredits="Copyright (C) 2003, Hisham Muhammad - Released under the GNU GPL." 14 | helpOnNoArguments=yes 15 | scriptUsage=" (url)" 16 | scriptNotes="Optimistically, it assumes only the version number has changed, "\ 17 | "and the compilation process is still identical. The generated recipe is "\ 18 | "better understood as a 'template' for the new version recipe." 19 | scriptExample='Allegro 4.1.12, NewVersion --source 0.9.7 Wine 0.9.14' 20 | 21 | Add_Option_Entry "s" "source" "Recipe version number to use as a base for the new version" "" 22 | Add_Option_Entry "n" "former-name" "App name of the Recipe to use as a base. Only necessary if it's different from the name of the new Recipe" "" 23 | Add_Option_Boolean "k" "keep-existing" "Keep existing recipe if one already exists" 24 | Parse_Options "$@" 25 | 26 | Parse_Conf Compile.conf 27 | Import Compile 28 | 29 | unset packagename versionnumber 30 | 31 | Check_Dir_Variable compileRecipesDir 32 | [ ! -w "$compileRecipesDir" -o ! -x "$compileRecipesDir" ] && chown `whoami` "${compileRecipesDir}" 33 | 34 | if [ -z "$(Arg 2)" ] 35 | then 36 | Die "Please specify a package and version number. See --help." 37 | fi 38 | 39 | app="$(Arg 1)" 40 | newversion="$(Arg 2)" 41 | newurl="$(Arg 3)" 42 | 43 | [ -d "$compileRecipesDir/$app" ] && [ ! -w "$compileRecipesDir/$app" -o ! -x "$compileRecipesDir/$app" ] && chown `whoami` "$compileRecipesDir/$app" 44 | [ -d "$compileRecipesDir/$app/$newversion" ] && [ ! -w "$compileRecipesDir/$app/$newversion" -o ! -x "$compileRecipesDir/$app/$newversion" ] && chown -R `whoami` "$compileRecipesDir/$app/$newversion" 45 | 46 | if Is_Entry "former-name" 47 | then srcApp="`Entry "former-name"`" 48 | else srcApp="$app" 49 | fi 50 | 51 | if Is_Entry "source" 52 | then sourceVersion="`Entry "source"`" 53 | else sourceVersion='' 54 | fi 55 | 56 | bakedrecipedir=`GetRecipe "$srcApp" "$sourceVersion"` 57 | [ "$bakedrecipedir" ] || Die "Error getting recipe" 58 | Log_Normal "Recipe found in $bakedrecipedir" 59 | 60 | [ -f "$bakedrecipedir/Recipe" ] || Die "$bakedrecipedir/Recipe not found" 61 | oldrecipe=$bakedrecipedir/Recipe 62 | source $oldrecipe 63 | 64 | if Is_Entry "former-name" 65 | then packagename="$app" 66 | else packagename=`Get_Token "$bakedrecipedir" "/" "-2"` 67 | fi 68 | 69 | oldversionandrevision=`Get_Token "$bakedrecipedir" "/" "-1"` 70 | oldversion=`String_Version "$oldversionandrevision"` 71 | 72 | oldrecipedir="$bakedrecipedir" 73 | 74 | if [ "$oldversion" = "$newversion" -a ! "$newurl" ] || [ "$newversion" = "$oldversionandrevision" -a ! "$newurl" ] 75 | then 76 | Die "Current version is already $newversion." 77 | elif [ "$cvs" -o "$svn" -o "$git" -o "$bzr" -o "$hg" ] 78 | then 79 | Die "NewVersion does not support upgrading cvs/svn/git/bzr/hg recipes." 80 | fi 81 | 82 | Log_Normal "Creating recipe for $packagename $newversion based on $oldversionandrevision." 83 | 84 | destinationDir="$compileRecipesDir" 85 | newrecipedir="$destinationDir/$packagename/$newversion" 86 | 87 | mkdir -p "$destinationDir/$packagename" 88 | if [ "$oldrecipedir" = "$newrecipedir" ] 89 | then 90 | Log_Question "There is already a recipe for $packagename $newversion, at" 91 | Log_Question "$oldrecipedir" 92 | Boolean "keep-existing" && exit 0 93 | if ! Ask "Create another?" 94 | then 95 | exit 0 96 | fi 97 | else 98 | cp -R "$oldrecipedir" "$newrecipedir" 99 | fi 100 | 101 | cd "$newrecipedir" || Die "Failed creating new recipe dir." 102 | 103 | [ -e "Recipe" ] || Die "Recipe file not found." 104 | 105 | # Use -a to avoid considering the file as binary if there are multibyte characters 106 | grep -av '# Recipe for version' Recipe > Recipe.old 107 | 108 | if [ "$compileRecipeAuthor" != "" ] 109 | then 110 | echo "# Recipe for version $newversion by $compileRecipeAuthor, on" `date` > Recipe 111 | cat Recipe.old >> Recipe 112 | else 113 | Log_Terse "Please fill in the 'compileRecipeAuthor' variable in $goboSettings/Compile/Compile.conf" 114 | mv Recipe.old Recipe 115 | fi 116 | 117 | # update compile_version 118 | sed -i '/^compile_version=/d' Recipe 119 | grep -a '# Recipe for version\|# Recipe (MakeRecipe)' Recipe > Recipe.new 120 | grep -av '# Recipe for version\|# Recipe (MakeRecipe)' Recipe > Recipe.old 121 | echo "compile_version=$scriptVersion" >> Recipe.new 122 | cat Recipe.old >> Recipe.new 123 | mv Recipe.new Recipe 124 | # Note: For a future version it might make sense to "sort" the resulting Recipe as the last step. 125 | # This way we could add/edit values in-place without worrying about order and get consistend results. 126 | 127 | if [ "$newurl" ] 128 | then 129 | # TODO: generalize mirror system 130 | newurl=`echo "$newurl" | sed 's|http://.*\.dl.sourceforge.net/sourceforge/|$httpSourceforge/|'` 131 | newurl=`echo "$newurl" | sed 's|ftp://ftp\.gnu\.org/gnu/|$ftpGnu/|'` 132 | 133 | source Recipe 134 | switchurls="s|$url|$newurl|g;" 135 | switchurls="${switchurls}s|^url=.*$|url=\"$newurl\"|g;" 136 | fi 137 | 138 | # if both old and new version are in "x.y.z" format... 139 | if echo "$oldversion;;;$newversion" | grep -aq "^[^.]\+\.[^.]\+\.[^.]\+;;;[^.]\+\.[^.]\+\.[^.]\+$" 140 | then 141 | # ...replace all "x.y" occurrences too 142 | oldmajormiddle=`echo "$oldversion" | cut -d. -f 1-2` 143 | newmajormiddle=`echo "$newversion" | cut -d. -f 1-2` 144 | switchmajormiddle="s|$oldmajormiddle|$newmajormiddle|g;" 145 | fi 146 | 147 | # convert old recipe type to new recipe type 148 | # recipe type compileprogram is renamed to configure 149 | sed -i 's/is_\(.*\)=yes/recipe_type=\1/ 150 | s/compileprogram/configure/' Recipe 151 | 152 | Escaped() { 153 | echo "$@" | sed 's,\.,\\.,g' 154 | } 155 | 156 | Update_Recipe() { 157 | recipedir=$1 158 | arch=$2 159 | oldversion_escaped=$(Escaped $oldversion) 160 | newversion_escaped=$(Escaped $newversion) 161 | if [ "$compileRecipeAuthor" != "" ] 162 | then startline=2 163 | else startline=1 164 | fi 165 | Quiet pushd $recipedir 166 | # Version-specific data should be stripped out 167 | mv Recipe Recipe.old 168 | if [ "${switchmajormiddle}" -a "${switchurls}" ] 169 | then 170 | # Test case note: use a different minor on the version and on the url 171 | # e.g., for minor in $(seq 9); do NewVersion Lua 5.1.9 http://www.lua.org/ftp/lua-5.1.${minor}.tar.gz; done 172 | switchvar="${switchurls}${startline}~1$(Escaped ${switchmajormiddle})" 173 | sed_args="${switchvar};s:${oldversion_escaped%_bin}:${newversion_escaped%_bin}:g" 174 | elif [ "${switchmajormiddle}" ] 175 | then 176 | # Test case note: use a minor different from that of the oldversion 177 | # e.g., for minor in $(seq 9); do NewVersion Lua 5.1.$minor; done 178 | switchvar="$(Escaped ${switchmajormiddle})" 179 | sed_args="s:${oldversion_escaped%_bin}:${newversion_escaped%_bin}:g;${switchvar}" 180 | elif [ "${switchurls}" ] 181 | then 182 | # Test case note: remove or add a digit from the last known version, and provide a URL 183 | # e.g., NewVersion Lua 5.9 http://www.lua.org/ftp/lua-5.9.tar.gz 184 | switchvar=${switchurls} 185 | sed_args="${switchvar};s:${oldversion_escaped%_bin}:${newversion_escaped%_bin}:g" 186 | else 187 | # Test case note: remove or add a digit from the last known version 188 | # e.g., NewVersion Lua 5.9, NewVersion Lua 5.9.0.1 189 | sed_args="s:${oldversion_escaped%_bin}:${newversion_escaped%_bin}:g" 190 | fi 191 | sed "${sed_args}" Recipe.old |\ 192 | awk ' 193 | BEGIN { skip=0; } 194 | /^file_md5s=\([^)]*$/ { skip=2; } 195 | /^file_sizes=\([^)]*$/ { skip=2; } 196 | /^file_md5s=\(.*\)$/ { skip=1; } 197 | /^file_sizes=\(.*\)$/ { skip=1; } 198 | /^file_md5=.*$/ { skip=1; } 199 | /^file_size=.*$/ { skip=1; } 200 | /^\)$/ { skip--; } 201 | { if (skip<1) print; else if (skip==1) skip=0; } 202 | ' >> Recipe 203 | 204 | rm Recipe.old 205 | 206 | unset url urls file files 207 | source Recipe 208 | 209 | if [ "$newurl" ] 210 | then 211 | [ -z "$arch" ] && url="$newurl" || Log_Terse "Not updating $arch arch with passed URL. Please check." 212 | fi 213 | 214 | if Starts_With "http:" $url 215 | then 216 | Quiet pushd "$compileArchivesDir" 217 | Log_Normal "Checking URL '$url'..." 218 | quietflag="--quiet" 219 | Boolean "verbose" && unset quietflag 220 | if ! wget -t 5 $quietflag --spider "$url" 221 | then 222 | Log_Terse "URL may be invalid. Please check." 223 | fi 224 | Quiet popd 225 | fi 226 | 227 | if ls *.patch &> /dev/null 228 | then 229 | Log_Terse "This recipe contains $arch patches. Please check if they still apply." 230 | fi 231 | 232 | if [ "$url" -o "$urls" ] 233 | then 234 | if [ "$newversion" = "git" ] 235 | then 236 | sed -i "s,\(^url=.*\),git=\"$url\",g" "$recipedir/Recipe" 237 | fi 238 | Log_Normal "Downloading source code..." 239 | if ! FetchArchive --program "$packagename" --version-number "$newversion" --no-verify-files "$recipedir/Recipe" 240 | then 241 | rm -rf "$recipedir" 242 | Die "Could not download $arch source code, aborting." 243 | fi 244 | if [ "$newversion" = "git" ] 245 | then 246 | # Do not append new file_size/file_md5 entries 247 | true 248 | elif [ "$url" ] 249 | then 250 | [ -z "${file}" ] && file="`basename $url`" 251 | filesize="`Get_Size $compileArchivesDir/$file`" 252 | filemd5="`Get_MD5 $compileArchivesDir/$file`" 253 | sed -i "s,\(^url=.*\),\1\nfile_size=$filesize\nfile_md5=$filemd5,g" "$recipedir/Recipe" 254 | else # There are multiple URLs 255 | echo "file_sizes=(" > file_sizes.tmp 256 | echo "file_md5s=(" > file_md5s.tmp 257 | Zip ' 258 | [ -z "$file" ] && file="`basename $url`" 259 | echo "`Get_Size $compileArchivesDir/$file`" >> file_sizes.tmp 260 | echo "`Get_MD5 $compileArchivesDir/$file`" >> file_md5s.tmp 261 | ' urls url files file 262 | echo ")" >> file_sizes.tmp 263 | echo ")" >> file_md5s.tmp 264 | cat Recipe file_sizes.tmp file_md5s.tmp > Recipe.new 265 | mv -f Recipe.new Recipe 266 | rm -f file_sizes.tmp file_md5s.tmp 267 | fi 268 | fi 269 | Quiet popd 270 | } 271 | 272 | Update_Recipe $newrecipedir "" 273 | for arch in ${compileSupportedArchitectures[@]} 274 | do 275 | if [ -f $newrecipedir/$arch/Recipe ] 276 | then 277 | Update_Recipe $newrecipedir/$arch $arch 278 | fi 279 | done 280 | 281 | Log_Normal "Recipe template for $packagename $newversion created" 282 | Log_Normal "Printing result ($newrecipedir/Recipe):" 283 | cat "$newrecipedir/Recipe" >&$normalFD 284 | for arch in ${compileSupportedArchitectures[@]} 285 | do 286 | if [ -f $newrecipedir/$arch/Recipe ] 287 | then 288 | Log_Normal "Printing recipe for $arch architecture:" 289 | cat "$newrecipedir/$arch/Recipe" >&$normalFD 290 | fi 291 | done 292 | Log_Normal "Done" 293 | -------------------------------------------------------------------------------- /bin/SandboxInstall: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source ScriptFunctions 4 | Import File 5 | Import GoboLinux 6 | Import OptionParser 7 | Import String 8 | Import Directories 9 | Import UnionFS 10 | 11 | helpOnNoArguments=yes 12 | scriptDescription="Runs 'make install', using a sandbox environment." 13 | scriptCredits="Copyright (C) Hisham Muhammad, 2001-2005 - Released under the GNU GPL." 14 | scriptUsage="[] [ -- ]" 15 | scriptExample="--makefile makefile.unix --target install_shared WeirdSuperLib 2.4" 16 | scriptNotes=" 17 | Normally you'll want to use Compile(1) instead. 18 | '$scriptName' is called by Compile(1). 19 | " 20 | Add_Option_Entry "t" "target" "Makefile target to be used." "install" 21 | Add_Option_Entry "f" "makefile" "Specify which makefile to use." "Makefile" 22 | Add_Option_Entry "m" "make" "Use the given variant of make (ie: cmake). Use in recipe_type={makefile,configure}" "ColorMake" 23 | Add_Option_Entry "c" "command" "Use the given command instead of make (ie: python). Options --target and --makefile are then ignored." 24 | Add_Option_Entry "a" "add-allowed" "Specify additional allowed directories or files. Colon separated list." 25 | Add_Option_Entry "u" "unmanaged-files" "Specify allowed directories or files, which should be handled as unmanaged. Colon separated list." 26 | Add_Option_Boolean "F" "no-sandbox" "Do not protect the installation with a sandbox." 27 | Add_Option_Entry "e" "expand-sandbox" "By default, the sandbox is built relative to the current "\ 28 | "directory, '.'. Passing 1 to this option will build it relative to the parent directory, '..',"\ 29 | "passing 2 relative to '../..', and so on." "" 30 | Add_Option_Boolean "l" "allow-leftovers" "When using UnionFS, do not return a failure code when it catches files outside the sandbox." 31 | 32 | Parse_Options "$@" 33 | 34 | Boolean "verbose" && verbose="--verbose" 35 | 36 | Dir_Set Sandbox || Set_Boolean "no-sandbox" 37 | 38 | if Dir_Set Sandbox 39 | then 40 | Is_Writable "${goboPrograms}" || Die "Needs write access to ${goboPrograms}" 41 | fi 42 | 43 | ### Version #################################################################### 44 | 45 | # TODO: this code is copy-and-pasted from SymlinkProgram. 46 | # It should move into functions. 47 | 48 | [ "$(Arg 2)" ] || Die "Argument missing: specify program and version." 49 | 50 | unset unionsandbox 51 | 52 | if ! Boolean "no-sandbox" 53 | then 54 | if ! Union_Is_Supported 55 | then 56 | Die "unionfs is unavailable. Cannot proceed with the installation." 57 | else 58 | Log_Normal "$(Union_Backend) is available. Using UnionSandbox." 59 | unionsandbox=yes 60 | fi 61 | fi 62 | 63 | package="`basename "$(Arg 1)" /`" 64 | package="`GuessProgramCase "$(Arg 1)"`" 65 | packageDir=`Get_Dir runtime "$package" ''` 66 | 67 | if ! Is_Directory "$packageDir" 68 | then Die "Directory $packageDir does not exist." 69 | fi 70 | 71 | installPackageDir=`Get_Dir install "$package" ''` 72 | current="$packageDir/Current" 73 | 74 | requested_version=$(Arg 2) 75 | vdir=`Get_Dir runtime "$package" "$requested_version"` 76 | if { ! Is_Directory "$vdir" ;} && { ! Boolean "no-sandbox" ;} 77 | then Die "There is no version $requested_version for package $package." 78 | fi 79 | 80 | Dir_Set Current && [ -n "$version" -a "$version" != "$requested_version" ] && ln -sfn `basename "$vdir"` "$current" 81 | version="$requested_version" 82 | 83 | # exports to UnionSandbox 84 | export unionfsPackageDir="$installPackageDir/$version" 85 | 86 | if Dir_Set Current && ! Exists "$current" 87 | then 88 | youngestdir=`ls --sort=time "$packageDir" | head -n 1` 89 | ln -s "$youngestdir" "$current" 90 | fi 91 | 92 | ### Install #################################################################### 93 | 94 | function cleanup() { 95 | # If not using UnionSandbox (i.e., --no-sandbox) 96 | # undo symlink from Settings to Defaults/Settings 97 | settings="$installPackageDir/Settings" 98 | if ! [ "$unionsandbox" ] 99 | then 100 | umount "${default_settings}" 101 | fi 102 | } 103 | 104 | function installation_failed() { 105 | cleanup 106 | Die "${1}" 107 | } 108 | 109 | trap "installation_failed 'Caught signal. Exiting...'" SIGHUP SIGINT SIGTERM 110 | 111 | Log_Normal "Installing $package..." 112 | 113 | unset $expandsandbox 114 | if Is_Entry "expand-sandbox" 115 | then 116 | for i in $(seq $(Entry "expand-sandbox")) 117 | do 118 | expandsandbox=$expandsandbox/.. 119 | done 120 | fi 121 | 122 | allowed=".$expandsandbox:$installPackageDir/$version:$packageDir/Settings" 123 | Is_Entry "add-allowed" && allowed="$allowed:$(Entry "add-allowed")" 124 | Is_Entry "unmanaged-files" && eval $(Split_String "unmanagedarray" "$(Entry "unmanaged-files")" ":") 125 | Log_Verbose "Sandbox options:" 126 | Log_Verbose "Allowed directories: ${allowed}" 127 | Log_Verbose "Unmanaged directories: ${unmanagedarray[@]}" 128 | settings="$installPackageDir/Settings" 129 | default_settings="$installPackageDir/$version/Resources/Defaults/Settings" 130 | 131 | for unmanaged in "${unmanagedarray[@]}" 132 | do 133 | # If it's not a directory (it's possible that it's a non-existant directory, but that's ok), strip one level 134 | # Also remove any $goboPrefix, since we will add it later to ensure that it is used even for recipes that don't use it 135 | [ ! -d "${unmanaged}" ] && unmanaged=$(echo "${unmanaged}" | sed -e 's,\(.*\)/[^/]*,\1,') 136 | [ "$goboPrefix" ] && unmanaged=$(echo "${unmanaged}" | sed -e 's,'"$goboPrefix"',,' ) 137 | # Make sure the directories exist 138 | Assert_Dir "${goboPrefix}${unmanaged}" 139 | Assert_Dir "${installPackageDir}/${version}/Resources/Unmanaged${unmanaged}" 140 | # Map them 141 | unmanagedmap="${installPackageDir}/${version}/Resources/Unmanaged${unmanaged}=${goboPrefix}${unmanaged}${unmanagedmap:+:${unmanagedmap}}" 142 | done 143 | 144 | if [ -n "$unionsandbox" ] 145 | then 146 | sandbox_rw="$installPackageDir/$version/.SandboxInstall_Root" 147 | rm -rf -- "$sandbox_rw" 148 | #map_settings="--map ${default_settings}=${settings}${unmanagedmap:+:${unmanagedmap}}" 149 | if [ -z "$unmanagedmap" ] 150 | then map_settings= 151 | else map_settings="--map ${unmanagedmap}" 152 | fi 153 | sandbox="UnionSandbox $verbose --writedir $sandbox_rw --sandbox $allowed $map_settings -- " 154 | fi 155 | 156 | Boolean "no-sandbox" && sandbox= 157 | 158 | # If not using UnionSandbox (i.e., --no-sandbox) 159 | # symlink Settings to Defaults/Settings 160 | if [ -z "$unionsandbox" ] 161 | then 162 | Assert_Dir $default_settings 163 | mount --bind "${default_settings}" "${settings}" 164 | fi 165 | 166 | eval `Args_To_Array args 3` 167 | 168 | if Is_Entry_Set "make" 169 | then makecmd=`Entry "make"` 170 | else makecmd="${compileMakeCommand:-ColorMake}" 171 | fi 172 | 173 | if Is_Entry "command" 174 | then $sandbox `Entry "command"` "${args[@]}" || installation_failed 175 | else $sandbox $makecmd -f "`Entry "makefile"`" installprefix="${installPackageDir}/${version}" INSIDE_GOBO_SANDBOX=1 "${args[@]}" `Entry "target"` || installation_failed 176 | fi 177 | result="$?" 178 | 179 | if [ "$unionsandbox" ] 180 | then 181 | # Postprocess contents of $sandbox_rw here 182 | Log_Normal "Postprocessing Sandbox" 183 | Quiet pushd $sandbox_rw 184 | rm -rf ./$goboData/Compile/Sources 185 | rm -rf ./$goboKernel/Objects 186 | rm -f ./$goboKernel/Kernel/Modules/*/modules.* 187 | rm -f ./$goboKernel/Devices/null 188 | rm -f ./$goboKernel/Devices/tty 189 | rm -rf ./$goboVariable/tmp/{*,.*} &> /dev/null 190 | rm -rf ./$goboVariable/cache/* 191 | rm -rf ./$goboVariable/log/* 192 | rm -rf ./$goboVariable/{run,}/mount/utab 193 | rm -rf ./$goboVariable/scrollkeeper 194 | rm -f ./$goboSettings/{passwd,passwd-,group,group-} 195 | rm -f ./$goboSettings/mtab 196 | rm -f Programs/Glibc/Settings/ld.so.cache 197 | if [ "$package" != "Python" -a -d Programs/Python ] 198 | then find Programs/Python -type f -name "*.pyc" -or -name "*.pyo" | xargs rm -f &> /dev/null 199 | fi 200 | rm -rf Users/*/.distcc 201 | rm -rf Users/*/.cache 202 | rm -rf Users/*/.cargo 203 | rm -rf Users/*/.oracle_jre_usage 204 | rmdir Users/* Users &> /dev/null 205 | find -type c | xargs rm -f &> /dev/null 206 | find -type d -name "__pycache__" | xargs rm -rf &> /dev/null 207 | find -type f -name "*__dir_opaque" | xargs rm -f &> /dev/null 208 | find -type f -name "*_HIDDEN~" | xargs rm -f &> /dev/null 209 | find -type f -name "*_DELETED~" | xargs rm -f &> /dev/null 210 | find -type f -name "\.wh.*" | xargs rm -f &> /dev/null 211 | find -type d | xargs rmdir -p --ignore-fail-on-non-empty &> /dev/null 212 | 213 | # Sometimes writes to symlinks let files appear in a previous directory of the same program. 214 | # We try to detect these cases here, moving files written there to the appropriate place. 215 | ls "./$installPackageDir" 2> /dev/null | grep -v "$version\|Current\|Settings\|Variable" | while read wrong_version 216 | do 217 | installPackageDirWrongVersion="./$installPackageDir/$wrong_version" 218 | installPackageDirVersion="$installPackageDir/$version" 219 | Log_Verbose "Fixing files copied into previous version" 220 | for file in $(ls $installPackageDirWrongVersion) 221 | do 222 | Log_Verbose "$installPackageDirWrongVersion/$file -> $installPackageDirVersion/" 223 | cp -a --no-preserve=xattr "$installPackageDirWrongVersion/$file" "$installPackageDirVersion/" 224 | done 225 | done 226 | 227 | # Aggressively move everything that was installed into other programs' dirs 228 | # back into the area of the one we are installing. 229 | [ -d ./Programs ] && for p in `ls ./Programs | grep -v "^$package$"` 230 | do 231 | for entry in ./Programs/$p/* 232 | do 233 | if Ends_With "/Settings" $entry 234 | then 235 | mkdir -p $default_settings 236 | cp -a --no-preserve=xattr $verbose $entry/* $default_settings/ 237 | elif Ends_With "/Variable" $entry 238 | then 239 | cp -a --no-preserve=xattr $verbose $entry/* $installPackageDir/Variable/ 240 | else 241 | cp -a --no-preserve=xattr $verbose $entry/* $installPackageDir/$version/ 242 | fi 243 | done 244 | rm -rf ./Programs/$p 245 | done 246 | rm -rf ./Programs 247 | 248 | # This doesn't use $goboIndex because $goboIndex is actually /usr. 249 | # This is confusing. We should clean this up. 250 | mkdir -p $default_settings 251 | cp -a --no-preserve=xattr $verbose ./$goboSystem/Index/* $installPackageDir/$version 2>/dev/null 252 | cp -a --no-preserve=xattr $verbose ./$goboSettings/* $default_settings 2>/dev/null 253 | cp -a --no-preserve=xattr $verbose ./usr/local/* $installPackageDir/$version 2>/dev/null 254 | rm -rf ./usr/local 255 | cp -a --no-preserve=xattr $verbose ./usr/* $installPackageDir/$version 2>/dev/null 256 | rm -rf ./usr 2> /dev/null 257 | rm -f $installPackageDir/$version/etc/mtab 258 | rmdir --ignore-fail-on-non-empty $installPackageDir/$version/etc 2> /dev/null 259 | rm -rf ./$goboSystem/Index 260 | rm -rf ./$goboSettings 261 | rmdir $sandbox_rw/System 2> /dev/null 262 | 263 | # lib64 -> lib 264 | if [ -d $installPackageDir/$version/lib64 ] 265 | then 266 | libfiles=$(find $installPackageDir/$version/lib -type f 2> /dev/null | wc -l | awk {'print $1'}) 267 | if [ $libfiles -eq 0 ] 268 | then 269 | rmdir $installPackageDir/$version/lib 270 | mv $installPackageDir/$version/{lib64,lib} 271 | elif [ -d $installPackageDir/$version/lib ] 272 | then 273 | cp -a --no-preserve=xattr $installPackageDir/$version/lib64/* $installPackageDir/$version/lib 274 | rm -rf -- $installPackageDir/$version/lib64 275 | fi 276 | fi 277 | 278 | # share/pkgconfig -> lib/pkgconfig 279 | if [ -d $installPackageDir/$version/share/pkgconfig ] 280 | then 281 | mkdir -p $installPackageDir/$version/lib/pkgconfig 282 | cp -a --no-preserve=xattr $installPackageDir/$version/share/pkgconfig/* $installPackageDir/$version/lib/pkgconfig/ 283 | rm -rf -- $installPackageDir/$version/share/pkgconfig 284 | fi 285 | 286 | # man -> share/man 287 | rmdir $installPackageDir/$version/man 2> /dev/null 288 | if [ -d $installPackageDir/$version/man ] 289 | then 290 | mkdir -p $installPackageDir/$version/share/man 291 | cp -a --no-preserve=xattr $installPackageDir/$version/man/* $installPackageDir/$version/share/man 292 | rm -rf -- $installPackageDir/$version/man 293 | fi 294 | 295 | rm -f $installPackageDir/$version/share/info/dir 296 | 297 | # LibTool .la files are deprecated 298 | rm -f -- $installPackageDir/$version/lib/*.la 299 | 300 | # Remove extended attributes associated with overlayfs -- it's possible that temporary overlayfs xattrs 301 | # used during the installation process marked files or directories opaque. Unless we reset those xattrs, 302 | # we may have problems with Runner when it creates a union sandbox using the overlayfs backend. 303 | fname= 304 | xattr_pattern="trusted.overlay." 305 | getfattr -P -R -d -m "$xattr_pattern" --absolute-names "$installPackageDir/$version" 2> /dev/null | while read i 306 | do 307 | if echo "$i" | grep -q "^# file:" 308 | then 309 | fname="$(echo "$i" | awk {'print $3'})" 310 | elif echo "$i" | grep -q "^${xattr_pattern}" 311 | then 312 | xattr="$(echo "$i" | cut -d= -f1)" 313 | setfattr --remove "$xattr" "$fname" 314 | fi 315 | done 316 | 317 | Quiet popd 318 | 319 | [ -d "$sandbox_rw" ] && leftovers=`(cd $sandbox_rw; find * | grep -v ${installPackageDir}/${version}-safelinking) 2>/dev/null` 320 | [ "$leftovers" ] && { 321 | Log_Normal "Left over files:\n$leftovers" 322 | if ! Boolean "allow-leftovers" 323 | then exit 21 # Remember Fibo. 324 | fi 325 | } 326 | Quiet rmdir $sandbox_rw 327 | fi 328 | 329 | cleanup 330 | exit $result 331 | -------------------------------------------------------------------------------- /bin/ContributeRecipe: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # ContributeRecipe - submits a GoboLinux recipe for review 3 | # Copyright (C) 2008-2020 Michael Homer 4 | # Copyright (C) 2020 Rune Morling 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program. If not, see . 18 | 19 | ### Imports ################################################################### 20 | 21 | source ScriptFunctions 22 | Import GoboLinux 23 | Import OptionParser 24 | Import Versions 25 | Import Archive 26 | Import RecipeTools 27 | 28 | Parse_Conf Compile/Compile.conf 29 | 30 | submissionTarget='http://recipes.gobolinux.org/review/submit?ver=1' 31 | ### Options ################################################################### 32 | 33 | scriptDescription="Contribute a recipe to the global store" 34 | scriptCredits="Copyright (C) 2008-2009 Michael Homer. Released under the GNU GPL." 35 | helpOnNoArguments=yes 36 | scriptUsage="{ | [] }" 37 | scriptExample="firefox" 38 | Add_Option_Boolean "g" "gobo" "GoboLinux developer: push straight to repo." 39 | Add_Option_Boolean "p" "pretend" "Don't really submit, just dump the report to stdout." 40 | Add_Option_Boolean "s" "show-secret" "Show secret GitHub oauth token on stdout." 41 | Parse_Options "$@" 42 | 43 | ### Utils ##################################################################### 44 | 45 | # Actually enable pretending to do a command 46 | pretend() { 47 | if Boolean "p" 48 | then 49 | echo "# $@" 50 | else 51 | "$@" 52 | fi 53 | } 54 | 55 | run_fail() { 56 | if Boolean "p" 57 | then 58 | echo "# $@" 59 | else 60 | "$@" || Die "Failed during: $@" 61 | fi 62 | } 63 | 64 | run_retry() { 65 | if Boolean "p" 66 | then 67 | echo "# $@" 68 | else 69 | for i in $(seq 3) 70 | do 71 | "$@" && return 72 | done 73 | Die "Max number of retries reached, aborting." 74 | fi 75 | } 76 | 77 | handle_description() { 78 | local name="$1" 79 | local version="$2" 80 | 81 | # Handle descriptions 82 | description="Resources/Description" 83 | if ! [ -e "$description" ] 84 | then 85 | mkdir -p Resources/ 86 | DescribeProgram -m ascii $name > "$description" 87 | if [ `cat $description | wc -c` -eq 0 ] 88 | then 89 | rm $description 90 | license="" 91 | sourcedir="$compileSourcesDir/$(echo $name | tr '[:upper:]' '[:lower:]')-$version" 92 | if [ ! -d "$sourcedir" ] 93 | then 94 | sourcedir="$compileSourcesDir/$name-$version" 95 | fi 96 | if [ -d "$sourcedir" ] 97 | then 98 | for licensefile in $sourcedir/COPYING* $sourcedir/LICENSE* $sourcedir/license* 99 | do 100 | if [ -e $licensefile ] 101 | then 102 | md5license=`md5sum $licensefile | cut -d" " -f1` 103 | case "$md5license" in 104 | # GPL3 105 | f27defe1e96c2e1ecd4e0c9be8967949) newlicense="GNU General Public License version 3" ;; 106 | d32239bcb673463ab874e80d47fae504) newlicense="GNU General Public License version 3" ;; 107 | # GPL2 Mass Ave 108 | 8ca43cbc842c2336e835926c2166c28b) newlicense="GNU General Public License version 2" ;; 109 | 18810669f13b87348459e611d31ab760) newlicense="GNU General Public License version 2" ;; 110 | 7975d4f2e1ca1e9df4dcfd94c6e1ae48) newlicense="GNU General Public License version 2" ;; 111 | cbbd794e2a0a289b9dfcc9f513d1996e) newlicense="GNU General Public License version 2" ;; 112 | e2ab865bd66f4d8e34f31582339c911a) newlicense="GNU General Public License version 2" ;; 113 | 0278281246c1e59af1ef0ae1784a4948) newlicense="GNU General Public License version 2" ;; 114 | # GPL2 Franklin St mentions Library 115 | 59530bdf33659b29e73d4adb9f9f6552) newlicense="GNU General Public License version 2" ;; 116 | 751419260aa954499f7abaabaa882bbe) newlicense="GNU General Public License version 2" ;; 117 | eb723b61539feef013de476e68b5c50a) newlicense="GNU General Public License version 2" ;; 118 | a21edfd959813dc8af8161fe3f7ffaa2) newlicense="GNU General Public License version 2" ;; 119 | 4325afd396febcb659c36b49533135d4) newlicense="GNU General Public License version 2" ;; 120 | eee1a5a93345d061765a5df481d19b7a) newlicense="GNU General Public License version 2" ;; 121 | 6d5a9d4c4d3af25cd68fd83e8a8cb09c) newlicense="GNU General Public License version 2" ;; 122 | 6ddd5335ef96fb858a138230af773710) newlicense="GNU General Public License version 2" ;; 123 | 8ef380476f642c20ebf40fecb0add2ec) newlicense="GNU General Public License version 2" ;; 124 | 9ea3144f04c41cd2eada5d3f472e6ea5) newlicense="GNU General Public License version 2" ;; 125 | 892f569a555ba9c07a568a7c0c4fa63a) newlicense="GNU General Public License version 2" ;; 126 | # GPL2 Temple Place 127 | 94d55d512a9ba36caa9b7df079bae19f) newlicense="GNU General Public License version 2" ;; 128 | 393a5ca445f6965873eca0259a17f833) newlicense="GNU General Public License version 2" ;; 129 | fdafc691aa5fb7f8e2a9e9521fef771b) newlicense="GNU General Public License version 2" ;; 130 | 0636e73ff0215e8d672dc4c32c317bb3) newlicense="GNU General Public License version 2" ;; 131 | a87895c4956801618eb9d3a4f8afe8f8) newlicense="GNU General Public License version 2" ;; 132 | c93c0550bd3173f4504b2cbd8991e50b) newlicense="GNU General Public License version 2" ;; 133 | 5574c6965ae5f583e55880e397fbb018) newlicense="GNU General Public License version 2" ;; 134 | b0c80473f97008e42e29a9f80fcc55ff) newlicense="GNU General Public License version 2" ;; 135 | bae3019b4c6dc4138c217864bd04331f) newlicense="GNU General Public License version 2" ;; 136 | 03b36fdd84f74b8d8189a202b980b67f) newlicense="GNU General Public License version 2" ;; 137 | 7b0683f0a63b15f8cc8273f96fd564a9) newlicense="GNU General Public License version 2" ;; 138 | 15fac19769be7c6091cda2f70757f064) newlicense="GNU General Public License version 2" ;; 139 | 361b6b837cad26c6900a926b62aada5f) newlicense="GNU General Public License version 2" ;; 140 | 878e3965c7b52d85827c75f5a2f3b314) newlicense="GNU General Public License version 2" ;; 141 | 526c29250ae72f6933cdc01414b9943b) newlicense="GNU General Public License version 2" ;; 142 | 9ac2e7cff1ddaf48b6eab6028f23ef88) newlicense="GNU General Public License version 2" ;; 143 | c46082167a314d785d012a244748d803) newlicense="GNU General Public License version 2" ;; 144 | # GPL2 Linux kernel 145 | d7810fab7487fb0aad327b76f1be7cd7) newlicense="GNU General Public License version 2" ;; 146 | # LGPL2 Mass Ave 147 | 55ca817ccb7d5b5b66355690e9abc605) newlicense="GNU Library General Public License version 2" ;; 148 | ac4e4df3bbeacd481df543d2b12860b3) newlicense="GNU Library General Public License version 2" ;; 149 | 252890d9eee26aab7b432e8b8a616475) newlicense="GNU Library General Public License version 2" ;; 150 | # LGPL2 Temple Place 151 | 3bf50002aefd002f49e7bb854063f7e7) newlicense="GNU Library General Public License version 2" ;; 152 | 7be2873b6270e45abacc503abbe2aa3d) newlicense="GNU Library General Public License version 2" ;; 153 | f30a9716ef3762e3467a2f62bf790f0a) newlicense="GNU Library General Public License version 2" ;; 154 | c46bda00ffbb0ba1dac22f8d087f54d9) newlicense="GNU Library General Public License version 2" ;; 155 | 1e992216ed56a0fc1b6ea4a2de2962c7) newlicense="GNU Library General Public License version 2" ;; 156 | 6e29c688d912da12b66b73e32b03d812) newlicense="GNU Library General Public License version 2" ;; 157 | # LGPL2.1 158 | fad9b3332be894bab9bc501572864b29) newlicense="GNU Lesser General Public License version 2.1" ;; 159 | d7b37bf80a3df5a65b355433ae36d206) newlicense="GNU Lesser General Public License version 2.1" ;; 160 | fbc093901857fcd118f065f900982c24) newlicense="GNU Lesser General Public License version 2.1" ;; 161 | 13b7ddb75583d236cf6855762f047e34) newlicense="GNU Lesser General Public License version 2.1" ;; 162 | e3eda01d9815f8d24aae2dbd89b68b06) newlicense="GNU Lesser General Public License version 2.1" ;; 163 | 7fbc338309ac38fefcd64b04bb903e34) newlicense="GNU Lesser General Public License version 2.1" ;; 164 | a049c5e22d3bd7bc3c9a2e9135a6d104) newlicense="GNU Lesser General Public License version 2.1" ;; 165 | # MPL1.1 166 | bfe1f75d606912a4111c90743d6c7325) newlicense="Mozilla Public License 1.1" ;; 167 | # Apache License 2.0 168 | 218532c6a293a0aef9ab37fe496c3cd2) newlicense="Apache License 2.0" ;; 169 | *) 170 | Log_Terse "Could not autodetermine licensing for writing the Description file." 171 | Ask_Continue "Press Enter to view the license file $licensefile." 172 | ${PAGER:-less} $licensefile 173 | ;; 174 | esac # esac is ridiculous. 175 | if [ "$license" = "" ] 176 | then license="$newlicense" 177 | else license="$license, $newlicense" 178 | fi 179 | fi 180 | done 181 | fi 182 | if [ "$license" = "" ] 183 | then license="***REPLACE THIS WITH THE NAME OF THE LICENSE***" 184 | fi 185 | if ! [ "$EDITOR" ] 186 | then 187 | Log_Terse "EDITOR variable is not set. Can't edit description. Use \`export EDITOR='...'\` to set it." 188 | return 0 189 | fi 190 | cat < $description 191 | [Name] $name 192 | [Summary] ***REPLACE THIS WITH A SHORT ONE LINE DESCRIPTION*** 193 | [Description] ***REPLACE THIS WITH A MORE DETAILED DESCRIPTION*** 194 | [License] $license 195 | [Homepage] ***REPLACE THIS WITH THE HOMEPAGE URL*** 196 | EOF 197 | $EDITOR $description 198 | while grep -q "***REPLACE" $description 199 | do 200 | if Ask "Description wasn't filled properly. Retry?" 201 | then $EDITOR $description 202 | else 203 | rm $description 204 | return 1 205 | fi 206 | done 207 | fi 208 | fi 209 | return 0 210 | } 211 | 212 | ### Operation ################################################################# 213 | 214 | if Boolean "p" 215 | then 216 | echo "" 217 | Log_Normal "Running with '--pretend': Will show commands but not commit changes to remotes.\n" 218 | fi 219 | 220 | # sets 'recipedir', 'program' and 'version' 221 | Set_Recipe_Program_And_Version_From_Args 222 | 223 | cd "$recipedir" 224 | 225 | handle_description "$program" "$version" 226 | 227 | RecipeLint $program $version 228 | [ $? = 2 ] && Die "Recipe failed validation. Not submitting." 229 | 230 | [ -r "$recipedir/Resources/Description" ] || Die "No description file found. Not submitting." 231 | 232 | [ -r "$recipedir/Recipe" ] || Die "Could not read Recipe file in $recipedir." 233 | 234 | # Perform some simple cleanups 235 | for i in `find $recipedir -name Recipe` 236 | do 237 | [ -w `dirname "$i"` ] || Die "Need write permissions to the recipe." 238 | sed -i.bak -e 's,$target/../Settings,$settings_target,g' \ 239 | -e 's,$target/../Variable,$variable_target,g' \ 240 | $i 241 | rm $i.bak 242 | done 243 | 244 | branch="submit-$program-$version" 245 | 246 | echo "" 247 | Log_Normal "Creating local branch "$branch" ...\n" 248 | 249 | run_fail git pull 250 | run_fail git checkout -B "$branch" 251 | run_fail git add . 252 | run_fail git commit -m "$program $version" 253 | 254 | if Boolean "gobo" 255 | then 256 | 257 | echo "" 258 | Log_Normal "GoboLinux Maintainer workflow selected ...\n" 259 | 260 | run_fail git stash 261 | run_fail cd "$compileRecipesDir" 262 | run_fail git checkout "$compileUpstreamBranch" 263 | run_fail git pull 264 | run_fail git merge "submit-$program-$version" 265 | run_fail git rebase 266 | run_retry git push 267 | run_fail git stash pop 268 | run_fail git branch -D "submit-$program-$version" 269 | 270 | else 271 | 272 | echo "" 273 | Log_Normal "GoboLinux Contributor workflow selected ...\n" 274 | 275 | pretend git config hub.protocol https 276 | hub --version &> /dev/null || Die "You need to install 'hub' to auto-submit pull-requests" 277 | 278 | echo "" 279 | Log_Normal "When using 2FA, use GITHUB_TOKEN as your password (instead of your normal GitHub password)" 280 | 281 | OAUTH_MSG="Tip: Specify '-s' to have ContributeRecipe print your oauth_token for convenience." 282 | 283 | if Boolean "s" 284 | then 285 | if [ ! -z "${GITHUB_TOKEN}" ] 286 | then 287 | OAUTH_MSG="oauth_token: ${GITHUB_TOKEN}" 288 | elif [ -f ~/.config/hub ] 289 | then 290 | OAUTH_MSG="$(grep oauth ~/.config/hub)" 291 | else 292 | OAUTH_MSG="Could not find a suitable GitHub oauth_token to display?" 293 | fi 294 | fi 295 | 296 | Log_Normal "${OAUTH_MSG}\n" 297 | 298 | run_retry hub fork --remote-name origin-fork 299 | run_retry git push --set-upstream origin-fork "submit-$program-$version" 300 | run_retry hub pull-request -p -h "origin-fork/submit-$program-$version" -m "$program $version" 301 | run_fail git checkout master 302 | fi 303 | 304 | echo "" 305 | Log_Normal "All done.\n" 306 | -------------------------------------------------------------------------------- /bin/MakeRecipe: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source ScriptFunctions 4 | Import File 5 | Import Log 6 | Import OptionParser 7 | Import GoboLinux 8 | Import Archive 9 | 10 | scriptsversion=`Get_Version Scripts Current` 11 | 12 | if echo "$scriptsversion" | grep -qi GIT || \ 13 | [ "`GuessLatest $scriptsversion 2.9.0`" = "$scriptsversion" ] 14 | then 15 | # Version is valid, proceed. 16 | : 17 | else 18 | Die "Your Scripts package is too old. Please update it by running 'InstallPackage Scripts'." 19 | fi 20 | 21 | ### Options ################################################################### 22 | 23 | scriptDescription="Create a recipe template." 24 | scriptCredits="Copyright (C) 2003, Hisham Muhammad - Released under the GNU GPL." 25 | helpOnNoArguments=yes 26 | scriptUsage="{{[ []] } | { cvs } | { svn } | { git } | { bzr } | { hg }" 27 | scriptNotes="A URL, a cvs, svn, git, bzr or hg command line should be passed as a parameter." 28 | scriptExample=("Help2Man 1.33.1 http://ftp.gnu.org/gnu/help2man/help2man_1.33.1.tar.gz 29 | DirectFB cvs :pserver:anonymous:@cvs.directfb.org:/cvs/directfb DirectFB 30 | SYSLINUX git http://www.kernel.org/pub/scm/boot/syslinux/syslinux.git") 31 | Add_Option_Boolean "F" "no-fetch" "Do not try to download the package. Assume it is already present." 32 | Add_Option_Boolean "C" "no-check" "Do not check for existing recipes for that program." 33 | Add_Option_Boolean "b" "batch" "Do not ask for confirmation." 34 | Add_Option_Boolean "" "no-check-certificate" "Do not check certificates when downloading files. NOTE: This can be dangerous!" 35 | 36 | Parse_Options "$@" 37 | 38 | unset packagename versionnumber 39 | 40 | Import Compile 41 | Parse_Conf Compile.conf 42 | 43 | ################################################## 44 | # Checking Scripts package version 45 | ################################################## 46 | 47 | wget="wget" 48 | if Boolean "no-check-certificate" 49 | then 50 | Log_Normal "NOTE: Ignoring certificates when downloading sources" 51 | wget="wget --no-check-certificate" 52 | fi 53 | 54 | [ "$PAGER" ] || PAGER=less 55 | 56 | Check_Dir_Variable compileRecipesDir 57 | [ ! -w "${compileRecipesDir}" -o ! -x "${compileRecipesDir}" ] && chown $(whoami) "${compileRecipesDir}" 58 | 59 | if [ "$(Arg 3)" ] 60 | then 61 | packagename="$(Arg 1)" 62 | versionnumber="$(Arg 2)" 63 | source_url="$(Arg 3)" 64 | elif [ "$(Arg 2)" ] 65 | then 66 | packagename="$(Arg 1)" 67 | source_url="$(Arg 2)" 68 | else 69 | source_url="$(Arg 1)" 70 | fi 71 | 72 | [ "$source_url" ] || Die "Missing parameter." 73 | echo "$source_url" | grep -q ":" || Die "Expected URL as a last parameter." 74 | 75 | # catch parameter errors using cvs 76 | if [ "$packagename" = "cvs" -a "${versionnumber:0:1}" = ":" ] 77 | then Die "You must pass the program name when using a cvs command." 78 | fi 79 | 80 | svn=no 81 | cvs=no 82 | git=no 83 | bzr=no 84 | hg=no 85 | if [ "$versionnumber" = "cvs" ] 86 | then 87 | cvs=yes 88 | cvs_server="$source_url" 89 | cvs_module="$(Arg 4)" 90 | cvs_server=`echo "$cvs_server" | sed 's,anonymous@,anonymous:@,g'` 91 | elif [ "$versionnumber" = "svn" -o "$versionnumber" = "SVN" ] 92 | then 93 | svn=yes 94 | svn_uri="$source_url" 95 | elif [ "$versionnumber" = "git" ] 96 | then 97 | git=yes 98 | git_repository="$source_url" 99 | elif [ "$versionnumber" = "bzr" ] 100 | then 101 | bzr=yes 102 | bzr_repository="$source_url" 103 | elif [ "$versionnumber" = "hg" ] 104 | then 105 | hg=yes 106 | hg_repository="$source_url" 107 | else 108 | # TODO: generalize mirror system 109 | url=`echo "$source_url" | sed -r 's|http://.*.sourceforge.net(/sourceforge)?/|$httpSourceforge/|'` 110 | url=`echo "$url" | sed 's|ftp://ftp\.gnu\.org/gnu/|$ftpGnu/|'` 111 | 112 | [ "$packagename" ] || packagename=$(Package_Name_From_Url "$source_url") 113 | [ "$versionnumber" ] || versionnumber=$(Version_Number_From_Url "$source_url") 114 | fi 115 | 116 | # Enforce some naming conventions 117 | packagename=`NamingConventions "$packagename"` 118 | 119 | if ! Boolean "no-check" && ! Boolean "batch" 120 | then 121 | if Has_Recipe pull $packagename $versionnumber 122 | then 123 | Log_Question "There is already a recipe for $packagename $versionnumber." 124 | if ! Ask "Create another?" 125 | then 126 | exit 0 127 | fi 128 | 129 | else 130 | ignorelist="\--\(cvs\|svn\|git\|bzr\|hg\)\|/\(cvs\|svn\|git\|bzr\|hg\)-r[0-9]*" 131 | sameprogramrecipe=`Which_Recipe none $packagename | grep -vi "$ignorelist"` 132 | if [ "$sameprogramrecipe" ] 133 | then 134 | Log_Question "There is already a recipe for $packagename, at" 135 | Log_Question "$sameprogramrecipe" 136 | [ "${sameprogramrecipe:0:1}" = "/" ] && packagename=$(basename $(dirname $sameprogramrecipe)) 137 | if Ask "Use 'NewVersion $packagename $versionnumber' instead of MakeRecipe?" 138 | then 139 | NewVersion "$packagename" "$versionnumber" "$source_url" 140 | exit 0 141 | fi 142 | fi 143 | fi 144 | fi 145 | 146 | if ! Boolean "batch" 147 | then 148 | unset buildtype 149 | [ "$cvs" = yes ] && buildtype="CVS" 150 | [ "$svn" = yes ] && buildtype="SVN" 151 | [ "$git" = yes ] && buildtype="GIT" 152 | [ "$bzr" = yes ] && buildtype="BZR" 153 | [ "$hg" = yes ] && buildtype="HG" 154 | 155 | if [ ! -z "$buildtype" ] 156 | then Ask_Continue "Creating recipe template for $buildtype build of $packagename." 157 | else Ask_Continue "Creating recipe template for $packagename version $versionnumber." 158 | fi 159 | fi 160 | 161 | recipedir="$compileRecipesDir/$packagename/$versionnumber" 162 | 163 | [ -d "$compileRecipesDir/$packagename" ] && [ ! -w "$compileRecipesDir/$packagename" -o ! -x "$compileRecipesDir/$packagename" ] && chown $(whoami) "$compileRecipesDir/$packagename" 164 | [ -d "$compileRecipesDir/$packagename/$versionnumber" ] && [ ! -w "$compileRecipesDir/$packagename/$versionnumber" -o ! -x "$compileRecipesDir/$packagename/$versionnumber" ] && chown -R $(whoami) "$compileRecipesDir/$packagename/$versionnumber" 165 | mkdir -p $recipedir/Resources 166 | 167 | recipefile="$recipedir/Recipe" 168 | rm -f "$recipefile" 169 | 170 | if [ "$compileRecipeAuthor" != "" ] 171 | then echo "# Recipe (MakeRecipe) for $packagename by $compileRecipeAuthor, on" `date` >> "$recipefile" 172 | echo "# Recipe for version $versionnumber by $compileRecipeAuthor, on" `date` >> "$recipefile" 173 | else Log_Terse "Please fill up 'compileRecipeAuthor' variable at $goboSettings/Compile/Compile.conf" 174 | fi 175 | 176 | echo "compile_version=$scriptVersion" >> "$recipefile" 177 | if [ "$cvs" = "yes" ] 178 | then 179 | echo "cvs=\"$cvs_server\"" >> "$recipefile" 180 | echo "cvs_module=$cvs_module" >> "$recipefile" 181 | checkoutdir="$compileSourcesDir/$packagename-cvs" 182 | fetchparams="--save-to $compileSourcesDir --save-directory $checkoutdir" 183 | elif [ "$svn" = "yes" ] 184 | then 185 | echo "svn=\"$svn_uri\"" >> "$recipefile" 186 | checkoutdir="$compileSourcesDir/$packagename-svn" 187 | fetchparams="--save-to $compileSourcesDir --save-directory $checkoutdir" 188 | elif [ "$git" = "yes" ] 189 | then 190 | echo "git=\"$git_repository\"" >> "$recipefile" 191 | checkoutdir="$compileSourcesDir/$packagename-git" 192 | fetchparams="--save-to $compileSourcesDir --save-directory $checkoutdir" 193 | elif [ "$bzr" = "yes" ] 194 | then 195 | echo "bzr=\"$bzr_repository\"" >> "$recipefile" 196 | checkoutdir="$compileSourcesDir/$packagename-bzr" 197 | fetchparams="--save-to $compileSourcesDir --save-directory $checkoutdir" 198 | elif [ "$hg" = "yes" ] 199 | then 200 | echo "hg=\"$hg_repository\"" >> "$recipefile" 201 | checkoutdir="$compileSourcesDir/$packagename-hg" 202 | fetchparams="--save-to $compileSourcesDir --save-directory $checkoutdir" 203 | else 204 | echo "url=\"$url\"" >> "$recipefile" 205 | basefile=$(basename "$source_url") 206 | file="$compileArchivesDir/$basefile" 207 | fetchparams="--save-to $compileArchivesDir" 208 | if { ! Boolean "no-fetch" ;} && Starts_With "http" "$source_url" 209 | then 210 | # Detect URLs that feature redirects, like funky "...download.php?pkg=1234" URLs. 211 | file_headers=`Temporary_File` 212 | $wget --spider --server-response "$source_url" 2> $file_headers 213 | filename=`grep -i "content-disposition:.*filename=" "$file_headers" | sed 's/.*filename=\([^;]*\).*/\1/;s/^["'\'']//;s/["'\'']$//' | uniq` 214 | if [ -z "$filename" ] 215 | then 216 | filename=`grep -i '=> .*' "$file_headers" | sed 's,.*=> .\(.*\).$,\1,' | tail -n 1` 217 | fi 218 | if [ -n "$filename" -a "$filename" != "$basefile" ] 219 | then 220 | basefile="$filename" 221 | file="$compileArchivesDir/$basefile" 222 | echo "file=\"$basefile\"" >> "$recipefile" 223 | fi 224 | rm $file_headers 225 | fi 226 | fi 227 | 228 | if ! Boolean "no-fetch" 229 | then 230 | programversion="--program $packagename --version-number $versionnumber" 231 | FetchArchive --no-verify-files $programversion $fetchparams "$recipefile" || Die "Could not fetch sources." 232 | elif ! [ -e "$file" ] 233 | then 234 | Die "--no-fetch used, but source archive is not available in ${compileArchivesDir}." 235 | fi 236 | 237 | if [ "$url" ] 238 | then 239 | echo "file_size="`Get_Size "$file"` >> "$recipefile" 240 | echo "file_md5="`Get_MD5 "$file"` >> "$recipefile" 241 | 242 | # TODO: report if multiple directories, tell the user to verify it 243 | file_contents=`Temporary_File` 244 | List_Archive_Files "$file" >> "$file_contents" 245 | # bdir=`grep "^[^/]*/$" "$file_contents" | tr -d "/" | head -n 1` 246 | bdir=`head -n 1 "$file_contents" | sed 's,^\./,,;s,/[^/]*$,,'` 247 | if [ -n "$bdir" -a "$bdir" != "$bname" ] 248 | then 249 | echo "dir='$bdir'" >> "$recipefile" 250 | fi 251 | elif [ "$cvs" = "yes" -o "$svn" = "yes" -o "$git" = "yes" -o "$bzr" = "yes" -o "$hg" = "yes" ] 252 | then 253 | file_contents=`Temporary_File` 254 | find "$checkoutdir" | sed "s,^$compileSourcesDir/,,g" >> "$file_contents" 255 | fi 256 | 257 | exitStatus=0 258 | 259 | if grep -q "CMakeLists.txt" "$file_contents" 260 | then 261 | Log_Normal "$packagename $versionnumber build system seems to be based on CMake." 262 | echo "recipe_type=cmake" >> "$recipefile" 263 | elif grep -E -q "Setup.l?hs" "$file_contents" 264 | then 265 | # Note: check Haskell Cabal before regular configure because cabal 266 | # will often invoke autoconf operations 267 | Log_Normal "$packagename $versionnumber build system seems to be based on Haskell Cabal." 268 | echo "recipe_type=cabal" >> "$recipefile" 269 | elif grep -q "configure.in$" "$file_contents" \ 270 | || grep -q "configure.ac$" "$file_contents" 271 | then 272 | Log_Normal "$packagename $versionnumber build system seems to be based on Autoconf." 273 | echo "recipe_type=configure" >> "$recipefile" 274 | if ! grep -q "configure$" "$file_contents" 275 | then echo "autogen_before_configure=yes" >> "$recipefile" 276 | fi 277 | elif grep -q "/configure$" "$file_contents" 278 | then 279 | Log_Terse "$packagename $versionnumber build system seems to have a non-Autoconf configure. You may need to add the configure_options flag." 280 | echo "recipe_type=configure" >> "$recipefile" 281 | elif grep -q "Makefile.PL$" "$file_contents" || grep -q "Build.PL$" "$file_contents" 282 | then 283 | Log_Normal "$packagename $versionnumber seems to be a Perl module." 284 | Die "Use a 'CPAN:' dependency instead." 285 | elif grep -q "Imakefile$" "$file_contents" 286 | then 287 | Log_Normal "$packagename $versionnumber build system seems to be based on imake." 288 | echo "recipe_type=xmkmf" >> "$recipefile" 289 | elif grep -q "meson.build$" "$file_contents" 290 | then 291 | Log_Normal "$packagename $versionnumber build system seems to be based on Meson." 292 | echo "recipe_type=meson" >> "$recipefile" 293 | elif grep -q "SConstruct$" "$file_contents" 294 | then 295 | Log_Normal "$packagename $versionnumber build system seems to be based on SCons." 296 | echo "recipe_type=scons" >> "$recipefile" 297 | elif ! cat "$file_contents" | cut -d"/" -f 1-2 | grep -iq makefile && \ 298 | grep -q "\.py$" "$file_contents" 299 | then 300 | Log_Normal "$packagename $versionnumber build system seems to be based on Python." 301 | echo "recipe_type=python" >> "$recipefile" 302 | else 303 | basemakefile=`grep -i "^[^/]*/Makefile$" "$file_contents" 2>/dev/null` 304 | if [ "$basemakefile" ] 305 | then 306 | Log_Normal "$packagename $versionnumber build system seems to be based on Makefiles." 307 | echo "recipe_type=makefile" >> "$recipefile" 308 | if [ "$cvs" = "yes" -o "$svn" = "yes" -o "$git" = "yes" -o "$bzr" = "yes" -o "$hg" = "yes" ] 309 | then basemakefile="$compileSourcesDir/$basemakefile" 310 | else Unpack_Archive "$file" . force "$basemakefile" 311 | fi 312 | if [ "$basemakefile" != "Makefile" ] 313 | then echo "makefile='$(basename $basemakefile)'" >> "$recipefile" 314 | fi 315 | makevars=() 316 | for var in BASEDIR DESTDIR PREFIX basedir destdir prefix 317 | do 318 | if cat "$basemakefile" | grep "^[[:blank:]]*$var[[:blank:]]*=" &> /dev/null || \ 319 | cat "$basemakefile" | grep "^[[:blank:]]*$var[[:blank:]]*?=" &> /dev/null 320 | then 321 | makevars=("${makevars[@]}" "\"$var=\$target\"") 322 | Log_Normal "Detected Makefile variable $var." 323 | fi 324 | done 325 | for var in sysconfdir 326 | do 327 | if cat "$basemakefile" | grep "^[[:blank:]]*$var[[:blank:]]*=" &> /dev/null || \ 328 | cat "$basemakefile" | grep "^[[:blank:]]*$var[[:blank:]]*?=" &> /dev/null 329 | then 330 | makevars=("${makevars[@]}" "\"$var=\$settings_target\"") 331 | Log_Normal "Detected Makefile variable $var." 332 | fi 333 | done 334 | if [ "${makevars[*]}" ] 335 | then 336 | echo "make_variables=(" >> "$recipefile" 337 | for mv in "${makevars[@]}" 338 | do 339 | echo " $mv" >> "$recipefile" 340 | done 341 | echo ")" >> "$recipefile" 342 | else 343 | Log_Normal "No variables detected. Do you want to look at the top Makefile? (Y/n)" 344 | read 345 | if [ "$REPLY" != "n" ] 346 | then 347 | $PAGER "$basemakefile" 348 | fi 349 | fi 350 | if [ "$cvs" = "no" -a "$svn" = "no" -a "$git" = "no" -a "$bzr" = "no" -a "$hg" = "no" ] 351 | then 352 | rm "$basemakefile" 353 | rmdir -p $(dirname "$basemakefile") 354 | fi 355 | else 356 | Log_Terse "Could not detect recipe type. Recipe needs to be completed manually." 357 | exitStatus=1 358 | fi 359 | fi 360 | rm -f "$file_contents" 361 | 362 | Log_Verbose "Done creating recipe template for $packagename $versionnumber." 363 | 364 | exit $exitStatus 365 | -------------------------------------------------------------------------------- /Functions/Compile: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | Import File 4 | Import RecipeTools 5 | 6 | ################################################## 7 | # Setting up variables 8 | ################################################## 9 | 10 | if [ -z "$compileRecipeDir" ] 11 | then 12 | compileRecipeDir="${compileRecipesDir}" 13 | fi 14 | 15 | compileSupportedArchitectures=("i686" "x86_64" "ppc" "arm" "sh4") 16 | 17 | ################################################## 18 | # API functions 19 | ################################################## 20 | 21 | function Check_Dir_Variable() { 22 | var="$1" 23 | eval [ "\"\${${var}}\"" ] || Die "Variable \\\$$var is not set. Please update your Compile.conf." 24 | eval Assert_Dir "\"\${${var}}\"" 25 | } 26 | 27 | # Return status: 28 | # 0 - Files were verified and are okay. 29 | # 1 - Files are corrupted 30 | # 2 - Files look incomplete 31 | # 3 - Files are missing 32 | # 4 - File cannot be verified 33 | function Verify_Files() { 34 | local myfiles=($1) 35 | local sizes=($2) 36 | local sums=($3) 37 | local use_sha=($4) 38 | if [ $use_sha == 1 ] 39 | then Get_Sum="Get_SHA" 40 | else Get_Sum="Get_MD5" 41 | fi 42 | for i in $(seq 0 $[${#myfiles[@]}-1]) 43 | do 44 | file="$compileArchivesDir/${myfiles[i]}" 45 | file_size="${sizes[i]}" 46 | file_sum="${sums[i]}" 47 | if [ -f "$file" ] 48 | then 49 | size=$(Get_Size "$file") 50 | sum=$(${Get_Sum} "$file") 51 | if [ -n "$file_size" ] && [ "$file_size" != "$size" ] 52 | then 53 | Log_Terse "Warning: $file is either not complete or corrupted." 54 | return 2 55 | elif [ -n "$file_size" ] 56 | then 57 | if [ -z "$file_sum" ] 58 | then 59 | Log_Normal "Warning: no MD5/SHA checksum." 60 | Log_Normal "Assuming $file is complete based only on size." 61 | return 0 62 | elif [ "$file_sum" = "$sum" ] 63 | then 64 | Log_Verbose "$file is complete and matches MD5/SHA checksum." 65 | else 66 | Log_Error "According to MD5/SHA checksum, $file is corrupted." 67 | return 1 68 | fi 69 | else 70 | if [ -z "$file_sum" ] 71 | then 72 | Log_Terse "Warning: no file size or MD5/SHA checksum. $file cannot be verified" 73 | return 4 74 | elif [ "$file_sum" = "$sum" ] 75 | then 76 | Log_Normal "Warning: no file size." 77 | Log_Normal "Assuming $file is complete based only on MD5/SHA checksum." 78 | return 0 79 | else 80 | Log_Error "According to MD5/SHA checksum, $file is corrupted." 81 | return 1 82 | fi 83 | fi 84 | else 85 | return 3 86 | fi 87 | done 88 | return 0 89 | } 90 | 91 | function get_url_basename() { 92 | local url="$1" 93 | if [ "$cached_bname_input" = "$url" ] 94 | then 95 | echo "$cached_bname_output" 96 | return 97 | fi 98 | bname=`basename "$url" .tar.gz` 99 | bname=`basename "$bname" .tar.bz2` 100 | bname=`basename "$bname" .tar.xz` 101 | bname=`basename "$bname" .tgz` 102 | bname=`basename "$bname" .tbz2` 103 | bname=`basename "$bname" .zip` 104 | bname=`basename "$bname" .tar.lzma` 105 | cached_bname_input="$url" 106 | cached_bname_output="$bname" 107 | echo "$bname" 108 | } 109 | 110 | function Package_Name_From_Url() { 111 | local url="$1" 112 | local bname=$(get_url_basename "$url") 113 | local packagename=`echo "$bname" | sed 's/-[[:digit:]].*//g'` 114 | local deduced=`DeduceName "README" "$packagename"` 115 | [ "$deduced" ] && packagename=$deduced 116 | echo "$packagename" 117 | } 118 | 119 | function Version_Number_From_Url() { 120 | local url="$1" 121 | local bname=$(get_url_basename "$url") 122 | local versionnumber=`echo "$bname" | sed 's/.*-\([[:digit:]].*\)/\1/;s/\///g;'` 123 | echo "$versionnumber" 124 | } 125 | 126 | Find_Recipe() { 127 | app="$1" 128 | appversion="$2" 129 | tarballurl="$3" 130 | 131 | if Has_Substring "$appversion" ":/" 132 | then 133 | tarballurl="$2" 134 | appversion=$(Version_Number_From_Url "$tarballurl") 135 | fi 136 | 137 | Find_Recipe_Program_And_Version pull "$app" "$appversion" 138 | err=$? 139 | if [ "$err" = 0 ] 140 | then 141 | echo "$recipedir/Recipe" 142 | return 0 143 | fi 144 | 145 | Find_Recipe_Program_And_Version no "$app" "" 146 | err=$? 147 | if [ "$err" = 0 ] && [ "$appversion" ] 148 | then 149 | Log_Terse "Could not find recipe for $app $appversion." 150 | { Boolean "batch" || Ask_Continue "Attempt to create recipe for version $appversion?" 151 | } && NewVersion $app $appversion "${tarballurl}" 152 | Find_Recipe_Program_And_Version no "$app" "" && { 153 | echo "$recipedir/Recipe" 154 | return 0 155 | } 156 | return 1 157 | fi 158 | 159 | Log_Error "Could not find a recipe for $app" 160 | ls $compileRecipesDir | cut -d' ' -f2 | uniq | Corrections --log-name Compile --stdin "$app">&2 161 | if [ "$tarballurl" ] 162 | then 163 | Log_Normal "Will attempt to create one based on URL '$tarballurl'..." 164 | if MakeRecipe --batch "$app" "$appversion" "$tarballurl" 165 | then 166 | Log_Normal "Will attempt to use newly created recipe..." 167 | Find_Recipe_Program_And_Version no "$app" "$appversion" && { 168 | echo "$recipedir/Recipe" 169 | return 0 170 | } 171 | fi 172 | fi 173 | 174 | return 1 175 | } 176 | 177 | Available_BuildTypes() { 178 | sed 's,.*Functions/BuildType_\(.*\)$,\1,' < <(ls "${scriptPath}/../Functions"/BuildType_*) 179 | } 180 | 181 | ################################################## 182 | # Helper functions 183 | ################################################## 184 | 185 | function is_function_set() { 186 | [ "`type -t $1`" = "function" ] 187 | } 188 | 189 | ### Future Scripts functions... ### 190 | 191 | function Run_Hook() { 192 | hook="$1" 193 | ret=0 194 | if is_function_set "$hook" 195 | then 196 | real_run_hook "$hook" || ret=$? 197 | fi 198 | for flag in "${useflags[@]}" 199 | do 200 | if is_function_set "using_${flag}_${hook}" 201 | then 202 | real_run_hook "using_${flag}_${hook}" || ret=$? 203 | fi 204 | done 205 | return $ret 206 | } 207 | 208 | function real_run_hook() { 209 | Parameters "$@" hookname 210 | hookscript=./${hookname}.sh 211 | echo "#!/bin/bash" > ${hookscript} 212 | echo "source ScriptFunctions" >> ${hookscript} 213 | echo "Import GoboLinux" >> ${hookscript} 214 | echo "Import OptionParser" >> ${hookscript} 215 | echo "Import Log" >> ${hookscript} 216 | for v in ${variablestoexport[@]} 217 | do 218 | echo "export ${v}=\"$(eval echo \$${v})\"" >> ${hookscript} 219 | done 220 | echo "source $goboSettings/Compile/Compile.conf" >> ${hookscript} 221 | echo "source ${recipe}" >> ${hookscript} 222 | [ -e "$archrecipe" ] && echo "source ${archrecipe}" >> ${hookscript} 223 | echo "$hookname" >> ${hookscript} 224 | chmod a+x "${hookscript}" 225 | "${hookscript}" 226 | rtn=$? 227 | rm -f ${hookscript} 228 | return ${rtn} 229 | } 230 | 231 | function Add_Use_Flags_Options_To_Array() { 232 | array=$1 233 | for flag in "${useflags[@]}" 234 | do 235 | if [ -n "`eval echo '$'with_$flag`" ] 236 | then 237 | eval $(Combine_Arrays $array $array with_$flag) 238 | fi 239 | done 240 | } 241 | 242 | # 243 | # do_fetch 244 | # Fetches sources 245 | # $1: [0|1] -> 1 to ignore certificates when downloading sources, 0 otherwise 246 | # returns: 247 | # 0 <- success 248 | # 1 <- Error fetching sources 249 | # 2 <- Downloaded files were corrupted 250 | # 3 <- fetch cancelled by user 251 | function do_fetch() { 252 | ignore_certificate=$1 253 | fetch_extra_params="" 254 | [[ $ignore_certificate -eq 1 ]] && fetch_extra_params="--no-check-certificate" 255 | 256 | savedir="--save-to $(echo ${sourcedir}|sed s/"\(.*\)\/${save_directory}.*"/"\1"/) --save-directory ${save_directory}" 257 | if is_scm_recipe 258 | then 259 | # If sources were already fetched, do not patch again 260 | if [ -d "${sourcedir}" ] 261 | then 262 | if [ -z "$(echo "${version}" | grep -qiE "svn|cvs|git|bzr|hg")" ] 263 | then 264 | if Boolean "lazy" 265 | then REPLY=u 266 | elif Boolean "no-web" 267 | then REPLY=u 268 | elif Boolean "batch" 269 | then REPLY=r 270 | else 271 | Log_Question "Directory '${basedir}' already exists." 272 | Ask_Option "What to do? [R]emove and check out/[B]ackup and check out/[U]se it/[C]ancel." 273 | fi 274 | case $REPLY in 275 | [Rr]) rm -rf "${basedir}" 2>/dev/null ;; 276 | [Bb]) mv "${basedir}" "${basedir}.backup"; chown -R `whoami` "${basedir}.backup" ;; 277 | [Uu]) nofetch=yes; skippatching=yes ;; 278 | [Cc]) Log_Error "Fetch cancelled by user."; return 3 ;; 279 | esac # esac is ridiculous. 280 | else skippatching=yes 281 | fi 282 | else 283 | if Boolean "no-web" 284 | then 285 | Log_Error "Files are not available and --no-web was used." 286 | return 1 287 | fi 288 | fi 289 | [ "$nofetch" = "yes" ] || FetchArchive -P "$appname" -V "$versionnumber" $verbose $batch $savedir "$recipe" "$archrecipe" $fetch_extra_params || { 290 | Log_Error "Error fetching snapshot from repository." 291 | return 1 292 | } 293 | else 294 | if ! Boolean "no-web" 295 | then 296 | FetchArchive -P "$appname" -V "$versionnumber" $verbose $batch "$recipe" "$archrecipe" $fetch_extra_params || { 297 | Log_Error "Error fetching archive(s)." 298 | return 1 299 | } 300 | else 301 | # Use sha checksum if available 302 | if [ -n "${file_shas}" ]; 303 | then Verify_Files "${files[*]}" "${file_sizes[*]}" "${file_shas[*]}" 1 304 | else Verify_Files "${files[*]}" "${file_sizes[*]}" "${file_md5s[*]}" 0 305 | fi 306 | result=$? 307 | case $result in 308 | 1) Log_Error "Files are corrupted. Exiting."; return 2 ;; 309 | 2) Boolean "batch" || Ask_Continue "Continue anyway?" || return 3 ;; 310 | 3) Log_Error "Files are not available. Exiting."; return 1 ;; 311 | esac 312 | fi 313 | fi 314 | } 315 | 316 | function do_unpack() { 317 | pfiles=` 318 | for i in "${files[@]}" 319 | do ls "$compileArchivesDir"/"$i" 320 | done 321 | ` 322 | String_To_Array files "$pfiles" 323 | 324 | if [ "$uncompress" = "no" ] 325 | then 326 | [ "$basedir" ] || basedir=$appname 327 | [ "$unpack_files" ] || unpack_files=files_in_root 328 | fi 329 | 330 | unpack=yes 331 | if [ -d "${basedirs[0]}" ] 332 | then 333 | if Boolean "lazy" 334 | then REPLY=u 335 | elif Boolean "batch" 336 | then REPLY=r 337 | else 338 | Log_Question "Directory '${basedir}' already exists." 339 | Ask_Option "What to do? [R]emove and reunpack/[B]ackup and reunpack/[U]se it/[C]ancel." 340 | fi 341 | case $REPLY in 342 | [Rr]) rm -rf "${basedir}" 2>/dev/null || rm -rf "${basedirs[0]}" ;; 343 | [Bb]) mv "${basedir}" "${basedir}.backup"; chown -R `whoami` "${basedir}.backup" ;; 344 | [Uu]) unpack=no; skippatching="yes" ;; 345 | [Cc]) exit 0 ;; 346 | esac # esac is ridiculous. 347 | fi 348 | 349 | tempdir="$appname.$versionnumber.Compile.temp" 350 | [ "$unpack" = "yes" ] && \ 351 | for ((i=0; i < ${#files[@]}; i++)) 352 | do 353 | drop=. 354 | skipdir= 355 | if [ "$unpack_files" = "files_in_root" ] 356 | then 357 | drop="${basedirs[0]}" 358 | elif [ "$unpack_files" = "inside_first" ] 359 | then 360 | if [ $i -gt 0 ] 361 | then 362 | drop="${basedirs[0]}" 363 | fi 364 | elif [ "$unpack_files" = "contents_inside_first" ] 365 | then 366 | drop="${basedirs[0]}" 367 | skipdir="${basedirs[i]}" 368 | elif [ "$unpack_files" = "dirs" ] 369 | then 370 | if [ "$i" -eq 0 ] 371 | then 372 | drop=. 373 | else 374 | drop="${basedirs[i]}" 375 | if [ ! "$keep_existing_target" ] && echo "$drop" | Quiet grep "$target" 376 | then keep_existing_target=yes 377 | fi 378 | fi 379 | fi 380 | 381 | if [ "$unpack_files" -o $i -eq 0 ]; then 382 | Quiet pushd "$compileSourcesDir" 383 | [ -d "${tempdir}" ] && rm -rf "${tempdir}" 384 | mkdir "${tempdir}" 385 | fi 386 | 387 | Log_Normal "Unpacking file ${files[i]}..." 388 | if [ "$uncompress" = "no" ] 389 | then Verbose cp -v "${files[i]}" "${tempdir}" || Die "Could not copy '${files[i]}'." 390 | else Verbose Unpack_Archive "${files[i]}" "${tempdir}" || Die "Could not unpack '${files[i]}'." 391 | fi 392 | 393 | if [ "$unpack_files" -o $i -eq $(( ${#files[@]} - 1 )) ]; then 394 | mkdir -p "$drop" 395 | $chown -R --reference="${tempdir}" "${tempdir}" 396 | Quiet mv "${tempdir}"/"$skipdir"/* "${tempdir}"/"$skipdir"/.[A-z]* "$drop" 397 | rm -rf "${tempdir}" 398 | Quiet popd 399 | fi 400 | done 401 | if [ "$unpack" = "no" ] 402 | then skippatching=yes 403 | fi 404 | } 405 | 406 | function do_patch() { 407 | pushd "${basedir}" &> /dev/null 408 | 409 | # Store state of nullglob and then set it explicitly 410 | shopt nullglob &>/dev/null && nullglob=1 || nullglob=0 411 | shopt -s nullglob 412 | 413 | for i in "$recipedir/"*.patch "$archsubdir/"*.patch 414 | do 415 | Log_Normal "Applying patch $i..." 416 | patch -Np1 -i "$i" || Die "Failed on patch $i" 417 | done 418 | # restore state of nullglob 419 | [ "1" = "$nullglob" ] || shopt -u nullglob 420 | 421 | while read patch 422 | do 423 | Log_Verbose "Applying patch generated from ${patch}..." 424 | patch -Np1 < <(export_marked; ApplyVariables -i Compile "${patch}") || Die "Failed on patch generated from $patch" 425 | done < <(find "$recipedir" -name "*.patch.in" | sort) 426 | 427 | popd &> /dev/null 428 | } 429 | 430 | function do_configuration() { 431 | ! is_function_set ${recipe_type}_do_configuration || ${recipe_type}_do_configuration 432 | } 433 | 434 | function do_build() { 435 | ! is_function_set ${recipe_type}_do_build || ${recipe_type}_do_build 436 | } 437 | 438 | function do_install() { 439 | ! is_function_set ${recipe_type}_do_install || ${recipe_type}_do_install "${1}" "${2}" 440 | } 441 | 442 | function do_strip() { 443 | Log_Normal "Stripping executables..." 444 | [ "$STRIP" ] || STRIP=strip 445 | local d 446 | for d in bin sbin 447 | do 448 | Quiet pushd "$target/$d" 449 | for i in * 450 | do 451 | if file "$i" | grep -q -i "ELF .* executable" 452 | then Verbose $STRIP "$i" 453 | fi 454 | done 455 | Quiet popd 456 | done 457 | } 458 | 459 | function do_symlink() { 460 | local forcelink=no 461 | [ "force" == "$(Entry symlink)" ] && forcelink=yes 462 | while true 463 | do 464 | case "$1" in 465 | --force-link) forcelink=yes ; shift ;; 466 | *) break ;; 467 | esac # it still is. 468 | done 469 | 470 | if [ "$(Entry symlink)" == "no" ] && [ "$forcelink" != "yes" ] 471 | then 472 | Clean_Program_Tree "${goboPrograms}/$1/$2" || wrap_fail "Failed cleaning up tree." 473 | else 474 | unset updateoptions 475 | Boolean "batch" && updateoptions="--auto" 476 | if [ ! "$compileMetaRecipe" ] || [ "$compileMetaRecipe" -a "$update_each_settings" = "yes" ] 477 | then 478 | if ! Boolean "no-updatesettings" 479 | then UpdateSettings $updateoptions "$1" "$2" || wrap_fail "Failed updating settings." 480 | fi 481 | fi 482 | [ "$needs_safe_linking" = "yes" ] && safeopts="--libraries safe --executables safe" 483 | [ "$forcelink" = "yes" ] && forcesymlinking="--force" 484 | [ "$batch" ] && unmanaged_opts="--unmanaged install" 485 | Boolean "no-unmanaged" && unmanaged_opts="--unmanaged skip" 486 | SymlinkProgram $safeopts $unmanaged_opts $forcesymlinking ${symlink_options:+"${symlink_options[@]}"} "$1" "$2" || wrap_fail "Linking step failed." 487 | fi 488 | } 489 | 490 | function install_extras() { 491 | if [ -d "$reciperesources" ] 492 | then 493 | cp -Rf "$reciperesources" "$installprefix" || wrap_fail "Failed copying files." 494 | fi 495 | if [ -d "$archreciperesources" ] 496 | then 497 | cp -Rf "$archreciperesources" "$installprefix" || wrap_fail "Failed copying files." 498 | fi 499 | if [ "$revision" ] 500 | then 501 | echo "$revision" | tee "$installprefix/Resources/Revision" >/dev/null || wrap_fail "Failed installing file." 502 | fi 503 | 504 | if [ "$app" = "$appname" ] 505 | then 506 | CheckDependencies --mode=convert --file $recipedir/Resources/Dependencies | tee "$installprefix/Resources/Dependencies" >/dev/null 507 | fi 508 | 509 | if [ "$app" ] 510 | then name=$app 511 | else name=$appname 512 | fi 513 | unixname=`echo $name | tr "[:upper:]" "[:lower:]"`-$version 514 | docdir="$installprefix/doc/$unixname" 515 | 516 | for d in "${dirs[@]}" 517 | do 518 | Quiet pushd "$d" && { 519 | for i in COPYING LICENSE README* NEWS AUTHORS BUGS TODO COPYRIGHT ${docs:+"${docs[@]}"} 520 | do 521 | if [ -e "$d/$i" ] 522 | then 523 | mkdir -p "$docdir" || return 1 524 | cp -a "$d/$i" "$docdir" || return 1 525 | fi 526 | done 527 | Quiet popd 528 | } 529 | done 530 | 531 | if [ "${unmanaged_files[*]}" ] 532 | then 533 | rm -f -- $target/Resources/UnmanagedFiles 534 | for file in "${unmanaged_files[@]}" 535 | do echo $file | sed 's,'"$goboPrefix"'/,/,' | tee -a "$target/Resources/UnmanagedFiles" >/dev/null 536 | done 537 | if echo "${unmanaged_files[@]}" | grep -q "$goboModules" && [ "$app" != "Linux" ] 538 | then 539 | mkdir -p "$target/$(basename $goboShared)/Compile/Recompile/Linux" 540 | touch "$target/$(basename $goboShared)/Compile/Recompile/Linux/$app" 541 | fi 542 | fi 543 | return 0 544 | } 545 | 546 | function assert_requirements() { 547 | Log_Normal "Asserting that requirements are met..." 548 | Process_Requirements_File "$recipedir" 549 | } 550 | 551 | function mark_export() { 552 | export variablestoexport="$variablestoexport $*" 553 | } 554 | 555 | function export_marked() { 556 | for var in $variablestoexport 557 | do 558 | export $var 559 | done 560 | } 561 | 562 | function Get_Dependency_Variables() { 563 | dependencies_file="$1" 564 | if [ -f "$dependencies_file" ] 565 | then 566 | while read dep 567 | do 568 | depname="$(echo $dep | cut -d ' ' -f1)" 569 | depverrev="$(echo $dep | cut -d ' ' -f2)" 570 | depver="$(echo $depverrev | cut -d '-' -f1)" 571 | depdir="$(echo $dep | cut -d' ' -f4)" 572 | lowercasename=`echo $depname | tr '[:upper:]-+:' '[:lower:]___'` 573 | dep_settings_path="$(Get_Dir runtimeSettings ${depname} ${depver})" 574 | dep_variable_path="$(Get_Dir runtimeVariable ${depname} ${depver})" 575 | eval $lowercasename'_path="'"$depdir"'"' 576 | eval $lowercasename'_settings_path="'"$dep_settings_path"'"' 577 | eval $lowercasename'_variable_path="'"$dep_variable_path"'"' 578 | mark_export ${lowercasename}_path ${lowercasename}_settings_path ${lowercasename}_variable_path 579 | done < <(CheckDependencies --no-recursive --types=installed --quiet-progress --mode=all --file "$dependencies_file") 580 | fi 581 | } 582 | 583 | function Fix_Legacy_Recipe_Types() { 584 | # Backwards compability fix 585 | [ "$is_compileprogram" = "yes" ] && recipe_type="configure" 586 | [ "$is_makefile" = "yes" ] && recipe_type="makefile" 587 | [ "$is_python" = "yes" ] && recipe_type="python" 588 | [ "$is_xmkmf" = "yes" ] && recipe_type="xmkmf" 589 | [ "$is_meta" = "yes" ] && recipe_type="meta" 590 | [ "$is_meson" = "yes" ] && recipe_type="meson" 591 | [ "$is_scons" = "yes" ] && recipe_type="scons" 592 | [ "$is_manifest" = "yes" ] && recipe_type="manifest" 593 | } 594 | -------------------------------------------------------------------------------- /bin/RecipeLint: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | . ScriptFunctions 4 | Import File 5 | Import GoboLinux 6 | Import OptionParser 7 | Import RecipeTools 8 | Parse_Conf Compile/Compile.conf 9 | 10 | helpOnNoArguments=yes 11 | scriptDescription="Perform all sorts of sanity checks on a recipe." 12 | scriptCredits="(C)2005-2020 Hisham Muhammad, released under the GNU GPL." 13 | scriptUsage=" []" 14 | scriptExample="Foo 1.0" 15 | Add_Option_Boolean "t" "thorough" "Perform thorough URL/file testing (don't use cache)." 16 | Add_Option_Boolean "D" "quick-and-dirty" "cut some corners (don't download files, etc; not recommended)." 17 | Add_Option_Boolean "W" "no-web" "fully offline operation (not recommended)." 18 | Add_Option_Boolean "" "no-check-certificate" "Do not check certificates when downloading files. NOTE: This can be dangerous!" 19 | 20 | Parse_Options "$@" 21 | 22 | [ "$httpSourceforge" ] || { 23 | echo -e "\033[41;33;1mFATAL ERROR: could not load initial configuration.\033[0m" 24 | errors=$[errors+1] 25 | exit 1 26 | } 27 | 28 | # sets 'recipedir', 'program' and 'version' 29 | Set_Recipe_Program_And_Version_From_Args $(Boolean "no-web" && echo none) 30 | 31 | if Boolean "no-web" 32 | then noweb=--no-web 33 | else noweb= 34 | fi 35 | 36 | wget="wget" 37 | if Boolean "no-check-certificate" 38 | then 39 | Log_Normal "NOTE: Ignoring certificates when downloading sources" 40 | wget="wget --no-check-certificate" 41 | fi 42 | 43 | workingdir=$PWD 44 | lintdir=`Temporary_Dir` 45 | 46 | function finish() { 47 | cd $workingdir 48 | rm -rf $lintdir 49 | if [ $errors -gt 0 -o $warnings -gt 0 ] 50 | then 51 | echo "$errors error(s), $warnings warning(s)." >> $report 52 | echo "$errors error(s), $warnings warning(s)." 53 | echo "Report in '$report'." 54 | [ $errors -gt 0 ] && exit 2 55 | exit 1 56 | else 57 | echo "Recipe looks sane." 58 | rm $report 59 | exit 0 60 | fi 61 | } 62 | 63 | trap finish EXIT 64 | 65 | # need to get the output of utilities in English. 66 | export LANG=C 67 | export LC_ALL=C 68 | 69 | function msg() { 70 | echo "$@" 71 | echo "$@" >> $report 72 | } 73 | 74 | function WARN() { 75 | echo -e "\033[33;1mWarning: $@\033[0m" 76 | echo "Warning: $@" >> $report 77 | warnings=$[warnings+1] 78 | } 79 | 80 | function ERROR() { 81 | echo -e "\033[31;1mERROR: $@\033[0m" 82 | echo "ERROR: $@" >> $report 83 | errors=$[errors+1] 84 | } 85 | 86 | function FATAL() { 87 | echo -e "\033[41;33;1mFATAL ERROR: $@\033[0m" 88 | echo "FATAL ERROR: $@" >> $report 89 | errors=$[errors+1] 90 | exit 1 91 | } 92 | 93 | errors=0 94 | warnings=0 95 | 96 | report=$goboTemp/$program--$version.report.txt 97 | touch "$report" &> /dev/null 98 | [ -w "$report" ] || { 99 | echo "No write permission for report file '$report'." 100 | exit 1 101 | } 102 | 103 | :> $report 104 | 105 | echo 106 | msg "RecipeLint" 107 | msg "==========" 108 | msg "Checking $program $version on `date`" 109 | ############################################################################### 110 | [ "$program" == `NamingConventions $program` ] || { 111 | ERROR "Name $program does not follow naming conventions." 112 | } 113 | echo "$program--$version" | grep -q " " && { 114 | ERROR "Name or version contains spaces." 115 | } 116 | 117 | msg "Checking version number..." 118 | pureversion=`echo $version | sed 's/^\(.*\)-r[0-9]*$/\1/'` 119 | revision=`echo $version | sed -n 's/^.*-\(r[0-9]*\)$/\1/p'` 120 | echo "$pureversion" | grep -E -q "^[0-9a-z_.]+$" || { 121 | ERROR "Version $pureversion contains invalid characters (only [0-9a-z._] allowed)." 122 | } 123 | echo "$pureversion" | grep -q "[0-9]\|^cvs$\|^svn$\|^git$\|^bzr$\|^hg$" || { 124 | WARN "Version $pureversion does not contain digits, may be incorrect." 125 | } 126 | [ "$revision" ] && { 127 | purerevision="${revision#r}" 128 | [ "$purerevision" -gt 0 ] || { 129 | ERROR "Invalid revision number $revision." 130 | } 131 | } || { 132 | # WARN "No revision id." 133 | : 134 | } 135 | 136 | ############################################################################### 137 | arches=() 138 | function check_dir() { 139 | local file 140 | for file in `ls "$2"` 141 | do 142 | case "$file" in 143 | Recipe) 144 | ;; 145 | Resources) 146 | ;; 147 | *.patch|*.patch.in) 148 | echo "$file" | grep -E -q "^[0-9]+" || { 149 | [ `ls $2/*.patch | wc -l` -gt 1 ] && { 150 | ERROR "Patch file $file is not numbered; unreliable patching order." 151 | } 152 | } 153 | ;; 154 | i686|ppc|arm|sh4|x86_64|cell) 155 | [ "$1" = "root" ] && { 156 | arches=("${arches[@]}" $file) 157 | } || { 158 | WARN "Nested arch subdir $2/$file" 159 | } 160 | ;; 161 | *) 162 | WARN "Unknown file $file." 163 | ;; 164 | esac 165 | done 166 | } 167 | check_dir root "$recipedir" 168 | for arch in "${arches[@]}" 169 | do 170 | check_dir non-root "$recipedir/$arch" 171 | done 172 | ############################################################################### 173 | cd "$recipedir" 174 | msg "Checking recipe contents..." 175 | [ -f Recipe ] || { 176 | FATAL "No Recipe file." 177 | } 178 | msg "Performing basic syntax validation..." 179 | 180 | # Workaround weird bash behavior 181 | temprecipe=`Temporary_File` 182 | echo > $temprecipe 183 | cat ./Recipe >> $temprecipe 184 | bash -n $temprecipe || { 185 | rm $temprecipe 186 | FATAL "Recipe does not parse as valid shell script." 187 | } 188 | rm $temprecipe 189 | 190 | test_recipe=yes 191 | cat Recipe | perl -e ' 192 | %decls = ( 193 | is_compileprogram => "bool", 194 | is_makefile => "bool", 195 | is_python => "bool", 196 | is_xmkmf => "bool", 197 | is_manifest => "bool", 198 | is_meson => "bool", 199 | is_scons => "bool", 200 | is_meta => "bool", 201 | recipe_type => "string", 202 | compile_version => "string", 203 | environment => "array", 204 | url => "string", 205 | urls => "array", 206 | mirror_url => "string", 207 | mirror_urls => "array", 208 | file => "string", 209 | files => "array", 210 | file_size => "string", 211 | file_md5 => "string", 212 | file_sha => "string", 213 | file_sizes => "array", 214 | file_md5s => "array", 215 | file_shas => "array", 216 | uncompress => "string", 217 | unpack_files => "string", 218 | docs => "array", 219 | dir => "string", 220 | dirs => "array", 221 | include => "array", 222 | keep_existing_target => "bool", 223 | configure_options => "array", 224 | cmake_options => "array", 225 | autogen => "string", 226 | autogen_before_configure => "bool", 227 | build_in_programs => "bool", 228 | build_variables => "array", 229 | install_variables => "array", 230 | make_variables => "array", 231 | meson_variables => "array", 232 | ninja_variables => "array", 233 | scons_variables => "array", 234 | configure => "string", 235 | make => "string", 236 | makefile => "string", 237 | build_target => "string", 238 | install_target => "string", 239 | do_build => "bool", 240 | do_install => "bool", 241 | needs_build_directory => "bool", 242 | needs_safe_linking => "bool", 243 | sandbox_options => "array", 244 | symlink_options => "array", 245 | cabal_options => "array", 246 | runhaskell => "string", 247 | manifest => "array", 248 | without => "array", 249 | create_dirs_first => "bool", 250 | python_options => "array", 251 | python_major => "string", 252 | override_default_options => "bool", 253 | build_script => "string", 254 | cvs => "string", 255 | cvss => "array", 256 | cvs_module => "string", 257 | cvs_modules => "array", 258 | cvs_tag => "string", 259 | cvs_opts => "string", 260 | cvs_options => "string", 261 | cvs_checkout_options => "string", 262 | cvs_rsh => "string", 263 | cvs_password => "string", 264 | svn => "string", 265 | svns => "array", 266 | git => "string", 267 | gits => "array", 268 | bzr => "string", 269 | bzrs => "array", 270 | hg => "string", 271 | hgs => "array", 272 | tag => "string", 273 | branch => "string", 274 | unmanaged_files => "array", 275 | part_of => "string", 276 | post_install_message => "string" 277 | ); 278 | sub check_array_name { 279 | my ($name, $num) = @_; 280 | if (($decls{$name} ne "array") && !($name =~ /^with_[a-z0-9_]+$/)) { 281 | print "Error at line ".$num.": ".$name." is not a valid array.\n"; 282 | exit 1; 283 | } 284 | } 285 | sub check_var { 286 | my ($name, $value, $num) = @_; 287 | if ($decls{$name} eq "string") { 288 | } elsif ($decls{$name} eq "bool") { 289 | if ($value ne "yes" && $value ne "no") { 290 | print "Error at line ".$num.": ".$value." is not valid for ".$name." (expected yes or no).\n"; 291 | exit 1; 292 | } 293 | } elsif ($name =~ m/^with_[a-z0-9_]+$/) { 294 | } else { 295 | print "Error at line ".$num.": ".$name." is not a valid variable.\n"; 296 | exit 1; 297 | } 298 | } 299 | %functions = (); 300 | $in_shell = 0; 301 | $in_array = 0; 302 | $n = 0; 303 | while (<>) { 304 | $n++; 305 | if ($in_shell) { 306 | if (/^\}[[:blank:]]*$/) { 307 | $in_shell = 0; 308 | } else { 309 | # ignore shell contents 310 | } 311 | } elsif ($in_array) { 312 | if (/^[[:blank:]]*\)[[:blank:]]*$/) { 313 | $in_array = 0; 314 | } elsif (/^[[:blank:]]*(.*)$/) { 315 | $array_contents = $1; 316 | # TODO: check array contents 317 | } else { 318 | # TODO: check array contents 319 | } 320 | } elsif ($want_bracket) { 321 | $want_bracket = 0; 322 | if (/^[[:blank:]]*\{[[:blank:]]*$/) { 323 | $in_shell = 1; 324 | } else { 325 | print "Error at line ".$n.": expected a {\n"; 326 | print; 327 | exit 1; 328 | } 329 | } else { 330 | if (/^[[:blank:]]*#.*$/) { 331 | } elsif (/^[[:blank:]]*$/) { 332 | } elsif (/^((pre|post)_(patch|install|build|link)|private__[a-z0-9_]*)[[:blank:]]*\([[:blank:]]*\)[[:blank:]]*$/) { 333 | $fn_name = $1; 334 | if ($functions{$fn_name} == 1) { 335 | print "Error at line ".$n.": function redefinition:\n"; 336 | print; 337 | exit 1; 338 | } 339 | $functions{%fn_name} = 1; 340 | $want_bracket = 1; 341 | } elsif(/^do_(fetch|unpack|patch|configuration|build|install|symlink)\(\)/) { 342 | $fn_name = $1; 343 | if ($functions{$fn_name} == 1) { 344 | print "Error at line ".$n.": function redefinition:\n"; 345 | print; 346 | exit 1; 347 | } 348 | $functions{%fn_name} = 1; 349 | $in_shell = 1; 350 | } elsif (/^((pre|post)_(patch|install|build|link)|private__[a-z0-9_]*|using_[a-z0-9_]+|do_(fetch|unpack|patch|configuration|build|install|symlink))[[:blank:]]*\([[:blank:]]*\)[[:blank:]]*\{/) { 351 | $fn_name = $1; 352 | if ($functions{$fn_name} == 1) { 353 | print "Error at line ".$n.": function redefinition:\n"; 354 | print; 355 | exit 1; 356 | } 357 | $functions{%fn_name} = 1; 358 | $in_shell = 1; 359 | } elsif (/^([a-z][a-z0-9_]*)=\((.*)\)/) { 360 | check_array_name($1, $n); 361 | $array_contents = $2; 362 | # TODO: check contents 363 | } elsif (/^([a-z][a-z0-9_]*)=\(/) { 364 | check_array_name($1, $n); 365 | $in_array = 1; 366 | } elsif (/^([a-z][a-z0-9_]*)=([^[:blank:]\n]*)[[:blank:]]*$/ 367 | || /^([a-z][a-z0-9_]*)="([^"]*)"[[:blank:]]*$/ 368 | || /^([a-z][a-z0-9_]*)='\''([^'\'']*)'\''[[:blank:]]*$/) { 369 | check_var($1, $2, $n); 370 | $var_contents = $2; 371 | # TODO: check contents 372 | } else { 373 | print "Error at line ".$n.": unexpected construct:\n"; 374 | print; 375 | exit 1; 376 | } 377 | } 378 | } 379 | if ($in_array) { 380 | print "Error at EOF: ) not found for array construct.\n"; 381 | print "Parser expects ) by itself in a line.\n"; 382 | exit 1; 383 | } 384 | if ($in_shell) { 385 | print "Error at EOF: } not found for shell construct.\n"; 386 | print "Parser expects } by itself in the beginning of a line.\n"; 387 | exit 1; 388 | } 389 | ' || { 390 | ERROR "Recipe does not pass basic validation. Will not perform recipe tests." 391 | test_recipe=no 392 | } 393 | 394 | test_urls() { 395 | function use_cached_file() { 396 | if [ "$cached" = "yes" ] 397 | then 398 | msg "Using cached file $file from $compileArchivesDir..." 399 | spider=--spider 400 | cp "$compileArchivesDir/$file" . 401 | fi 402 | } 403 | 404 | function get_file() { 405 | if Boolean "no-web" 406 | then 407 | use_cached_file 408 | return 409 | fi 410 | if ! Boolean "thorough" 411 | then 412 | use_cached_file 413 | fi 414 | if [ "$spider" ] 415 | then msg "Checking URL..." 416 | else msg "Downloading file ($file_size bytes)..." 417 | fi 418 | if ! $wget --quiet $spider --timeout=20 --tries=3 "$url" 419 | then 420 | if [ "$mirror_url" ] 421 | then 422 | WARN "Primary URL unreacheable, trying the mirror instead..." 423 | $wget --quiet $spider --timeout=20 --tries=3 "$mirror_url" 424 | fi 425 | fi 426 | } 427 | 428 | for i in `seq 0 $[${#urls[@]}-1]` 429 | do 430 | url="${urls[$i]}" 431 | file="${files[$i]}" 432 | file_md5="${file_md5s[$i]}" 433 | file_size="${file_sizes[$i]}" 434 | if [ "$file_md5" -o "$file_size" ] 435 | then 436 | full_check=yes 437 | spider= 438 | if [ "$file_size" = "0" ] 439 | then 440 | ERROR "Zero file size specified for $url." 441 | fi 442 | else 443 | full_check=no 444 | spider=--spider 445 | fi 446 | [ "$file" ] || file=`basename "$url"` 447 | 448 | Boolean "quick-and-dirty" && continue 449 | 450 | if [ -e "$compileArchivesDir/$file" ] 451 | then cached=yes 452 | else cached= 453 | fi 454 | 455 | if [ ! "$cached" ] && [ "$file_size" ] && [ "$file_size" -gt 5000000 ] && ! Boolean "thorough" 456 | then 457 | WARN "File is big, will not download (to force, run with --thorough)." 458 | full_check=no 459 | spider=--spider 460 | fi 461 | 462 | if get_file "$url" 463 | then 464 | if [ "$full_check" = "yes" ] 465 | then 466 | if [ -e "$file" ] 467 | then 468 | if [ ${file%.gz} != $file -o ${file%.tgz} != $file ] 469 | then 470 | msg "Testing integrity of archive $file..." 471 | gunzip --test $file || { 472 | ERROR "Downloaded file $file is corrupted." 473 | } 474 | elif [ ${file%.bz2} != $file -o ${file%.tbz2} != $file ] 475 | then 476 | msg "Testing integrity of archive $file..." 477 | bunzip2 --test $file || { 478 | ERROR "Downloaded file $file is corrupted." 479 | } 480 | elif [ ${file%.zip} != $file ] 481 | then 482 | msg "Testing integrity of archive $file..." 483 | unzip -t $file || { 484 | ERROR "Downloaded file $file is corrupted." 485 | } 486 | elif [ ${file%.lzma} != $file ] 487 | then 488 | msg "Testing integrity of archive $file..." 489 | lzma -t $file || { 490 | ERROR "Downloaded file $file is corrupted." 491 | } 492 | elif [ ${file%.xz} != $file ] 493 | then 494 | msg "Testing integrity of archive $file..." 495 | xz -t $file || { 496 | ERROR "Downloaded file $file is corrupted." 497 | } 498 | elif [ ${file%.lz} != $file ] 499 | then 500 | msg "Testing integrity of archive $file..." 501 | lzip -t $file || { 502 | ERROR "Downloaded file $file is corrupted." 503 | } 504 | else 505 | WARN "Type of archive $file not detected. No integrity check performed." 506 | fi 507 | if [ "$file_sha" ] 508 | then 509 | msg "Checking SHA for $file..." 510 | [ `sha256sum "$file" | cut -d" " -f1` = "$file_sha" ] || { 511 | ERROR "SHA sum in recipe for $file does not match." 512 | } 513 | elif [ "$file_md5" ] 514 | then 515 | msg "Checking MD5 for $file..." 516 | [ `md5sum "$file" | cut -d" " -f1` = "$file_md5" ] || { 517 | ERROR "MD5 sum in recipe for $file does not match." 518 | } 519 | else 520 | WARN "No MD5/SHA sum in recipe." 521 | fi 522 | if [ "$file_size" ] 523 | then 524 | msg "Checking size for $file..." 525 | [ `wc -c "$file" | cut -d" " -f1` = "$file_size" ] || { 526 | ERROR "File size in recipe for $file does not match." 527 | } 528 | else 529 | WARN "No file size recipe." 530 | fi 531 | mv "$file" "$compileArchivesDir" 532 | else 533 | ERROR "Could not find downloaded file $file" 534 | fi 535 | else 536 | WARN "No MD5 or size -- full check on archive not performed." 537 | fi 538 | else 539 | ERROR "Unreachable URL: $url" 540 | fi 541 | done 542 | } 543 | 544 | test_recipe() { 545 | target="${goboPrograms}/$program/$version" 546 | settings_target="${goboPrograms}/$program/Settings" 547 | variable_target="${goboVariable}" 548 | source Recipe 549 | [ "$1" -a -e "$1/Recipe" ] && source "$1/Recipe" 550 | 551 | msg "Checking recipe declarations..." 552 | if [ ! "$recipe_type" ] 553 | then 554 | { 555 | if [ "$is_compileprogram" -o "$is_makefile" -o "$is_python" \ 556 | -o "$is_xmkmf" -o "$is_meta" -o "$is_manifest" ] 557 | then 558 | WARN "Recipe type is declarated in deprecated style." 559 | # Backwards compability fix 560 | [ "$is_compileprogram" = "yes" ] && recipe_type="configure" 561 | [ "$is_makefile" = "yes" ] && recipe_type="makefile" 562 | [ "$is_python" = "yes" ] && recipe_type="python" 563 | [ "$is_xmkmf" = "yes" ] && recipe_type="xmkmf" 564 | [ "$is_meta" = "yes" ] && recipe_type="meta" 565 | [ "$is_meson" = "yes" ] && recipe_type="meson" 566 | [ "$is_scons" = "yes" ] && recipe_type="scons" 567 | [ "$is_manifest" = "yes" ] && recipe_type="manifest" 568 | else 569 | ERROR "Recipe type is not declared." 570 | fi 571 | } 572 | fi 573 | case "$recipe_type" in 574 | (configure | makefile | cmake | python | xmkmf | meta | meson | scons | manifest | cabal | waf) 575 | false;; 576 | esac && ERROR "Unknown Recipe type $recipe_type specified" 577 | [ "$recipe_type" = "meta" ] && { 578 | for inc in "${include[@]}" 579 | do 580 | msg "Checking include $inc..." 581 | echo "$inc" | grep -q -- "--" || { 582 | ERROR "Include $include does not have -- separator." 583 | continue 584 | } 585 | iname="${inc%%--*}" 586 | iversion="${inc#*--}" 587 | [ "$iname" == `NamingConventions $iname` ] || { 588 | WARN "Name $iname does not follow naming conventions." 589 | } 590 | echo "$iversion" | grep -E -q "^[0-9a-z_.]+$" || { 591 | ERROR "Invalid characters in include version $iversion. Only [0-9a-z_.] allowed." 592 | } 593 | Boolean "quick-and-dirty" && continue 594 | msg "Checking availability of sub-recipe $iname $version..." 595 | Has_Recipe none "$iname" "$iversion" || { 596 | ERROR "Required recipe $iname $iversion not found in repository." 597 | } 598 | done 599 | return 600 | } 601 | [ "$url" -o "${urls[0]}" -o "$cvs" -o "$svn" -o "$git" -o "$bzr" -o "$hg" ] || { 602 | ERROR "No download location specified in recipe." 603 | } 604 | if [ "$compile_version" ] 605 | then 606 | echo "$compile_version" | grep -qi "CVS" && { 607 | ERROR "Recipe references CVS version of Compile." 608 | } 609 | echo "$compile_version" | grep -qi "SVN" && { 610 | ERROR "Recipe references SVN version of Compile." 611 | } 612 | else 613 | WARN "Recipe has no compile_version declaration." 614 | fi 615 | if [ "$unpack_files" ] 616 | then 617 | case "$unpack_files" in 618 | inside_first|contents_inside_first) 619 | [ "${#urls[@]}" -gt 1 ] || { 620 | WARN "unpack_files=$unpack_files makes no sense with only one archive." 621 | } 622 | ;; 623 | dirs) 624 | [ "${#urls[@]}" -gt 1 ] || { 625 | WARN "unpack_files=dirs makes no sense with only one archive." 626 | } 627 | [ "${#urls[@]}" -ne ${#dirs[@]} ] || { 628 | ERROR "with unpack_files=dirs, number of entries in urls and dirs must be the same." 629 | } 630 | ;; 631 | files_in_root) 632 | ;; 633 | *) 634 | ERROR "Invalid value '$unpack_files' for unpack_files." 635 | ;; 636 | esac 637 | fi 638 | declarations=( 639 | configure_options=configure 640 | autogen_before_configure=configure 641 | autogen=configure 642 | build_in_programs=configure,makefile,cmake,xmkmf,meson,scons,cabal,waf 643 | build_variables=configure,makefile,cmake,xmkmf,meson,scons,cabal,waf 644 | install_variables=configure,makefile,cmake,xmkmf,meson,scons,cabal,waf 645 | make_variables=configure,makefile,xmkmf 646 | cmake_variables=cmake 647 | configure=configure 648 | makefile=configure,makefile,cmake,xmkmf 649 | build_target=configure,makefile,cmake,xmkmf,python,meson,scons,waf 650 | install_target=configure,makefile,cmake,xmkmf,python,meson,scons,waf 651 | do_build=configure,makefile,cmake,python,cabal,waf 652 | do_install=configure,makefile,cmake,xmkmf,python,meson,scons,cabal,waf 653 | needs_build_directory=configure 654 | create_dirs_first=configure,makefile,cmake,manifest 655 | python_options=python 656 | override_default_options=python,meson,scons,configure,cabal,waf 657 | build_script=python 658 | ninja=meson 659 | ninja_variables=meson 660 | meson=meson 661 | meson_variables=meson 662 | scons=scons 663 | scons_variables=scons 664 | cabal_options=cabal 665 | runhaskell=cabal 666 | waf=waf 667 | waf_options=waf 668 | waf_variables=waf 669 | ) 670 | for decl in "${declarations[@]}" 671 | do 672 | dname="${decl%%=*}" 673 | dtypes="${decl#*=}" 674 | dtypes="${dtypes//,/ }" 675 | if eval "[ \"\$$dname\" ]" 676 | then 677 | msg "Checking $dname..." 678 | eval "ok=no 679 | for mode in $dtypes 680 | do 681 | eval '[ \"\$$dname\" -a \"\$recipe_type\" == \"'\$mode'\" ] && { ok=yes; break; }' 682 | done 683 | [ \$ok = yes ] || { 684 | ERROR \"Declaration $dname not valid in this recipes' mode.\" 685 | }" 686 | fi 687 | done 688 | 689 | function check_vars() { 690 | aname="$1" 691 | shift 692 | while [ "$1" ] 693 | do 694 | echo "$1" | grep -q "=" || { 695 | ERROR "Entry '$1' in $aname does not look like a variable assignment." 696 | } 697 | vname="${1%%=*}" 698 | echo "$vname" | grep -E -q "^[A-Za-z_][A-Za-z0-9_]*$" || { 699 | WARN "Entry '$vname' in $aname does not look like a variable name." 700 | } 701 | shift 702 | done 703 | } 704 | for vars in build_variables install_variables make_variables 705 | do 706 | eval "[ \"\${$vars[*]}\" ] && check_vars $vars \"\${$vars[@]}\"" 707 | done 708 | 709 | [ "${manifest[*]}" ] && { 710 | for mentry in "${manifest[@]}" 711 | do 712 | echo "$mentry" | grep -q ":" || { 713 | ERROR "Manifest entry '$mentry' is not of the format 'file:dir'." 714 | } 715 | done 716 | } 717 | 718 | urls=($url "${urls[@]}") 719 | files=($file "${files[@]}") 720 | file_md5s=($file_md5 "${file_md5s[@]}") 721 | file_sizes=($file_size "${file_sizes[@]}") 722 | [ "${urls[*]}" ] && test_urls 723 | 724 | msg "Looking for common error patterns..." 725 | grep -q '$goboPrograms' Recipe && { 726 | ERROR "Recipe references \$goboPrograms explicitly. Use \$target and \$_path." 727 | } 728 | # The obscure sed expression excludes url(s) variable from the check 729 | sed -e 's,#.*,,g' -e "/url/ {;/.*(/{;:loop;/.*)/b end;N; b loop;};:end;d}" Recipe | grep -q "/Programs" && { 730 | ERROR "Recipe references /Programs tree explicitly. Use \$target and \$_path." 731 | } 732 | grep -q "\$target/../Settings" Recipe && { 733 | WARN "Recipe uses old \$target/../Settings idiom. Use \$settings_target." 734 | } 735 | grep -q "\$target/../Variable" Recipe && { 736 | WARN "Recipe uses old \$target/../Variable idiom. Use \$variable_target." 737 | } 738 | sed 's,#.*,,g' Recipe | grep -q "/System[^\.]" && { 739 | ERROR "Recipe references /System tree explicitly. Use \$." 740 | } 741 | sed 's,#.*,,g' Recipe | grep "wget" | grep -q -v "url=\|urls=" && { 742 | ERROR "Recipe performs wget explicitly. Use the urls= array instead." 743 | } 744 | unset url 745 | unset file 746 | unset file_size 747 | unset file_md5 748 | unset urls 749 | unset files 750 | unset file_sizes 751 | unset file_md5s 752 | } 753 | 754 | if [ "$test_recipe" = "yes" ] 755 | then 756 | grep -q "url=\|urls=\|cvs=\|svn=\|git=\|bzr=\|hg=" Recipe && test_recipe 757 | for arch in "${arches[@]}" 758 | do 759 | [ -e "$arch/Recipe" ] || continue 760 | grep -q "url=\|urls=\|cvs=\|svn=\|git=\|bzr=\|hg=" "$arch/Recipe" && test_recipe "$arch" 761 | done 762 | fi 763 | 764 | test_resources() { 765 | msg "Checking resources..." 766 | if [ "$part_of" ] 767 | then 768 | meta=`GetRecipe "$noweb" "$part_of"` 769 | [ $? != 0 ] && ERROR "Meta-recipe $part_of not found in repository." 770 | Quiet pushd $meta 771 | fi 772 | [ -d Resources ] || { 773 | ERROR "No Resources directory." 774 | } 775 | [ -e Resources/PostInstall -a ! -x Resources/PostInstall ] && { 776 | ERROR "Resources/PostInstall must have its executable bit set." 777 | } 778 | msg "Checking Dependencies..." 779 | depfile=Resources/Dependencies 780 | if [ -f $depfile ] 781 | then 782 | grep -q "^# \*Warning\*" $depfile && { 783 | ERROR "Dependencies file contains unmatched library dependencies." 784 | } 785 | grep -q "^Perl-" $depfile && { 786 | ERROR "Dependencies file contains deprecated Perl module dependency:\n$(grep "^Perl-" $depfile)\n\nUse instead:\n$(grep "^Perl-" $depfile | sed 's,Perl-,CPAN:,g;s,-,::,g')" 787 | } 788 | missing_deps() { 789 | CheckDependencies $noweb --types=$1 --mode=all --quiet-progress --no-recursive --no-blacklist $program $version recipe $PWD | while read d_program d_version d_type d_url; 790 | do 791 | if [ "$d_type" = "None" ] 792 | then 793 | if [ "$d_version" != "None" ] 794 | then echo \"$d_program $d_version\" 795 | else echo \"$d_program\" 796 | fi 797 | fi 798 | done 799 | } 800 | 801 | eval "no_nothing=(`missing_deps recipe,official_package`)" 802 | eval "no_recipe=(`missing_deps recipe`)" 803 | j=0 804 | for prog in "${no_recipe[@]}" 805 | do 806 | noth="${no_nothing[$j]}" 807 | progname="${prog% *}" 808 | nothname="${noth% *}" 809 | if [ "$progname" = "$nothname" ] 810 | then 811 | if Boolean "no-web" 812 | then 813 | WARN "Dependency $prog not available locally (web access disabled)." 814 | else 815 | if ! $wget -q -O /dev/null http://svn.gobolinux.org/recipes/revisions/$prog 816 | then ERROR "Dependency $prog not available." 817 | else WARN "Dependency $prog is not available for public access yet." 818 | fi 819 | fi 820 | j=$[j+1] 821 | else 822 | WARN "Dependency $prog has no recipe." 823 | fi 824 | done 825 | else 826 | [ ! "$part_of" ] && ERROR "No $depfile file." 827 | fi 828 | [ "$part_of" ] && Quiet popd 829 | if [ -f Resources/Description ] 830 | then 831 | if grep -ie '^\[License\] \(GNU \)\?\(GPL\|General Public Licen[cs]e\)$' Resources/Description 832 | then 833 | ERROR "No version of GPL specified in Resources/Description." 834 | fi 835 | else 836 | WARN "No Resources/Description file." 837 | fi 838 | } 839 | 840 | cat Recipe | grep -q "recipe_type=meta" || test_resources 841 | 842 | valid_vars=" 843 | Compile_goboPrefix 844 | Compile_goboDevices 845 | Compile_goboModules 846 | Compile_goboExecutables 847 | Compile_goboHeaders 848 | Compile_goboModules 849 | Compile_goboLibraries 850 | Compile_goboPrograms 851 | Compile_goboSettings 852 | Compile_goboTemp 853 | Compile_goboVariable 854 | Compile_goboSystem 855 | Compile_goboData 856 | Compile_target 857 | Compile_settings_target 858 | Compile_variable_target 859 | " 860 | 861 | read_valid_dep_vars() 862 | { 863 | for i in `cat Resources/Dependencies | cut -d' ' -f1` 864 | do 865 | var=`echo $i | tr A-Z a-z | tr - _` 866 | valid_vars="$valid_vars 867 | Compile_$var""_path 868 | Compile_$var""_settings_path 869 | Compile_$var""_variable_path 870 | " 871 | done 872 | } 873 | 874 | test_patch() { 875 | patchfile=$1 876 | msg "Checking patch ${patchfile}..." 877 | grep -q "/Programs" "${patchfile}" && { 878 | if [ $(basename "${patchfile}" .in) = "${patchfile}" ] 879 | then instruction="Rename to ${patchfile}.in and use @%Compile_target%@ and @%Compile__path%@." 880 | else instruction="Use @%Compile_target%@ and @%Compile__path%@." 881 | fi 882 | ERROR "Patch references /Programs tree explicitly. $instruction" 883 | } 884 | grep -q "/System" "${patchfile}" && { 885 | if [ $(basename "${patchfile}" .in) = "${patchfile}" ] 886 | then instruction="Rename to ${patchfile}.in and use @%Compile_%@." 887 | else instruction="Use @%Compile_%@." 888 | fi 889 | ERROR "Patch references /System tree explicitly. $instruction" 890 | } 891 | firstrow=$(head -n1 "${patchfile}") 892 | echo ${firstrow} | grep -q '^--- ' || echo ${firstrow} | grep -q '^diff ' && 893 | WARN "Patch file ${patchfile} lacks rationale. Please consider adding reason for patch to the top of the file." 894 | 895 | for i in `sed -r '/@%[^ %]+%@/!d' $1` 896 | do 897 | var=`echo $i | sed -r '/@%[^ %]+%@/!d' | sed -r 's/^.*@%([^ %]+)%@.*$/\1/g'` 898 | if [ -n "$var" ] 899 | then 900 | if [ -z "`echo $valid_vars | grep $var`" ] 901 | then ERROR "Patch uses invalid environment variable (@%$var%@)." 902 | fi 903 | fi 904 | done 905 | } 906 | 907 | read_valid_dep_vars 908 | 909 | ls *.patch *.patch.in 2> /dev/null | while read patch 910 | do 911 | test_patch "$patch" 912 | done 913 | --------------------------------------------------------------------------------