V2
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..7485a91
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "test/rust-installer-v1"]
+	path = test/rust-installer-v1
+	url = https://github.com/rust-lang/rust-installer
diff --git a/README.md b/README.md
index f541504..ec6f787 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,9 @@
                    --work-dir=./temp \
                    --output-dir=./dist \
                    --non-installed-prefixes="foo,bin/bar,lib/baz" \
-                   --package-name=rustc-nightly-i686-apple-darwin
+                   --package-name=rustc-nightly-i686-apple-darwin \
+		   --component-name=rustc \
+		   --legacy-manifest-dirs=rustlib
 ```
 
 Or, to just generate the script.
@@ -23,7 +25,8 @@
                         --verify-bin=rustc \
                         --rel-manifest-dir=rustlib \
                         --success-message=Rust-is-ready-to-roll. \
-                        --output-script=install.sh
+                        --output-script=install.sh \
+			--legacy-manifest-dirs=rustlib
 ```
 
 *Note: the dashes in `success-message` are converted to spaces. The
diff --git a/gen-install-script.sh b/gen-install-script.sh
index f498d61..4dfb500 100755
--- a/gen-install-script.sh
+++ b/gen-install-script.sh
@@ -225,6 +225,7 @@
 valopt rel-manifest-dir "${CFG_VERIFY_BIN}lib" "The directory under lib/ where the manifest lives"
 valopt success-message "Installed." "The string to print after successful installation"
 valopt output-script "${CFG_SRC_DIR}/install.sh" "The name of the output script"
+valopt legacy-manifest-dirs "" "Places to look for legacy manifests to uninstall"
 
 if [ $HELP -eq 1 ]
 then
@@ -245,6 +246,7 @@
 SCRIPT=`echo "${SCRIPT}" | sed "s/%%TEMPLATE_VERIFY_BIN%%/${CFG_VERIFY_BIN}/"`
 SCRIPT=`echo "${SCRIPT}" | sed "s/%%TEMPLATE_REL_MANIFEST_DIR%%/${CFG_REL_MANIFEST_DIR}/"`
 SCRIPT=`echo "${SCRIPT}" | sed "s/%%TEMPLATE_SUCCESS_MESSAGE%%/\"${CFG_SUCCESS_MESSAGE}\"/"`
+SCRIPT=`echo "${SCRIPT}" | sed "s/%%TEMPLATE_LEGACY_MANIFEST_DIRS%%/\"${CFG_LEGACY_MANIFEST_DIRS}\"/"`
 
 echo "${SCRIPT}" > "${CFG_OUTPUT_SCRIPT}"
 need_ok "couldn't write script"
diff --git a/gen-installer.sh b/gen-installer.sh
index aab3c8c..24620fd 100755
--- a/gen-installer.sh
+++ b/gen-installer.sh
@@ -224,10 +224,12 @@
 fi
 
 valopt product-name "Product" "The name of the product, for display"
+valopt component-name "component" "The name of the component, distinct from other installed components"
 valopt package-name "package" "The name of the package, tarball"
 valopt verify-bin "program" "The command to run with --version to verify the install works"
 valopt rel-manifest-dir "${CFG_VERIFY_BIN}lib" "The directory under lib/ where the manifest lives"
 valopt success-message "Installed." "The string to print after successful installation"
+valopt legacy-manifest-dirs "" "Places to look for legacy manifests to uninstall"
 valopt non-installed-prefixes "" "Path prefixes that should be included but not installed"
 valopt image-dir "./install-image" "The directory containing the installation medium"
 valopt work-dir "./workdir" "The directory to do temporary work"
@@ -294,16 +296,17 @@
 rm "$TEMP_NON_INSTALLED_PREFIXES"
 need_ok "couldn't delete temp file"
 
-MANIFEST_NAME="$CFG_WORK_DIR/$CFG_PACKAGE_NAME/lib/$CFG_REL_MANIFEST_DIR/manifest.in"
-
-mkdir -p "$CFG_WORK_DIR/$CFG_PACKAGE_NAME/lib/$CFG_REL_MANIFEST_DIR"
-need_ok "couldn't create manifest dir"
-
 # Delete blank line added from above loop
 NEW_MANIFEST=`echo "$NEW_MANIFEST" | sed "/^$/d"`
 
