Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

split package registration and installation into separate programs

  • Loading branch information...
commit e59261f6f1b6432832ccca62717781eada6d3cd1 1 parent 663f8b2
Ryan Tomayko authored
Showing with 296 additions and 3 deletions.
  1. +5 −3 Makefile
  2. +209 −0 rpg-package-install.sh
  3. +82 −0 rpg-package-register.sh
8 Makefile
View
@@ -32,20 +32,22 @@ SOURCES = \
rpg-sh-setup.sh rpg.sh rpg-config.sh rpg-deps.sh rpg-fetch.sh \
rpg-install.sh rpg-list.sh rpg-version-test.sh rpg-uninstall.sh \
rpg-build.sh rpg-env.sh rpg-update.sh rpg-resolve.sh rpg-upgrade.sh \
- rpg-steal.sh rpg-fsck.sh rpg-status.sh rpg-outdated.sh
+ rpg-steal.sh rpg-fsck.sh rpg-status.sh rpg-outdated.sh \
+ rpg-package-register.sh rpg-package-install.sh
PROGRAMS = \
rpg-sh-setup rpg rpg-config rpg-deps rpg-fetch \
rpg-install rpg-list rpg-version-test rpg-uninstall \
rpg-build rpg-env rpg-update rpg-resolve rpg-upgrade \
- rpg-steal rpg-fsck rpg-status rpg-outdated rpg-parse-package-list
+ rpg-steal rpg-fsck rpg-status rpg-outdated rpg-parse-package-list \
+ rpg-package-register rpg-package-install
DOCHTML = \
rpg-sh-setup.html rpg.html rpg-config.html rpg-deps.html rpg-fetch.html \
rpg-install.html rpg-list.html rpg-version-test.html rpg-uninstall.html \
rpg-build.html rpg-env.html rpg-update.html rpg-resolve.html \
rpg-upgrade.html rpg-steal.html rpg-fsck.html rpg-status.html \
- rpg-outdated.html
+ rpg-outdated.html rpg-package-register.html rpg-package-install.html
STANDALONE = $(NAME)-sa
209 rpg-package-install.sh
View
@@ -0,0 +1,209 @@
+#!/bin/sh
+# The `rpg-package-install` program perform the actual installation of files
+# into the system installation locations. The `<package>` and `<version>`
+# supplied must already be registered in the package database as by invoking
+# the `rpg-package-register` program.
+#
+# If the package is already installed and at the version specified,
+# `rpg-package-install` exits immediately with a success exit status. The
+# `-f` argument can be used to force the install operations to be performed
+# on an already installed program.
+set -e
+. rpg-sh-setup
+
+[ "$*" ] || set -- '--help'; ARGV="$@"
+USAGE '${PROGNAME} [-f] <package> <version> ...
+Install a registered package from the database.
+
+This is a low level command. For an install front-end, see rpg-install(1).'
+
+force=false
+test "$1" = '-f' && {
+ force=true
+ shift
+}
+
+[ "$1$2" ] || {
+ warn "invalid arguments: '$*'";
+ exit 2
+}
+
+# Utility Functions
+# -----------------
+
+# Usage: rpg_ln <source> <dest>
+# Attempt to hard link <dest> to <source> but fall back to cp(1) if
+# you're crossing file systems or the ln fails otherwise.
+rpg_ln () {
+ if ln -f "$1" "$2"
+ then notice "$2 [ln]"
+ else notice "$2 [cp]"
+ cp "$1" "$2"
+ fi
+}
+
+# Recursive file hierarchy copy routine. Attempts to hardlink files
+# and falls back to normal copies.
+rpg_install_dir () {
+ local src="$1" dest="$2" manifest="$3"
+ mkdir -p "$dest"
+ for file in "$1"/*
+ do
+ if test -f "$file"
+ then # link dest to source
+ rpg_ln "$file" "$dest/$(basename $file)"
+ echo "$dest/$(basename $file)" >> "$manifest"
+
+ elif test -d "$file"
+ then # recurse into directories
+ rpg_install_dir "$file" "$dest/$(basename $file)" "$manifest"
+
+ else warn "unknown file type: $file"
+ return 1
+ fi
+ done
+ return 0
+}
+
+# Package Database Prep
+# ---------------------
+
+# Establish our directories in the package database. These should
+# have already been created by `rpg-package-register`. If not, bail
+# out now since something isn't right.
+package="$1"
+version="$2"
+packagedir="$RPGDB/$package"
+
+test -d "$packagedir/$version" || {
+ warn "package not registered: $package/$version"
+ exit 1
+}
+
+notice "$package $version"
+
+# Fetch the gem into the cache and unpack into the packs area if
+# its not already there.
+if test -d "$RPGPACKS/$package-$version"
+then notice "sources already exist. bypassing fetch and unpack."
+else gemfile=$(rpg-fetch "$package" "$version")
+ notice "unpacking $gemfile into $RPGPACKS"
+ mkdir -p "$RPGPACKS"
+ (cd "$RPGPACKS" && gem unpack "$gemfile" >/dev/null)
+fi
+
+# If the package already has an active/installed version, check if its
+# the same as the one we're installing and bail if so. Otherwise unlink
+# the active version and install over it for now.
+#
+# TODO handle uninstalling previous package version or fail or something.
+test -e "$packagedir/active" && {
+ activevers=$(readlink $packagedir/active)
+ if test "$activevers" = "$version"
+ then
+ if $force
+ then notice "$package $version is current. reinstalling due to -f"
+ unlink "$packagedir/active"
+ else notice "$package $version is current. not reinstalling."
+ exit 0
+ fi
+ else notice "$package $activevers is installed but $version requested"
+ unlink "$packagedir/active"
+ fi
+}
+
+# This is our file manifest. We record everything installed in here
+# so we know how to uninstall the package. Create/truncate it in case
+# it already exists.
+#
+# TODO if the manifest already exists that means the package was
+# previously installed or may currently be installed. Do something with
+# that information.
+manifest="$packagedir/$version/manifest"
+echo "# $(date)" > "$manifest"
+
+# Symlink the `installing` file to the version directory. This will let us
+# detect in progress or failed installations.
+ln -sf "$version" "$packagedir/installing"
+
+# Go into the unpackaged package dir to make installing a bit easier.
+cd "$RPGPACKS/$package-$version"
+
+
+# Extension Libraries
+# -------------------
+
+# Build extension libraries if they exist. Bail out if the build fails.
+exts="$(rpg-build "$(pwd)")" || {
+ warn "extension failed to build"
+ exit 1
+}
+
+# Install any extensions to `RPGLIB`. This is kind of tricky. We should
+# be running `make` in the extension directory but I haven't had time to
+# make it work right so just pull the prefix out of the `Makefile` and
+# install the shared libs manually.
+test -n "$exts" && {
+ mkdir -p "$RPGLIB"
+ echo "$exts" |
+ while read dl
+ do
+ # make install sitearchdir=/lib
+ prefix=$(
+ grep '^target_prefix.=' "$(dirname $dl)/Makefile" |
+ sed 's/^target_prefix *= *//'
+ )
+ dest="${RPGLIB}${prefix}/$(basename $dl)"
+ rpg_ln "$dl" "$dest"
+ echo "$dest" >> "$manifest"
+ done
+}
+
+# Ruby Library Files
+# ------------------
+
+# Recursively install all library files into `RPGLIB`.
+test -d lib && {
+ mkdir -p "$RPGLIB"
+ rpg_install_dir lib "$RPGLIB" "$manifest"
+}
+
+# Ruby Executables
+# ----------------
+
+# Write executable scripts into `RPGBIN` and rewrite shebang lines.
+test -d bin && {
+ mkdir -p "$RPGBIN"
+ for file in bin/*
+ do dest="$RPGBIN/$(basename $file)"
+ notice "$dest [!]"
+ sed "s@^#!.*ruby.*@#!$(ruby_command)@" \
+ < "$file" \
+ > "$dest"
+ chmod 0755 "$dest"
+ echo "$dest" >> "$manifest"
+ done
+}
+
+# Manpages
+# --------
+
+# Install any manpages included with the package into `RPGMAN`. Make
+# sure files are being installed under the prescribed hierarchy.
+test -d man && {
+ for file in man/*
+ do if test -f "$file" && expr "$file" : '.*\.[0-9][0-9A-Za-z]*$' >/dev/null
+ then
+ section=${file##*\.}
+ dest="$RPGMAN/man$section/$(basename $file)"
+ mkdir -p "$RPGMAN/man$section"
+ rpg_ln "$file" "$dest"
+ echo "$dest" >> "$manifest"
+ fi
+ done
+}
+
+
+# Mark this package as active
+unlink "$packagedir/installing"
+ln -sf "$version" "$packagedir/active"
82 rpg-package-register.sh
View
@@ -0,0 +1,82 @@
+#!/bin/sh
+# Register a gem in the package database.
+#
+# PGEMDB
+# foo/
+# 0.1/
+# 0.2/
+# bar/
+# 1.2/
+# 1.3/
+# name
+# version
+# gemspec
+# deps
+#
+set -e
+. rpg-sh-setup
+
+[ "$*" ] || set -- '--help'; ARGV="$@"
+USAGE '${PROGNAME} [-f] <file>...
+Register a gem in the package database and write location stdout.'
+
+force=false
+test "$1" = '-f' && {
+ force=true
+ shift
+}
+
+for file in "$@"
+do
+ # Information we can extract from the gem name.
+ gemname=$(basename $file .gem)
+ package=${gemname%-*}
+ version=${gemname##*-}
+
+ # These are directories and file locations into the package database.
+ packagedir="$RPGDB/$package/$version"
+ gemspec="$packagedir/gemspec"
+ deps="$packagedir/deps"
+
+ # Try to exit if the package is already registered and looks okay. The
+ # `-f` argument can be used to override and force the package to be
+ # registered again.
+ if test -f "$packagedir/gemspec" -a -f "$packagedir/name"
+ then
+ if $force
+ then notice "$package $version already registered: proceeding due to -f"
+ else notice "$package $version already registered: bypassing"
+ exit 0
+ fi
+ else
+ notice "$package $version -> $packagedir"
+ fi
+
+ # Create the package directory, write `name` and `version` files,
+ # extract and write gemspec related files.
+ #
+ # The `name` and `version` files are redundant since that info can be
+ # obtained from `$(basename $(dirname <path>))` and `$(basename <path>)`,
+ # but having them there makes some things a bit easier.
+ #
+ # TODO this gemspec extraction nonsense needs to go. find a better way
+ # to get the deps and other information.
+ mkdir -p "$packagedir"
+ echo "$package" > "$packagedir/name"
+ echo "$version" > "$packagedir/version"
+
+ gem spec --ruby "$file" > "$gemspec"
+ ruby <<RUBY
+ require 'rubygems'
+ spec = eval(File.read('$gemspec'), binding, '$gemspec', 1)
+ File.open('$deps', 'wb') do |fd|
+ spec.dependencies.each do |dep|
+ dep.requirement.as_list.each do |req|
+ fd.puts '%s %s %s' % [dep.type, dep.name, req]
+ end
+ end
+ end
+RUBY
+
+ echo "$packagedir"
+done
Please sign in to comment.
Something went wrong with that request. Please try again.