Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 76 lines (68 sloc) 2.454 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
20 USAGE '${PROGNAME} [-p <path>] <gem>
21 ${PROGNAME} -c [-m] <gem>
22 Unpack a gem file to disk or as a tar stream on stdout.
23
24 Options
25 -p <path> Unpack under <path> instead of the working directory
26 -c Write gem data tar stream to stdout. Do not create any files.
27 -m Change the behavior of the -c option. Write gem metadata
28 segment instead of the data segment.'
29 workdir=.
30 filter=untar
31 segment=data.tar.gz
32 while getopts cmp: opt
33 do
34 case $opt in
35 p) workdir="$OPTARG";;
36 c) filter=cat;;
37 m) segment=metadata.gz;;
38 ?) helpthem
39 exit 2;;
40 esac
41 done
42 shift $(( $OPTIND - 1 ))
43
44 # Piping the gemspec through tar isn't going to help anyone. Fail fast.
45 if test $segment = "metadata.gz" -a $filter = "untar"
46 then warn "illegal argument: -m must be used with -c"
47 exit 2
48 fi
49
50 # Make sure a gem file was given.
51 name=$(basename "$1" .gem)
52 test "$name" || { helpthem; exit 2; }
53
54 # Quickly check that the gem file is readable.
55 test -r "$1" || {
56 warn "gem file can not be read: $1"
57 exit 1
58 }
59
60 # This takes the gem's `data.tar` stream on stdin and untars it into a
61 # newly created directory after the gem name. When the `-c` option is not
62 # given, the gem tar stream is piped through here.
63 untar () {
64 mkdir "$workdir/$name"
65 tar -xom -C "$workdir/$name" -f - 2>/dev/null
66 }
67
68 # Pipe the gem directly into `tar` and extract only the file/segment we're
69 # interested in (the `-O` option causes the file to be written to stdout
70 # instead of to disk). Next, pipe that thing through gzip to decompress and
71 # finally into whatever filter was configured (`cat` with the `-c` option or
72 # our `untar` function above otherwise).
73 tar -xOmf - $segment < "$1" 2>/dev/null |
74 gzip -dc |
75 $filter
Something went wrong with that request. Please try again.