+MANIFEST_FILE="$CFG_WORK_DIR/$CFG_PACKAGE_NAME/$CFG_COMPONENT_NAME-manifest.in"
+COMPONENT_FILE="$CFG_WORK_DIR/$CFG_PACKAGE_NAME/components"
+
 # Write the manifest
-echo "$NEW_MANIFEST" > "$MANIFEST_NAME"
+echo "$NEW_MANIFEST" > "$MANIFEST_FILE"
+
+# Write the component name
+echo "$CFG_COMPONENT_NAME" > "$COMPONENT_FILE"
 
 # Generate the install script
 "$CFG_SRC_DIR/gen-install-script.sh" \
@@ -311,6 +314,7 @@
     --verify-bin="$CFG_VERIFY_BIN" \
     --rel-manifest-dir="$CFG_REL_MANIFEST_DIR" \
     --success-message="$CFG_SUCCESS_MESSAGE" \
+    --legacy-manifest-dirs="$CFG_LEGACY_MANIFEST_DIRS" \
     --output-script="$CFG_WORK_DIR/$CFG_PACKAGE_NAME/install.sh"
 
 need_ok "failed to generate install script"    
diff --git a/install-template.sh b/install-template.sh
index 6ca971f..16c41e3 100644
--- a/install-template.sh
+++ b/install-template.sh
@@ -346,10 +346,9 @@
 step_msg "validating $CFG_SELF args"
 validate_opt
 
-
-
 # Template configuration.
 # These names surrounded by '%%` are replaced by sed when generating install.sh
+# FIXME: Might want to consider loading this from a file and not generating install.sh
 
 # Rust or Cargo
 TEMPLATE_PRODUCT_NAME=%%TEMPLATE_PRODUCT_NAME%%
@@ -359,6 +358,11 @@
 TEMPLATE_REL_MANIFEST_DIR=%%TEMPLATE_REL_MANIFEST_DIR%%
 # 'Rust is ready to roll.' or 'Cargo is cool to cruise.'
 TEMPLATE_SUCCESS_MESSAGE=%%TEMPLATE_SUCCESS_MESSAGE%%
+# Locations to look for directories containing legacy, pre-versioned manifests
+TEMPLATE_LEGACY_MANIFEST_DIRS=%%TEMPLATE_LEGACY_MANIFEST_DIRS%%
+
+# The revision of the installer, bumped for incompatible changes
+INSTALLER_VERSION=2
 
 # OK, let's get installing ...
 
@@ -401,57 +405,102 @@
     err "can't install to same directory as installer"
 fi
 
+# Open the components file to get the list of components to install
+COMPONENTS=`cat "$CFG_SRC_DIR/components"`
+
+# Sanity check: do we have components?
+if [ ! -n "$COMPONENTS" ]; then
+    err "unable to find installation components"
+fi
+
 # Using an absolute path to libdir in a few places so that the status
 # messages are consistently using absolute paths.
 absolutify "${CFG_LIBDIR}"
 ABS_LIBDIR="${ABSOLUTIFIED}"
 
-# The file name of the manifest we're going to create during install
-INSTALLED_MANIFEST="${ABS_LIBDIR}/${TEMPLATE_REL_MANIFEST_DIR}/manifest"
+# Replace commas in legacy manifest list with spaces
+LEGACY_MANIFEST_DIRS=`echo "$TEMPLATE_LEGACY_MANIFEST_DIRS" | sed "s/,/ /g"`
 
-# First, uninstall from the installation prefix.
-# Errors are warnings - try to rm everything in the manifest even if some fail.
-if [ -f "${INSTALLED_MANIFEST}" ]
-then
-    msg
+# Uninstall from legacy manifests
+for md in $LEGACY_MANIFEST_DIRS; do
+    # First, uninstall from the installation prefix.
+    # Errors are warnings - try to rm everything in the manifest even if some fail.
+    if [ -f "$ABS_LIBDIR/$md/manifest" ]
+    then
+	msg
 
-    # Iterate through installed manifest and remove files
-    while read p; do
-        # The installed manifest contains absolute paths
-        msg "removing $p"
-        if [ -f "$p" ]
-        then
-            rm -f "$p"
-            if [ $? -ne 0 ]
+	# Iterate through installed manifest and remove files
+	while read p; do
+            # The installed manifest contains absolute paths
+            msg "removing $p"
+            if [ -f "$p" ]
             then
