diff options
author | rillig <rillig@pkgsrc.org> | 2019-10-13 13:26:22 +0000 |
---|---|---|
committer | rillig <rillig@pkgsrc.org> | 2019-10-13 13:26:22 +0000 |
commit | 67dc34e90ab1abfa84b4b14f5dfbd23f6ecbbb2b (patch) | |
tree | ffadd95323c14c83899debebfbecfee3b0d61090 /pkgtools/R2pkg | |
parent | ab4da724164cc49c5500a7e6ea0768bf3b6ab228 (diff) | |
download | pkgsrc-67dc34e90ab1abfa84b4b14f5dfbd23f6ecbbb2b.tar.gz |
pkgtools/R2pkg: separate R code from shell code
Before, it was difficult to edit the R code since all dollars,
backslashes and backticks had to be escaped. Separating the code also
makes the R part testable on its own.
Diffstat (limited to 'pkgtools/R2pkg')
-rw-r--r-- | pkgtools/R2pkg/Makefile | 36 | ||||
-rw-r--r-- | pkgtools/R2pkg/PLIST | 3 | ||||
-rw-r--r-- | pkgtools/R2pkg/files/R2pkg.R | 1265 | ||||
-rwxr-xr-x | pkgtools/R2pkg/files/R2pkg.sh | 1249 | ||||
-rw-r--r-- | pkgtools/R2pkg/files/RELEASE | 4 |
5 files changed, 1303 insertions, 1254 deletions
diff --git a/pkgtools/R2pkg/Makefile b/pkgtools/R2pkg/Makefile index 8935a078a03..45ee742c5df 100644 --- a/pkgtools/R2pkg/Makefile +++ b/pkgtools/R2pkg/Makefile @@ -1,7 +1,7 @@ -# $NetBSD: Makefile,v 1.6 2019/10/13 09:43:26 rillig Exp $ +# $NetBSD: Makefile,v 1.7 2019/10/13 13:26:22 rillig Exp $ # -VERS= 0.6.1 +VERS= 0.6.2 PKGNAME= R2pkg-${VERS} CATEGORIES= pkgtools @@ -10,33 +10,25 @@ HOMEPAGE= # none COMMENT= Tool to automate initial steps in building an R package LICENSE= modified-bsd -WRKSRC= ${WRKDIR} -NO_BUILD= yes -USE_LANGUAGES= # none -AUTO_MKDIRS= yes +WRKSRC= ${WRKDIR} +NO_BUILD= yes +USE_LANGUAGES= # none +AUTO_MKDIRS= yes -DEPENDS+= curl>=7.52.1:../../www/curl +DEPENDS+= curl>=7.52.1:../../www/curl -SUBST_CLASSES+= version -SUBST_STAGE.version= pre-configure -SUBST_MESSAGE.version= Substituting version in R2pkg.sh. -SUBST_FILES.version= R2pkg.sh -SUBST_VARS.version= VERS - -SUBST_CLASSES+= tools -SUBST_STAGE.tools= pre-configure -SUBST_MESSAGE.tools= Substituting tool locations. -SUBST_FILES.tools= R2pkg.sh -SUBST_VARS.tools= MAKE - -INSTALLATION_DIRS+= sbin ${PKGMANDIR}/man8 +SUBST_CLASSES+= R +SUBST_STAGE.R= pre-configure +SUBST_FILES.R= R2pkg.sh +SUBST_VARS.R= VERS MAKE LIBDIR +LIBDIR= ${PREFIX}/lib/R2pkg do-extract: - ${CP} ${FILESDIR}/R2pkg.sh ${WRKSRC} - ${CP} ${FILESDIR}/R2pkg.8 ${WRKSRC} + cd ${FILESDIR} && ${CP} R2pkg.* ${WRKSRC} do-install: ${INSTALL_SCRIPT} ${WRKSRC}/R2pkg.sh ${DESTDIR}${PREFIX}/sbin/R2pkg + ${INSTALL_DATA} ${WRKSRC}/R2pkg.R ${DESTDIR}${LIBDIR}/R2pkg.R ${INSTALL_MAN} ${WRKSRC}/R2pkg.8 ${DESTDIR}${PREFIX}/${PKGMANDIR}/man8/R2pkg.8 .include "../../math/R/buildlink3.mk" diff --git a/pkgtools/R2pkg/PLIST b/pkgtools/R2pkg/PLIST index eb6ed17ee3b..80fcd1da8ed 100644 --- a/pkgtools/R2pkg/PLIST +++ b/pkgtools/R2pkg/PLIST @@ -1,3 +1,4 @@ -@comment $NetBSD: PLIST,v 1.1 2015/04/25 22:06:34 brook Exp $ +@comment $NetBSD: PLIST,v 1.2 2019/10/13 13:26:22 rillig Exp $ +lib/R2pkg/R2pkg.R man/man8/R2pkg.8 sbin/R2pkg diff --git a/pkgtools/R2pkg/files/R2pkg.R b/pkgtools/R2pkg/files/R2pkg.R new file mode 100644 index 00000000000..22c32065d52 --- /dev/null +++ b/pkgtools/R2pkg/files/R2pkg.R @@ -0,0 +1,1265 @@ +# $NetBSD: R2pkg.R,v 1.1 2019/10/13 13:26:22 rillig Exp $ +# +# Copyright (c) 2014,2015,2016,2017,2018,2019 +# Brook Milligan. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the author nor the names of any contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# +# Create an R package in the current directory +# + +arg.level <- Sys.getenv('LEVEL') +arg.rpkg <- Sys.getenv('RPKG') +arg.packages_list <- Sys.getenv('PACKAGES_LIST') +arg.r2pkg <- Sys.getenv('R2PKG') +arg.args <- Sys.getenv('ARGS') +arg.recursive <- as.logical(Sys.getenv('RECURSIVE')) +arg.update <- as.logical(Sys.getenv('UPDATE')) +arg.dependency_list <- Sys.getenv('DEPENDENCY_LIST') +arg.maintainer_email <- Sys.getenv('MAINTAINER_EMAIL') +arg.rpkg_description_url <- Sys.getenv('RPKG_DESCRIPTION_URL') +arg.quiet_curl <- as.logical(Sys.getenv('QUIET_CURL')) + +level.message <- function(...) + message('[ ', arg.level, ' ] ', ...) + +warning.message <- function(...) + level.message('WARNING: ', ...) + +R_version <- function() +{ + info <- R.Version() + version <- paste0(info[['major']],'.',info[['minor']]) + version +} + +set.locale <- function() { invisible(Sys.setlocale('LC_ALL','C')) } + +trim.space <- function(s) gsub('[[:space:]]','',s) +trim.blank <- function(s) gsub('[[:blank:]]','',s) +one.space <- function(s) gsub('[[:blank:]]+',' ',s) +one.line <- function(s) gsub('\n',' ',s) +pkg.vers <- function(s) gsub('_','.',s) +field <- function(key,value) paste(key,'=\t',value,sep='') + +# The list of "recommended packages which are to be included in all +# binary distributions of R." (R FAQ 5.1.2 2018-10-18) +# +base.packages.FAQ.5.1.2 <- c( + 'KernSmooth', + 'MASS', + 'Matrix', + 'boot', + 'class', + 'cluster', + 'codetools', + 'foreign', + 'lattice', + 'mgcv', + 'nlme', + 'nnet', + 'rpart', + 'spatial', + 'survival') + +# Other R packages that appear in dependency lists but are included in +# the R package. +# +base.packages.other <- c( + 'grDevices', + 'graphics', + 'grid', + 'methods', + 'parallel', + 'splines', + 'stats', + 'tools', + 'utils') +base.packages <- c('R',base.packages.FAQ.5.1.2,base.packages.other) + +licenses <- list() +licenses[['ACM']] <- 'acm-license' +licenses[['ACM | file LICENSE']] <- 'acm-license # OR file LICENSE' +licenses[['APACHE']] <- 'apache-1.1 OR apache-2.0' +licenses[['Apache License 2.0']] <- 'apache-2.0' +licenses[['Apache License (== 2.0)']] <- 'apache-2.0' +licenses[['Apache License (== 2.0) | file LICENSE']] <- 'apache-2.0 # OR file LICENSE' +licenses[['ARTISTIC']] <- 'artistic OR artistic-2.0' +licenses[['Artistic-2.0']] <- 'artistic-2.0' +licenses[['BSD']] <- '2-clause-bsd OR modified-bsd OR original-bsd' +licenses[['BSD-2']] <- '2-clause-bsd' +licenses[['BSD_2_clause + file LICENSE']] <- '2-clause-bsd # + file LICENSE' +licenses[['BSD 3 clause']] <- 'modified-bsd' +licenses[['BSD 3 clause + file LICENSE']] <- 'modified-bsd # + file LICENSE' +licenses[['BSD_3_clause + file LICENSE']] <- 'modified-bsd # + file LICENSE' +licenses[['BSL-1.0']] <- 'boost-license' +licenses[['CC0']] <- 'cc0-1.0-universal' +licenses[['GPL']] <- 'gnu-gpl-v1 OR gnu-gpl-v2 OR gnu-gpl-v3' +licenses[['GPL-1']] <- 'gnu-gpl-v1' +licenses[['GPL-2']] <- 'gnu-gpl-v2' +licenses[['GPL-2 | file LICENSE']] <- 'gnu-gpl-v2 # OR file LICENSE' +licenses[['GPL-3']] <- 'gnu-gpl-v3' +licenses[['GPL-2 | GPL-3']] <- 'gnu-gpl-v2 OR gnu-gpl-v3' +licenses[['GPL (>= 2)']] <- 'gnu-gpl-v2 OR gnu-gpl-v3' +licenses[['GPL (>= 2.0)']] <- 'gnu-gpl-v2 OR gnu-gpl-v3' +licenses[['GPL (>= 2) | file LICENSE']] <- 'gnu-gpl-v2 OR gnu-gpl-v3 # OR file LICENSE' +licenses[['GPL (>= 3)']] <- 'gnu-gpl-v3' +licenses[['LGPL']] <- 'gnu-lgpl-v2 OR gnu-lgpl-v2.1 OR gnu-lgpl-v3' +licenses[['LGPL-2']] <- 'gnu-lgpl-v2' +licenses[['LGPL-2.1']] <- 'gnu-lgpl-v2.1' +licenses[['LGPL-3']] <- 'gnu-lgpl-v3' +licenses[['LGPL-3 + file LICENSE']] <- 'gnu-lgpl-v3 # + file LICENSE' +licenses[['LGPL-2 | LGPL-3']] <- 'gnu-lgpl-v2 OR gnu-lgpl-v3' +licenses[['LGPL (>= 2)']] <- 'gnu-lgpl-v2 OR gnu-lgpl-v2.1 OR gnu-lgpl-v3' +licenses[['LUCENT']] <- 'lucent' +licenses[['Lucent Public License']] <- 'lucent' +licenses[['MIT']] <- 'mit' +licenses[['MIT + file LICENSE']] <- 'mit # + file LICENSE' +licenses[['MIT + file LICENSE | Unlimited']] <- 'mit # + file LICENSE OR unlimited' +licenses[['MPL-1.0']] <- 'mpl-1.0' +licenses[['MPL-1.1']] <- 'mpl-1.1' +licenses[['MPL-2.0']] <- 'mpl-2.0' +licenses[['MPL-2.0 | file LICENSE']] <- 'mpl-2.0 # OR file LICENSE' +licenses[['POSTGRESQL']] <- 'postgresql-license' + +adjacent.duplicates <- function(x) +{ + a <- x[-length(x)] + b <- x[-1] + dups <- a == b + dups <- c(FALSE,dups) + dups +} + +paste2 <- function(s1,s2) +{ + if (is.na(s1) && is.na(s2)) return ('') + if (is.na(s1) && !is.na(s2)) return (s2) + if (!is.na(s1) && is.na(s2)) return (s1) + if (!is.na(s1) && !is.na(s2)) return (paste(s1,s2)) +} + +end.paragraph <- function(l,l1=l,l2=list()) +{ + if (length(l1) > 0 || length(l2) > 0) + l <- append(l,'') + l +} + +as.sorted.list <- function(df) +{ + l <- list() + df <- df[!duplicated(df),] + if (nrow(df) > 0) + { + key <- as.vector(df[,1]) + value <- as.vector(df[,2]) + key <- order(key,value) + l <- as.list(value[key]) + } + l +} + +read.file.as.dataframe <- function(filename) +{ + # message('===> read.file.as.dataframe(',filename,')') + contents <- as.list(readLines(filename)) + df <- data.frame() + for (line in contents) + { + # str(line) + df <- rbind(df,data.frame(line=line,stringsAsFactors=FALSE)) + } + df +} + +categorize.key_value <- function(df,line='line') +{ + re.skip_blank <- '[[:blank:]]*' + re.blank <- '[[:blank:]]+' + re.anything <- '.*' + + re.key <- '[^+=[:blank:]]+' + re.operator <- '[+=]+' + re.delimiter <- re.skip_blank + re.value <- re.anything + re.optional_TODO <- '(#[[:blank:]]*TODO[[:blank:]]*:[[:blank:]]*)*' + + re.match_key_value_line <- paste0('^', + re.skip_blank, + re.optional_TODO, + re.key, + re.skip_blank, + re.operator, + re.delimiter, + re.value, + '$') + + re.match_key <- paste0('^', + re.skip_blank, + re.optional_TODO, + '(',re.key,')', + re.skip_blank, + re.operator, + re.delimiter, + re.value, + '$') + + df$key_value <- grepl(re.match_key_value_line,df[,line]) + df$key <- sub(re.match_key,'\\2',df[,line]) + df$key[!df$key_value] <- NA + df +} + +categorize.depends <- function(df,line='line') +{ + df$depends <- df$key_value & df$key == 'DEPENDS' + df$category[df$depends] <- unlist(sapply(strsplit(df[df$depends,line],'/',fixed=TRUE),'[',3)) + df +} + +categorize.buildlink <- function(df,line='line') +{ + df$buildlink3.mk <- grepl('buildlink3.mk',df[,line]) + df$category[df$buildlink3.mk] <- unlist(sapply(strsplit(df[df$buildlink3.mk,line],'/',fixed=TRUE),'[',3)) + df +} + +fix.continued.lines <- function(df,line='line') +{ + if (nrow(df) > 1) + { + continued <- grepl('\\\\$',df[,line]) + continued_key_value <- df$key_value & continued + if (FALSE %in% df[continued,'key_value']) + { + level.warning('unhandled continued line(s)') + } + for (i in 1:(length(continued_key_value)-1)) + { + next_line <- i + 1 + if (continued_key_value[i]) + { + df[i,line] <- sub('[[:blank:]]*\\\\$','',df[i,line]) + df$key_value[next_line] <- TRUE + df$key[next_line] <- df$key[i] + df[next_line,line] <- paste0(df$key[next_line],'+=',df[next_line,line]) + } + } + } + df +} + +read.Makefile.as.dataframe <- function() +{ + # message('===> read.Makefile.as.dataframe():') + + re.skip_blank <- '[[:blank:]]*' + re.blank <- '[[:blank:]]+' + re.anything <- '.*' + + re.key <- '[^+=[:blank:]]+' + re.operator <- '[+=]+' + re.delimiter <- re.skip_blank + re.value <- re.anything + re.optional_TODO <- '(#[[:blank:]]*TODO[[:blank:]]*:[[:blank:]]*)*' + + re.match_operator <- paste0('^', + re.skip_blank, + re.optional_TODO, + re.key, + re.skip_blank, + '(',re.operator,')', + re.delimiter, + re.value, + '$') + re.match_delimiter <- paste0('^', + re.skip_blank, + re.optional_TODO, + re.key, + re.skip_blank, + re.operator, + '(',re.delimiter,')', + re.value, + '$') + re.match_value <- paste0('^', + re.skip_blank, + re.optional_TODO, + re.key, + re.skip_blank, + re.operator, + re.delimiter, + '(',re.value,')', + '$') + re.match_optional_TODO <- paste0('^', + re.skip_blank, + '(',re.optional_TODO,')', + re.key, + re.skip_blank, + re.operator, + re.delimiter, + re.value, + '$') + + df <- read.file.as.dataframe('Makefile.orig') + + df$order <- 1:nrow(df) + df$category <- NA + + df <- categorize.key_value(df) + df <- fix.continued.lines(df) + df <- categorize.depends(df) + df <- categorize.buildlink(df) + + df$operator <- sub(re.match_operator,'\\2',df$line) + df$delimiter <- sub(re.match_delimiter,'\\2',df$line) + df$old_value <- sub(re.match_value,'\\2',df$line) + df$old_todo <- sub(re.match_optional_TODO,'\\1',df$line) + + df$operator[!df$key_value] <- NA + df$delimiter[!df$key_value] <- NA + df$old_value[!df$key_value] <- NA + df$old_todo[!df$key_value] <- NA + + df +} + +read.file.as.list <- function(filename) +{ + result <- list() + info <- file.info(filename) + size <- info[filename,'size'] + if (!is.na(size) && size > 0) + { + contents <- readLines(filename) + result <- as.list(contents) + } + result +} + +read.file.as.value <- function(filename) +{ + value <- '' + l <- read.file.as.list(filename) + if (length(l) == 1) + { + line <- l[[1]] + fields <- strsplit(line,'[[:blank:]]+') + value <- fields[[1]][2] + } + value +} + +read.file.as.values <- function(filename) +{ + message('===> read.file.as.values(',filename,'):') + values <- list() + l <- read.file.as.list(filename) + print(l) + for (line in l) + { + # fields <- strsplit(line,'[[:blank:]]+') + # value <- fields[[1]][2] + } + print(values) + values +} + +simplify.whitespace <- function(s) { gsub('[[:blank:]]+',' ',s) } +remove.punctuation <- function(s) +{ + punctuation <- '[,-]' + gsub(punctuation,'',s) +} +remove.quotes <- function(s) +{ + quotes <- '[\'`"]' #" to de-confuse mcedit + gsub(quotes,'',s) +} +remove.articles <- function(s) +{ + pattern <- '^([[:blank:]]*)An* |([[:blank:]]+)[Aa]n*[[:blank:]]+' + result <- gsub(pattern,'\\1',s) + result +} + +case.insensitive.equals <- function(s1,s2) +{ + s1.lower <- tolower(simplify.whitespace(s1)) + s2.lower <- tolower(simplify.whitespace(s2)) + result <- s1.lower == s2.lower + result +} + +weakly.equals <- function(s1,s2) +{ + result <- case.insensitive.equals(remove.articles(remove.quotes(remove.punctuation(s1))), + remove.articles(remove.quotes(remove.punctuation(s2)))) + result +} + +new.field.if.different <- function(filename,s) +{ + field <- field(filename,one.line(s)) + field.list <- read.file.as.list(filename) + if (length(field.list) == 1) + { + f <- field.list[[1]] + if (case.insensitive.equals(f,field)) + field <- f + } + field +} + +todo.license <- function(s) +{ + if (is.null(licenses[[s]])) + todo <- '# TODO: LICENSE' + else + todo <- 'LICENSE' + todo +} + +pkgsrc.license <- function(s) +{ + license <- licenses[[s]] + if (is.null(license)) + license <- s + license +} + +package <- function(s) one.line(s) +version <- function(s) one.line(s) +comment <- function(s) one.line(s) +use.tools <- function(s) read.file.as.list(s) + +license <- function(s) +{ + license <- pkgsrc.license(s) + old.license <- read.file.as.value('LICENSE') + if (old.license != '' && old.license != license) + license <- paste0(license,' # [R2pkg] previously: ',old.license) + license +} + +maintainer <- function(email) +{ + MAINTAINER <- read.file.as.value('MAINTAINER') + if (MAINTAINER == '') + MAINTAINER <- email + MAINTAINER +} + +make.sed.command <- function(key,value) +{ + address <- paste0('/^[[:blank:]]*',key,'/') + match <- paste0('(',key,'[[:blank:]]*=[[:blank:]]*).*$') + replacement <- paste0('\\1',value) + command <- paste0(' -e "',address,'s/',match,'/',replacement,'/"') + command +} + +sed.categories <- function(categories) make.sed.command('CATEGORIES',categories) +sed.comment <- function(comment) +{ + old.comment <- read.file.as.value('COMMENT') + if (weakly.equals(old.comment,comment)) + comment <- old.comment + make.sed.command('COMMENT',comment) +} +sed.maintainer <- function(email) +{ + make.sed.command('MAINTAINER',maintainer(email)) +} +sed.license <- function(license) +{ + make.sed.command('LICENSE',license) +} +sed.r_pkgver <- function(r_pkgver) make.sed.command('R_PKGVER',r_pkgver) + +buildlink3.mk <- function(s1,s2) +{ + BUILDLINK3.MK <- data.frame() + buildlink3.mk.list <- read.file.as.list('BUILDLINK3.MK') + for (line in buildlink3.mk.list) + { + fields <- strsplit(line[[1]],'/',fixed=TRUE) + key <- fields[[1]][3] + value <- line + BUILDLINK3.MK <- rbind(BUILDLINK3.MK,data.frame(key=key,value=value)) + } + if (find.Rcpp(s1,s2)) + { + buildlink3.line <- '.include "../../devel/R-Rcpp/buildlink3.mk"' + key <- 'devel' + value <- buildlink3.line + BUILDLINK3.MK <- rbind(BUILDLINK3.MK,data.frame(key=key,value=value)) + } + BUILDLINK3.MK +} + +makefile.field <- function(key,value) +{ + # message('===> makefile.field(',key,',',value,'):') + field <- paste0(key,'= ',value) + # print(field) + field +} + +makefile.fields <- function(key,values) +{ + # message('===> makefile.fields():') + fields <- list() + for (l in values) + { + value <- unlist(l) + # message('===> value=',value,' ',length(value),' ',value == '') + # print(value) + if (value != '') + fields <- append(fields,makefile.field(key,list(value))) + else + fields <- append(fields,list('')) + # print(fields) + } + # print(fields) + fields +} + +categories <- function() basename(dirname(getwd())) +description <- function(s) strwrap(s,width=71) + +filter.imports <- function(s) +{ + for (pkg in base.packages) + { + re.pkg <- paste('^',pkg,sep='') + s <- s[!grepl(re.pkg,s)] + } + s +} + +find.Rcpp <- function(s1,s2) +{ + s <- paste(s1,s2) + Rcpp <- grepl('Rcpp',s) + Rcpp +} + +make.imports <- function(s1,s2) +{ + s <- paste2(s1,s2) + s <- gsub('([[:alnum:]]+)[[:blank:]]+(\\([^\\)]*\\))?[[:blank:]]*,?','\\1 \\2,',s) + imports <- na.omit(unlist(strsplit(s,',[[:blank:]]*'))) + imports <- trim.space(imports) + imports <- filter.imports(imports) + imports +} + +make.dependency <- function(s) +{ + s <- gsub('\\)','',s) + s <- gsub('-','.',s) + s <- unlist(strsplit(s,'\\(')) + s +} + +depends <- function(dependency) dependency[1] + +depends.pkg <- function(dependency) +{ + # XXX message('===> ',depends(dependency)) + result <- Sys.glob(paste0('../../*/R-',depends(dependency))) + result +} + +new.depends.pkg <- function(dependency) +{ + result <- Sys.glob(paste0('../../wip/R-',depends(dependency))) + result +} + +depends.pkg.fullname <- function(dependency,index=1) +{ + result <- system(paste('cd',depends.pkg(dependency)[index],'&& bmake show-var VARNAME=PKGNAME'),intern=TRUE) + result +} + +depends.pkg.name <- function(dependency,index=1) +{ + result <- sub('^(.*)-([^-]*)$','\\1',depends.pkg.fullname(dependency,index)) + result +} + +depends.pkg.vers <- function(dependency,index=1) +{ + result <- sub('^(.*)-([^-]*)$','\\2',depends.pkg.fullname(dependency,index)) + result +} + +depends.vers <- function(dependency,index=1) +{ + if (length(dependency) == 2) + result <- dependency[2] + else + result <- paste0('>=',depends.pkg.vers(dependency,index)) + result <- trim.space(result) + result +} + +depends.vers.2 <- function(dependency) +{ + result <- ifelse(length(dependency) == 2, dependency[2], '>=???') + result <- trim.space(result) + result +} + +depends.dir <- function(dependency,index=1) +{ + fields <- strsplit(depends.pkg(dependency)[index],'/',fixed=TRUE) + result <- fields[[1]][3] + result +} + +depends.line <- function(dependency,index=1) +{ + result <- paste0('DEPENDS+=\tR-',depends(dependency),depends.vers(dependency,index),':',depends.pkg(dependency)[index]) + result +} + +depends.line.2 <- function(dependency) +{ + result <- paste0('DEPENDS+=\tR-',depends,depends.vers.2(dependency),':../../???/R-',depends) + result <- paste0(result,' # XXX - found') + for (pkg in depends.pkg(dependency)) + result <- paste(result,pkg) + result +} + +buildlink3.file <- function(dependency,index=1) +{ + result <- paste0(depends.pkg(dependency)[index],'/buildlink3.mk') + result +} + +buildlink3.line <- function(dependency,index=1) +{ + result <- paste0('.include "',buildlink3.file(dependency,index),'"') + result +} + +dependency.dir <- function(dependency) +{ + result <- paste0('../../wip/R-',depends(dependency)) + result +} + +message.wip.dependency <- function(dependency,index=1) +{ + dir <- depends.dir(dependency,index) + dir.in.wip <- grepl('wip',dir) + wd.in.wip <- grepl('/wip/',getwd()) + if (dir.in.wip && !wd.in.wip) + level.warning('R-',arg.rpkg,' should not depend on a wip package: ',depends.pkg(dependency)[index]) +} + +message.too.many.dependencies <- function(dependency) +{ + msg <- paste0('[ ',arg.level,' ] WARNING: too many dependencies found for ',depends(dependency),':') + for (pkg in depends.pkg(dependency)) + msg <- paste(msg,pkg) + msg +} + +update.dependency <- function(dependency,index=1) +{ + level.warning('updating dependency for ',depends(dependency),': ',depends.pkg(dependency)[index]) + grep <- paste0('grep -E -q -e "',depends(dependency),'" ',arg.packages_list) + command <- paste0(grep,' || (cd ',depends.pkg(dependency)[index],' && ',arg.r2pkg,' ',arg.args,' ',depends(dependency),')') + error <- system(command) + if (error != 0) + level.warning('error updating dependency for ',depends(dependency)) +} + +make.depends <- function(s1,s2) +{ + imports <- make.imports(s1,s2) + # XXX message('===> imports:') + # XXX print(imports) + DEPENDS <- data.frame() + BUILDLINK3.MK <- buildlink3.mk(s1,s2) + if (length(imports) > 0) + { + for (i in 1:length(imports)) + { + dependency <- make.dependency(imports[i]) + # XXX message('[ ',${LEVEL},' ] ===> ',i,' / ',length(imports),': ',depends(dependency)) + if (length(depends.pkg(dependency)) == 0) # a dependency cannot be found + { + level.message('0 dependencies match ',dependency) + if (arg.recursive) + { + dir.create(path=dependency.dir(dependency),recursive=TRUE) + update.dependency(dependency) + } + else + level.warning('dependency needed for ',depends(dependency)) + } + else if (length(depends.pkg(dependency)) == 1) # a unique dependency found + { + level.message('1 dependency matches ',dependency,': ',depends.pkg(dependency)) + message.wip.dependency(dependency) + if (arg.recursive && arg.update) + update.dependency(dependency) + if (file.exists(buildlink3.file(dependency))) + BUILDLINK3.MK <- rbind(BUILDLINK3.MK,data.frame(key=depends.dir(dependency),value=buildlink3.line(dependency))) + else + DEPENDS <- rbind(DEPENDS,data.frame(key=depends.dir(dependency),value=depends.line(dependency))) + } + else if (length(depends.pkg(dependency)) == 2) # two dependencies found + { + d <- depends.pkg(dependency) + index <- grep('/wip/',d,invert=TRUE) + level.message('2 dependencies match ',dependency,':',paste(' ',depends.pkg(dependency))) + # message('===> depends(dependency): ',depends(dependency)) + # message('===> depends.pkg(dependency):',paste(' ',d)) + # message('===> index: ',index) + # message('===> buildlinke.line(): ',buildlink3.line(dependency,index)) + if (length(index) == 1) # a unique, non-wip, dependency found + { + level.message('choosing unique non-wip dependency for ',dependency,': ',depends.pkg(dependency)[index]) + if (arg.recursive && arg.update) + update.dependency(dependency,index) + if (file.exists(buildlink3.file(dependency,index))) + BUILDLINK3.MK <- rbind(BUILDLINK3.MK,data.frame(key=depends.dir(dependency,index),value=buildlink3.line(dependency,index))) + else + DEPENDS <- rbind(DEPENDS,data.frame(key=depends.dir(dependency,index),value=depends.line(dependency,index))) + } + else + { + level.message('no unique non-wip dependency matches') + message(message.too.many.dependencies(dependency)) + DEPENDS <- rbind(DEPENDS,data.frame(key='???',value=depends.line.2(dependency))) + } + } + else # more than 2 dependencies found + { + level.message(length(depends.pkg(dependency)),' dependencies match ',dependency,':',paste(' ',depends.pkg(dependency))) + message(message.too.many.dependencies(dependency)) + DEPENDS <- rbind(DEPENDS,data.frame(key='???',value=depends.line.2(dependency))) + } + if (length(new.depends.pkg(dependency)) > 0) + system(paste('echo',depends(dependency),arg.rpkg,'>>',arg.dependency_list)) + } + } + DEPENDS <- as.sorted.list(DEPENDS) + DEPENDS <- end.paragraph(DEPENDS) + BUILDLINK3.MK <- as.sorted.list(BUILDLINK3.MK) + result <- list(DEPENDS,BUILDLINK3.MK) + result +} + +use.languages <- function(s1,s2) +{ +# message('===> use.languages(',s1,',',s2,'):') +# USE_LANGUAGES <- read.file.as.values('USE_LANGUAGES') +# if (length(USE_LANGUAGES) == 0) +# { +# if (find.Rcpp(s1,s2)) +# USE_LANGUAGES <- append(USE_LANGUAGES,list('USE_LANGUAGES+= c c++')) +# } + USE_LANGUAGES <- list() + if (find.Rcpp(s1,s2)) + USE_LANGUAGES <- append(USE_LANGUAGES,list('c c++')) + if (length(USE_LANGUAGES) == 0) + USE_LANGUAGES <- '# none' + USE_LANGUAGES <- end.paragraph(USE_LANGUAGES) + USE_LANGUAGES +} + +copy.description <- function(connection) +{ + description <- readLines(connection) + writeLines(description,con='DESCRIPTION') +} + +write.Makefile <- function(metadata) +{ + RCSID <- paste0('# $','NetBSD$') + CATEGORIES <- makefile.field('CATEGORIES',categories()) + MAINTAINER <- makefile.field('MAINTAINER',maintainer(arg.maintainer_email)) + COMMENT <- makefile.field('COMMENT',comment(metadata[3])) + LICENSE <- makefile.field('LICENSE',license(metadata[5])) + R_PKGNAME <- makefile.field('R_PKGNAME',package(metadata[1])) + R_PKGVER <- makefile.field('R_PKGVER',version(metadata[2])) + USE_LANGUAGES <- makefile.fields('USE_LANGUAGES',use.languages(metadata[6],metadata[7])) + DEPENDENCIES <- make.depends(metadata[6],metadata[7]) + DEPENDS <- DEPENDENCIES[1] + BUILDLINK3.MK <- DEPENDENCIES[2] + INCLUDE.R <- '.include "../../math/R/Makefile.extension"' + INCLUDE.PKG <- '.include "../../mk/bsd.pkg.mk"' + + Makefile <- list() + Makefile <- append(Makefile,RCSID) + Makefile <- append(Makefile,'') + Makefile <- append(Makefile,R_PKGNAME) + Makefile <- append(Makefile,R_PKGVER) + Makefile <- append(Makefile,CATEGORIES) + Makefile <- append(Makefile,'') + Makefile <- append(Makefile,MAINTAINER) + Makefile <- append(Makefile,COMMENT) + Makefile <- append(Makefile,LICENSE) + Makefile <- append(Makefile,'') + Makefile <- append(Makefile,DEPENDS) + Makefile <- append(Makefile,USE_LANGUAGES) + Makefile <- append(Makefile,INCLUDE.R) + Makefile <- append(Makefile,BUILDLINK3.MK) + Makefile <- append(Makefile,INCLUDE.PKG) + Makefile <- paste(unlist(Makefile),collapse='\n') + + write(Makefile,'Makefile') +} + +construct.line <- function(df,key,value) +{ + key <- df[df$key==key,'key'] + operator <- df[df$key==key,'operator'] + delimiter <- df[df$key==key,'delimiter'] + value <- df[df$key==key,value] + df$new_line[df$key==key] <- paste0(key,operator,delimiter,value) + df +} + +element <- function(df,key,value,quiet=FALSE) +{ + key.index <- match(key,df$key,0) + if (key.index != 0 && df$key_value[key.index]) + result <- df[key.index,value] + else + { + result <- '???' + if (!quiet) + { + if (key.index == 0) + level.warning(key,' not found') + else + level.warning(key,' is not a key-value field') + } + } + result +} + +make.categories <- function(df) +{ + # message('===> make.categories():') + directory <- basename(dirname(getwd())) + categories <- unlist(element(df,'CATEGORIES','old_value')) + categories <- unlist(strsplit(categories,'[[:blank:]]+')) + categories <- c(directory,categories) + categories <- categories[ categories != 'R' ] + if (directory != 'wip') + categories <- categories[ categories != 'wip' ] + categories <- categories[!duplicated(categories)] + categories <- paste(categories,collapse=' ') + categories +} + +make.maintainer <- function(df) +{ + old.maintainer <- element(df,'MAINTAINER','old_value') + new.maintainer <- element(df,'MAINTAINER','new_value') + maintainer <- ifelse(old.maintainer == '',new.maintainer,old.maintainer) + maintainer +} + +make.comment <- function(df) +{ + old.comment <- element(df,'COMMENT','old_value') + new.comment <- element(df,'COMMENT','new_value') + comment <- old.comment + if (!weakly.equals(old.comment,new.comment)) + comment <- paste0(comment,' # [R2pkg] updated to: ',new.comment) + comment +} + +make.new_license <- function(df,license) +{ + new_license <- licenses[[license]] + if (is.null(new_license)) + new_license <- license + df$new_value[df$key == 'LICENSE'] <- new_license + df +} + +license.marked.todo <- function(todo) { todo != '' } +license.in.pkgsrc <- function(license) { license %in% sapply(licenses,'[',1) } + +make.license <- function(df) +{ + # message('===> make.license():') + old_license <- element(df,'LICENSE','old_value') + old_todo <- element(df,'LICENSE','old_todo') + new_license <- element(df,'LICENSE','new_value') + + if (license.in.pkgsrc(old_license) && license.in.pkgsrc(new_license)) + { + if (case.insensitive.equals(old_license,new_license)) + { + license <- old_license + todo <- old_todo + } + else + { + license <- paste0(new_license,' # [R2pkg] previously: ',old_license) + todo <- old_todo + } + } + else if (license.in.pkgsrc(old_license) && !license.in.pkgsrc(new_license)) + { + license <- paste0(old_license,' # [R2pkg] updated to: ',new_license) + todo <- '# TODO: ' + } + else if (!license.in.pkgsrc(old_license) && license.in.pkgsrc(new_license)) + { + license <- paste0(new_license,' # [R2pkg] previously: ',old_license) + todo <- '' + } + else if (!license.in.pkgsrc(old_license) && !license.in.pkgsrc(new_license)) + { + license <- paste0(new_license,' # [R2pkg] previously: ',old_license) + todo <- '# TODO: ' + } + + df$value[df$key == 'LICENSE'] <- license + df$todo[df$key == 'LICENSE'] <- todo + + df +} + +make.r_pkgver <- function(df) element(df,'R_PKGVER','new_value') + +find.order <- function(df,key,field) +{ + x <- df[,key] + value <- match(TRUE,x) + if (!is.na(value)) + value <- df[value,field] + value +} + +write.makefile <- function(lines) write(lines,'Makefile') + +update.Makefile.with.metadata <- function(df,metadata) +{ + # message('===> update.Makefile.with.metadata():') + + df$new_value <- NA + + df <- make.new_license(df,metadata[5]) + + df$new_value[df$key == 'CATEGORIES'] <- categories() + df$new_value[df$key == 'MAINTAINER'] <- arg.maintainer_email + df$new_value[df$key == 'COMMENT'] <- one.line(metadata[3]) + df$new_value[df$key == 'R_PKGVER'] <- version(metadata[2]) + + # str(df) + # print(df) + df +} + +update.Makefile.with.new.values <- function(df) +{ + # message('===> update.Makefile.with.new.values():') + df$value <- NA + df$todo <- '' + df <- make.license(df) + df$value[df$key == 'CATEGORIES'] <- make.categories(df) + df$value[df$key == 'MAINTAINER'] <- make.maintainer(df) + df$value[df$key == 'COMMENT'] <- make.comment(df) + df$value[df$key == 'R_PKGVER'] <- make.r_pkgver(df) + + # str(df) + # print(df) + df +} + +update.Makefile.with.new.line <- function(df) +{ + # message('===> update.Makefile.with.new.line():') + df$new_line <- NA + + construct_key_value <- df$key_value & !is.na(df$value) + df$new_line[construct_key_value] <- + paste0(df$todo[construct_key_value], + df$key[construct_key_value], + df$operator[construct_key_value], + df$delimiter[construct_key_value], + df$value[construct_key_value]) + + copy_line <- !df$key_value | !construct_key_value + df$new_line[copy_line] <- df$line[copy_line] + + # str(df) + # print(df) + df +} + +annotate.distname.in.Makefile <- function(df) +{ + match <- grepl('^[[:blank:]]*DISTNAME',df$new_line) + line <- df$new_line[match] + value <- sub('^[[:blank:]]*DISTNAME[[:blank:]]*=[[:blank:]]*','',line) + pkgname <- sub('_.+$','',value) + pkgver <- sub('^.+_','',value) + PKGNAME <- paste0('R_PKGNAME=',pkgname) + PKGVER <- paste0('R_PKGVER=',pkgver) + comment <- paste0(' # [R2pkg] replace this line with ',PKGNAME,' and ',PKGVER,' as first stanza') + df$new_line[match] <- paste0(line,comment) + df +} + +annotate.Makefile <- function(df) +{ + df <- annotate.distname.in.Makefile(df) + df +} + +remove.master.sites.from.Makefile <- function(df) +{ + match <- grepl('^[[:blank:]]*MASTER_SITES',df$new_line) + df <- df[!match,] + df +} + +remove.homepage.from.Makefile <- function(df) +{ + match <- grepl('^[[:blank:]]*HOMEPAGE',df$new_line) + df <- df[!match,] + df +} + +remove.buildlink.abi.depends.from.Makefile <- function(df) +{ + match <- grepl('^[[:blank:]]*BUILDLINK_ABI_DEPENDS',df$new_line) + df <- df[!match,] + df +} + +remove.buildlink.api.depends.from.Makefile <- function(df) +{ + match <- grepl('^[[:blank:]]*BUILDLINK_API_DEPENDS',df$new_line) + df <- df[!match,] + df +} + +remove.lines.from.Makefile <- function(df) +{ + df <- remove.master.sites.from.Makefile(df) + df <- remove.homepage.from.Makefile(df) + df <- remove.buildlink.abi.depends.from.Makefile(df) + df <- remove.buildlink.api.depends.from.Makefile(df) + df +} + +reassign.order <- function(df) +{ + # message('===> reassign.order():') + # str(df) + # print(df) + + r_pkgname.order <- element(df,'R_PKGNAME','order') + categories.order <- element(df,'CATEGORIES','order') + if (r_pkgname.order > categories.order) + { + r_pkgname.index <- df$key == 'R_PKGNAME' + r_pkgname.index[ is.na(r_pkgname.index) ] <- FALSE + r_pkgver.index <- df$key == 'R_PKGVER' + r_pkgver.index[ is.na(r_pkgver.index) ] <- FALSE + df[r_pkgname.index,'order'] <- categories.order - 0.2 + df[r_pkgver.index,'order'] <- categories.order - 0.1 + } + df +} + +conflicts <- function(pkg) +{ + conflict <- paste0('R>=',R_version()) + conflicts <- list() + if (pkg %in% base.packages) + { + conflicts <- append(conflicts,makefile.field('CONFLICTS',conflict)) + conflicts <- end.paragraph(conflicts) + } + conflicts +} + +conflicts.order <- function(df) +{ + order <- element(df,'COMMENT','order') + order +} + +make.df.conflicts <- function(df,metadata) +{ + df.conflicts <- data.frame() + conflicts.exist <- element(df,'CONFLICTS','old_value',quiet=TRUE) != '???' + if (!conflicts.exist) + { + c <- conflicts(metadata[1]) + order <- conflicts.order(df) + order <- order + 2.5 + i <- 0 + for (conflict in c) + { + i <- i + 1 + category <- as.character(i) + depends <- FALSE + buildlink3.mk <- FALSE + x <- data.frame(new_line=conflict,order=order,category=category,depends=depends,buildlink3.mk=buildlink3.mk) + df.conflicts <- rbind(df.conflicts,x) + } + } + df.conflicts +} + +make.df.depends <- function(df,DEPENDS) +{ + # message('===> make.df.depends():') + # str(df) + # print(df) + df.depends <- data.frame() + if (TRUE %in% df$depends) + df.depends <- data.frame(new_line=df[df$depends,'line'],stringsAsFactors=FALSE) + for (line in DEPENDS) + df.depends <- rbind(df.depends,data.frame(new_line=line,stringsAsFactors=FALSE)) + if (nrow(df.depends) > 0) + { + df.depends$category <- NA + df.depends$buildlink3.mk <- FALSE + df.depends <- categorize.key_value(df.depends,'new_line') + df.depends <- categorize.depends(df.depends,'new_line') + df.depends$key_value <- NULL + df.depends$key <- NULL + df.depends <- df.depends[!duplicated(df.depends),] + df.depends$order <- find.order(df,'depends','order') + } + # message('===> df.depends:') + # str(df.depends) + # print(df.depends) + df.depends +} + +make.df.buildlink3 <- function(df,BUILDLINK3.MK) +{ + # message('===> make.df.buildlink3():') + df.buildlink3.mk <- data.frame() + if (TRUE %in% df$buildlink3.mk) + df.buildlink3.mk <- data.frame(new_line=df[df$buildlink3.mk,'line'],stringsAsFactors=FALSE) + for (line in BUILDLINK3.MK) + df.buildlink3.mk <- rbind(df.buildlink3.mk,data.frame(new_line=line,stringsAsFactors=FALSE)) + if (nrow(df.buildlink3.mk) > 0) + { + df.buildlink3.mk$category <- NA + df.buildlink3.mk$depends <- FALSE + df.buildlink3.mk <- categorize.buildlink(df.buildlink3.mk,'new_line') + df.buildlink3.mk <- df.buildlink3.mk[!duplicated(df.buildlink3.mk),] + df.buildlink3.mk$order <- find.order(df,'buildlink3.mk','order') + } + # str(df.buildlink3.mk) + # print(df.buildlink3.mk) + df.buildlink3.mk +} + +make.df.makefile <- function(df,df.conflicts,df.depends,df.buildlink3.mk) +{ + # message('===> make.df.makefile():') + # message('===> df:') + # str(df) + # print(df) + fields <- c('new_line','order','category','depends','buildlink3.mk') + df.makefile <- df[!df$depends & !df$buildlink3.mk,fields] + df.makefile <- rbind(df.makefile,df.conflicts,df.depends,df.buildlink3.mk) + df.makefile <- df.makefile[order(df.makefile$order,df.makefile$category,df.makefile$new_line),] + df.makefile <- df.makefile[!adjacent.duplicates(df.makefile$new_line),] + df.makefile +} + +update.Makefile <- function(metadata) +{ + DEPENDENCIES <- make.depends(metadata[6],metadata[7]) + DEPENDS <- DEPENDENCIES[[1]] + BUILDLINK3.MK <- DEPENDENCIES[[2]] + # message('===> DEPENDS:') + # str(DEPENDS) + # print(DEPENDS) + # message('===> BUILDLINK3.MK:') + # str(BUILDLINK3.MK) + # print(BUILDLINK3.MK) + + # message('===> df:') + df <- read.Makefile.as.dataframe() + df <- update.Makefile.with.metadata(df,metadata) + df <- update.Makefile.with.new.values(df) + df <- update.Makefile.with.new.line(df) + df <- annotate.Makefile(df) + df <- remove.lines.from.Makefile(df) + df <- reassign.order(df) + + df.conflicts <- make.df.conflicts(df,metadata) + df.depends <- make.df.depends(df,DEPENDS) + df.buildlink3 <- make.df.buildlink3(df,BUILDLINK3.MK) + df.makefile <- make.df.makefile(df,df.conflicts,df.depends,df.buildlink3) + + write.makefile(df.makefile[,'new_line']) +} + +create.Makefile <- function(metadata) +{ + if (arg.update && file.exists('Makefile.orig')) + update.Makefile(metadata) + else + write.Makefile(metadata) +} + +create.DESCR <- function(metadata) +{ + DESCR <- description(metadata[4]) + write(DESCR,'DESCR') +} + +set.locale() + +error <- download.file(url=arg.rpkg_description_url,destfile='DESCRIPTION',quiet=arg.quiet_curl,method='curl') +if (error) + { + message('ERROR: Downloading the DESCRIPTION file for ',arg.rpkg,' failed;') + message(' perhaps the package no longer exists?') + quit(save='no',status=error) + } + +metadata <- read.dcf(file='DESCRIPTION', fields=c('Package','Version','Title','Description','License','Imports','Depends')) + +create.Makefile(metadata) +create.DESCR(metadata) diff --git a/pkgtools/R2pkg/files/R2pkg.sh b/pkgtools/R2pkg/files/R2pkg.sh index e1bd4723351..8e4d59fa54b 100755 --- a/pkgtools/R2pkg/files/R2pkg.sh +++ b/pkgtools/R2pkg/files/R2pkg.sh @@ -1,5 +1,5 @@ #!/bin/sh -# $NetBSD: R2pkg.sh,v 1.7 2019/10/13 09:43:26 rillig Exp $ +# $NetBSD: R2pkg.sh,v 1.8 2019/10/13 13:26:22 rillig Exp $ # # Copyright (c) 2014,2015,2016,2017,2018,2019 # Brook Milligan. All rights reserved. @@ -51,9 +51,9 @@ EDIT=1 LEVEL=0 MAINTAINER_EMAIL=pkgsrc-users@NetBSD.org PID=$$ -QUIET=0 -RECURSIVE=0 -UPDATE=0 +QUIET=false +RECURSIVE=false +UPDATE=false VERBOSE=0 DESCRIPTION=no @@ -64,13 +64,13 @@ while getopts cDehqruVvE:M:L:P: f do case ${f} in # options without arguments - c) UPDATE=0; ARGS="${ARGS} -c";; + c) UPDATE=false; ARGS="${ARGS} -c";; D) DESCRIPTION=yes; DESCRIPTION_CONNECTION="'DESCRIPTION'"; ARGS="${ARGS} -D";; e) EDIT=0; ARGS="${ARGS} -e";; h) echo "${USAGE}"; exit 0;; - q) QUIET=1; ARGS="${ARGS} -q";; - r) RECURSIVE=1; RECURSIVE_MESSAGE=1; ARGS="${ARGS} -r";; - u) UPDATE=1; ARGS="${ARGS} -u";; + q) QUIET=true; ARGS="${ARGS} -q";; + r) RECURSIVE=true; ARGS="${ARGS} -r";; + u) UPDATE=true; ARGS="${ARGS} -u";; V) echo "${NAME} v${VERS}"; exit 0;; v) VERBOSE=$((${VERBOSE}+1)); ARGS="${ARGS} -v";; # options taking arguments @@ -100,7 +100,7 @@ fi R_FILE=${TMPDIR}/R2pkg.$$.R -if [ ${UPDATE} -eq 1 -a -r Makefile ]; then +if [ ${UPDATE} = true -a -r Makefile ]; then BANNER_MSG="[ ${LEVEL} ] ===> Updating R package R-${RPKG} in $(pwd)" else BANNER_MSG="[ ${LEVEL} ] ===> Creating R package R-${RPKG} in $(pwd)" @@ -109,7 +109,7 @@ fi PACKAGES_LIST=${TMPDIR}/R2pkg.packages.${PID} DEPENDENCY_LIST=${TMPDIR}/R2pkg.depends.${PID} -if [ ${QUIET} -eq 1 ]; then +if [ ${QUIET} = true ]; then STDOUT_MAKESUM=">/dev/null" STDOUT_EXTRACT=">/dev/null" QUIET_CURL="TRUE" @@ -186,1224 +186,13 @@ preserve_original_content () make_package () { - R_CMD="Rscript --no-save ${R_FILE}" - cat << EOF > ${R_FILE} -R_version <- function() -{ - info <- R.Version() - version <- paste0(info[['major']],'.',info[['minor']]) - version -} - -set.locale <- function() { invisible(Sys.setlocale('LC_ALL','C')) } - -trim.space <- function(s) gsub('[[:space:]]','',s) -trim.blank <- function(s) gsub('[[:blank:]]','',s) -one.space <- function(s) gsub('[[:blank:]]+',' ',s) -one.line <- function(s) gsub('\n',' ',s) -pkg.vers <- function(s) gsub('_','.',s) -field <- function(key,value) paste(key,'=\t',value,sep='') - -# The list of "recommended packages which are to be included in all -# binary distributions of R." (R FAQ 5.1.2 2018-10-18) -# -base.packages.FAQ.5.1.2 <- c( - 'KernSmooth', - 'MASS', - 'Matrix', - 'boot', - 'class', - 'cluster', - 'codetools', - 'foreign', - 'lattice', - 'mgcv', - 'nlme', - 'nnet', - 'rpart', - 'spatial', - 'survival') - -# Other R packages that appear in dependency lists but are included in -# the R package. -# -base.packages.other <- c( - 'grDevices', - 'graphics', - 'grid', - 'methods', - 'parallel', - 'splines', - 'stats', - 'tools', - 'utils') -base.packages <- c('R',base.packages.FAQ.5.1.2,base.packages.other) - -licenses <- list() -licenses[['ACM']] <- 'acm-license' -licenses[['ACM | file LICENSE']] <- 'acm-license # OR file LICENSE' -licenses[['APACHE']] <- 'apache-1.1 OR apache-2.0' -licenses[['Apache License 2.0']] <- 'apache-2.0' -licenses[['Apache License (== 2.0)']] <- 'apache-2.0' -licenses[['Apache License (== 2.0) | file LICENSE']] <- 'apache-2.0 # OR file LICENSE' -licenses[['ARTISTIC']] <- 'artistic OR artistic-2.0' -licenses[['Artistic-2.0']] <- 'artistic-2.0' -licenses[['BSD']] <- '2-clause-bsd OR modified-bsd OR original-bsd' -licenses[['BSD-2']] <- '2-clause-bsd' -licenses[['BSD_2_clause + file LICENSE']] <- '2-clause-bsd # + file LICENSE' -licenses[['BSD 3 clause']] <- 'modified-bsd' -licenses[['BSD 3 clause + file LICENSE']] <- 'modified-bsd # + file LICENSE' -licenses[['BSD_3_clause + file LICENSE']] <- 'modified-bsd # + file LICENSE' -licenses[['BSL-1.0']] <- 'boost-license' -licenses[['CC0']] <- 'cc0-1.0-universal' -licenses[['GPL']] <- 'gnu-gpl-v1 OR gnu-gpl-v2 OR gnu-gpl-v3' -licenses[['GPL-1']] <- 'gnu-gpl-v1' -licenses[['GPL-2']] <- 'gnu-gpl-v2' -licenses[['GPL-2 | file LICENSE']] <- 'gnu-gpl-v2 # OR file LICENSE' -licenses[['GPL-3']] <- 'gnu-gpl-v3' -licenses[['GPL-2 | GPL-3']] <- 'gnu-gpl-v2 OR gnu-gpl-v3' -licenses[['GPL (>= 2)']] <- 'gnu-gpl-v2 OR gnu-gpl-v3' -licenses[['GPL (>= 2.0)']] <- 'gnu-gpl-v2 OR gnu-gpl-v3' -licenses[['GPL (>= 2) | file LICENSE']] <- 'gnu-gpl-v2 OR gnu-gpl-v3 # OR file LICENSE' -licenses[['GPL (>= 3)']] <- 'gnu-gpl-v3' -licenses[['LGPL']] <- 'gnu-lgpl-v2 OR gnu-lgpl-v2.1 OR gnu-lgpl-v3' -licenses[['LGPL-2']] <- 'gnu-lgpl-v2' -licenses[['LGPL-2.1']] <- 'gnu-lgpl-v2.1' -licenses[['LGPL-3']] <- 'gnu-lgpl-v3' -licenses[['LGPL-3 + file LICENSE']] <- 'gnu-lgpl-v3 # + file LICENSE' -licenses[['LGPL-2 | LGPL-3']] <- 'gnu-lgpl-v2 OR gnu-lgpl-v3' -licenses[['LGPL (>= 2)']] <- 'gnu-lgpl-v2 OR gnu-lgpl-v2.1 OR gnu-lgpl-v3' -licenses[['LUCENT']] <- 'lucent' -licenses[['Lucent Public License']] <- 'lucent' -licenses[['MIT']] <- 'mit' -licenses[['MIT + file LICENSE']] <- 'mit # + file LICENSE' -licenses[['MIT + file LICENSE | Unlimited']] <- 'mit # + file LICENSE OR unlimited' -licenses[['MPL-1.0']] <- 'mpl-1.0' -licenses[['MPL-1.1']] <- 'mpl-1.1' -licenses[['MPL-2.0']] <- 'mpl-2.0' -licenses[['MPL-2.0 | file LICENSE']] <- 'mpl-2.0 # OR file LICENSE' -licenses[['POSTGRESQL']] <- 'postgresql-license' - -adjacent.duplicates <- function(x) -{ - a <- x[-length(x)] - b <- x[-1] - dups <- a == b - dups <- c(FALSE,dups) - dups -} - -paste2 <- function(s1,s2) -{ - if (is.na(s1) && is.na(s2)) return ('') - if (is.na(s1) && !is.na(s2)) return (s2) - if (!is.na(s1) && is.na(s2)) return (s1) - if (!is.na(s1) && !is.na(s2)) return (paste(s1,s2)) -} - -end.paragraph <- function(l,l1=l,l2=list()) -{ - if (length(l1) > 0 || length(l2) > 0) - l <- append(l,'') - l -} - -as.sorted.list <- function(df) -{ - l <- list() - df <- df[!duplicated(df),] - if (nrow(df) > 0) - { - key <- as.vector(df[,1]) - value <- as.vector(df[,2]) - key <- order(key,value) - l <- as.list(value[key]) - } - l -} - -read.file.as.dataframe <- function(filename) -{ - # message('===> read.file.as.dataframe(',filename,')') - contents <- as.list(readLines(filename)) - df <- data.frame() - for (line in contents) - { - # str(line) - df <- rbind(df,data.frame(line=line,stringsAsFactors=FALSE)) - } - df -} - -categorize.key_value <- function(df,line='line') -{ - re.skip_blank <- '[[:blank:]]*' - re.blank <- '[[:blank:]]+' - re.anything <- '.*' - - re.key <- '[^+=[:blank:]]+' - re.operator <- '[+=]+' - re.delimiter <- re.skip_blank - re.value <- re.anything - re.optional_TODO <- '(#[[:blank:]]*TODO[[:blank:]]*:[[:blank:]]*)*' - - re.match_key_value_line <- paste0('^', - re.skip_blank, - re.optional_TODO, - re.key, - re.skip_blank, - re.operator, - re.delimiter, - re.value, - '\$') - - re.match_key <- paste0('^', - re.skip_blank, - re.optional_TODO, - '(',re.key,')', - re.skip_blank, - re.operator, - re.delimiter, - re.value, - '\$') - - df\$key_value <- grepl(re.match_key_value_line,df[,line]) - df\$key <- sub(re.match_key,'\\\2',df[,line]) - df\$key[!df\$key_value] <- NA - df -} - -categorize.depends <- function(df,line='line') -{ - df\$depends <- df\$key_value & df\$key == 'DEPENDS' - df\$category[df\$depends] <- unlist(sapply(strsplit(df[df\$depends,line],'/',fixed=TRUE),'[',3)) - df -} - -categorize.buildlink <- function(df,line='line') -{ - df\$buildlink3.mk <- grepl('buildlink3.mk',df[,line]) - df\$category[df\$buildlink3.mk] <- unlist(sapply(strsplit(df[df\$buildlink3.mk,line],'/',fixed=TRUE),'[',3)) - df -} - -fix.continued.lines <- function(df,line='line') -{ - if (nrow(df) > 1) - { - continued <- grepl('\\\\\\\\$',df[,line]) - continued_key_value <- df\$key_value & continued - if (FALSE %in% df[continued,'key_value']) - { - message('[ ${LEVEL} ] WARNING: unhandled continued line(s)') - } - for (i in 1:(length(continued_key_value)-1)) - { - next_line <- i + 1 - if (continued_key_value[i]) - { - df[i,line] <- sub('[[:blank:]]*\\\\\\\\$','',df[i,line]) - df\$key_value[next_line] <- TRUE - df\$key[next_line] <- df\$key[i] - df[next_line,line] <- paste0(df\$key[next_line],'+=',df[next_line,line]) - } - } - } - df -} - -read.Makefile.as.dataframe <- function() -{ - # message('===> read.Makefile.as.dataframe():') - - re.skip_blank <- '[[:blank:]]*' - re.blank <- '[[:blank:]]+' - re.anything <- '.*' - - re.key <- '[^+=[:blank:]]+' - re.operator <- '[+=]+' - re.delimiter <- re.skip_blank - re.value <- re.anything - re.optional_TODO <- '(#[[:blank:]]*TODO[[:blank:]]*:[[:blank:]]*)*' - - re.match_operator <- paste0('^', - re.skip_blank, - re.optional_TODO, - re.key, - re.skip_blank, - '(',re.operator,')', - re.delimiter, - re.value, - '\$') - re.match_delimiter <- paste0('^', - re.skip_blank, - re.optional_TODO, - re.key, - re.skip_blank, - re.operator, - '(',re.delimiter,')', - re.value, - '\$') - re.match_value <- paste0('^', - re.skip_blank, - re.optional_TODO, - re.key, - re.skip_blank, - re.operator, - re.delimiter, - '(',re.value,')', - '\$') - re.match_optional_TODO <- paste0('^', - re.skip_blank, - '(',re.optional_TODO,')', - re.key, - re.skip_blank, - re.operator, - re.delimiter, - re.value, - '\$') - - df <- read.file.as.dataframe('Makefile.orig') - - df\$order <- 1:nrow(df) - df\$category <- NA - - df <- categorize.key_value(df) - df <- fix.continued.lines(df) - df <- categorize.depends(df) - df <- categorize.buildlink(df) - - df\$operator <- sub(re.match_operator,'\\\2',df\$line) - df\$delimiter <- sub(re.match_delimiter,'\\\2',df\$line) - df\$old_value <- sub(re.match_value,'\\\2',df\$line) - df\$old_todo <- sub(re.match_optional_TODO,'\\\1',df\$line) - - df\$operator[!df\$key_value] <- NA - df\$delimiter[!df\$key_value] <- NA - df\$old_value[!df\$key_value] <- NA - df\$old_todo[!df\$key_value] <- NA - - df -} - -read.file.as.list <- function(filename) -{ - result <- list() - info <- file.info(filename) - size <- info[filename,'size'] - if (!is.na(size) && size > 0) - { - contents <- readLines(filename) - result <- as.list(contents) - } - result -} - -read.file.as.value <- function(filename) -{ - value <- '' - l <- read.file.as.list(filename) - if (length(l) == 1) - { - line <- l[[1]] - fields <- strsplit(line,'[[:blank:]]+') - value <- fields[[1]][2] - } - value -} - -read.file.as.values <- function(filename) -{ - message('===> read.file.as.values(',filename,'):') - values <- list() - l <- read.file.as.list(filename) - print(l) - for (line in l) - { - # fields <- strsplit(line,'[[:blank:]]+') - # value <- fields[[1]][2] - } - print(values) - values -} - -simplify.whitespace <- function(s) { gsub('[[:blank:]]+',' ',s) } -remove.punctuation <- function(s) -{ - punctuation <- '[,-]' - gsub(punctuation,'',s) -} -remove.quotes <- function(s) -{ - quotes <- '[\'\`"]' - gsub(quotes,'',s) -} -remove.articles <- function(s) -{ - pattern <- '^([[:blank:]]*)An* |([[:blank:]]+)[Aa]n*[[:blank:]]+' - result <- gsub(pattern,'\\\1',s) - result -} - -case.insensitive.equals <- function(s1,s2) -{ - s1.lower <- tolower(simplify.whitespace(s1)) - s2.lower <- tolower(simplify.whitespace(s2)) - result <- s1.lower == s2.lower - result -} - -weakly.equals <- function(s1,s2) -{ - result <- case.insensitive.equals(remove.articles(remove.quotes(remove.punctuation(s1))), - remove.articles(remove.quotes(remove.punctuation(s2)))) - result -} - -new.field.if.different <- function(filename,s) -{ - field <- field(filename,one.line(s)) - field.list <- read.file.as.list(filename) - if (length(field.list) == 1) - { - f <- field.list[[1]] - if (case.insensitive.equals(f,field)) - field <- f - } - field -} - -todo.license <- function(s) -{ - if (is.null(licenses[[s]])) - todo <- '# TODO: LICENSE' - else - todo <- 'LICENSE' - todo -} - -pkgsrc.license <- function(s) -{ - license <- licenses[[s]] - if (is.null(license)) - license <- s - license -} - -package <- function(s) one.line(s) -version <- function(s) one.line(s) -comment <- function(s) one.line(s) -use.tools <- function(s) read.file.as.list(s) - -license <- function(s) -{ - license <- pkgsrc.license(s) - old.license <- read.file.as.value('LICENSE') - if (old.license != '' && old.license != license) - license <- paste0(license,' # [R2pkg] previously: ',old.license) - license -} - -maintainer <- function(email) -{ - MAINTAINER <- read.file.as.value('MAINTAINER') - if (MAINTAINER == '') - MAINTAINER <- email - MAINTAINER -} - -make.sed.command <- function(key,value) -{ - address <- paste0('/^[[:blank:]]*',key,'/') - match <- paste0('(',key,'[[:blank:]]*=[[:blank:]]*).*$') - replacement <- paste0('\\\1',value) - command <- paste0(' -e "',address,'s/',match,'/',replacement,'/"') - command -} - -sed.categories <- function(categories) make.sed.command('CATEGORIES',categories) -sed.comment <- function(comment) -{ - old.comment <- read.file.as.value('COMMENT') - if (weakly.equals(old.comment,comment)) - comment <- old.comment - make.sed.command('COMMENT',comment) -} -sed.maintainer <- function(email) -{ - make.sed.command('MAINTAINER',maintainer(email)) -} -sed.license <- function(license) -{ - make.sed.command('LICENSE',license) -} -sed.r_pkgver <- function(r_pkgver) make.sed.command('R_PKGVER',r_pkgver) - -buildlink3.mk <- function(s1,s2) -{ - BUILDLINK3.MK <- data.frame() - buildlink3.mk.list <- read.file.as.list('BUILDLINK3.MK') - for (line in buildlink3.mk.list) - { - fields <- strsplit(line[[1]],'/',fixed=TRUE) - key <- fields[[1]][3] - value <- line - BUILDLINK3.MK <- rbind(BUILDLINK3.MK,data.frame(key=key,value=value)) - } - if (find.Rcpp(s1,s2)) - { - buildlink3.line <- '.include "../../devel/R-Rcpp/buildlink3.mk"' - key <- 'devel' - value <- buildlink3.line - BUILDLINK3.MK <- rbind(BUILDLINK3.MK,data.frame(key=key,value=value)) - } - BUILDLINK3.MK -} - -makefile.field <- function(key,value) -{ - # message('===> makefile.field(',key,',',value,'):') - field <- paste0(key,'= ',value) - # print(field) - field -} - -makefile.fields <- function(key,values) -{ - # message('===> makefile.fields():') - fields <- list() - for (l in values) - { - value <- unlist(l) - # message('===> value=',value,' ',length(value),' ',value == '') - # print(value) - if (value != '') - fields <- append(fields,makefile.field(key,list(value))) - else - fields <- append(fields,list('')) - # print(fields) - } - # print(fields) - fields -} - -categories <- function() basename(dirname(getwd())) -description <- function(s) strwrap(s,width=71) - -filter.imports <- function(s) -{ - for (pkg in base.packages) - { - re.pkg <- paste('^',pkg,sep='') - s <- s[!grepl(re.pkg,s)] - } - s -} - -find.Rcpp <- function(s1,s2) -{ - s <- paste(s1,s2) - Rcpp <- grepl('Rcpp',s) - Rcpp -} - -make.imports <- function(s1,s2) -{ - s <- paste2(s1,s2) - s <- gsub('([[:alnum:]]+)[[:blank:]]+(\\\([^\\\)]*\\\))?[[:blank:]]*,?','\\\\1 \\\\2,',s) - imports <- na.omit(unlist(strsplit(s,',[[:blank:]]*'))) - imports <- trim.space(imports) - imports <- filter.imports(imports) - imports -} - -make.dependency <- function(s) -{ - s <- gsub('\\\\)','',s) - s <- gsub('-','.',s) - s <- unlist(strsplit(s,'\\\\(')) - s -} - -depends <- function(dependency) dependency[1] - -depends.pkg <- function(dependency) -{ - # XXX message('===> ',depends(dependency)) - result <- Sys.glob(paste0('../../*/R-',depends(dependency))) - result -} - -new.depends.pkg <- function(dependency) -{ - result <- Sys.glob(paste0('../../wip/R-',depends(dependency))) - result -} - -depends.pkg.fullname <- function(dependency,index=1) -{ - result <- system(paste('cd',depends.pkg(dependency)[index],'&& bmake show-var VARNAME=PKGNAME'),intern=TRUE) - result -} - -depends.pkg.name <- function(dependency,index=1) -{ - result <- sub('^(.*)-([^-]*)$','\\\\1',depends.pkg.fullname(dependency,index)) - result -} - -depends.pkg.vers <- function(dependency,index=1) -{ - result <- sub('^(.*)-([^-]*)$','\\\\2',depends.pkg.fullname(dependency,index)) - result -} - -depends.vers <- function(dependency,index=1) -{ - if (length(dependency) == 2) - result <- dependency[2] - else - result <- paste0('>=',depends.pkg.vers(dependency,index)) - result <- trim.space(result) - result -} - -depends.vers.2 <- function(dependency) -{ - result <- ifelse(length(dependency) == 2, dependency[2], '>=???') - result <- trim.space(result) - result -} - -depends.dir <- function(dependency,index=1) -{ - fields <- strsplit(depends.pkg(dependency)[index],'/',fixed=TRUE) - result <- fields[[1]][3] - result -} - -depends.line <- function(dependency,index=1) -{ - result <- paste0('DEPENDS+=\tR-',depends(dependency),depends.vers(dependency,index),':',depends.pkg(dependency)[index]) - result -} - -depends.line.2 <- function(dependency) -{ - result <- paste0('DEPENDS+=\tR-',depends,depends.vers.2(dependency),':../../???/R-',depends) - result <- paste0(result,' # XXX - found') - for (pkg in depends.pkg(dependency)) - result <- paste(result,pkg) - result -} - -buildlink3.file <- function(dependency,index=1) -{ - result <- paste0(depends.pkg(dependency)[index],'/buildlink3.mk') - result -} - -buildlink3.line <- function(dependency,index=1) -{ - result <- paste0('.include "',buildlink3.file(dependency,index),'"') - result -} - -dependency.dir <- function(dependency) -{ - result <- paste0('../../wip/R-',depends(dependency)) - result -} - -message.wip.dependency <- function(dependency,index=1) -{ - dir <- depends.dir(dependency,index) - dir.in.wip <- grepl('wip',dir) - wd.in.wip <- grepl('/wip/',getwd()) - if (dir.in.wip && !wd.in.wip) - message('[ ${LEVEL} ] WARNING: R-${RPKG} should not depend on a wip package: ',depends.pkg(dependency)[index]) -} - -message.too.many.dependencies <- function(dependency) -{ - msg <- paste0('[ ${LEVEL} ] WARNING: too many dependencies found for ',depends(dependency),':') - for (pkg in depends.pkg(dependency)) - msg <- paste(msg,pkg) - msg -} - -update.dependency <- function(dependency,index=1) -{ - message('[ ${LEVEL} ] WARNING: updating dependency for ',depends(dependency),': ',depends.pkg(dependency)[index]) - grep <- paste0('grep -E -q -e "',depends(dependency),'" ${PACKAGES_LIST}') - command <- paste0(grep,' || (cd ',depends.pkg(dependency)[index],' && ${R2PKG} ${ARGS} ',depends(dependency),')') - error <- system(command) - if (error != 0) - message('[ ${LEVEL} ] WARNING: error updating dependency for ',depends(dependency)) -} - -make.depends <- function(s1,s2) -{ - imports <- make.imports(s1,s2) - # XXX message('===> imports:') - # XXX print(imports) - DEPENDS <- data.frame() - BUILDLINK3.MK <- buildlink3.mk(s1,s2) - if (length(imports) > 0) - { - for (i in 1:length(imports)) - { - dependency <- make.dependency(imports[i]) - # XXX message('[ ',${LEVEL},' ] ===> ',i,' / ',length(imports),': ',depends(dependency)) - if (length(depends.pkg(dependency)) == 0) # a dependency cannot be found - { - message('[ ${LEVEL} ] 0 dependencies match ',dependency) - if (${RECURSIVE}) - { - dir.create(path=dependency.dir(dependency),recursive=TRUE) - update.dependency(dependency) - } - else - message('[ ${LEVEL} ] WARNING: dependency needed for ',depends(dependency)) - } - else if (length(depends.pkg(dependency)) == 1) # a unique dependency found - { - message('[ ${LEVEL} ] 1 dependency matches ',dependency,': ',depends.pkg(dependency)) - message.wip.dependency(dependency) - if (${RECURSIVE} && ${UPDATE}) - update.dependency(dependency) - if (file.exists(buildlink3.file(dependency))) - BUILDLINK3.MK <- rbind(BUILDLINK3.MK,data.frame(key=depends.dir(dependency),value=buildlink3.line(dependency))) - else - DEPENDS <- rbind(DEPENDS,data.frame(key=depends.dir(dependency),value=depends.line(dependency))) - } - else if (length(depends.pkg(dependency)) == 2) # two dependencies found - { - d <- depends.pkg(dependency) - index <- grep('/wip/',d,invert=TRUE) - message('[ ${LEVEL} ] 2 dependencies match ',dependency,':',paste(' ',depends.pkg(dependency))) - # message('===> depends(dependency): ',depends(dependency)) - # message('===> depends.pkg(dependency):',paste(' ',d)) - # message('===> index: ',index) - # message('===> buildlinke.line(): ',buildlink3.line(dependency,index)) - if (length(index) == 1) # a unique, non-wip, dependency found - { - message('[ ${LEVEL} ] choosing unique non-wip dependency for ',dependency,': ',depends.pkg(dependency)[index]) - if (${RECURSIVE} && ${UPDATE}) - update.dependency(dependency,index) - if (file.exists(buildlink3.file(dependency,index))) - BUILDLINK3.MK <- rbind(BUILDLINK3.MK,data.frame(key=depends.dir(dependency,index),value=buildlink3.line(dependency,index))) - else - DEPENDS <- rbind(DEPENDS,data.frame(key=depends.dir(dependency,index),value=depends.line(dependency,index))) - } - else - { - message('[ ${LEVEL} ] no unique non-wip dependency matches') - message(message.too.many.dependencies(dependency)) - DEPENDS <- rbind(DEPENDS,data.frame(key='???',value=depends.line.2(dependency))) - } - } - else # more than 2 dependencies found - { - message('[ ${LEVEL} ] ',length(depends.pkg(dependency)),' dependencies match ',dependency,':',paste(' ',depends.pkg(dependency))) - message(message.too.many.dependencies(dependency)) - DEPENDS <- rbind(DEPENDS,data.frame(key='???',value=depends.line.2(dependency))) - } - if (length(new.depends.pkg(dependency)) > 0) - system(paste('echo',depends(dependency),'${RPKG} >> ${DEPENDENCY_LIST}')) - } - } - DEPENDS <- as.sorted.list(DEPENDS) - DEPENDS <- end.paragraph(DEPENDS) - BUILDLINK3.MK <- as.sorted.list(BUILDLINK3.MK) - result <- list(DEPENDS,BUILDLINK3.MK) - result -} - -use.languages <- function(s1,s2) -{ -# message('===> use.languages(',s1,',',s2,'):') -# USE_LANGUAGES <- read.file.as.values('USE_LANGUAGES') -# if (length(USE_LANGUAGES) == 0) -# { -# if (find.Rcpp(s1,s2)) -# USE_LANGUAGES <- append(USE_LANGUAGES,list('USE_LANGUAGES+= c c++')) -# } - USE_LANGUAGES <- list() - if (find.Rcpp(s1,s2)) - USE_LANGUAGES <- append(USE_LANGUAGES,list('c c++')) - if (length(USE_LANGUAGES) == 0) - USE_LANGUAGES <- '# none' - USE_LANGUAGES <- end.paragraph(USE_LANGUAGES) - USE_LANGUAGES -} - -copy.description <- function(connection) -{ - description <- readLines(connection) - writeLines(description,con='DESCRIPTION') -} - -write.Makefile <- function(metadata) -{ - RCSID <- '# \$NetBSD\$' - CATEGORIES <- makefile.field('CATEGORIES',categories()) - MAINTAINER <- makefile.field('MAINTAINER',maintainer('${MAINTAINER_EMAIL}')) - COMMENT <- makefile.field('COMMENT',comment(metadata[3])) - LICENSE <- makefile.field('LICENSE',license(metadata[5])) - R_PKGNAME <- makefile.field('R_PKGNAME',package(metadata[1])) - R_PKGVER <- makefile.field('R_PKGVER',version(metadata[2])) - USE_LANGUAGES <- makefile.fields('USE_LANGUAGES',use.languages(metadata[6],metadata[7])) - DEPENDENCIES <- make.depends(metadata[6],metadata[7]) - DEPENDS <- DEPENDENCIES[1] - BUILDLINK3.MK <- DEPENDENCIES[2] - INCLUDE.R <- '.include "../../math/R/Makefile.extension"' - INCLUDE.PKG <- '.include "../../mk/bsd.pkg.mk"' - - Makefile <- list() - Makefile <- append(Makefile,RCSID) - Makefile <- append(Makefile,'') - Makefile <- append(Makefile,R_PKGNAME) - Makefile <- append(Makefile,R_PKGVER) - Makefile <- append(Makefile,CATEGORIES) - Makefile <- append(Makefile,'') - Makefile <- append(Makefile,MAINTAINER) - Makefile <- append(Makefile,COMMENT) - Makefile <- append(Makefile,LICENSE) - Makefile <- append(Makefile,'') - Makefile <- append(Makefile,DEPENDS) - Makefile <- append(Makefile,USE_LANGUAGES) - Makefile <- append(Makefile,INCLUDE.R) - Makefile <- append(Makefile,BUILDLINK3.MK) - Makefile <- append(Makefile,INCLUDE.PKG) - Makefile <- paste(unlist(Makefile),collapse='\n') - - write(Makefile,'Makefile') -} - -construct.line <- function(df,key,value) -{ - key <- df[df\$key==key,'key'] - operator <- df[df\$key==key,'operator'] - delimiter <- df[df\$key==key,'delimiter'] - value <- df[df\$key==key,value] - df\$new_line[df\$key==key] <- paste0(key,operator,delimiter,value) - df -} - -element <- function(df,key,value,quiet=FALSE) -{ - key.index <- match(key,df\$key,0) - if (key.index != 0 && df\$key_value[key.index]) - result <- df[key.index,value] - else - { - result <- '???' - if (!quiet) - { - if (key.index == 0) - message('[ ${LEVEL} ] WARNING: ',key,' not found') - else - message('[ ${LEVEL} ] WARNING: ',key,' is not a key-value field') - } - } - result -} - -make.categories <- function(df) -{ - # message('===> make.categories():') - directory <- basename(dirname(getwd())) - categories <- unlist(element(df,'CATEGORIES','old_value')) - categories <- unlist(strsplit(categories,'[[:blank:]]+')) - categories <- c(directory,categories) - categories <- categories[ categories != 'R' ] - if (directory != 'wip') - categories <- categories[ categories != 'wip' ] - categories <- categories[!duplicated(categories)] - categories <- paste(categories,collapse=' ') - categories -} - -make.maintainer <- function(df) -{ - old.maintainer <- element(df,'MAINTAINER','old_value') - new.maintainer <- element(df,'MAINTAINER','new_value') - maintainer <- ifelse(old.maintainer == '',new.maintainer,old.maintainer) - maintainer -} - -make.comment <- function(df) -{ - old.comment <- element(df,'COMMENT','old_value') - new.comment <- element(df,'COMMENT','new_value') - comment <- old.comment - if (!weakly.equals(old.comment,new.comment)) - comment <- paste0(comment,' # [R2pkg] updated to: ',new.comment) - comment -} - -make.new_license <- function(df,license) -{ - new_license <- licenses[[license]] - if (is.null(new_license)) - new_license <- license - df\$new_value[df\$key == 'LICENSE'] <- new_license - df -} - -license.marked.todo <- function(todo) { todo != '' } -license.in.pkgsrc <- function(license) { license %in% sapply(licenses,'[',1) } - -make.license <- function(df) -{ - # message('===> make.license():') - old_license <- element(df,'LICENSE','old_value') - old_todo <- element(df,'LICENSE','old_todo') - new_license <- element(df,'LICENSE','new_value') - - if (license.in.pkgsrc(old_license) && license.in.pkgsrc(new_license)) - { - if (case.insensitive.equals(old_license,new_license)) - { - license <- old_license - todo <- old_todo - } - else - { - license <- paste0(new_license,' # [R2pkg] previously: ',old_license) - todo <- old_todo - } - } - else if (license.in.pkgsrc(old_license) && !license.in.pkgsrc(new_license)) - { - license <- paste0(old_license,' # [R2pkg] updated to: ',new_license) - todo <- '# TODO: ' - } - else if (!license.in.pkgsrc(old_license) && license.in.pkgsrc(new_license)) - { - license <- paste0(new_license,' # [R2pkg] previously: ',old_license) - todo <- '' - } - else if (!license.in.pkgsrc(old_license) && !license.in.pkgsrc(new_license)) - { - license <- paste0(new_license,' # [R2pkg] previously: ',old_license) - todo <- '# TODO: ' - } - - df\$value[df\$key == 'LICENSE'] <- license - df\$todo[df\$key == 'LICENSE'] <- todo - - df -} - -make.r_pkgver <- function(df) element(df,'R_PKGVER','new_value') - -find.order <- function(df,key,field) -{ - x <- df[,key] - value <- match(TRUE,x) - if (!is.na(value)) - value <- df[value,field] - value -} - -write.makefile <- function(lines) write(lines,'Makefile') - -update.Makefile.with.metadata <- function(df,metadata) -{ - # message('===> update.Makefile.with.metadata():') - - df\$new_value <- NA - - df <- make.new_license(df,metadata[5]) - - df\$new_value[df\$key == 'CATEGORIES'] <- categories() - df\$new_value[df\$key == 'MAINTAINER'] <- '${MAINTAINER_EMAIL}' - df\$new_value[df\$key == 'COMMENT'] <- one.line(metadata[3]) - df\$new_value[df\$key == 'R_PKGVER'] <- version(metadata[2]) - - # str(df) - # print(df) - df -} - -update.Makefile.with.new.values <- function(df) -{ - # message('===> update.Makefile.with.new.values():') - df\$value <- NA - df\$todo <- '' - df <- make.license(df) - df\$value[df\$key == 'CATEGORIES'] <- make.categories(df) - df\$value[df\$key == 'MAINTAINER'] <- make.maintainer(df) - df\$value[df\$key == 'COMMENT'] <- make.comment(df) - df\$value[df\$key == 'R_PKGVER'] <- make.r_pkgver(df) - - # str(df) - # print(df) - df -} - -update.Makefile.with.new.line <- function(df) -{ - # message('===> update.Makefile.with.new.line():') - df\$new_line <- NA - - construct_key_value <- df\$key_value & !is.na(df\$value) - df\$new_line[construct_key_value] <- - paste0(df\$todo[construct_key_value], - df\$key[construct_key_value], - df\$operator[construct_key_value], - df\$delimiter[construct_key_value], - df\$value[construct_key_value]) - - copy_line <- !df\$key_value | !construct_key_value - df\$new_line[copy_line] <- df\$line[copy_line] - - # str(df) - # print(df) - df -} - -annotate.distname.in.Makefile <- function(df) -{ - match <- grepl('^[[:blank:]]*DISTNAME',df\$new_line) - line <- df\$new_line[match] - value <- sub('^[[:blank:]]*DISTNAME[[:blank:]]*=[[:blank:]]*','',line) - pkgname <- sub('_.+$','',value) - pkgver <- sub('^.+_','',value) - PKGNAME <- paste0('R_PKGNAME=',pkgname) - PKGVER <- paste0('R_PKGVER=',pkgver) - comment <- paste0(' # [R2pkg] replace this line with ',PKGNAME,' and ',PKGVER,' as first stanza') - df\$new_line[match] <- paste0(line,comment) - df -} - -annotate.Makefile <- function(df) -{ - df <- annotate.distname.in.Makefile(df) - df -} - -remove.master.sites.from.Makefile <- function(df) -{ - match <- grepl('^[[:blank:]]*MASTER_SITES',df\$new_line) - df <- df[!match,] - df -} - -remove.homepage.from.Makefile <- function(df) -{ - match <- grepl('^[[:blank:]]*HOMEPAGE',df\$new_line) - df <- df[!match,] - df -} - -remove.buildlink.abi.depends.from.Makefile <- function(df) -{ - match <- grepl('^[[:blank:]]*BUILDLINK_ABI_DEPENDS',df\$new_line) - df <- df[!match,] - df -} - -remove.buildlink.api.depends.from.Makefile <- function(df) -{ - match <- grepl('^[[:blank:]]*BUILDLINK_API_DEPENDS',df\$new_line) - df <- df[!match,] - df -} - -remove.lines.from.Makefile <- function(df) -{ - df <- remove.master.sites.from.Makefile(df) - df <- remove.homepage.from.Makefile(df) - df <- remove.buildlink.abi.depends.from.Makefile(df) - df <- remove.buildlink.api.depends.from.Makefile(df) - df -} - -reassign.order <- function(df) -{ - # message('===> reassign.order():') - # str(df) - # print(df) - - r_pkgname.order <- element(df,'R_PKGNAME','order') - categories.order <- element(df,'CATEGORIES','order') - if (r_pkgname.order > categories.order) - { - r_pkgname.index <- df\$key == 'R_PKGNAME' - r_pkgname.index[ is.na(r_pkgname.index) ] <- FALSE - r_pkgver.index <- df\$key == 'R_PKGVER' - r_pkgver.index[ is.na(r_pkgver.index) ] <- FALSE - df[r_pkgname.index,'order'] <- categories.order - 0.2 - df[r_pkgver.index,'order'] <- categories.order - 0.1 - } - df -} - -conflicts <- function(pkg) -{ - conflict <- paste0('R>=',R_version()) - conflicts <- list() - if (pkg %in% base.packages) - { - conflicts <- append(conflicts,makefile.field('CONFLICTS',conflict)) - conflicts <- end.paragraph(conflicts) - } - conflicts -} - -conflicts.order <- function(df) -{ - order <- element(df,'COMMENT','order') - order -} - -make.df.conflicts <- function(df,metadata) -{ - df.conflicts <- data.frame() - conflicts.exist <- element(df,'CONFLICTS','old_value',quiet=TRUE) != '???' - if (!conflicts.exist) - { - c <- conflicts(metadata[1]) - order <- conflicts.order(df) - order <- order + 2.5 - i <- 0 - for (conflict in c) - { - i <- i + 1 - category <- as.character(i) - depends <- FALSE - buildlink3.mk <- FALSE - x <- data.frame(new_line=conflict,order=order,category=category,depends=depends,buildlink3.mk=buildlink3.mk) - df.conflicts <- rbind(df.conflicts,x) - } - } - df.conflicts -} - -make.df.depends <- function(df,DEPENDS) -{ - # message('===> make.df.depends():') - # str(df) - # print(df) - df.depends <- data.frame() - if (TRUE %in% df\$depends) - df.depends <- data.frame(new_line=df[df\$depends,'line'],stringsAsFactors=FALSE) - for (line in DEPENDS) - df.depends <- rbind(df.depends,data.frame(new_line=line,stringsAsFactors=FALSE)) - if (nrow(df.depends) > 0) - { - df.depends\$category <- NA - df.depends\$buildlink3.mk <- FALSE - df.depends <- categorize.key_value(df.depends,'new_line') - df.depends <- categorize.depends(df.depends,'new_line') - df.depends\$key_value <- NULL - df.depends\$key <- NULL - df.depends <- df.depends[!duplicated(df.depends),] - df.depends\$order <- find.order(df,'depends','order') - } - # message('===> df.depends:') - # str(df.depends) - # print(df.depends) - df.depends -} - -make.df.buildlink3 <- function(df,BUILDLINK3.MK) -{ - # message('===> make.df.buildlink3():') - df.buildlink3.mk <- data.frame() - if (TRUE %in% df\$buildlink3.mk) - df.buildlink3.mk <- data.frame(new_line=df[df\$buildlink3.mk,'line'],stringsAsFactors=FALSE) - for (line in BUILDLINK3.MK) - df.buildlink3.mk <- rbind(df.buildlink3.mk,data.frame(new_line=line,stringsAsFactors=FALSE)) - if (nrow(df.buildlink3.mk) > 0) - { - df.buildlink3.mk\$category <- NA - df.buildlink3.mk\$depends <- FALSE - df.buildlink3.mk <- categorize.buildlink(df.buildlink3.mk,'new_line') - df.buildlink3.mk <- df.buildlink3.mk[!duplicated(df.buildlink3.mk),] - df.buildlink3.mk\$order <- find.order(df,'buildlink3.mk','order') - } - # str(df.buildlink3.mk) - # print(df.buildlink3.mk) - df.buildlink3.mk -} - -make.df.makefile <- function(df,df.conflicts,df.depends,df.buildlink3.mk) -{ - # message('===> make.df.makefile():') - # message('===> df:') - # str(df) - # print(df) - fields <- c('new_line','order','category','depends','buildlink3.mk') - df.makefile <- df[!df\$depends & !df\$buildlink3.mk,fields] - df.makefile <- rbind(df.makefile,df.conflicts,df.depends,df.buildlink3.mk) - df.makefile <- df.makefile[order(df.makefile\$order,df.makefile\$category,df.makefile\$new_line),] - df.makefile <- df.makefile[!adjacent.duplicates(df.makefile\$new_line),] - df.makefile -} - -update.Makefile <- function(metadata) -{ - DEPENDENCIES <- make.depends(metadata[6],metadata[7]) - DEPENDS <- DEPENDENCIES[[1]] - BUILDLINK3.MK <- DEPENDENCIES[[2]] - # message('===> DEPENDS:') - # str(DEPENDS) - # print(DEPENDS) - # message('===> BUILDLINK3.MK:') - # str(BUILDLINK3.MK) - # print(BUILDLINK3.MK) - - # message('===> df:') - df <- read.Makefile.as.dataframe() - df <- update.Makefile.with.metadata(df,metadata) - df <- update.Makefile.with.new.values(df) - df <- update.Makefile.with.new.line(df) - df <- annotate.Makefile(df) - df <- remove.lines.from.Makefile(df) - df <- reassign.order(df) - - df.conflicts <- make.df.conflicts(df,metadata) - df.depends <- make.df.depends(df,DEPENDS) - df.buildlink3 <- make.df.buildlink3(df,BUILDLINK3.MK) - df.makefile <- make.df.makefile(df,df.conflicts,df.depends,df.buildlink3) - - write.makefile(df.makefile[,'new_line']) -} - -create.Makefile <- function(metadata) -{ - if (${UPDATE} == 1 && file.exists('Makefile.orig')) - update.Makefile(metadata) - else - write.Makefile(metadata) -} - -create.DESCR <- function(metadata) -{ - DESCR <- description(metadata[4]) - write(DESCR,'DESCR') -} - -set.locale() - -error <- download.file(url='${RPKG_DESCRIPTION_URL}',destfile='DESCRIPTION',quiet=${QUIET_CURL},method='curl') -if (error) - { - message('ERROR: Downloading the DESCRIPTION file for ${RPKG} failed;') - message(' perhaps the package no longer exists?') - quit(save='no',status=error) - } - -metadata <- read.dcf(file='DESCRIPTION', fields=c('Package','Version','Title','Description','License','Imports','Depends')) - -create.Makefile(metadata) -create.DESCR(metadata) -EOF - eval ${R_CMD} + env LEVEL="${LEVEL}" RPKG="${RPKG}" PACKAGES_LIST="${PACKAGES_LIST}" \ + R2PKG="${R2PKG}" ARGS="${ARGS}" RECURSIVE="${RECURSIVE}" \ + UPDATE="${UPDATE}" DEPENDENCY_LIST="${DEPENDENCY_LIST}" \ + MAINTAINER_EMAIL="${MAINTAINER_EMAIL}" \ + RPKG_DESCRIPTION_URL="${RPKG_DESCRIPTION_URL}" \ + QUIET_CURL="${QUIET_CURL}" \ + Rscript --no-save "@LIBDIR@/R2pkg.R" retval=${?} if [ ${retval} -ne 0 ]; then echo "ERROR: making ${RPKG} package failed." 1>&2 @@ -1565,7 +354,7 @@ cleanup () messages () { - if [ ${QUIET} -eq 0 -a ${LEVEL} -eq 0 ]; then + if [ ${QUIET} = false -a ${LEVEL} -eq 0 ]; then cat << EOF Please do not forget the following: @@ -1578,7 +367,7 @@ EOF [ -f buildlink3.mk ] && echo "- check buildlink3.mk" [ "${DESCRIPTION}" = "yes" ] && echo "- remove DESCRIPTION." - if [ ${RECURSIVE} -ne 0 ]; then + if [ ${RECURSIVE} = true ]; then cat << EOF Recursive packages may have been created in ../../wip; please do the following: diff --git a/pkgtools/R2pkg/files/RELEASE b/pkgtools/R2pkg/files/RELEASE index e25c9f0d3d0..1de56b4db9d 100644 --- a/pkgtools/R2pkg/files/RELEASE +++ b/pkgtools/R2pkg/files/RELEASE @@ -1,4 +1,4 @@ -$NetBSD: RELEASE,v 1.4 2019/10/13 09:43:26 rillig Exp $ +$NetBSD: RELEASE,v 1.5 2019/10/13 13:26:22 rillig Exp $ RELEASE ======= @@ -61,3 +61,5 @@ R2pkg v.0.6.1 (2019-10-13) * Quote variables to prevent unintended interpolation. * Write error messages to stderr instead of stdout. + +* Separate R source code from shell code. |