You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							370 lines
						
					
					
						
							9.9 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							370 lines
						
					
					
						
							9.9 KiB
						
					
					
				| #!/bin/sh | |
| set -e | |
| 
 | |
| # Configuration | |
| 
 | |
| # Build/install-time directories | |
| dir_build='/tmp/astronaut/build'  # Temporary directory to build packages | |
| dir_source='/tmp/astronaut/source'  # Directory where the package sources will be placed | |
| dir_install='/tmp/astronaut/install'  # Directory where the package will be installed | |
| # The source directory will have subdirs for each different $name, | |
| #   specified inside the satellite file. | |
| # The $dir_install variable will have '{pkg}' replaced with $_satname, | |
| #   which is the filename of the satellite, without the .sat suffix. | |
| 
 | |
| # Runtime directories | |
| dir_prefix='usr'  # Prefix directory | |
| 
 | |
| # Finer-grained control of runtime dirs | |
| # This can't be set from the command line, but might need to be adapted for your distro. | |
| 
 | |
| dir_bindir='bin' | |
| dir_sbindir='sbin' | |
| dir_libexecdir='libexec' | |
| dir_sysconfdir='etc' | |
| dir_libdir='lib' | |
| dir_includedir='include' | |
| dir_datadir='share' | |
| dir_infodir='share/info' | |
| dir_localedir='share/locale' | |
| dir_mandir='share/man' | |
| dir_docdir='share/doc' | |
| 
 | |
| # Default commands | |
| cmd_download='curl -# -L -o {dst} {src}'  # Command to execute to download files | |
| cmd_extract='tar -x -C {dst} -f {src}'  # Command to execute to extract files | |
| 
 | |
| # If we can't find the satellite file,  we'll look in this directory for it. | |
| dir_satellites= | |
| 
 | |
| # Options are comma-separated and parsed from front to back. | |
| # This means that in '!opt,someotheropt,opt', opt is disabled. | |
| 
 | |
| options=  # The least-priority global options | |
| package_options() { :; }  # Per-package options function. | |
| # Example for package_options: | |
| # package_options() { | |
| #     case "$1" in | |
| #         package1) echo 'opt1,opt2,opt3' ;; | |
| #         package2) echo 'someotheropts' ;; | |
| #     esac | |
| # } | |
| 
 | |
| # Load any user configuration | |
| [ -f /etc/astronaut.conf ] && . /etc/astronaut.conf | |
| [ -f "$HOME/.astronaut.conf" ] && . "$HOME/.astronaut.conf" | |
| 
 | |
| # Options not in the configuration | |
| download_only=false | |
| _vcs_only=false | |
| _nuke_dir_install=false | |
| _user_options=  # Options specified in the command line get the highest priority | |
| _sat_options=  # Options defined by the satellite | |
| 
 | |
| # Should be specified in the satellite | |
| name= | |
| version= | |
| update_url= | |
| vcs_compile=false | |
| 
 | |
| # Check if running from a wrapper | |
| if [ "$(basename "$0")" != "astronaut" ]; then | |
|     type _astronaut_wrapper_pre > /dev/null || _astronaut_wrapper_pre() { :; } | |
|     type _astronaut_wrapper_post > /dev/null || _astronaut_wrapper_post() { :; } | |
| else | |
|     _astronaut_wrapper_pre() { :; } | |
|     _astronaut_wrapper_post() { :; } | |
| fi | |
| 
 | |
| # Some printing functions | |
| _show_help() { | |
| echo "This astronaut will help you build some satellites. | |
| Just describe what he's got to do in a satellite file. | |
| Usage: $0 [-bsip <dir>] [-hIdv] [-o <options>] <satellite>... | |
|  | |
| -h/? Show this message | |
| -b   Set build directory [WARNING: Will be deleted before build] | |
| -s   Set source directory | |
| -i   Set install directory | |
| -p   Set prefix directory | |
| -I   Nuke install directory before build [WARNING: You will not be prompted] | |
| -d   Only download package files | |
| -v   Only build vcs package if any updates have been made to it | |
| -o   Set package options (comma-separated) | |
|  | |
| Tips:$([ "$(basename "$0")" = "astronaut" ] && printf "\n- Use \`head -n 50 $0 > astronaut.conf.example\` to generate a default configuration file.") | |
| - Keep in mind that when specifying options on the command line in a string, the first always takes priority. | |
|     For example, in \"opt,someotheropt,!opt\", opt is enabled, due to it being the first occurrence. | |
| - If you have set \$dir_satellites in the config, you can omit the .sat suffix. | |
| " | |
| } | |
| 
 | |
| _msg() { | |
|     echo "=> $@" | |
| } | |
| 
 | |
