arx 0.1.1 → 0.2.0
raw patch · 6 files changed
+287/−179 lines, 6 filesdep −vectordep −vector-algorithmsPVP ok
version bump matches the API change (PVP)
Dependencies removed: vector, vector-algorithms
API changes (from Hackage documentation)
- System.Posix.ARX.HEREDat: leastStringNotIn :: ByteString -> ByteString
Files
- README +83/−41
- System/Posix/ARX/HEREDat.hs +2/−57
- arx.cabal +1/−5
- docs/blessed/arx.man +70/−11
- docs/blessed/arx.txt +83/−41
- model-scripts/tmpx.sh +48/−24
README view
@@ -39,101 +39,111 @@ arx tmpx ... | ssh user@host.com sudo sh - For all subcommands, when options overlap in their effect -- for exam-- ple, setting the output with -o -- the rightmost option takes prece-- dence. Whenever -h, -? or --help is present on the command line, help+ Scripts generated by tmpx will pass their arguments to the contained+ script or command. To pass arguments when piping to sh, use -s:++ arx tmpx ... | ssh user@host.com sudo sh -s a b c++ Some arguments to the generated script will be treated specially,+ namely, --extract, --no-rm and --no-run. Please see the section on+ Passing Arguments, below, for more information about these options.++ARX COMMANDLINE PROCESSING+ For all subcommands, when options overlap in their effect -- for exam-+ ple, setting the output with -o -- the rightmost option takes prece-+ dence. Whenever -h, -? or --help is present on the command line, help is displayed and the program exits. - When paths are specified on an arx command line, they must be quali-+ When paths are specified on an arx command line, they must be quali- fied, starting with /, ./ or ../. This simplifies the command line syn- tax, overall, without introducing troublesome ambiguities. TMPX The tmpx subcommand bundles together archives, environment settings and- an executable or shell command in to a Bourne-compatible script that- runs the command or executable in a temporary directory, after having+ an executable or shell command in to a Bourne-compatible script that+ runs the command or executable in a temporary directory, after having unpacked the archives and set the environment. Any number of file path arguments may be specified; they will be inter-- preted as tar archives to include in bundled script. If - is given,- then STDIN will be included as an archive stream. If no arguments are- given, it is assumed that no archives are desired and only the command+ preted as tar archives to include in bundled script. If - is given,+ then STDIN will be included as an archive stream. If no arguments are+ given, it is assumed that no archives are desired and only the command and environment are bundled. - The temporary directory created by the script is different for each- invocation, with a name of the form /tmp/tmpx.<timestamp>.<pid>. The- timestamp used is a UTC, ISO 8601 format timestamp. One happy conse-- quence of this is that earlier jobs sort ASCIIbetically before later- jobs. After execution, the temporary directory is removed (or not,+ The temporary directory created by the script is different for each+ invocation, with a name of the form /tmp/tmpx-<timestamp>-<randomhex>.+ The timestamp format is %Y.%m.%dT%H.%M.%SZ, in UTC. One happy conse-+ quence of this is that earlier jobs sort ASCIIbetically before later+ jobs. After execution, the temporary directory is removed (or not, depending on the -rm[10!_] family of options). -rm0, -rm1, -rm_, -rm!- By default, the temporary directory created by the script+ By default, the temporary directory created by the script will be deleted no matter the exit status status of the task. These options cause a script to be generated that deletes the- temporary directory only on success, only on failure, always+ temporary directory only on success, only on failure, always (the default) or never. -b <size>- Please see the documentation for this option, shared with+ Please see the documentation for this option, shared with shdat, below. -o <path>- By default, the generated script is sent to STDOUT. With -o,+ By default, the generated script is sent to STDOUT. With -o, output is redirected to the given path. -e <path>- Causes the file specified to be packaged as the task to be- run. A binary executable, a Ruby script or a longish shell+ Causes the file specified to be packaged as the task to be+ run. A binary executable, a Ruby script or a longish shell script all fit here. - In addition to these options, arguments of the form VAR=VALUE are rec-- ognized as environment mappings and stored away in the script, to be+ In addition to these options, arguments of the form VAR=VALUE are rec-+ ognized as environment mappings and stored away in the script, to be sourced on execution. - Without -e, the tmpx subcommand tries to find the task to be run as a- sequence of arguments delimited by a run of slashes. The following+ Without -e, the tmpx subcommand tries to find the task to be run as a+ sequence of arguments delimited by a run of slashes. The following forms are all recognized: arx tmpx ...some args... // ...command... arx tmpx ...some args... // ...command... // ...more args... arx tmpx // ...command... // ...some args... - The slash runs must have the same number of slashes and must be the- longest continuous runs of slashes on the command line. The command- will be included as is in a Bourne shell script.+ The slash runs must have the same number of slashes and must be the+ longest continuous runs of slashes on the command line. The command+ will be included as-is in a Bourne shell script. SHDAT- The shdat subcommand translates binary data in to a shell script which- outputs the binary data. The data is encoded in HERE documents in such- a way that data without NULs is not changed and that data with NULs is- minimally expanded: about 1% for randomish data like compressed tar-+ The shdat subcommand translates binary data in to a shell script which+ outputs the binary data. The data is encoded in HERE documents in such+ a way that data without NULs is not changed and that data with NULs is+ minimally expanded: about 1% for randomish data like compressed tar- balls and about 10% in pathological cases. - The shdat subcommand can be given any number of paths, which will be+ The shdat subcommand can be given any number of paths, which will be concatenated in the order given. If no path is given, or if - is given, then STDIN will be read. -b <size>- The size of data chunks to place in each HERE document. The- argument is a positive integer followed by suffixes like B,- K, KiB, M and MiB, in the manner of dd, head and many other- tools. The default is 4MiB. This is unlikely to make a dif-+ The size of data chunks to place in each HERE document. The+ argument is a positive integer followed by suffixes like B,+ K, KiB, M and MiB, in the manner of dd, head and many other+ tools. The default is 4MiB. This is unlikely to make a dif- ference for you unless the generated script is intended to be run on a memory-constrained system. -o <path>- By default, the generated script is sent to STDOUT. With -o,+ By default, the generated script is sent to STDOUT. With -o, output is redirected to the given path. EXAMPLES # Installer script that preserves failed builds.- git archive HEAD | bzip2 | arx tmpx -rm0 // make install > go.sh+ git archive HEAD | bzip2 | arx tmpx -rm0 - // make install > go.sh # Now install as root; but don't log in as root. cat ./go.sh | ssh joey@hostname sudo /bin/sh # Variation of the above.- git archive HEAD | bzip2 | arx tmpx -rm0 -e ./build-script.py+ git archive HEAD | bzip2 | arx tmpx -rm0 - -e ./build-script.py > go.sh # Bundle an instance of an application with DB credentials and run it. arx tmpx -rm! ./app.tbz ./stage-info.tgz // rake start | ssh ...@@ -145,9 +155,41 @@ arx tmpx // 'cd arx-* && cabal configure && cabal build' // \ -rm0 ./dist/arx-0.0.0.tar.gz | sh +PASSING ARGUMENTS TO GENERATED SCRIPTS+ The scripts generated by tmpx treat some arguments as special, internal+ options, to allow for inspecting them should there be a need to deter-+ mine their contents.++ --extract+ Unpack the data in the present directory and do nothing else.++ --no-rm+ Run the script as normal but do not delete the generated tem-+ porary directory.++ --no-run+ Unpack into a temporary directory as normal but do not run+ the user's command.++ To prevent arguments from being specially treated, use // in the argu-+ ment list:++ a-tmpx-script.sh --no-rm // a b c --extract++ In the above example, --extract will be passed to the inner command, in+ the same way as a, b, c. The following example causes ab, c and --no-rm+ to be printed one after another, each on their own line.++ arx tmpx // printf "'%s\n'" '"$@"' | sh -s // ab c --no-rm++NOTES+ The timestamp is not the common ISO 8601 format, %Y-%m-%dT%H:%M:%SZ,+ because of software and build processes that attach special meaning to+ colons in pathnames.+ BUGS- The command line parser offers no hints or help of any kind; it fails- with the simple message "argument error". The two most common mistakes+ The command line parser offers no hints or help of any kind; it fails+ with the simple message "argument error". The two most common mistakes I make are: o Not qualifying paths with /, ./ or ../.
System/Posix/ARX/HEREDat.hs view
@@ -25,10 +25,6 @@ import qualified Blaze.ByteString.Builder as Blaze import qualified Blaze.ByteString.Builder.Char8 as Blaze import qualified Data.ByteString.Nums.Careless as Bytes-import Data.Vector.Unboxed (Vector)-import qualified Data.Vector.Unboxed as Vector-import qualified Data.Vector.Unboxed.Mutable as Vector-import qualified Data.Vector.Algorithms.Intro as Vector import System.Posix.ARX.BlazeIsString @@ -213,11 +209,8 @@ {-| -}-script chunk = mconcat $ case chunk of- SafeChunk bytes -> [clip len, dataSection eof bytes]- where- len = Bytes.length bytes- eof = blz (leastStringNotIn bytes)+script block = mconcat $ case block of+ SafeChunk bytes -> [script (chunk bytes)] -- Convert to Encoded EncodedChunk bytes len (EscapeChar _ trN _ sedRN) (EscapeChar b _ sedPE sedRE) -> [ "{ ", mconcat tr, " | ", mconcat sed, " | ", clip len, " ;}",@@ -232,54 +225,6 @@ nl = Blaze.fromChar '\n' dataSection eof bytes = mconcat [" <<\\", eof, nl, blz bytes, nl, eof, nl] clip len = "head -c " `mappend` Blaze.fromShow len--{-| Finds a short hexadecimal string that is not in the input.-- A string of length @n@ has at most @n - (k - 1)@ substrings of some fixed,- positive length @k@ -- the substring starting at the first byte and- extending for @k@, the substring starting at the second byte and extending- for @k@ and so on, on until the end where we have to stop @k - 1@ short of- the last byte. We choose @k@ such that it contains enough hexadecimal- digits to enumerate all the substrings; for a 4M input, we want @k = 6@.-- We can take all the hex substrings of length @k@ in the input, sort them,- and then find the gaps. We take the least substring in the first gap for- our chosen substring. This gives us an O(n log n) algorithm.-- The measurable length of a 'ByteString' is at most the maximum 'Word'- (since the length function results in an 'Int'); this is one less than 2- to the bit width of a 'Word' (because there is a 0 'Word'). Thus a 'Word'- suffices to enumerate all the possible substrings in a 'ByteString'; and- one more. (Substrings are zero-indexed and the length is 1-indexed.) We- can leverage this fact to translate all substrings to 'Word' and store- them in an unboxed vector, using integer operations to find the least- subtring in the first gap. Space usage is linear in the length of the- input string; for a 4M string, the sorted vector could consume 32M on 64- bit machines.- -}-leastStringNotIn :: ByteString -> ByteString-leastStringNotIn bytes = hex- where- len = Bytes.length bytes- digits = 1 + floor (logBase 16 (fromIntegral len))- substrings = [ s | s <- Bytes.take digits <$> Bytes.tails bytes, isHex s ]- sortedWords :: Vector Word- sortedWords = Vector.create $ do- v <- Vector.new len- zipWithM_ (Vector.write v) [0..] (Bytes.hex <$> substrings)- Vector.sort v- return v- isHex "" = False- isHex s = Bytes.all (`Bytes.elem` "0123456789ABCDEF") s- -- Find the smallest number not in the list, assuming it is sorted.- minW = f 0 (Vector.toList sortedWords)- where- f candidate l = case l of [ ] -> candidate- h:t | candidate < h -> candidate- | otherwise -> f (h+1) t- padded = "0000000000000000" `mappend`- Data.ByteString.Char8.pack (showHex minW "")- (_, hex) = Bytes.splitAt (Bytes.length padded - digits) padded {- Catting a tarball escaped this way to a shell behind a TTY won't work very
arx.cabal view
@@ -1,5 +1,5 @@ name : arx-version : 0.1.1+version : 0.2.0 category : Text license : BSD3 license-file : LICENSE@@ -77,8 +77,6 @@ , process >= 1.0 , shell-escape >= 0.1.1 , template-haskell- , vector >= 0.9- , vector-algorithms >= 0.5.3 exposed-modules : System.Posix.ARX System.Posix.ARX.CLI System.Posix.ARX.CLI.CLTokens@@ -113,8 +111,6 @@ , process >= 1.0 , shell-escape >= 0.1.1 , template-haskell- , vector >= 0.9- , vector-algorithms >= 0.5.3 extensions : FlexibleInstances FunctionalDependencies MultiParamTypeClasses
docs/blessed/arx.man view
@@ -1,4 +1,4 @@-.TH "ARX" "1" "2012-02-24" "0.1.0" "arx"+.TH "ARX" "1" "2012-10-29" "0.2.0" "arx" .SH NAME arx \- archived execution .@@ -28,7 +28,7 @@ .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u ..-.\" Man page generated from reStructeredText.+.\" Man page generated from reStructuredText. . .SH SYNOPSIS .sp@@ -78,6 +78,20 @@ .ft P .fi .sp+Scripts generated by \fItmpx\fP will pass their arguments to the contained script+or command. To pass arguments when piping to \fIsh\fP, use \fI\-s\fP:+.sp+.nf+.ft C+arx tmpx ... | ssh user@host.com sudo sh \-s a b c+.ft P+.fi+.sp+Some arguments to the generated script will be treated specially, namely,+\fB\-\-extract\fP, \fB\-\-no\-rm\fP and \fB\-\-no\-run\fP. Please see the section on Passing+Arguments, below, for more information about these options.+.SH ARX COMMANDLINE PROCESSING+.sp For all subcommands, when options overlap in their effect \-\- for example, setting the output with \fB\-o\fP \-\- the rightmost option takes precedence. Whenever \fB\-h\fP, \fB\-?\fP or \fB\-\-help\fP is present on the command line, help is@@ -100,11 +114,11 @@ bundled. .sp The temporary directory created by the script is different for each-invocation, with a name of the form \fB/tmp/tmpx.<timestamp>.<pid>\fP. The-timestamp used is a UTC, ISO 8601 format timestamp. One happy consequence of-this is that earlier jobs sort ASCIIbetically before later jobs. After-execution, the temporary directory is removed (or not, depending on the-\fB\-rm[10!_]\fP family of options).+invocation, with a name of the form \fB/tmp/tmpx\-<timestamp>\-<randomhex>\fP. The+timestamp format is %Y.%m.%dT%H.%M.%SZ, in UTC. One happy consequence of this+is that earlier jobs sort ASCIIbetically before later jobs. After execution,+the temporary directory is removed (or not, depending on the \fB\-rm[10!_]\fP+family of options). .INDENT 0.0 .INDENT 3.5 .INDENT 0.0@@ -147,7 +161,7 @@ .sp The slash runs must have the same number of slashes and must be the longest continuous runs of slashes on the command line. The command will be included-as is in a Bourne shell script.+as\-is in a Bourne shell script. .SH SHDAT .sp The \fIshdat\fP subcommand translates binary data in to a shell script which@@ -181,12 +195,12 @@ .nf .ft C # Installer script that preserves failed builds.-git archive HEAD | bzip2 | arx tmpx \-rm0 // make install > go.sh+git archive HEAD | bzip2 | arx tmpx \-rm0 \- // make install > go.sh # Now install as root; but don\(aqt log in as root. cat ./go.sh | ssh joey@hostname sudo /bin/sh # Variation of the above.-git archive HEAD | bzip2 | arx tmpx \-rm0 \-e ./build\-script.py+git archive HEAD | bzip2 | arx tmpx \-rm0 \- \-e ./build\-script.py > go.sh # Bundle an instance of an application with DB credentials and run it. arx tmpx \-rm! ./app.tbz ./stage\-info.tgz // rake start | ssh ...@@ -199,6 +213,52 @@ \-rm0 ./dist/arx\-0.0.0.tar.gz | sh .ft P .fi+.SH PASSING ARGUMENTS TO GENERATED SCRIPTS+.sp+The scripts generated by \fItmpx\fP treat some arguments as special, internal+options, to allow for inspecting them should there be a need to determine+their contents.+.INDENT 0.0+.INDENT 3.5+.INDENT 0.0+.TP+.B \fB\-\-extract\fP+Unpack the data in the present directory and do nothing else.+.TP+.B \fB\-\-no\-rm\fP+Run the script as normal but do not delete the generated temporary+directory.+.TP+.B \fB\-\-no\-run\fP+Unpack into a temporary directory as normal but do not run the user\(aqs+command.+.UNINDENT+.UNINDENT+.UNINDENT+.sp+To prevent arguments from being specially treated, use \fB//\fP in the argument+list:+.sp+.nf+.ft C+a\-tmpx\-script.sh \-\-no\-rm // a b c \-\-extract+.ft P+.fi+.sp+In the above example, \fB\-\-extract\fP will be passed to the inner command, in+the same way as \fBa\fP, \fBb\fP, \fBc\fP. The following example causes \fBab\fP,+\fBc\fP and \fB\-\-no\-rm\fP to be printed one after another, each on their own line.+.sp+.nf+.ft C+arx tmpx // printf "\(aq%s\en\(aq" \(aq"$@"\(aq | sh \-s // ab c \-\-no\-rm+.ft P+.fi+.SH NOTES+.sp+The timestamp is not the common ISO 8601 format, %Y\-%m\-%dT%H:%M:%SZ, because+of software and build processes that attach special meaning to colons in+pathnames. .SH BUGS .sp The command line parser offers no hints or help of any kind; it fails with the@@ -214,5 +274,4 @@ .SH COPYRIGHT 2011, Jason Dusek .\" Generated by docutils manpage writer.-.\" .
docs/blessed/arx.txt view
@@ -39,101 +39,111 @@ arx tmpx ... | ssh user@host.com sudo sh - For all subcommands, when options overlap in their effect -- for exam-- ple, setting the output with -o -- the rightmost option takes prece-- dence. Whenever -h, -? or --help is present on the command line, help+ Scripts generated by tmpx will pass their arguments to the contained+ script or command. To pass arguments when piping to sh, use -s:++ arx tmpx ... | ssh user@host.com sudo sh -s a b c++ Some arguments to the generated script will be treated specially,+ namely, --extract, --no-rm and --no-run. Please see the section on+ Passing Arguments, below, for more information about these options.++ARX COMMANDLINE PROCESSING+ For all subcommands, when options overlap in their effect -- for exam-+ ple, setting the output with -o -- the rightmost option takes prece-+ dence. Whenever -h, -? or --help is present on the command line, help is displayed and the program exits. - When paths are specified on an arx command line, they must be quali-+ When paths are specified on an arx command line, they must be quali- fied, starting with /, ./ or ../. This simplifies the command line syn- tax, overall, without introducing troublesome ambiguities. TMPX The tmpx subcommand bundles together archives, environment settings and- an executable or shell command in to a Bourne-compatible script that- runs the command or executable in a temporary directory, after having+ an executable or shell command in to a Bourne-compatible script that+ runs the command or executable in a temporary directory, after having unpacked the archives and set the environment. Any number of file path arguments may be specified; they will be inter-- preted as tar archives to include in bundled script. If - is given,- then STDIN will be included as an archive stream. If no arguments are- given, it is assumed that no archives are desired and only the command+ preted as tar archives to include in bundled script. If - is given,+ then STDIN will be included as an archive stream. If no arguments are+ given, it is assumed that no archives are desired and only the command and environment are bundled. - The temporary directory created by the script is different for each- invocation, with a name of the form /tmp/tmpx.<timestamp>.<pid>. The- timestamp used is a UTC, ISO 8601 format timestamp. One happy conse-- quence of this is that earlier jobs sort ASCIIbetically before later- jobs. After execution, the temporary directory is removed (or not,+ The temporary directory created by the script is different for each+ invocation, with a name of the form /tmp/tmpx-<timestamp>-<randomhex>.+ The timestamp format is %Y.%m.%dT%H.%M.%SZ, in UTC. One happy conse-+ quence of this is that earlier jobs sort ASCIIbetically before later+ jobs. After execution, the temporary directory is removed (or not, depending on the -rm[10!_] family of options). -rm0, -rm1, -rm_, -rm!- By default, the temporary directory created by the script+ By default, the temporary directory created by the script will be deleted no matter the exit status status of the task. These options cause a script to be generated that deletes the- temporary directory only on success, only on failure, always+ temporary directory only on success, only on failure, always (the default) or never. -b <size>- Please see the documentation for this option, shared with+ Please see the documentation for this option, shared with shdat, below. -o <path>- By default, the generated script is sent to STDOUT. With -o,+ By default, the generated script is sent to STDOUT. With -o, output is redirected to the given path. -e <path>- Causes the file specified to be packaged as the task to be- run. A binary executable, a Ruby script or a longish shell+ Causes the file specified to be packaged as the task to be+ run. A binary executable, a Ruby script or a longish shell script all fit here. - In addition to these options, arguments of the form VAR=VALUE are rec-- ognized as environment mappings and stored away in the script, to be+ In addition to these options, arguments of the form VAR=VALUE are rec-+ ognized as environment mappings and stored away in the script, to be sourced on execution. - Without -e, the tmpx subcommand tries to find the task to be run as a- sequence of arguments delimited by a run of slashes. The following+ Without -e, the tmpx subcommand tries to find the task to be run as a+ sequence of arguments delimited by a run of slashes. The following forms are all recognized: arx tmpx ...some args... // ...command... arx tmpx ...some args... // ...command... // ...more args... arx tmpx // ...command... // ...some args... - The slash runs must have the same number of slashes and must be the- longest continuous runs of slashes on the command line. The command- will be included as is in a Bourne shell script.+ The slash runs must have the same number of slashes and must be the+ longest continuous runs of slashes on the command line. The command+ will be included as-is in a Bourne shell script. SHDAT- The shdat subcommand translates binary data in to a shell script which- outputs the binary data. The data is encoded in HERE documents in such- a way that data without NULs is not changed and that data with NULs is- minimally expanded: about 1% for randomish data like compressed tar-+ The shdat subcommand translates binary data in to a shell script which+ outputs the binary data. The data is encoded in HERE documents in such+ a way that data without NULs is not changed and that data with NULs is+ minimally expanded: about 1% for randomish data like compressed tar- balls and about 10% in pathological cases. - The shdat subcommand can be given any number of paths, which will be+ The shdat subcommand can be given any number of paths, which will be concatenated in the order given. If no path is given, or if - is given, then STDIN will be read. -b <size>- The size of data chunks to place in each HERE document. The- argument is a positive integer followed by suffixes like B,- K, KiB, M and MiB, in the manner of dd, head and many other- tools. The default is 4MiB. This is unlikely to make a dif-+ The size of data chunks to place in each HERE document. The+ argument is a positive integer followed by suffixes like B,+ K, KiB, M and MiB, in the manner of dd, head and many other+ tools. The default is 4MiB. This is unlikely to make a dif- ference for you unless the generated script is intended to be run on a memory-constrained system. -o <path>- By default, the generated script is sent to STDOUT. With -o,+ By default, the generated script is sent to STDOUT. With -o, output is redirected to the given path. EXAMPLES # Installer script that preserves failed builds.- git archive HEAD | bzip2 | arx tmpx -rm0 // make install > go.sh+ git archive HEAD | bzip2 | arx tmpx -rm0 - // make install > go.sh # Now install as root; but don't log in as root. cat ./go.sh | ssh joey@hostname sudo /bin/sh # Variation of the above.- git archive HEAD | bzip2 | arx tmpx -rm0 -e ./build-script.py+ git archive HEAD | bzip2 | arx tmpx -rm0 - -e ./build-script.py > go.sh # Bundle an instance of an application with DB credentials and run it. arx tmpx -rm! ./app.tbz ./stage-info.tgz // rake start | ssh ...@@ -145,9 +155,41 @@ arx tmpx // 'cd arx-* && cabal configure && cabal build' // \ -rm0 ./dist/arx-0.0.0.tar.gz | sh +PASSING ARGUMENTS TO GENERATED SCRIPTS+ The scripts generated by tmpx treat some arguments as special, internal+ options, to allow for inspecting them should there be a need to deter-+ mine their contents.++ --extract+ Unpack the data in the present directory and do nothing else.++ --no-rm+ Run the script as normal but do not delete the generated tem-+ porary directory.++ --no-run+ Unpack into a temporary directory as normal but do not run+ the user's command.++ To prevent arguments from being specially treated, use // in the argu-+ ment list:++ a-tmpx-script.sh --no-rm // a b c --extract++ In the above example, --extract will be passed to the inner command, in+ the same way as a, b, c. The following example causes ab, c and --no-rm+ to be printed one after another, each on their own line.++ arx tmpx // printf "'%s\n'" '"$@"' | sh -s // ab c --no-rm++NOTES+ The timestamp is not the common ISO 8601 format, %Y-%m-%dT%H:%M:%SZ,+ because of software and build processes that attach special meaning to+ colons in pathnames.+ BUGS- The command line parser offers no hints or help of any kind; it fails- with the simple message "argument error". The two most common mistakes+ The command line parser offers no hints or help of any kind; it fails+ with the simple message "argument error". The two most common mistakes I make are: o Not qualifying paths with /, ./ or ../.
model-scripts/tmpx.sh view
@@ -3,29 +3,54 @@ unset rm_ dir tmp=true ; run=true rm0=true ; rm1=true # To be set by tool.-for arg in "$@"-do- case "$arg" in- --no-rm) rm_=false ;;- --no-run) run=false ;;- --extract) rm_=false ; tmp=false ; run=false ;;- esac-done-if $tmp-then- dir=/tmp/tmpx-`hexdump -n8 -e '"%08x-%08x"' < /dev/urandom`- : ${rm_:=true}- if $rm_+token=`date -u +%FT%TZ | tr :- ..`-`hexdump -n4 -e '"%08x"' </dev/urandom`+opts() {+ cmd="$1" ; shift+ n=$#+ i=0+ magic_slash=false+ # Walk the args in order, processing options and placing non-option+ # arguments at the end. When finished, arguments are in reverse order.+ while [ "$i" -lt "$n" ]+ do+ arg="$1" ; shift+ case "$arg!$magic_slash" in+ --no-rm!false) rm_=false ;;+ --no-run!false) run=false ;;+ --extract!false) rm_=false ; tmp=false ; run=false ;;+ //!false) magic_slash=true ;;+ *) set -- "$@" "$arg" ;;+ esac+ i=$(($i+1))+ done+ # Unreverse the args.+ n=$#+ i=0+ while [ "$i" -lt "$n" ]+ do+ arg="$1" ; shift+ set -- "$@" "$arg"+ i=$(($i+1))+ done+ # Set the trap.+ if $tmp then- trap 'case $?/$rm0/$rm1 in- 0/true/*) rm -rf "$dir" ;;- [1-9]*/*/true) rm -rf "$dir" ;;- esac' EXIT- trap 'exit 2' HUP INT QUIT BUS SEGV PIPE TERM+ dir=/tmp/tmpx-"$token"+ : ${rm_:=true}+ if $rm_+ then+ trap 'case $?/$rm0/$rm1 in+ 0/true/*) rm -rf "$dir" ;;+ [1-9]*/*/true) rm -rf "$dir" ;;+ esac' EXIT+ trap 'exit 2' HUP INT QUIT BUS SEGV PIPE TERM+ fi+ mkdir "$dir"+ cd "$dir" fi- mkdir "$dir"- cd "$dir"-fi+ # Call the command with the reassembled ARGV, options removed.+ "$cmd" "$@"+} go () { unpack_env > ./env unpack_run > ./run ; chmod ug+x ./run@@ -34,7 +59,7 @@ unpack_dat if $run then- ( . ../env && ../run )+ ( . ../env && ../run "$@" ) fi } unpack_env () { : # NOOP@@ -46,5 +71,4 @@ unpack_dat () { : # NOOP # To be set by tool. }-go-exit+opts go "$@"