#!/bin/echo "This file is sourced, not run" # This file contains generic functions, presumably reusable in other contexts. # Create a blank directory at first argument, deleting existing contents if any proc blank_tempdir { # sanity test: never rm -rf something we don't own. test -z $1 && dienow touch -c $1 || dienow # Delete old directory, create new one. test -z $NO_CLEANUP && rm -rf $1 mkdir -p $1 || dienow } # output the sha1sum of a file proc sha1file { sha1sum /dev/null @Argv | tail -n +2 | awk '{print $1}' } # dienow() is an exit function that works properly even from a subshell. # (actually_dienow is run in the parent shell via signal handler.) proc actually_dienow { echo -e "\n\e[31mExiting due to errors ($ARCH_NAME $STAGE_NAME $PACKAGE)\e[0m" > !2 exit 1 } trap actually_dienow SIGUSR1 global TOPSHELL := $Pid proc dienow { kill -USR1 $TOPSHELL exit 1 } # Turn a bunch of output lines into a much quieter series of periods, # roughly one per screenfull proc dotprogress { global x := '0' while read i { global x := $($x + ) if [[ "$x" -eq 25 ]] { global x := '0' echo -n . } } echo } # Announce an action to the world proc announce { # Write a line to the log file with easily greppable header echo "=== $1 ($ARCH_NAME $STAGE_NAME)" # Set the title bar of the current xterm test -z $NO_TITLE_BAR && echo -en "\033]2;$ARCH_NAME $STAGE_NAME $1\007" } # Filter out unnecessary noise, keeping just lines starting with "===" proc maybe_quiet { test -z $FORK && cat || grep "^===" } # Run a command background if FORK is set, in foreground otherwise proc maybe_fork { test -z $BUILD_VERBOSE || echo "$ifsjoin(Argv)" if test -z $FORK { eval "$ifsjoin(Argv)" } else { eval "$ifsjoin(Argv)" & } } # Kill a process and all its decendants proc killtree { var KIDS = ''"" while [ $# -ne 0 ] { KIDS := ""$KIDS $[pgrep -P$1]"" shift } KIDS := $[echo -n $KIDS] if test ! -z $KIDS { # Depth first kill avoids reparent_to_init hiding stuff. killtree $KIDS kill $KIDS !2 >/dev/null } } # Search a colon-separated path for files matching a pattern. # Arguments are 1) path to search, 2) pattern, 3) command to run on each file. # During command, $DIR/$FILE points to file found. proc path_search { # For each each $PATH element, loop through each file in that directory, # and create a symlink to the wrapper with that name. In the case of # duplicates, keep the first one. echo $1 | sed 's/:/\n/g' | while read DIR { find "$DIR/" -maxdepth 1 -mindepth 1 -name $2 | sed 's@.*/@@' | \ while read FILE { eval $3 # Output is verbose. Pipe it to dotprogress. echo $FILE } } } # Abort if we haven't got a prerequisite in the $PATH proc check_prerequisite { if test -z $[which $1] { test -z $FAIL_QUIET && echo No $1 in '$PATH'. > !2 dienow } } # Search through all the files under a directory and collapse together # identical files into hardlinks proc collapse_hardlinks { global SHA1LIST := ''"" find $1 -type f | while read FILE { echo $FILE global SHA1 := $[sha1file $FILE] global MATCH := $[echo $SHA1LIST | grep "^$SHA1] if test -z $MATCH { # Yes, the quote spanning two lines here is intentional global SHA1LIST := ""$SHA1LIST $SHA1 $FILE"" } else { global FILE2 := $[echo $MATCH | sed 's/[^ ]* //] cmp -s $FILE $FILE2 || continue ln -f $FILE $FILE2 || dienow } } } # Check if $1 is in the comma separated list $2 proc is_in_list { test $2 == all || test ! -z $[echo ,"$2", | grep ,"$1",] } (CommandList children: [ (FuncDef name: blank_tempdir body: (BraceGroup children: [ (AndOr children: [ (C {(Lit_Other "[")} {(-z)} {(DQ ($ VSub_Number "$1"))} {(Lit_Other "]")}) (C {(dienow)}) ] op_id: Op_DAmp ) (AndOr children: [(C {(touch)} {(-c)} {(DQ ($ VSub_Number "$1"))}) (C {(dienow)})] op_id: Op_DPipe ) (AndOr children: [ (C {(Lit_Other "[")} {(-z)} {(DQ ($ VSub_Name "$NO_CLEANUP"))} {(Lit_Other "]")}) (C {(rm)} {(-rf)} {(DQ ($ VSub_Number "$1"))}) ] op_id: Op_DAmp ) (AndOr children: [(C {(mkdir)} {(-p)} {(DQ ($ VSub_Number "$1"))}) (C {(dienow)})] op_id: Op_DPipe ) ] spids: [16] ) spids: [12 15] ) (FuncDef name: sha1file body: (BraceGroup children: [ (Pipeline children: [ (C {(sha1sum)} {(/dev/null)} {(DQ ($ VSub_At "$@"))}) (C {(tail)} {(-n)} {(Lit_Other "+") (2)}) (C {(awk)} {(SQ <"{print $1}">)}) ] negated: False ) ] spids: [100] ) spids: [96 99] ) (FuncDef name: actually_dienow body: (BraceGroup children: [ (SimpleCommand words: [ {(echo)} {(-e)} { (DQ (EscapedLiteralPart token:) (EscapedLiteralPart token:) ("[31mExiting due to errors (") ($ VSub_Name "$ARCH_NAME") (" ") ($ VSub_Name "$STAGE_NAME") (" ") ($ VSub_Name "$PACKAGE") (")") (EscapedLiteralPart token:) ("[0m") ) } ] redirects: [(Redir op_id:Redir_GreatAnd fd:-1 arg_word:{(2)} spids:[163])] ) (C {(exit)} {(1)}) ] spids: [142] ) spids: [138 141] ) (C {(trap)} {(actually_dienow)} {(SIGUSR1)}) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:TOPSHELL) op: Equal rhs: {($ VSub_Dollar "$$")} spids: [180] ) ] spids: [180] ) (FuncDef name: dienow body: (BraceGroup children: [(C {(kill)} {(-USR1)} {($ VSub_Name "$TOPSHELL")}) (C {(exit)} {(1)})] spids: [188] ) spids: [184 187] ) (FuncDef name: dotprogress body: (BraceGroup children: [ (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:x) op:Equal rhs:{(0)} spids:[219])] spids: [219] ) (While cond: [(C {(read)} {(i)})] body: (DoGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:x) op: Equal rhs: { (ArithSubPart anode: (ArithBinary op_id: Arith_Plus left: (ArithWord w:{($ VSub_Name "$x")}) right: (ArithWord w:{(Lit_Digits 1)}) ) spids: [234 240] ) } spids: [233] ) ] spids: [233] ) (If arms: [ (if_arm cond: [ (DBracket expr: (BoolBinary op_id: BoolBinary_eq left: {(DQ ($ VSub_Name "$x"))} right: {(25)} ) ) ] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:x) op: Equal rhs: {(0)} spids: [261] ) ] spids: [261] ) (C {(echo)} {(-n)} {(.)}) ] spids: [-1 258] ) ] spids: [-1 272] ) ] spids: [230 275] ) ) (C {(echo)}) ] spids: [216] ) spids: [212 215] ) (FuncDef name: announce body: (BraceGroup children: [ (C {(echo)} { (DQ ("=== ") ($ VSub_Number "$1") (" (") ($ VSub_Name "$ARCH_NAME") (" ") ($ VSub_Name "$STAGE_NAME") (")") ) } ) (AndOr children: [ (C {(Lit_Other "[")} {(-z)} {(DQ ($ VSub_Name "$NO_TITLE_BAR"))} {(Lit_Other "]")}) (C {(echo)} {(-en)} { (DQ (EscapedLiteralPart token:) ("33]2;") ($ VSub_Name "$ARCH_NAME") (" ") ($ VSub_Name "$STAGE_NAME") (" ") ($ VSub_Number "$1") (EscapedLiteralPart token:) (07) ) } ) ] op_id: Op_DAmp ) ] spids: [291] ) spids: [287 290] ) (FuncDef name: maybe_quiet body: (BraceGroup children: [ (AndOr children: [ (C {(Lit_Other "[")} {(-z)} {(DQ ($ VSub_Name "$FORK"))} {(Lit_Other "]")}) (AndOr children: [(C {(cat)}) (C {(grep)} {(DQ ("^==="))})] op_id: Op_DPipe ) ] op_id: Op_DAmp ) ] spids: [355] ) spids: [351 354] ) (FuncDef name: maybe_fork body: (BraceGroup children: [ (AndOr children: [ (C {(Lit_Other "[")} {(-z)} {(DQ ($ VSub_Name "$BUILD_VERBOSE"))} {(Lit_Other "]")}) (C {(echo)} {(DQ ($ VSub_Star "$*"))}) ] op_id: Op_DPipe ) (If arms: [ (if_arm cond: [(C {(Lit_Other "[")} {(-z)} {(DQ ($ VSub_Name "$FORK"))} {(Lit_Other "]")})] action: [(C {(eval)} {(DQ ($ VSub_Star "$*"))})] spids: [-1 427] ) ] else_action: [ (Sentence child: (C {(eval)} {(DQ ($ VSub_Star "$*"))}) terminator: ) ] spids: [437 449] ) ] spids: [391] ) spids: [387 390] ) (FuncDef name: killtree body: (BraceGroup children: [ (Assignment keyword: Assign_Local pairs: [(assign_pair lhs:(LhsName name:KIDS) op:Equal rhs:{(DQ )} spids:[467])] spids: [465] ) (While cond: [(C {(Lit_Other "[")} {($ VSub_Pound "$#")} {(-ne)} {(0)} {(Lit_Other "]")})] body: (DoGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:KIDS) op: Equal rhs: { (DQ ($ VSub_Name "$KIDS") (" ") (CommandSubPart command_list: (CommandList children: [(C {(pgrep)} {(-P) ($ VSub_Number "$1")})] ) left_token: spids: [493 498] ) ) } spids: [489] ) ] spids: [489] ) (C {(shift)}) ] spids: [486 505] ) ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:KIDS) op: Equal rhs: { (DQ (CommandSubPart command_list: (CommandList children: [(C {(echo)} {(-n)} {($ VSub_Name "$KIDS")})] ) left_token: spids: [511 517] ) ) } spids: [509] ) ] spids: [509] ) (If arms: [ (if_arm cond: [ (C {(Lit_Other "[")} {(KW_Bang "!")} {(-z)} {(DQ ($ VSub_Name "$KIDS"))} {(Lit_Other "]")} ) ] action: [ (C {(killtree)} {($ VSub_Name "$KIDS")}) (SimpleCommand words: [{(kill)} {($ VSub_Name "$KIDS")}] redirects: [(Redir op_id:Redir_Great fd:2 arg_word:{(/dev/null)} spids:[552])] ) ] spids: [-1 536] ) ] spids: [-1 556] ) ] spids: [462] ) spids: [458 461] ) (FuncDef name: path_search body: (BraceGroup children: [ (Pipeline children: [ (C {(echo)} {(DQ ($ VSub_Number "$1"))}) (C {(sed)} {(SQ <"s/:/\\n/g">)}) (While cond: [(C {(read)} {(DIR)})] body: (DoGroup children: [ (Pipeline children: [ (C {(find)} {(DQ ($ VSub_Name "$DIR") (/))} {(-maxdepth)} {(1)} {(-mindepth)} {(1)} {(-name)} {(DQ ($ VSub_Number "$2"))} ) (C {(sed)} {(SQ <"s@.*/@@">)}) (While cond: [(C {(read)} {(FILE)})] body: (DoGroup children: [ (C {(eval)} {(DQ ($ VSub_Number "$3"))}) (C {(echo)} {($ VSub_Name "$FILE")}) ] spids: [658 679] ) ) ] negated: False ) ] spids: [615 682] ) ) ] negated: False ) ] spids: [576] ) spids: [572 575] ) (FuncDef name: check_prerequisite body: (BraceGroup children: [ (If arms: [ (if_arm cond: [ (C {(Lit_Other "[")} {(-z)} { (DQ (CommandSubPart command_list: (CommandList children: [(C {(which)} {(DQ ($ VSub_Number "$1"))})] ) left_token: spids: [705 711] ) ) } {(Lit_Other "]")} ) ] action: [ (AndOr children: [ (C {(Lit_Other "[")} {(-z)} {(DQ ($ VSub_Name "$FAIL_QUIET"))} {(Lit_Other "]")}) (SimpleCommand words: [ {(echo)} {(No)} {(DQ ($ VSub_Number "$1"))} {(KW_In in)} {(SQ <"$PATH">) (.)} ] redirects: [(Redir op_id:Redir_GreatAnd fd:-1 arg_word:{(2)} spids:[747])] ) ] op_id: Op_DAmp ) (C {(dienow)}) ] spids: [-1 717] ) ] spids: [-1 754] ) ] spids: [695] ) spids: [691 694] ) (FuncDef name: collapse_hardlinks body: (BraceGroup children: [ (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:SHA1LIST) op:Equal rhs:{(DQ )} spids:[773])] spids: [773] ) (Pipeline children: [ (C {(find)} {(DQ ($ VSub_Number "$1"))} {(-type)} {(f)}) (While cond: [(C {(read)} {(FILE)})] body: (DoGroup children: [ (C {(echo)} {(DQ ($ VSub_Name "$FILE"))}) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:SHA1) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [(C {(sha1file)} {(DQ ($ VSub_Name "$FILE"))})] ) left_token: spids: [808 814] ) } spids: [807] ) ] spids: [807] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:MATCH) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [ (Pipeline children: [ (C {(echo)} {(DQ ($ VSub_Name "$SHA1LIST"))}) (C {(grep)} {(DQ ("^") ($ VSub_Name "$SHA1"))}) ] negated: False ) ] ) left_token: spids: [818 833] ) } spids: [817] ) ] spids: [817] ) (If arms: [ (if_arm cond: [ (C {(Lit_Other "[")} {(-z)} {(DQ ($ VSub_Name "$MATCH"))} {(Lit_Other "]")} ) ] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:SHA1LIST) op: Equal rhs: { (DQ ($ VSub_Name "$SHA1LIST") ("\n") ($ VSub_Name "$SHA1") (" ") ($ VSub_Name "$FILE") ) } spids: [856] ) ] spids: [856] ) ] spids: [-1 849] ) ] else_action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:FILE2) op: Equal rhs: { (DQ (CommandSubPart command_list: (CommandList children: [ (Pipeline children: [ (C {(echo)} {(DQ ($ VSub_Name "$MATCH"))}) (C {(sed)} {(SQ <"s/[^ ]* //">)}) ] negated: False ) ] ) left_token: spids: [871 885] ) ) } spids: [869] ) ] spids: [869] ) (AndOr children: [ (C {(cmp)} {(-s)} {(DQ ($ VSub_Name "$FILE"))} {(DQ ($ VSub_Name "$FILE2"))} ) (ControlFlow token: ) ] op_id: Op_DPipe ) (AndOr children: [ (C {(ln)} {(-f)} {(DQ ($ VSub_Name "$FILE"))} {(DQ ($ VSub_Name "$FILE2"))} ) (C {(dienow)}) ] op_id: Op_DPipe ) ] spids: [866 923] ) ] spids: [797 926] ) ) ] negated: False ) ] spids: [770] ) spids: [766 769] ) (FuncDef name: is_in_list body: (BraceGroup children: [ (AndOr children: [ (C {(Lit_Other "[")} {(DQ ($ VSub_Number "$2"))} {(Lit_Other "=") (Lit_Other "=")} {(all)} {(Lit_Other "]")} ) (C {(Lit_Other "[")} {(KW_Bang "!")} {(-z)} { (DQ (CommandSubPart command_list: (CommandList children: [ (Pipeline children: [ (C {(echo)} {(Lit_Comma ",") (DQ ($ VSub_Number "$2")) (Lit_Comma ",")} ) (C {(grep)} {(Lit_Comma ",") (DQ ($ VSub_Number "$1")) (Lit_Comma ",")} ) ] negated: False ) ] ) left_token: spids: [964 982] ) ) } {(Lit_Other "]")} ) ] op_id: Op_DPipe ) ] spids: [939] ) spids: [935 938] ) ] )