-                warn "failed to remove $p"
+		rm -f "$p"
+		if [ $? -ne 0 ]
+		then
+                    warn "failed to remove $p"
+		fi
+            else
+		warn "supposedly installed file $p does not exist!"
             fi
-        else
-            warn "supposedly installed file $p does not exist!"
-        fi
-    done < "${INSTALLED_MANIFEST}"
+	done < "$ABS_LIBDIR/$md/manifest"
 
-    # If we fail to remove $TEMPLATE_REL_MANIFEST_DIR below, then the
-    # installed manifest will still be full; the installed manifest
-    # needs to be empty before install.
-    msg "removing ${INSTALLED_MANIFEST}"
-    rm -f "${INSTALLED_MANIFEST}"
-    # For the above reason, this is a hard error
-    need_ok "failed to remove installed manifest"
+	# If we fail to remove $md below, then the
+	# installed manifest will still be full; the installed manifest
+	# needs to be empty before install.
+	msg "removing $ABS_LIBDIR/$md/manifest"
+	rm -f "$ABS_LIBDIR/$md/manifest"
+	# For the above reason, this is a hard error
+	need_ok "failed to remove installed manifest"
 
-    # Remove $TEMPLATE_REL_MANIFEST_DIR directory
-    msg "removing ${ABS_LIBDIR}/${TEMPLATE_REL_MANIFEST_DIR}"
-    rm -Rf "${ABS_LIBDIR}/${TEMPLATE_REL_MANIFEST_DIR}"
-    if [ $? -ne 0 ]
-    then
-        warn "failed to remove ${TEMPLATE_REL_MANIFEST_DIR}"
+	# Remove $TEMPLATE_REL_MANIFEST_DIR directory
+	msg "removing ${ABS_LIBDIR}/$md"
+	rm -Rf "${ABS_LIBDIR}/$md"
+	if [ $? -ne 0 ]
+	then
+            warn "failed to remove $md"
+	fi
+
+	UNINSTALLED_SOMETHING=1
     fi
-else
-    # There's no manifest. If we were asked to uninstall, then that's a problem.
-    if [ -n "${CFG_UNINSTALL}" ]
-    then
-        err "unable to find installation manifest at ${CFG_LIBDIR}/${TEMPLATE_REL_MANIFEST_DIR}"
-    fi
+done
+
+# Check installed version
+if [ -f "$ABS_LIBDIR/$TEMPLATE_REL_MANIFEST_DIR/rust-installer-version" ]; then
+    INSTALLED_VERSION=`cat $ABS_LIBDIR/$TEMPLATE_REL_MANIFEST_DIR/rust-installer-version"`
+fi
+
+case "$INSTALLED_VERSION" in
+
+    # TODO: If this is a previous version, then upgrade in place to the
+    # current version before uninstalling. No need to do this yet because
+    # there is no prior version (only the legacy 'unversioned' installer
+    # which we've already dealt with).
+
+    # This is the current version. Nothing need to be done except uninstall.
+    "2")
+	;;
+
+    # TODO: If this is an unknown (future) version then bail.
+    *)
+	echo "The copy of $TEMPLATE_PRODUCT_NAME at $PREFIX was installed using an"
+	echo "unknown version ($INSTALLED_VERSION) of rust-installer. Uninstall"
+	echo "it first with the installer used for the original installation"
+	echo "before continuing."
+	exit 1
+	;;
+esac
+
+# TODO: Uninstall (our components only) before reinstalling
+if [ -n "$INSTALLED_VERSION" ]; then
+    for component in $COMPONENTS; do
+    done
+fi
+
+# There's no installed version. If we were asked to uninstall, then that's a problem.
+if [ -n "${CFG_UNINSTALL}" -a ! -n "$UNINSTALLED_SOMETHING" ]
+then
+    err "unable to find installation manifest at ${CFG_LIBDIR}/${TEMPLATE_REL_MANIFEST_DIR}"
 fi
 
 # If we're only uninstalling then exit
@@ -463,57 +512,82 @@
     exit 0
 fi
 
-# Create the installed manifest, which we will fill in with absolute file paths
-mkdir -p "${CFG_LIBDIR}/${TEMPLATE_REL_MANIFEST_DIR}"
-need_ok "failed to create ${TEMPLATE_REL_MANIFEST_DIR}"
-touch "${INSTALLED_MANIFEST}"
-need_ok "failed to create installed manifest"
-
 msg
 
-# Now install, iterate through the new manifest and copy files
-while read p; do
+# Create the directory to contain the manifests
+mkdir -p "${CFG_LIBDIR}/${TEMPLATE_REL_MANIFEST_DIR}"
+need_ok "failed to create ${TEMPLATE_REL_MANIFEST_DIR}"
 
-    # Decide the destination of the file
-    FILE_INSTALL_PATH="${CFG_DESTDIR}${CFG_PREFIX}/$p"
+# Install each component
+for component in $COMPONENTS; do
 
-    if echo "$p" | grep "^lib/" > /dev/null
-    then
-        pp=`echo $p | sed 's/^lib\///'`
-        FILE_INSTALL_PATH="${CFG_LIBDIR}/$pp"
+    # The file name of the manifest we're installing from
+    INPUT_MANIFEST="${CFG_SRC_DIR}/$component-manifest.in"
+
+    # The file name of the manifest we're going to create during install
+    INSTALLED_MANIFEST="${ABS_LIBDIR}/${TEMPLATE_REL_MANIFEST_DIR}/$component-manifest"
+
+    # Create the installed manifest, which we will fill in with absolute file paths
+    touch "${INSTALLED_MANIFEST}"
+    need_ok "failed to create installed manifest"
+
+    # Sanity check: do we have our input manifests?
+    if [ ! -f "$INPUT_MANIFEST" ]; then
+	err "manifest for $component does not exist at $INPUT_MANIFEST"
     fi
 
-    if echo "$p" | grep "^share/man/" > /dev/null
-    then
-        pp=`echo $p | sed 's/^share\/man\///'`
-        FILE_INSTALL_PATH="${CFG_MANDIR}/$pp"
-    fi
+    # Now install, iterate through the new manifest and copy files
+    while read p; do
 
-    # Make sure there's a directory for it
-    umask 022 && mkdir -p "$(dirname ${FILE_INSTALL_PATH})"
-    need_ok "directory creation failed"
+	# Decide the destination of the file
+	FILE_INSTALL_PATH="${CFG_DESTDIR}${CFG_PREFIX}/$p"
 
-    # Make the path absolute so we can uninstall it later without
-    # starting from the installation cwd
-    absolutify "${FILE_INSTALL_PATH}"
-    FILE_INSTALL_PATH="${ABSOLUTIFIED}"
+	if echo "$p" | grep "^lib/" > /dev/null
+	then
+            pp=`echo $p | sed 's/^lib\///'`
+            FILE_INSTALL_PATH="${CFG_LIBDIR}/$pp"
+	fi
 
-    # Install the file
-    msg "installing ${FILE_INSTALL_PATH}"
-    if echo "$p" | grep "^bin/" > /dev/null
-    then
-        install -m755 "${CFG_SRC_DIR}/$p" "${FILE_INSTALL_PATH}"
-    else
-        install -m644 "${CFG_SRC_DIR}/$p" "${FILE_INSTALL_PATH}"
-    fi
-    need_ok "file creation failed"
+	if echo "$p" | grep "^share/man/" > /dev/null
+	then
+            pp=`echo $p | sed 's/^share\/man\///'`
+            FILE_INSTALL_PATH="${CFG_MANDIR}/$pp"
+	fi
 
-    # Update the manifest
-    echo "${FILE_INSTALL_PATH}" >> "${INSTALLED_MANIFEST}"
-    need_ok "failed to update manifest"
+	# Make sure there's a directory for it
+	umask 022 && mkdir -p "$(dirname ${FILE_INSTALL_PATH})"
+	need_ok "directory creation failed"
 
