diff --git a/com.oracle.truffle.r.test.packages/r/install.packages.R b/com.oracle.truffle.r.test.packages/r/install.packages.R
index 798ee89b0ec8a8e1432a1004f8b645b9fdac397b..01facbd88a767347d392589cdeaedb117e837654 100644
--- a/com.oracle.truffle.r.test.packages/r/install.packages.R
+++ b/com.oracle.truffle.r.test.packages/r/install.packages.R
@@ -42,8 +42,10 @@
 
 # BioConductor has it's own install mechanism but it is layered on the CRAN model.
 
-# By default, we use the CRAN mirror specified by --cran-mirror or env var CRAN_MIRROR.
-# If unset, it defaults to "http://cran.cnr.berkeley.edu/"
+# A list of repos can be provided  with the --repos argument, which ia comma separated string of name=value pairs.
+# The names "CRAN", "BIOC" and "FASTR" are understood and have default values.
+# By default, we use the CRAN mirror specified in the --repos argument or env var CRAN_MIRROR.
+# The default value for --repos is "CRAN=http://cran.cnr.berkeley.edu"
 
 # Packages are installed into the directory specified by the --lib arg (or R_LIBS_USER env var)
 
@@ -102,7 +104,8 @@
 args <- commandArgs(TRUE)
 
 usage <- function() {
-	cat(paste("usage: Rscript [--cran-mirror url] ",
+	cat(paste("usage: Rscript ",
+					  "[--repos name=value,...]",
                       "[--verbose | -v] [-V] [--dryrun]",
                       "[--no-install | -n] ",
 				      "[--create-blacklist] [--blacklist-file file] [--ignore-blacklist]",
@@ -258,26 +261,35 @@ set.repos <- function() {
 	# Based on the value of repos.list we set the "repos" option
 	# which is used by available.packages etc.
 	repos <- character()
-	needCran <- F
-	if ("BIOC" %in% repo.list) {
-		# source("http://bioconductor.org/biocLite.R")
-		# repos["BIOC"] <- biocinstallRepos()[1]
-		# above is correct but provokes bug:
-		# Error in read.table():  more columns than column names
-		repos["BIOC"] <- "https://bioconductor.org/packages/3.4/bioc"
-		needCran <- T
-	}
-	if (needCran || "CRAN" %in% repo.list) {
-		# set from the cran-mirror value
-		if (is.na(cran.mirror)) {
-			# not set on command line
-			cran.mirror <<- Sys.getenv("CRAN_MIRROR", unset = "http://cran.cnr.berkeley.edu/")
+	for (repo in repo.list) {
+		parts <- strsplit(repo, "=", fixed=T)[[1]]
+		name <- parts[[1]]
+		if (length(parts) > 1) {
+			uri <- parts[[2]]
+		} else {
+			uri <- NA_character_
+		}
+		if (name == "BIOC") {
+			# source("http://bioconductor.org/biocLite.R")
+			# repos["BIOC"] <- biocinstallRepos()[1]
+			# above is correct but provokes bug:
+			# Error in read.table():  more columns than column names
+			repos[["BIOC"]] <- "https://bioconductor.org/packages/3.4/bioc"
+		} else if (name == "CRAN") {
+			if (is.na(uri)) {
+				# not set on command line
+				cran.mirror <<- Sys.getenv("CRAN_MIRROR", unset = "http://cran.cnr.berkeley.edu/")
+			} else {
+				cran.mirror <- uri
+			}
+			repos[["CRAN"]] <- cran.mirror
+		} else if (name == "FASTR") {
+			# set the FastR internal repo
+			repos[["FASTR"]] <- paste0("file://", normalizePath("com.oracle.truffle.r.test.native/packages/repo"))
+		} else {
+			# User defined
+			repos[[name]] <- uri
 		}
-		repos["CRAN"] <- cran.mirror
-	}
-	if ("FASTR" %in% repo.list) {
-		# set the FastR internal repo
-		repos["FASTR"] <- paste0("file://", normalizePath("com.oracle.truffle.r.test.native/packages/repo"))
 	}
 	options(repos = repos)
 }
@@ -833,8 +845,6 @@ parse.args <- function() {
 			initial.blacklist.file <<- get.argvalue()
 		} else if (a == "--repos") {
 			repo.list <<- strsplit(get.argvalue(), ",")[[1]]
-		} else if (a == "--cran-mirror") {
-			cran.mirror <<- get.argvalue()
 		} else if (a == "--random") {
 			random.count <<- as.integer(get.argvalue())
 			if (is.na(random.count)) {
diff --git a/documentation/dev/testing.md b/documentation/dev/testing.md
index 9d7e514bda36279d8287feec74a4611809412ee7..45c3893fa88ea26b2006ced2ac56bb560bbe110a 100644
--- a/documentation/dev/testing.md
+++ b/documentation/dev/testing.md
@@ -63,7 +63,7 @@ The command has a rather daunting set of options but, for normal use, most of th
 
 ##### Usage
 
-    mx installpkgs [--repos list] [--cran-mirror url]
+    mx installpkgs [--repos list]
                    [--verbose | -v] [-V]
                    [--dryrun]
                    [--no-install | -n]
@@ -100,7 +100,7 @@ There are many packages that cannot be installed due to either missing functiona
 3. TODO
 
 ##### CRAN Mirror
-Packages are downloaded and installed from the repos given by the `repos` argument, a comma-separated list, that defaults to `CRAN`. CRAN packages are downloaded from a CRAN mirror. When the standard `utils::install_packages` function is run interactively, the user is prompted for a mirror. To avoid such interaction, `install.packages` has two ways for specifying a mirror. The default CRAN mirror is `http://cran.cnr.berkeley.edu/` but this can be changed either with the command line argument `--cran-mirror` or the environment variable `CRAN_MIRROR`.  The `FASTR` repo is internal to the source base and contains FastR-specific test packages. The BioConductor repo can be added by setting `--repos BIOC`. It also implies `CRAN`.
+Packages are downloaded and installed from the repos given by the `repos` argument, a comma-separated list of `name[=value]` pairs, that defaults to `CRAN`. CRAN packages are downloaded from a CRAN mirror. When the standard `utils::install_packages` function is run interactively, the user is prompted for a mirror. To avoid such interaction, `install.packages` has two ways for specifying a mirror. The default CRAN mirror is `http://cran.cnr.berkeley.edu/` but this can be changed either with `CRAN=url` or the environment variable `CRAN_MIRROR`.  The `FASTR` repo is internal to the source base and contains FastR-specific test packages. The BioConductor repo can be added by setting `--repos BIOC`. User defined repos can be specified by `USERNAME=url`. N.B. For file system paths this must be a `file:` URL.
 
 ##### Installation Directory
 The directory in which to install the package can be specified either by setting the `R_LIBS_USER` environment variable or with the `--lib` command line argument. The former is recommended and indeed required for running tests after installation (the testing system does not honor the `--lib` argument).
@@ -160,6 +160,10 @@ Testing packages requires that they are first installed, so all of the above is
 
 Install the `A3` package (and its dependents) in `$R_LIBS_USER`, creating the `package.blacklist` file first if it does not exist. The dependents (`xtable`, `pbapply`) will be installed implicitly by the  underlying R install.packages function
 
+    $ mx installpkgs --repos CRAN=file://path-to-local-cran-mirror --pkg-pattern '^A3$'
+
+Similar to above but uses a local CRAN mirror stored in `path-to-local-cran-mirror`.
+
     $ mx installpkgs --install-dependents-first--pkg-pattern '^A3$'
 
 Similar to the above but the dependents of A3 are explicitly installed first. This is equivalent to using `--pkg-filelist` file, where file would contain xtable, pbapply and A3 in that order.