| _exiterr() { | |
|     echo "===> Houston, we've got a problem: $@" 1>&2 | |
|     exit 1 | |
| } | |
| 
 | |
| # Gather info | |
| while getopts "h?s:b:i:p:IcCdvo:" opt; do | |
|     case "$opt" in | |
|         h|\?) | |
|             _show_help | |
|             exit 0 | |
|             ;; | |
|         s) | |
|             dir_source="$OPTARG" | |
|             ;; | |
|         b) | |
|             dir_build="$OPTARG" | |
|             ;; | |
|         i) | |
|             dir_install="$OPTARG" | |
|             ;; | |
|         p) | |
|             dir_prefix="$OPTARG" | |
|             ;; | |
|         I) | |
|             _nuke_dir_install=true | |
|             ;; | |
|         d) | |
|             download_only=true | |
|             ;; | |
|         v) | |
|             _vcs_only=true | |
|             ;; | |
|         o) | |
|             _user_options="$OPTARG,$_user_options" | |
|             ;; | |
|     esac | |
| done | |
| 
 | |
| shift $(expr $OPTIND - 1) | |
| [ "$1" = "--" ] && shift | |
| 
 | |
| if [ ! "$1" ]; then | |
|     _show_help | |
|     exit 1 | |
| fi | |
| 
 | |
| # Tools for the astronaut | |
| _mksum() { | |
|     echo "$(md5sum "$@" 2> /dev/null | cut -d' ' -f1)" | |
| } | |
| 
 | |
| safe_sed() { | |
|     echo "$1" | sed 's/[[&\.*^$/]/\\&/g' | |
| } | |
| 
 | |
| download() { | |
|     mkdir -p "$dir_source/$name" | |
| 
 | |
|     [ "$3" ] && local filename="$3" || local filename="$(basename $(echo "$1" | cut -d? -f1))" | |
|     local path="$dir_source/$name/$filename" | |
| 
 | |
|     [ "$2" -a -f "$path" ] && local checksum="$(_mksum "$path")" || true | |
| 
 | |
|     if [ ! -e "$path" -o "$checksum" != "$2" ]; then | |
|         _msg "Downloading $filename" | |
| 
 | |
|         [ "$4" ] && local cmd="$4" || local cmd="$cmd_download" | |
|         eval $(echo "$cmd" | sed -e "s/{dst}/'$(safe_sed "$path")'/g" -e "s/{src}/'$(safe_sed "$1")'/g") | |
| 
 | |
|         checksum="$(_mksum "$path")" | |
|         if [ "$2" -a "$checksum" != "$2" ]; then | |
|             _msg "Checksum: $checksum" | |
|             _exiterr 'Checksum failed' | |
|         fi | |
|     fi | |
| } | |
| 
 | |
| extract() { | |
|     _msg "Extracting $1" | |
|     [ "$2" ] && local dest="$2" || local dest='.' | |
|     [ "$3" ] && local cmd="$3" || local cmd="$cmd_extract" | |
|     eval $(echo "$cmd" | sed -e "s/{src}/'$(safe_sed "$dir_source/$name/$1")'/g" -e "s/{dst}/'$(safe_sed "$dest")'/g") | |
| } | |
| 
 | |
| getfile() { | |
|     cp -a "$dir_source/$name/$1" "./$1" | |
| } | |
| 
 | |
| extrafile() { | |
|     local dir="$(dirname "$_satellite")" | |
|     [ -d "$dir/extrafiles" ] && local dir="$dir/extrafiles/$name" || true | |
| 
 | |
|     cp -a "$dir/$1" "./$1" | |
| } | |
| 
 | |
| dlextract() { | |
|     download "$1" "$2" | |
|     extract "$(basename "$(echo "$1" | cut -d? -f1)")" | |
| } | |
| 
 | |
| dlfile() { | |
|     download "$1" "$2" | |
|     getfile "$(basename "$(echo "$1" | cut -d? -f1)")" | |
| } | |
| 
 | |
| option() { | |
|     local check=$1 | |
|     shift | |
| 
 | |
|     local negate=false | |
|     local variable=false | |
|     case "$check" in | |
|         =*) | |
|             local variable=true | |
|             local check="$(echo "$check" | cut -c 2-)" | |
|             ;; | |
|         !*) | |
|             local negate=true | |
|             local check="$(echo "$check" | cut -c 2-)" | |
|             ;; | |
|     esac | |
| 
 | |
|     local enabled=false | |
|     local found=false | |
|     local opt | |
|     local IFS=',' | |
|     for option in $options; do | |
|         local option_negate=false | |
|         local option_variable=false | |
|         case "$option" in | |
|             *=*) | |
|                 local value="$(echo "$option" | cut -d '=' -f 2)" | |
|                 local option="$(echo "$option" | cut -d '=' -f 1)" | |
|                 local option_variable=true | |
|                 ;; | |
|             !*) | |
|                 local option="$(echo "$option" | cut -c 2-)" | |
|                 local option_negate=true | |
|                 ;; | |
|         esac | |
| 
 | |
