#! /opt/gensoft/exe/R/4.6.1/bin/Rscript

##################################################################
#                                                                #  
#  script to install packages to $USER/R library                 #
#                                                                #  
#  R on the cluster is run on exec nodes with no internet access #
#                                                                #  
#  package installation may requires net access (CRAN,           #
#  Bioconductor, git) so must be run LOCALY on submit nodes      #
#                                                                #  
##################################################################



##################################################################
#               EDIT TO SUIT YOUR NEEDS                          #  
##################################################################
#---- Default CRAN repository.
DEFAULT_REPO <- "http://cran.r-project.org"
GIT_API <- "api.github.com"


#---- silently use library
suppressPackageStartupMessages(library("optparse"))
suppressPackageStartupMessages(library("stringi"))


#---- exit with status.
my_quit <- function(exit_val) {
	quit(save="default", status=exit_val)
}

#---- check extension
#---- return TRUE // FALSE if filename ends with accepted extension 
check_ext <- function(filename) {
	accepted_ext <- c("tgz", "tar.gz")
	ret <- FALSE
	for ( ext in accepted_ext ) {
		if (stri_sub(filename, from=-nchar(ext, type="char")) == ext) {
			ret <- TRUE	
			break
		}
	}
	return (ret)
}

#---- Default user library.
platform <- R.version$platform
major    <- R.version$major
minor    <- R.version$minor
version  <- paste(major, minor, sep = ".")
user_lib  <- Sys.getenv("R_LIBS_USER")
libmsg  <- paste("$HOME", "R", platform, paste(version, 'library', sep='-'), sep="/")
help_userlib <- paste ("library directories where to install the packages.\n", 
											 "\t\t(default:", libmsg, "or\n",
											 "\t\t$R_LIBS_USER if set)")


#--- optparser definition.
option_list <- list(
    # Bioconductor installation
	make_option(c("--bioclite"),
	    default = FALSE,
	    action="store_true",
		dest = "bioconductor",
		help = paste("Install package from bioclite bioconductor. (default: OFF)\n")),
	make_option(c("--bioclite-update"),
	    default = TRUE,
	    action="store_false",
	    dest = "update",
		help = "Turns on bioclite automatic updating. (default: OFF)"),
	make_option(c("--bioclite-autoupdate"),
	    default = TRUE,
	    action="store_false",
        dest = "autoupdate",
        help = "Turns on bioclite BiocInstaller auto updating. (default: OFF)"),

    # git package installation
	make_option(c("--git-hub"),
	    default = FALSE,
	    action="store_true",
	    dest = "git",
		help = paste("Install package from git-hub (default: OFF)\n", 
                     "\t\trepository address must be in format: 'username/repo[/subdir][@ref|#pull]'")),
	make_option(c("--git-ref"),
	    dest = "git_ref",
        default = "master",
		help = "git reference. Could be a commit, tag, or branch name. (default: master)"),
	make_option(c("--git-subdir"),
	    dest = "git_subdir",
        default = NULL,
		help = "subdirectory within repo that contains the R package. (default: NULL)"),
	make_option(c("--git-host-api"),
	    dest = "git_api",
        default = GIT_API,
		help = paste("Github API host to use. (default: ", GIT_API, ')', sep='')),
	make_option(c("--git-auth-token"),
	    dest = "git_pat",
        default = NULL,
		help = "personal access token (PAT) to use . (default: NULL"),

#	# wrapper to install.packages
	make_option(c("-u", "--libs"),
	    default = user_lib,
		dest = "user_lib",
		help = help_userlib),
  make_option(c("-r", "--repos"),
	    default = DEFAULT_REPO,
		dest = "repo",
		help = paste("the base URL(s) of the repositories to use.\n", "\t\t(default: ", DEFAULT_REPO,")", sep='')), 
	make_option(c("-s", "--from-source-pkg"),
		default = FALSE,
		action="store_true",
		dest = "src_pkg",
		help = "install from local source pkg. (.tgz or .tar.gz only)")
)

parser <- OptionParser(usage = "usage: R_install_packages [options] pkgs",
  option_list=option_list,
  description = "Download and install packages from CRAN-like repositories, Bioconductor, git-hub or from local source archive to your $HOME/R library", 
  epilogue = "for comments, bugs report etc... contact Eric Deveaud <edeveaud@pasteur.fr>"
)

arguments <- parse_args(parser, args = commandArgs(trailingOnly = TRUE) , positional_arguments = TRUE)

opt <- arguments$options
args <- arguments$args


#---- something to do ?
if(! length(args)) {
	my_quit(1)
}

#---- get command line
repo <- opt$repo
user_lib <- opt$user_lib
src_pkg <- opt$src_pkg
Bioconductor <- opt$bioconductor
BiocUpdate <- opt$update
BiocAutoupdate <- opt$autoupdate
git <- opt$git
git_ref  <- opt$git_ref
git_subdir  <- opt$git_subdir
git_api  <- opt$git_api
git_pat  <- opt$git_pat

#---- consistency check for biocoonductor related options
if (!Bioconductor &&  (!BiocUpdate || !BiocAutoupdate)) {
    cat ("Error: use of --bioclite-update or --autoupdate without --bioclite context.")
    my_quit(1)
}

#---- consistency check for git related options
#if (!git && ( is.null(git_username)|| is.null(git_subdir) || is.null(git_pat))){
#    cat ("Error: use of git specific options without --git context.")
#    my_quit(1)
#}

#---- check for required devtools library.
if( git) {
    tryCatch ({suppressPackageStartupMessages(library('devtools'))
    }, error = function(err) {
        cat ("Error: devtools not available: run 'R_install_packages devtools'  first.\n")
        my_quit(1)
    })
}

#---- check for BiocManager availability
if (Bioconductor) {
    tryCatch ({suppressPackageStartupMessages(library('BiocManager'))
    }, error = function(err) {
        cat ("Error: BiocManager not available: run 'R_install_packages BiocManager'  first.\n")
        my_quit(1)
    })
}

#---- installation form local package source archive
if (src_pkg) {
	#---- check for file existence
	#---- set repo and type accordingly with local installation.
	for (path in args) {
	  # check file
	  if ( ! file.exists(path) ) { 
			cat (paste("Error", item, ": no such file"))
	  }
		# check extension
		if ( ! check_ext(path) )	{
			cat (paste("Error", item, ": incorrect file type: (.tar.gz or .gz)"))
			my_quit(1)
		}
	}
	repo <- NULL;
}


#---- finally do the job.
#---- silently create the personal library if it doesn't exist.
#---- Ignore warnings if the directory already exists.
dir.create(user_lib, showWarnings = FALSE, recursive = TRUE)
print (paste("installing packages:", args , "to", user_lib))
tryCatch({
  #---- bioconductor pakage
  if (Bioconductor) {
    # bioclite check for write rigths on first elem of .libPaths
    # so add user_lib
    .libPaths(c(user_lib, .libPaths())) 
    BiocManager::install(pkgs=args, updates=BiocUpdate, ask=FALSE, lib=user_lib, dependencies=TRUE)
  }
  else if (git) { 
    install_github(args, ref = git_ref, subdir = git_subdir,
           host = git_api, lib=user_lib) 
 } else {
    install.packages(args, lib=user_lib, repos=repo)
  }
}, warning = function(warn) {
    cat (paste("Warning:", warn))
}, error = function(err) {
    cat (paste("Fatal:", err))
	  my_quit(1)
}, finally = {
    my_quit(0)
})