-# The manifest lists all files to install
-done < "${CFG_SRC_DIR}/${CFG_LIBDIR_RELATIVE}/${TEMPLATE_REL_MANIFEST_DIR}/manifest.in"
+	# Make the path absolute so we can uninstall it later without
+	# starting from the installation cwd
+	absolutify "${FILE_INSTALL_PATH}"
+	FILE_INSTALL_PATH="${ABSOLUTIFIED}"
+
+	# Install the file
+	msg "installing ${FILE_INSTALL_PATH}"
+	if echo "$p" | grep "^bin/" > /dev/null
+	then
+            install -m755 "${CFG_SRC_DIR}/$p" "${FILE_INSTALL_PATH}"
+	else
+            install -m644 "${CFG_SRC_DIR}/$p" "${FILE_INSTALL_PATH}"
+	fi
+	need_ok "file creation failed"
+
+	# Update the manifest
+	echo "${FILE_INSTALL_PATH}" >> "${INSTALLED_MANIFEST}"
+	need_ok "failed to update manifest"
+
+	# The manifest lists all files to install
+    done < "$INPUT_MANIFEST"
+
+    # Update the components
+    echo "$component " >> "${ABS_LIBDIR}/${TEMPLATE_REL_MANIFEST_DIR}/components"
+    need_ok "failed to update components list for $component"
+
+done
+
+# Drop the version number into the manifest dir
+echo "$INSTALLER_VERSION" > "${ABS_LIBDIR}/${TEMPLATE_REL_MANIFEST_DIR}/rust-installer-version"
 
 msg
 
diff --git a/test.sh b/test.sh
new file mode 100755
index 0000000..d082454
--- /dev/null
+++ b/test.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+
+S="$(cd $(dirname $0) && pwd)"
+
+TEST_DIR="$S/test"
+WORK_DIR="$TEST_DIR/workdir"
+OUT_DIR="$TEST_DIR/outdir"
+PREFIX_DIR="$TEST_DIR/prefix"
+
+pre() {
+    echo "test: $1"
+    rm -Rf "$WORK_DIR"
+    rm -Rf "$OUT_DIR"
+    rm -Rf "$PREFIX_DIR"
+    mkdir -p "$WORK_DIR"
+    mkdir -p "$OUT_DIR"
+    mkdir -p "$PREFIX_DIR"
+}
+
+post() {
+    rm -Rf "$WORK_DIR"
+    rm -Rf "$OUT_DIR"
+    rm -Rf "$PREFIX_DIR"
+}
+
+try() {
+    cmd="$@"
+    echo \$ "$cmd"
+    $@ > /dev/null
+    if [ $? -ne 0 ]; then
+	echo "command failed: '$cmd'"
+	exit 1
+    fi
+}
+
+pre "install / uninstall v1"
+try sh "$S/gen-installer.sh" \
+    --product-name=Rust \
+    --verify-bin=rustc \
+    --rel-manifest-dir=rustlib \
+    --success-message=Rust-is-ready-to-roll. \
+    --image-dir="$TEST_DIR/repo1" \
+    --work-dir="$WORK_DIR" \
+    --output-dir="$OUT_DIR" \
+    --non-installed-prefixes=something-to-not-install,dir-to-not-install \
+    --package-name=rustc-nightly \
+    --component-name=rustc
+try "$WORK_DIR/rustc-nightly/install.sh" --prefix="$PREFIX_DIR"
+try test -f "$PREFIX_DIR/something-to-install"
+try test -f "$PREFIX_DIR/dir-to-install/foo"
+post
diff --git a/test/repo1/bin/rustc b/test/repo1/bin/rustc
new file mode 100755
index 0000000..96b4b06
--- /dev/null
+++ b/test/repo1/bin/rustc
@@ -0,0 +1 @@
+#!/bin/sh
\ No newline at end of file
diff --git a/test/repo1/dir-to-install/foo b/test/repo1/dir-to-install/foo
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/repo1/dir-to-install/foo
diff --git a/test/repo1/dir-to-not-install/foo b/test/repo1/dir-to-not-install/foo
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/repo1/dir-to-not-install/foo
diff --git a/test/repo1/something-to-install b/test/repo1/something-to-install
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/repo1/something-to-install
diff --git a/test/repo1/something-to-not-install b/test/repo1/something-to-not-install
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/repo1/something-to-not-install
diff --git a/test/rust-installer-v1 b/test/rust-installer-v1
new file mode 160000
index 0000000..dc09347
--- /dev/null
+++ b/test/rust-installer-v1
@@ -0,0 +1 @@
+Subproject commit dc09347b1caca92bbaa3fa6aa7180d50a9beb19c