Advertisement
devinteske

unpackng.sh

Feb 9th, 2016
572
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 23.44 KB | None | 0 0
  1. #!/bin/sh
  2. # -*- tab-width:  4 -*- ;; Emacs
  3. # vi: set tabstop=4     :: Vi/ViM
  4. ############################################################ INFORMATION
  5. #
  6. # Command Usage:
  7. #
  8. #   ./unpack.sh [-afho] package-archive [package-archive ...]
  9. #
  10. #   OPTIONS:
  11. #       -a     Move the package-archive to an `archive' sub-directory (next
  12. #              to the unpacked `src' directory) after successfully unpacking
  13. #              the package. Not performed by default.
  14. #       -f     Force. Allow unpacking to a directory that already exists.
  15. #       -h     Print this message to stderr and exit.
  16. #       -o     Unpack archive to origin sub-directory. Default is to unpack
  17. #              to the local directory.
  18. #
  19. ############################################################ GLOBALS
  20.  
  21. #
  22. # Global exit status variables
  23. #
  24. SUCCESS=0
  25. FAILURE=1
  26.  
  27. #
  28. # Program name and directory
  29. #
  30. progname="${0##*/}"
  31. progdir="${0%/*}"
  32.  
  33. #
  34. # Options
  35. #
  36. FORCE=          # -f
  37. MOVE_PACKAGE=       # -a
  38. USE_ORIGIN_SUBDIR=  # -o
  39.  
  40. #
  41. # Miscellaneous
  42. #
  43. VALID_VARNAME_CHARS="0-9ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_"
  44. export VALID_VARNAME_CHARS # NB: exported for awk(1) `ENVIRON[]' visibility
  45.  
  46.  
  47. # fprintf $fd $fmt [ $opts ... ]
  48. #
  49. # Like printf, except allows you to print to a specific file-descriptor. Useful
  50. # for printing to stderr (fd=2) or some other known file-descriptor.
  51. #
  52. fprintf()
  53. {
  54.     local fd=$1
  55.     [ $# -gt 1 ] || return $FAILURE
  56.     shift 1
  57.     printf "$@" >&$fd
  58. }
  59.  
  60. # eprintf $fmt [ $opts ... ]
  61. #
  62. # Print a message to stderr (fd=2).
  63. #
  64. eprintf()
  65. {
  66.     fprintf 2 "$@"
  67. }
  68.  
  69. # die [ $fmt [ $opts ... ]]
  70. #
  71. # Optionally print a message to stderr before exiting with failure status.
  72. #
  73. die()
  74. {
  75.     local fmt="$1"
  76.     [ $# -gt 0 ] && shift 1
  77.     [  "$fmt"  ] && eprintf "$fmt\n" "$@"
  78.    
  79.     exit $FAILURE
  80. }
  81.  
  82. # usage
  83. #
  84. # Prints a short syntax statement and exits.
  85. #
  86. usage()
  87. {  
  88.     local optfmt="\t%-7s%s\n"
  89.  
  90.     eprintf "Usage: %s [-afho] package-archive [package-archive ...]\n" \
  91.             "$progname"
  92.  
  93.     eprintf "OPTIONS:\n"
  94.     eprintf "$optfmt" "-a" \
  95.             "Move the package-archive to an \`archive' sub-directory (next"
  96.    eprintf "$optfmt" "" \
  97.            "to the unpacked \`src' directory) after successfully unpacking"
  98.     eprintf "$optfmt" "" \
  99.             "the package. Not performed by default."
  100.     eprintf "$optfmt" "-f" \
  101.             "Force. Allow unpacking to a directory that already exists."
  102.     eprintf "$optfmt" "-h" \
  103.             "Print this message to stderr and exit."
  104.     eprintf "$optfmt" "-o" \
  105.             "Unpack archive to origin sub-directory. Default is to unpack"
  106.     eprintf "$optfmt" "" \
  107.             "to the local directory."
  108.  
  109.     die
  110. }
  111.  
  112. # read_pkg_origin
  113. # Usage:
  114. #   read_pkg_origin DATA [DATA] ...
  115. #       OR
  116. #   read_pkg_origin < FILE
  117. #
  118. # DESCRIPTION:
  119. #   Takes the contents of a packing-list (+CONTENTS) either in the form of data
  120. #   being piped-in, or as one or more arguments provided to this function. When
  121. #   provided as an argument, you must encapsulate the data from each packing-
  122. #   list with double-quotes to preserve the multi-line nature of the data. For
  123. #   example:
  124. #
  125. #   Simple:
  126. #       read_pkg_origin "$(cat ./+CONTENTS)"
  127. #   - or -
  128. #       read_pkg_origin "`cat ./+CONTENTS`"
  129. #
  130. #   Compound:
  131. #       data="$(cat ./+CONTENTS)"
  132. #   - or -
  133. #       data="`cat ./+CONTENTS`"
  134. #   - or -
  135. #       data=$(cat ./+CONTENTS)
  136. #   - or -
  137. #       data=`cat ./+CONTENTS`
  138. #   - then -
  139. #       read_pkg_origin "$data"
  140. #
  141. #   While you should avoid the following [unsupported] syntaxes:
  142. #
  143. #   To be avoided:
  144. #       read_pkg_origin $(cat ./+CONTENTS)
  145. #   - or -
  146. #       read_pkg_origin `cat ./+CONTENTS`
  147. #   - or -
  148. #       read_pkg_origin $data
  149. #
  150. #   Using double-quote encapsulation, you can optionally query multiple
  151. #   packing-lists with the following example syntax:
  152. #
  153. #   Multiple arguments:
  154. #       read_pkg_origin "$(cat pkgA/+CONTENTS)" "$(cat pkgB/+CONTENTS)"
  155. #   - or -
  156. #       dataA=$(cat pkgA/+CONTENTS)
  157. #       dataB=$(cat pkgB/+CONTENTS)
  158. #       read_pkg_origin "$dataA" "$dataB"
  159. #
  160. #   Finally, you can pipe the packing-list data directly into the function. See
  161. #   below:
  162. #
  163. #   Handling PIPE data:
  164. #       cat ./+CONTENTS | read_pkg_origin
  165. #   - or -
  166. #       read_pkg_origin < ./+CONTENTS
  167. #
  168. #   Only the first such ORIGIN field from any/all supplied packing-list data is
  169. #   printed, with the exception of when multiple arguments are provided (when
  170. #   the first ORIGIN field is printed for each argument, as-if each argument
  171. #   was a full-and-complete packing-list from an independent package).
  172. #
  173. read_pkg_origin()
  174. {
  175.     local ORIGIN="@comment ORIGIN:*"
  176.  
  177.     if [ $# -gt 0 ]; then
  178.         # Parse each argument as a full-and-complete packing-list
  179.         while [ $# -gt 0 ]; do
  180.             echo "$1" | (
  181.             while read LINE; do
  182.                 case "$LINE" in $ORIGIN)
  183.                     echo "${LINE#*:}" && break
  184.                 esac
  185.             done )
  186.             shift 1
  187.         done
  188.         return $SUCCESS
  189.     fi
  190.  
  191.     #
  192.     # Expect PIPE data to be provided from STDIN (otherwise, as
  193.     # expected, the user will be prompted to provide the input on
  194.     # the command-line when `read' is invoked
  195.     #
  196.     (
  197.         while read LINE; do
  198.             case "$LINE" in $ORIGIN)
  199.                 echo "${LINE#*:}" && break
  200.             esac
  201.         done
  202.     )
  203. }
  204.  
  205. # manifest_read [-p $prefix] [-r $filter_object] [-R $filter_value] [$file]
  206. # manifest_read [-p $prefix] [-r $filter_object] [-R $filter_value] -i "$data"
  207. #
  208. # Read MANIFEST $file in JSON format. If no other arguments are given, all
  209. # objects/properties are read into the current sh(1) namespace as a series of
  210. # environment variables.  If `-i' is given, take first argument as a full-and-
  211. # complete MANIFEST. If neither $file nor $data is given, read from stdin.
  212. #
  213. # If given `-p $prefix', each environment variable begins with `${prefix}_'.
  214. # If given `-r $filter_object', only objects matching $filter_object regular
  215. # expression are read into the current namespace.
  216. # If given `-R $filter_value', only properties whose value match $filter_value
  217. # regular expression are read into the current namespace.
  218. #
  219. manifest_read_awk='
  220.    BEGIN {
  221.        nkeys[depth = 0] = 0
  222.        building_array = building_string = 0
  223.        valid_chars = ENVIRON["VALID_VARNAME_CHARS"]
  224.        if (filter_object) filter_object = "^" filter_object "$"
  225.        if (filter_value) filter_value = "^" filter_value "$"
  226.    }
  227.    ############################################### FUNCTIONS
  228.    function trim_match()
  229.    {
  230.        match_text = substr($0, RSTART, RLENGTH)
  231.        $0 = substr($0, RSTART + RLENGTH)
  232.        return match_text
  233.    }
  234.    function trim_keyword()
  235.    {
  236.        if (!(keylen = length(key[depth]))) return
  237.  
  238.        keyword = substr(keyword, 0, length(keyword) - keylen - 1)
  239.        # NB: The "-1" is for keyword separator "_"
  240.  
  241.        key[depth] = ""
  242.        # NB: Prevents extra calls from reacting (depth retained)
  243.    }
  244.    function objsafe(name)
  245.    {
  246.        gsub("[^" valid_chars "]", "_", name)
  247.        return name
  248.    }
  249.    function json_print(object, value)
  250.    {
  251.        gsub(/'\''/, "'\''\\'\'\''", value)
  252.        object = objsafe(object)
  253.        print object "='\''" value "'\''"
  254.        if (!building_array) print object "_type=scalar"
  255.    }
  256.    function json_filtered_print(object, value)
  257.    {
  258.        if (object !~ filter_object) return
  259.        if (value !~ filter_value) return
  260.        return json_print(object, value)
  261.    }
  262.    function json_unset_value(object)
  263.    {
  264.        print "unset", objsafe(object) "_value"
  265.    }
  266.    function json_filtered_unset_value(object)
  267.    {
  268.        if (object !~ filter_object) return
  269.        return json_unset_value(object)
  270.    }
  271.    function json_objname()
  272.    {
  273.        if (building_array)
  274.            return keyword "_" building_array++
  275.        else if (depth <= 1)
  276.            return keyword
  277.  
  278.        if ((keylen = length(key[depth]))) keylen++
  279.        # NB: If non-NULL current-depth key, increment for separator
  280.  
  281.        return substr(keyword, 0, length(keyword) - keylen) \
  282.            "_" nkeys[depth]
  283.    }
  284.    ############################################### MAIN LOOP
  285.    { while ($0) { # Loop until done processing everything on this line
  286.        if (building_string) {
  287.            while (match($0, /^[^"]*\\"/))
  288.                value = value trim_match()
  289.            if (!match($0, /^[^"]*"/)) { # No ending quote
  290.                value = value $0
  291.                next # Continue reading on next line
  292.            }
  293.            building_string = 0
  294.            value = value substr($0, RSTART, RLENGTH - 1)
  295.            trim_match()
  296.            sub(/^[[:space:]]*,[[:space:]]*/, "")
  297.            json_filtered_print(keyword, value)
  298.            trim_keyword()
  299.        }
  300.        ################################### OPENING PATTERNS
  301.        else if (match($0, /^[[:space:]]*{[[:space:]]*/)) {
  302.            nkeys[++depth] = 0
  303.            trim_match()
  304.        } else if (keyword && match($0, /^[[:space:]]*\[/)) {
  305.            building_array = 1
  306.            trim_match()
  307.        }
  308.        ################################### OBJECTS
  309.        else if (match($0, \
  310.            /^[[:space:]]*"[^"]+"[[:space:]]*:[[:space:]]*/ \
  311.        )) {
  312.            nkeys[depth]++
  313.            key[depth] = trim_match()
  314.            sub(/^[[:space:]]*"/, "", key[depth])
  315.            sub(/"[[:space:]]*:[[:space:]]*$/, "", key[depth])
  316.            if (keyword) json_filtered_print( \
  317.                keyword "_" nkeys[depth], objsafe(key[depth]) \
  318.            )
  319.            keyword = keyword ( keyword ? "_" : "" ) key[depth]
  320.        }
  321.        ################################### PROPERTIES
  322.        else if (keyword && match($0, /^[[:space:]]*"/)) {
  323.            value = ""
  324.            trim_match()
  325.            while (match($0, /^[^"]*\\"/))
  326.                value = value trim_match()
  327.            if (!match($0, /^[^"]*"/)) {
  328.                building_string = 1
  329.                value = $0
  330.                next
  331.            }
  332.            value = value substr($0, RSTART, RLENGTH - 1)
  333.            trim_match()
  334.            sub(/^[[:space:]]*,[[:space:]]*/, "")
  335.    
  336.            object = json_objname()
  337.            if (depth <= 1)
  338.                json_filtered_print(object, value)
  339.            else {
  340.                json_filtered_print(object, key[depth])
  341.                json_filtered_print(object "_value", value)
  342.            }
  343.            if (building_array)
  344.                json_filtered_unset_value(object)
  345.            else
  346.                trim_keyword()
  347.        }
  348.        else if (keyword && match($0, \
  349.            /^[[:space:]]*[^[:space:],}\]]+[[:space:]]*/ \
  350.        )) {
  351.            value = trim_match()
  352.            sub(/^[[:space:]]*/, "", value)
  353.            sub(/[[:space:]]*$/, "", value)
  354.            sub(/^[[:space:]]*,[[:space:]]*/, "")
  355.            json_filtered_print(keyword, value)
  356.            trim_keyword()
  357.        }
  358.        ################################### CLOSING PATTERNS
  359.        else if (match($0, /^[[:space:]]*\][[:space:]]*/)) {
  360.            json_filtered_print(keyword, --building_array)
  361.            json_filtered_print(keyword "_type", "array")
  362.            building_array = 0
  363.            trim_keyword()
  364.            trim_match()
  365.            sub(/^[[:space:]]*,[[:space:]]*/, "")
  366.        }
  367.        else if (match($0, /^[[:space:]]*}[[:space:]]*/)) {
  368.            if (keyword) json_filtered_print(keyword, nkeys[depth])
  369.            building_array = 0 # Pedantic
  370.            nkeys[depth] = 0 # Pedantic
  371.            depth-- # NB: Done prior to calling trim_keyword()
  372.            trim_keyword()
  373.            trim_match()
  374.            sub(/^[[:space:]]*,[[:space:]]*/, "")
  375.        }
  376.    } }
  377. ' # END-QUOTE
  378. manifest_read()
  379. {
  380.     local __prefix __obj_regex __value_regex __arg_is_data=
  381.  
  382.     local OPTIND=1 OPTARG __flag
  383.     while getopts ip:r:R: __flag; do
  384.         case "$__flag" in
  385.         i) __arg_is_data=1 ;;
  386.         p) __prefix="$OPTARG" ;;
  387.         r) __obj_regex="$OPTARG" ;;
  388.         R) __value_regex="$OPTARG" ;;
  389.         \?|*) return $FAILURE
  390.         esac
  391.     done
  392.     shift $(( $OPTIND - 1 ))
  393.  
  394.     if [ "$__arg_is_data" ]; then
  395. # XXX       eval "$( echo "$1" | awk -v keyword="$__prefix" \
  396.         echo "$( echo "$1" | awk -v keyword="$__prefix" \
  397.            -v filter_object="$__obj_regex" \
  398.            -v filter_value="$__value_regex" \
  399.            "$manifest_read_awk" )"
  400.     else
  401. # XXX       eval "$( awk -v keyword="$__prefix" \
  402.         echo "$( awk -v keyword="$__prefix" \
  403.            -v filter_object="$__obj_regex" \
  404.            -v filter_value="$__value_regex" \
  405.            "$manifest_read_awk" "$@" )"
  406.     fi
  407. }
  408. manifest_read "$@"
  409. exit
  410.  
  411. # read_pkgng_origin
  412. # Usage:
  413. #   read_pkgng_origin DATA [DATA] ...
  414. #       OR
  415. #   read_pkgng_origin < FILE
  416. #
  417. # DESCRIPTION:
  418. #   Takes the contents of a packing-list (+MANIFEST or +COMPACT_MANIFEST)
  419. #   either in the form of data being piped-in, or as one or more arguments
  420. #   provided to this function. When provided as an argument, you must
  421. #   encapsulate the data from each packing-list with double-quotes to preserve
  422. #   the multi-line nature of the data. For example:
  423. #
  424. #   Simple:
  425. #       read_pkgng_origin "$(cat ./+COMPACT_MANIFEST)"
  426. #   - or -
  427. #       read_pkgng_origin "`cat ./+COMPACT_MANIFEST`"
  428. #
  429. #   Compound:
  430. #       data="$(cat ./+COMPACT_MANIFEST)"
  431. #   - or -
  432. #       data="`cat ./+COMPACT_MANIFEST`"
  433. #   - or -
  434. #       data=$(cat ./+COMPACT_MANIFEST)
  435. #   - or -
  436. #       data=`cat ./+COMPACT_MANIFEST`
  437. #   - then -
  438. #       read_pkgng_origin "$data"
  439. #
  440. #   While you should avoid the following [unsupported] syntaxes:
  441. #
  442. #   To be avoided:
  443. #       read_pkgng_origin $(cat ./+COMPACT_MANIFEST)
  444. #   - or -
  445. #       read_pkgng_origin `cat ./+COMPACT_MANIFEST`
  446. #   - or -
  447. #       read_pkgng_origin $data
  448. #
  449. #   Using double-quote encapsulation, you can optionally query multiple
  450. #   packing-lists with the following example syntax:
  451. #
  452. #   Multiple arguments:
  453. #       read_pkgng_origin \
  454. #           "$(cat pkgA/+COMPACT_MANIFEST)" "$(cat pkgB/+COMPACT_MANIFEST)"
  455. #   - or -
  456. #       dataA=$(cat pkgA/+COMPACT_MANIFEST)
  457. #       dataB=$(cat pkgB/+COMPACT_MANIFEST)
  458. #       read_pkgng_origin "$dataA" "$dataB"
  459. #
  460. #   Finally, you can pipe the packing-list data directly into the function. See
  461. #   below:
  462. #
  463. #   Handling PIPE data:
  464. #       cat ./+COMPACT_MANIFEST | read_pkgng_origin
  465. #   - or -
  466. #       read_pkgng_origin < ./+COMPACT_MANIFEST
  467. #
  468. #   Only the first such "origin" field from any/all supplied packing-list data
  469. #   is printed, with the exception of when multiple arguments are provided
  470. #   (when the first "origin" field is printed for each argument, as-if each
  471. #   argument was a full-and-complete packing-list from an independent package).
  472. #
  473. read_pkgng_origin()
  474. {
  475.     local origin
  476.  
  477.     if [ $# -gt 0 ]; then
  478.         # Parse each argument as a full-and-complete packing-list
  479.         while [ $# -gt 0 ]; do
  480.             origin=
  481.             manifest_read -r origin -i "$1"
  482.             echo "$origin"
  483.             shift 1
  484.         done
  485.         return $SUCCESS
  486.     fi
  487.  
  488.     #
  489.     # Expect PIPE data to be provided from STDIN (otherwise, as
  490.     # expected, the user will be prompted to provide the input on
  491.     # the command-line when `awk' is invoked
  492.     #
  493.     origin=
  494.     manifest_read -r origin
  495.     echo "$origin"
  496. }
  497.  
  498. ############################################################ MAIN
  499.  
  500. #
  501. # Perform sanity checks
  502. #
  503. [ $# -gt 0 ] || usage
  504.  
  505. #
  506. # Process command-line options
  507. #
  508. while getopts hoaf flag; do
  509.     case "$flag" in
  510.     h|\?) usage;;
  511.     o) USE_ORIGIN_SUBDIR=1;;
  512.     a) MOVE_PACKAGE=1;;
  513.     f) FORCE=1;;
  514.     esac
  515. done
  516. shift $(( $OPTIND - 1 ))
  517.  
  518. #
  519. # Perform [another] sanity check
  520. #
  521. [ $# -gt 0 ] || usage
  522.  
  523. #
  524. # Loop over each remaining package-archive argument(s)
  525. #
  526. while [ $# -gt 0 ]; do
  527.  
  528.     package="$1"
  529.     shift 1
  530.  
  531.     printf "===> Unpacking \`%s'\n" "$package"
  532.  
  533.    case "$package" in
  534.    *gz) ar_opt=z;;
  535.    *bz) ar_opt=j;;
  536.    *xz) ar_opt=J;;
  537.    esac
  538.  
  539.    CAT=
  540.    case "$ar_opt" in
  541.    J) tar --help 2>&1 | awk '/-J/&&found++;END{exit !found}' ||
  542.        CAT=xzcat ar_opt= ;;
  543.    esac
  544.  
  545.    #
  546.    # Extract packing-list from package
  547.    #
  548.    printf "Extracting +CONTENTS/+COMPACT_MANIFEST from package\n"
  549.    CONTENTS_FORMAT=pkg_tools
  550.    if [ "$CAT" ]; then
  551.        CONTENTS="$( $CAT "$package" |
  552.            tar ${ar_opt}xfO - +CONTENTS 2> /dev/null )"
  553.    else
  554.        CONTENTS="$( tar ${ar_opt}xfO "$package" +CONTENTS \
  555.            2> /dev/null )"
  556.    fi
  557.    if [ ! "$CONTENTS" ]; then
  558.        CONTENTS_FORMAT=pkgng
  559.        if [ "$CAT" ]; then
  560.            CONTENTS="$( $CAT "$package" |
  561.                tar ${ar_opt}xfO - +COMPACT_MANIFEST \
  562.                2> /dev/null )"
  563.        else
  564.            CONTENTS="$( tar ${ar_opt}xfO "$package" \
  565.                +COMPACT_MANIFEST 2> /dev/null )"
  566.        fi
  567.    fi
  568.    if [ ! "$CONTENTS" ]; then
  569.        eprintf "ERROR: Unable to extract packing-list from package\n"
  570.        eprintf "ERROR: Skipping package\n"
  571.        continue
  572.    fi
  573.  
  574.    #
  575.    # Get the package_name
  576.    #
  577.    # NOTE: By truncating the ORIGIN field of the packing-list we can
  578.    #       reliably determine the package's base name without having
  579.    #       to resort to attempting to infer its name based on the
  580.    #       package's file (which contains the version string). In
  581.    #       addition, it gives us a more definitive way of storing our
  582.    #       package sources (by ORIGIN, which indicates author and/or
  583.    #       section, rather than by base-name only).
  584.    # NOTE: For pkgng, the ORIGIN is the "origin" field in either +MANIFEST
  585.    #       or +COMPACT_MANIFEST.
  586.    #
  587.    case "$CONTENTS_FORMAT" in
  588.    pkg_tools)
  589.        printf "Reading ORIGIN from packing-list: "
  590.        ORIGIN=$( read_pkg_origin "$CONTENTS" ) ;;
  591.    pkgng)
  592.        printf "Reading origin from packing-list: "
  593.        ORIGIN=$( read_pkgng_origin "$CONTENTS" ) ;;
  594.    *)
  595.        eprintf "ERROR: Unknown packing-list format!\n"
  596.        eprintf "ERROR: Unable to unpack \`%s' (skipping)\n" "$package"
  597.         continue
  598.     esac
  599.     if [ ! "$ORIGIN" ]; then
  600.         printf "\n"
  601.         eprintf "ERROR: No ORIGIN recorded for package\n"
  602.         eprintf "ERROR: Unable to unpack \`%s'\n" "$package"
  603.  
  604.        read -p "Please provide a path to unpack to: " ORIGIN
  605.        if [ ! "$ORIGIN" ]; then
  606.            eprintf "ERROR: No path provided (skipping package)\n"
  607.            continue
  608.        fi
  609.        USE_ORIGIN_SUBDIR=1
  610.    else
  611.        printf "%s\n" "$ORIGIN"
  612.    fi
  613.  
  614.    #
  615.    # Determine where we will unpack the package to.
  616.    #
  617.    if [ "$USE_ORIGIN_SUBDIR" ]; then
  618.        DEST="$ORIGIN"
  619.    else
  620.        DEST="${ORIGIN##*/}"
  621.    fi
  622.  
  623.    #
  624.    # Make sure that the directory in which we are going to unpack to
  625.    # doesn't already exist. If it does, issue an error and skip this
  626.    # package (unless `-f' is passed).
  627.    #
  628.    # Otherwise, create the destination and proceed with unpacking.
  629.    #
  630.    printf "Creating package repository directory: "
  631.    if [ -e "$DEST" ]; then
  632.        printf "\n"
  633.        eprintf "ERROR: Directory \`%s' already exists\n" "$DEST"
  634.        if [ ! "$FORCE" ]; then
  635.            eprintf "ERROR: Skipping package %s\n" \
  636.                    "(use \`-f' to override)"
  637.            continue
  638.        else
  639.            eprintf "ERROR: Proceeding anyway (\`-f' was passed)\n"
  640.        fi
  641.    fi
  642.    if ! mkdir -p "$DEST"; then
  643.        printf "\n"
  644.        eprintf "ERROR: Could not create directory \`%s'\n" "$DEST"
  645.        die "ERROR: Exiting"
  646.    fi
  647.    printf "%s\n" "$DEST"
  648.  
  649.    #
  650.    # Unpack the package
  651.    #
  652.    printf "Unpacking...\n"
  653.    if ! mkdir -p "$DEST/src"; then
  654.        eprintf "ERROR: Could not create directory \`%s/src'\n" "$DEST"
  655.        die "ERROR: Exiting"
  656.    fi
  657.    if [ "$CAT" ]; then
  658.        $CAT "$package" | tar ${ar_opt}xfp - -C "$DEST/src"
  659.    else
  660.        tar ${ar_opt}xfp "$package" -C "$DEST/src"
  661.    fi
  662.    if [ $? -ne $SUCCESS ]; then
  663.        eprintf "ERROR: Could not unpack \`%s' to \`%s/src'" \
  664.            "$package" "$DEST"
  665.        die "ERROR: Exiting"
  666.    fi
  667.  
  668.    #
  669.    # Copy the packing-list
  670.    #
  671.    case "$CONTENTS_FORMAT" in
  672.    pkg_tools)
  673.        printf "Generating \`PLIST' from \`+CONTENTS'...\n"
  674.        if ! grep -v '^@comment[[:space:]]\{1,\}MD5:' \
  675.           < "$DEST/src/+CONTENTS" > "$DEST/PLIST"; then
  676.            eprintf "ERROR: Could not create \`PLIST'"
  677.            die "ERROR: Exiting"
  678.        fi
  679.        ;;
  680.    pkgng)
  681.        printf "Generating \`MANIFEST' from \`+MANIFEST'...\n"
  682.        # XXX unfinished XXX
  683.        printf "WARNING! NOT ACTUALLY DONE YET\n"
  684.        ;;
  685.    esac
  686.  
  687.    #
  688.    # Remove compiled packing-list
  689.    #
  690.    case "$CONTENTS_FORMAT" in
  691.    pkg_tools)
  692.        printf "Deleting \`+CONTENTS'...\n"
  693.        rm -f "$DEST/src/+CONTENTS"
  694.        ;;
  695.    pkgng)
  696.        printf "Deleting \`+MANIFEST' and \`+COMPACT_MANIFEST'...\n"
  697.        printf "WARNING! NOT ACTUALLY DONE YET\n"
  698.        #rm -f "$DEST/src/+MANIFEST" "$DEST/src/+COMPACT_MANIFEST"
  699.        ;;
  700.    esac
  701.  
  702.    #
  703.    # Archive package
  704.    #
  705.    if [ "$MOVE_PACKAGE" = "1" ]; then
  706.        echo "Archiving package..."
  707.        if ! mkdir "$DEST/archive"; then
  708.            eprintf "ERROR: Unable to create %s \`%s/archive'" \
  709.                    "directory" "$DEST"
  710.            die "ERROR: Exiting"
  711.        fi
  712.        if ! mv "$package" "$ORIGIN/archive"; then
  713.            eprintf "ERROR: Unable to %s \`%s' to \`%s/archive'" \
  714.                    "move" "$package" "$DEST"
  715.            die "ERROR: Exiting"
  716.        fi
  717.    fi
  718.  
  719.    #
  720.    # Extract skeleton directory into package repository
  721.    #
  722.    printf "Copying \`skel' structure into package repository...\n"
  723.    tar co --exclude CVS -f - -C "$progdir/skel" . | tar xkvf - -C "$DEST"
  724.  
  725.    #
  726.    # Move in the appropriate Makefile
  727.    #
  728.    printf "Adjusting for archive format...\n"
  729.    case "$CONTENTS_FORMAT" in
  730.    pkg_tools)
  731.        case "$ar_opt" in
  732.        z) rm -vf "$DEST/Makefile.ng"
  733.           if [ ! -e "$DEST/Makefile" ] ||
  734.              cmp "$DEST/Makefile" "$progdir/skel/Makefile"
  735.           then
  736.            mv -vf "$DEST/Makefile.old" "$DEST/Makefile"
  737.           else
  738.            rm -vf "$DEST/Makefile.old"
  739.           fi
  740.           ;;
  741.        j) rm -vf "$DEST/Makefile.old" "$DEST/Makefile.ng" ;;
  742.        esac
  743.        ;;
  744.    pkgng)
  745.        rm -vf "$DEST/PLIST"
  746.        rm -vf "$DEST/Makefile.old"
  747.        if [ ! -e "$DEST/Makefile" ] ||
  748.           cmp "$DEST/Makefile" "$progdir/skel/Makefile"
  749.        then
  750.            mv -vf "$DEST/Makefile.ng" "$DEST/Makefile"
  751.        else
  752.            rm -vf "$DEST/Makefile.ng"
  753.        fi
  754.        cmp "$DEST/src/+COMMENT" "$progdir/skel/src/+COMMENT" \
  755.            2> /dev/null && rm -fv "$DEST/src/+COMMENT"
  756.        cmp "$DEST/src/+DESC" "$progdir/skel/src/+DESC" 2> /dev/null &&
  757.            rm -fv "$DEST/src/+DESC"
  758.        ;;
  759.    esac
  760.  
  761.    #
  762.    # That's it (onto the next, back at the top).
  763.     #
  764.     printf "Done.\n"
  765. done
  766.  
  767. ################################################################################
  768. # END
  769. ################################################################################
  770. #
  771. # $Header: //depot/bugatti/pkgbase/freebsd/unpack.sh#5 $
  772. #
  773. # $Copyright: 1999-2014 Devin Teske. All rights reserved. $
  774. #
  775. ################################################################################
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement