Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 110 lines (98 sloc) 3.618 kB
0783e80 @rtomayko rpg-unpack for extracting gems and gemspecs
authored
1 #!/bin/sh
2 # The `rpg-unpack` program reads the gem file's internal tar-based structure
3 # and either untars into a new directory or writes the data segment's tar
4 # stream to stdout.
5 #
6 # Gem files are more or less normal tarballs that looks like this:
7 #
8 # $ tar tv < sinatra-0.9.6.gem
9 # -rw-r--r-- wheel/wheel 117190 1969-12-31 16:00:00 data.tar.gz
10 # -rw-r--r-- wheel/wheel 1225 1969-12-31 16:00:00 metadata.gz
11 #
12 # The `metadata.gz` file is a gzip compressed YAML gemspec. The
13 # `data.tar.gz` holds the unprefixed files.
14 #
15 # There's also an older gem format apparently, but I'm hoping to not have to
16 # deal with it.
17 set -e
18 . rpg-sh-setup
19
64c9edb @rtomayko rpg-unpack writes name of unpack directory to stdout
authored
20 USAGE '${PROGNAME} [-p <path>|-P] <package> [<version>]
21 ${PROGNAME} -c [-m] <package> [<version>]
22 Unpack a gem file to disk or as a tar stream on standard output.
0783e80 @rtomayko rpg-unpack for extracting gems and gemspecs
authored
23
24 Options
25 -c Write gem data tar stream to stdout. Do not create any files.
d9b6758 @rtomayko rpg-unpack takes -f (force) and -n (noop) args
authored
26 -f Unpack over an existing directory.
0783e80 @rtomayko rpg-unpack for extracting gems and gemspecs
authored
27 -m Change the behavior of the -c option. Write gem metadata
64c9edb @rtomayko rpg-unpack writes name of unpack directory to stdout
authored
28 segment instead of the data segment.
d9b6758 @rtomayko rpg-unpack takes -f (force) and -n (noop) args
authored
29 -n Do nothing if unpack directory already exists.
30 -p <path> Unpack under <path> instead of the working directory.
31 -P Unpack under RPGPACKS instead of the working directory.
64c9edb @rtomayko rpg-unpack writes name of unpack directory to stdout
authored
32
33 The <package> may be a package name or path to a gem file on disk. When a
34 package name is given, the <version> may also be specified.'
0783e80 @rtomayko rpg-unpack for extracting gems and gemspecs
authored
35 workdir=.
36 filter=untar
37 segment=data.tar.gz
d9b6758 @rtomayko rpg-unpack takes -f (force) and -n (noop) args
authored
38 noop=false
39 force=false
40 while getopts cfmnPp: opt
0783e80 @rtomayko rpg-unpack for extracting gems and gemspecs
authored
41 do
42 case $opt in
43 p) workdir="$OPTARG";;
60855e5 @rtomayko rpg-unpack -P extracts to RPGPACKS instead of RPGCACHE (oops)
authored
44 P) workdir="$RPGPACKS";;
0783e80 @rtomayko rpg-unpack for extracting gems and gemspecs
authored
45 c) filter=cat;;
46 m) segment=metadata.gz;;
d9b6758 @rtomayko rpg-unpack takes -f (force) and -n (noop) args
authored
47 f) force=true;;
48 n) noop=true;;
0783e80 @rtomayko rpg-unpack for extracting gems and gemspecs
authored
49 ?) helpthem
50 exit 2;;
51 esac
52 done
53 shift $(( $OPTIND - 1 ))
54
55 # Piping the gemspec through tar isn't going to help anyone. Fail fast.
56 if test $segment = "metadata.gz" -a $filter = "untar"
57 then warn "illegal argument: -m must be used with -c"
58 exit 2
59 fi
60
64c9edb @rtomayko rpg-unpack writes name of unpack directory to stdout
authored
61 # Check whether a gem file or package name was given.
62 if expr "$1" : '.*\.gem' >/dev/null
63 then file="$1"
64 test -r "$file" || {
65 warn "gem file can not be read: $file"
66 exit 1
67 }
68 else file=$(rpg-fetch "$1" "${2:->0}")
69 fi
0783e80 @rtomayko rpg-unpack for extracting gems and gemspecs
authored
70
64c9edb @rtomayko rpg-unpack writes name of unpack directory to stdout
authored
71 # Extract the package name and version from the gem file.
72 basename=$(basename "$file" .gem)
73 package=${basename%-*}
74 version=${basename##*-}
0783e80 @rtomayko rpg-unpack for extracting gems and gemspecs
authored
75
76 # This takes the gem's `data.tar` stream on stdin and untars it into a
77 # newly created directory after the gem name. When the `-c` option is not
78 # given, the gem tar stream is piped through here.
79 untar () {
d9b6758 @rtomayko rpg-unpack takes -f (force) and -n (noop) args
authored
80 if $force
81 then mkdir -p "$workdir/$package-$version"
82 else mkdir "$workdir/$package-$version"
83 fi
64c9edb @rtomayko rpg-unpack writes name of unpack directory to stdout
authored
84 tar -xom -C "$workdir/$package-$version" -f - 2>/dev/null
0783e80 @rtomayko rpg-unpack for extracting gems and gemspecs
authored
85 }
86
d9b6758 @rtomayko rpg-unpack takes -f (force) and -n (noop) args
authored
87 # Bail out with just the unpack directory on stdout if the -n option was
88 # given.
89 $noop && test "$filter" = "untar" -a -d "$workdir/$package-$version" && {
90 notice "$workdir/$package-$version already exists. noop'ing."
91 echo "$workdir/$package-$version"
92 exit 0
93 }
64c9edb @rtomayko rpg-unpack writes name of unpack directory to stdout
authored
94
0783e80 @rtomayko rpg-unpack for extracting gems and gemspecs
authored
95 # Pipe the gem directly into `tar` and extract only the file/segment we're
96 # interested in (the `-O` option causes the file to be written to stdout
97 # instead of to disk). Next, pipe that thing through gzip to decompress and
98 # finally into whatever filter was configured (`cat` with the `-c` option or
99 # our `untar` function above otherwise).
64c9edb @rtomayko rpg-unpack writes name of unpack directory to stdout
authored
100 tar -xOmf - $segment < "$file" 2>/dev/null |
101 gzip -dc |
0783e80 @rtomayko rpg-unpack for extracting gems and gemspecs
authored
102 $filter
64c9edb @rtomayko rpg-unpack writes name of unpack directory to stdout
authored
103
104 # Write the path to the unpacked package directory on standard output.
105 if test "$filter" = "untar"
106 then echo "$workdir/$package-$version"
107 fi
108
109 true
Something went wrong with that request. Please try again.