|         if [ "$option" = "$check" ]; then | |
|             if [ "$variable" = true -a "$option_variable" = false ]; then | |
|                 _msg 'Tip: Define the option as option=value.' 1>&2 | |
|                 _exiterr "Satellite requested a variable option, but there was no value for option: '$option'." | |
|             fi | |
| 
 | |
|             [ "$option_negate" = true ] && local enabled=false || local enabled=true | |
|             local found=true | |
|             break | |
|         fi | |
|     done | |
| 
 | |
|     if [ "$found" = false ]; then | |
|         _msg 'Tip: Make sure to define every option you use in the satellite.' 1>&2 | |
|         _exiterr "Option '$check' was nowhere to be found." | |
|     fi | |
| 
 | |
|     if [ "$variable" = true ]; then | |
|         echo "$value" | |
|         return | |
|     fi | |
| 
 | |
|     if [ "$negate" = true ]; then | |
|         # Shitty way to do a simple "NOT" operation. | |
|         [ "$enabled" = true ] && local enabled=false || local enabled=true | |
|     fi | |
| 
 | |
|     if [ "$1" ]; then | |
|         if [ "$enabled" = true ]; then | |
|             "$@" | |
|         fi | |
|     else | |
|         [ "$enabled" = true ] | |
|     fi | |
| } | |
| 
 | |
| define_option() { | |
|     local option="$(echo "$1" | cut -d ':' -f 1)" | |
|     options="$options,$option" | |
| } | |
| 
 | |
| import() { | |
|     . "$(dirname "$_satellite")/functions/$1.sh" | |
| } | |
| 
 | |
| # Set some functions in accordance to the download_only option. | |
| header_end() { :; } | |
| if [ "$_vcs_only" = true ]; then | |
|     header_end() { | |
|         if [ ! "$vcs_compile" = true ]; then | |
|             exit 1 | |
|         fi | |
|     } | |
| fi | |
| if [ "$download_only" = true ]; then | |
|     # Disable some functions | |
|     extract() { :; } | |
|     getfile() { :; } | |
|     extrafile() { :; } | |
| 
 | |
|     # Exit at the end of the header | |
|     header_end() { exit; } | |
| fi | |
| 
 | |
| # Create the directories | |
| mkdir -p "$dir_source" | |
| dir_source="$(realpath "$dir_source")" | |
| 
 | |
| if [ "$download_only" = false ]; then | |
|     mkdir -p "$dir_build" | |
|     mkdir -p "$dir_install" | |
|     dir_build="$(realpath "$dir_build")" | |
|     dir_install="$(realpath "$dir_install")" | |
| fi | |
| 
 | |
| for _satellite in "$@"; do | |
|     _satname="$(basename "$_satellite" .sat)" | |
| 
 | |
|     # Try to find the satellite file if it can't be found. | |
|     if [ ! -f "$_satellite" ]; then | |
|         if [ -d "$dir_satellites" ]; then | |
|             file="$(find "$dir_satellites" -type f \( -name "$_satname.sat" -o -name "$_satname" \) -print -quit)" | |
|             if [ -f "$file" ]; then | |
|                 _satellite="$file" | |
|                 _satname="$(basename "$_satellite" .sat)" | |
|             fi | |
|         fi | |
| 
 | |
|         # If it still can't be found, exit. | |
|         if [ ! -f "$_satellite" ]; then | |
|             _exiterr "Can't find satellite: $_satellite" | |
|         fi | |
|     fi | |
| 
 | |
|     _satellite="$(realpath "$_satellite")" | |
| 
 | |
|     ( | |
|         options="$_user_options$(package_options "$_satname"),$options" | |
| 
 | |
|         if [ "$download_only" = true ]; then | |
|             # Just download it | |
|             . "$_satellite" | |
|         else | |
|             _astronaut_wrapper_pre | |
| 
 | |
|             # Remove install dir if appropriate | |
|             if [ "$_nuke_dir_install" = true -a ! -z "$dir_install" ]; then | |
|                 rm -rf "$dir_install" | |
|                 mkdir -p "$dir_install" | |
|             fi | |
| 
 | |
|             rm -rf "$dir_build" | |
|             mkdir -p "$dir_build" | |
| 
 | |
|             # Create the satellite | |
|             options="$_user_options$(package_options "$_satname"),$options" | |
|             cd "$dir_build" | |
|             . "$_satellite" | |
| 
 | |
|             _astronaut_wrapper_post | |
|         fi | |
|     ) | |
| done
 | |
| 
 |