--- /dev/null
+Package: cran2deb
+Version: 0.0
+Date: 2008-07-14
+Title: Convert CRAN packages into Debian packages
+Author: Charles Blundell <blundellc@gmail.com>, with assistance from Dirk Eddelbuettel <>
+Maintainer: Charles Blundell <blundellc@gmail.com>
+Depends: ctv, utils
+Description: Convert CRAN packages into Debian packages, mostly unassisted, easily
+ subverting the R package system.
+License: GPL-3
--- /dev/null
+get.dependencies <- function(pkg,extra_deps) {
+ if ('SystemRequirements' %in% colnames(pkg$description)) {
+ stop(paste('Unsupported SystemRequirements:',pkg$description[1,'SystemRequirements']))
+ }
+
+ # determine dependencies
+ dependencies <- r.dependencies.of(description=pkg$description)
+ depends <- list()
+ # these are used for generating the Depends fields
+ as.deb <- function(r,binary) {
+ return(pkgname.as.debian(paste(dependencies[r,]$name)
+ ,version=dependencies[r,]$version
+ ,repopref=pkg$repo
+ ,binary=binary))
+ }
+ depends$bin <- lapply(rownames(dependencies), as.deb, binary=T)
+ depends$build <- lapply(rownames(dependencies), as.deb, binary=F)
+ # add the command line dependencies
+ depends$bin = c(extra_deps$deb,depends$bin)
+ depends$build = c(extra_deps$deb,depends$build)
+
+ # make sure we depend upon R in some way...
+ if (!length(grep('^r-base',depends$build))) {
+ depends$build = c(depends$build,pkgname.as.debian('R',version='>= 2.7.0',binary=F))
+ depends$bin = c(depends$bin, pkgname.as.debian('R',version='>= 2.7.0',binary=T))
+ }
+ # also include stuff to allow tcltk to build (suggested by Dirk)
+ depends$build = c(depends$build,'xvfb','xauth','xfont-base')
+
+ # remove duplicates
+ depends <- lapply(depends,unique)
+
+ # append the Debian dependencies
+ depends$build=c(depends$build,'debhelper (>> 4.1.0)','cdbs')
+ if (pkg$archdep) {
+ depends$bin=c(depends$bin,'${shlibs:Depends}')
+ }
+
+ # the names of dependent source packages (to find the .changes file to
+ # upload via dput). these can be found recursively.
+ depends$r = lapply(r.dependency.closure(dependencies)
+ ,tolower)
+ # append command line dependencies
+ depends$r = c(extra_deps$r, depends$r)
+ return(depends)
+}
+
+generate.control <- function(pkg) {
+ # construct control file
+ control = data.frame()
+ control[1,'Source'] = pkg$srcname
+ control[1,'Section'] = 'math'
+ control[1,'Priority'] = 'optional'
+ control[1,'Maintainer'] = maintainer
+ control[1,'Build-Depends'] = paste(pkg$depends$build,collapse=', ')
+ control[1,'Standards-Version'] = '3.8.0'
+
+ control[2,'Package'] = pkg$debname
+ control[2,'Architecture'] = 'all'
+ if (pkg$archdep) {
+ control[2,'Architecture'] = 'any'
+ }
+ control[2,'Depends'] = paste(pkg$depends$bin,collapse=', ')
+
+ # bundles provide virtual packages of their contents
+ if (pkg$is_bundle) {
+ control[2,'Provides'] = paste(
+ lapply(r.bundle.contains(pkg$name)
+ ,function(name) return(pkgname.as.debian(paste(name)
+ ,repopref=pkg$repo
+ ,binary=T)))
+ ,collapse=', ')
+ }
+
+ # generate the description
+ descr = 'GNU R package "'
+ if ('Title' %in% colnames(pkg$description)) {
+ descr = paste(descr,pkg$description[1,'Title'],sep='')
+ } else {
+ descr = paste(descr,pkg$name,sep='')
+ }
+ if (pkg$is_bundle) {
+ long_descr <- pkg$description[1,'BundleDescription']
+ } else {
+ long_descr <- pkg$description[1,'Description']
+ }
+ # using \n\n.\n\n is not very nice, but is necessary to make sure
+ # the longer description does not begin on the synopsis line --- R's
+ # write.dcf does not appear to have a nicer way of doing this.
+ descr = paste(descr,'"\n\n', long_descr, sep='')
+ if ('URL' %in% colnames(pkg$description)) {
+ descr = paste(descr,'\n\nURL: ',pkg$description[1,'URL'],sep='')
+ }
+ control[2,'Description'] = descr
+
+ # Debian policy says 72 char width; indent minimally
+ write.dcf(control,file=pkg$debfile('control.in'),indent=1,width=72)
+ write.dcf(control,indent=1,width=72)
+}
+
--- /dev/null
+# sudo pbuilder --execute r -e 'rownames(installed.packages())'
+# XXX: has to be a better way of doing this
+base_pkgs=c('base', 'datasets','grDevices','graphics','grid', 'methods'
+ ,'splines','stats', 'stats4', 'tcltk', 'tools','utils')
+# found in R source directory:
+# 'profile', 'datasets'
+
+repourl.as.debian <- function(url) {
+ # map the url to a repository onto its name in debian package naming
+ if (length(grep('cran',url))) {
+ return('cran')
+ }
+ if (length(grep('bioc',url))) {
+ return('bioc')
+ }
+ stop(paste('unknown repository',url))
+}
+
+pkgname.as.debian <- function(name,repopref=NULL,version=NULL,binary=T) {
+ # generate the debian package name corresponding to the R package name
+ if (name %in% base_pkgs) {
+ name = 'R'
+ }
+ if (name == 'R') {
+ # R is special.
+ if (binary) {
+ debname='r-base-core'
+ } else {
+ debname='r-base-dev'
+ }
+ } else {
+ # XXX: data.frame rownames are unique, so always override repopref for
+ # now.
+ if (!(name %in% rownames(available))) {
+ bundle <- r.bundle.of(name)
+ if (is.na(bundle)) {
+ stop(paste('package',name,'is not available'))
+ }
+ name <- bundle
+ }
+ repopref <- repourl.as.debian(available[name,'Repository'])
+ debname = paste('r',tolower(repopref),tolower(name),sep='-')
+ }
+ if (!is.null(version) && length(version) > 1) {
+ debname = paste(debname,' (',version,')',sep='')
+ }
+ return(debname)
+}
+
--- /dev/null
+generate.changelog <- function(pkg) {
+ # construct a dummy changelog
+ # TODO: ``Writing R extensions'' mentions that a package may also have
+ # {NEWS,ChangeLog} files.
+ cat(paste(paste(pkg$srcname,' (',pkg$debversion,') unstable; urgency=low',sep='')
+ ,'' ,' * Initial release.',''
+ ,paste(' --',maintainer,'',format(Sys.time(),'%a, %d %b %Y %H:%M:%S %z'))
+ ,'',sep='\n'),file=pkg$debfile('changelog.in'))
+}
+
+generate.rules <- function(pkg) {
+ cat(paste('#!/usr/bin/make -f'
+ ,paste('debRreposname :=',pkg$repo)
+ ,'include /usr/share/R/debian/r-cran.mk'
+ ,'',sep='\n')
+ ,file=pkg$debfile('rules'))
+ Sys.chmod(pkg$debfile('rules'),'0700')
+}
+
+generate.copyright <- function(pkg) {
+ # generate copyright file; we trust DESCRIPTION
+ writeLines(strwrap(
+ paste('This Debian package of the GNU R package',pkg$name
+ ,'was generated automatically using cran2deb by'
+ ,paste(maintainer,'.',sep='')
+ ,''
+ ,'The original GNU R package is Copyright (C) '
+ # TODO: copyright start date, true copyright date
+ ,format(Sys.time(),'%Y')
+ ,pkg$description[1,'Author']
+ ,'and possibly others.'
+ ,''
+ ,'The original GNU R package is maintained by'
+ ,pkg$description[1,'Maintainer'],'and was obtained from:'
+ ,''
+ ,pkg$repoURL
+ ,''
+ ,''
+ ,'The GNU R package DESCRIPTION offers a'
+ ,'Copyright licenses under the terms of the',pkg$license
+ ,'license. On a Debian GNU/Linux system, common'
+ ,'licenses are included in the directory'
+ ,'/usr/share/common-licenses/.'
+ ,''
+ ,'The DESCRIPTION file for the original GNU R package '
+ ,'can be found in '
+ ,file.path('/usr/lib/R/site-library'
+ ,pkg$debname
+ ,'DESCRIPTION'
+ )
+ ,sep='\n'), width=72), con=pkg$debfile('copyright.in'))
+}
+
+prepare.new.debian <- function(pkg,extra_deps) {
+ # generate Debian version and name
+ pkg$repo = repourl.as.debian(pkg$repoURL)
+ pkg$debversion = version.new(pkg$version)
+ if (!length(grep('^[A-Za-z0-9][A-Za-z0-9+.-]+$',pkg$name))) {
+ stop(paste('Cannot convert package name into a Debian name',pkg$name))
+ }
+ pkg$srcname = tolower(pkg$name)
+ pkg$debname = pkgname.as.debian(pkg$name,repo=pkg$repo)
+
+ if (!length(grep('\\.tar\\.gz',pkg$archive))) {
+ stop('archive is not tarball')
+ }
+
+ # re-pack into a Debian-named archive with a Debian-named directory.
+ debpath = file.path(dirname(pkg$archive)
+ ,paste(pkg$srcname,'-'
+ ,pkg$version
+ ,sep=''))
+ file.rename(pkg$path, debpath)
+ pkg$path = debpath
+ debarchive = file.path(dirname(pkg$archive)
+ ,paste(pkg$srcname,'_'
+ ,pkg$version,'.orig.tar.gz'
+ ,sep=''))
+ wd <- getwd()
+ setwd(dirname(pkg$path))
+ # remove them pesky +x files
+ system(paste('find',shQuote(basename(pkg$path))
+ ,'-type f -exec chmod -x {} \\;'))
+ # tar it all back up
+ system(paste('tar -czf',shQuote(debarchive),shQuote(basename(pkg$path))))
+ setwd(wd)
+ file.remove(pkg$archive)
+ pkg$archive = debarchive
+
+ # make the debian/ directory
+ debdir <- file.path(pkg$path,'debian')
+ pkg$debfile <- function(x) { file.path(debdir,x) }
+ unlink(debdir,recursive=T)
+ dir.create(debdir)
+
+ # see if this is an architecture-dependent package.
+ # heuristic: if /src/ exists in pkg$path, then this is an
+ # architecture-dependent package.
+ # CRAN2DEB.pm is a bit fancier about this but ``Writing R extensions''
+ # says: ``The sources and headers for the compiled code are in src, plus
+ # optionally file Makevars or Makefile.'' It seems unlikely that
+ # architecture independent code would end up here.
+ if (pkg$is_bundle) {
+ # if it's a bundle, check each of the packages
+ pkg$archdep = F
+ for (pkgname in r.bundle.contains(pkg$name)) {
+ pkg$archdep = file.exists(file.path(pkg$path,pkgname,'src'))
+ if (pkg$archdep) {
+ break
+ }
+ }
+ } else {
+ pkg$archdep = file.exists(file.path(pkg$path,'src'))
+ }
+ pkg$arch <- 'all'
+ if (pkg$archdep) {
+ pkg$arch <- host.arch()
+ }
+
+ pkg$license <- accept.license(pkg)
+ pkg$depends <- get.dependencies(pkg,extra_deps)
+ generate.changelog(pkg)
+ generate.rules(pkg)
+ generate.copyright(pkg)
+ generate.control(pkg)
+
+ # TODO: debian/watch from pkg$repoURL
+
+ # convert text to utf8 (who knows what the original character set is --
+ # let's hope iconv DTRT).
+ for (file in c('control','changelog','copyright')) {
+ system(paste('iconv -o ',shQuote(pkg$debfile(file))
+ ,' -t utf8 '
+ ,shQuote(pkg$debfile(paste(file,'in',sep='.')))))
+ file.remove(pkg$debfile(paste(file,'in',sep='.')))
+ }
+ return(pkg)
+}
+
+build.debian <- function(pkg) {
+ wd <- getwd()
+ setwd(pkg$path)
+ message(paste('N: building Debian package'
+ ,pkg$debname
+ ,paste('(',pkg$debversion,')',sep='')
+ ,'...'))
+ ret = system(paste('pdebuild --configfile',pbuilder_config))
+ setwd(wd)
+ if (ret != 0) {
+ stop('Failed to build package.')
+ }
+}
+
--- /dev/null
+
+setup <- function() {
+ # set up the working directory
+ tmp <- tempfile('cran2deb')
+ dir.create(tmp)
+ return (tmp)
+}
+
+cleanup <- function(dir) {
+ # remove the working directory
+ unlink(dir,recursive=T)
+ invisible()
+}
+
+prepare.pkg <- function(dir, pkgname) {
+ # download and extract an R package named pkgname
+ # OR the bundle containing pkgname
+
+ # based loosely on library/utils/R/packages2.R::install.packages
+ # should do nothing Debian specific
+
+ # first a little trick; change pkgname if pkgname is contained in a bundle
+ if (!(pkgname %in% rownames(available))) {
+ bundle <- r.bundle.of(pkgname)
+ if (is.na(bundle)) {
+ stop(paste('package',pkgname,'is unavailable'))
+ }
+ pkgname <- bundle
+ }
+ archive <- download.packages(pkgname, dir, available=available, repos='', type="source")[1,2]
+ if (length(grep('\\.\\.',archive)) || normalizePath(archive) != archive) {
+ stop(paste('funny looking path',archive))
+ }
+ wd <- getwd()
+ setwd(dir)
+ if (length(grep('\\.zip$',archive))) {
+ cmd = paste('unzip',shQuote(archive))
+ } else if (length(grep('\\.tar\\.gz$',archive))) {
+ cmd = paste('tar','xzf',shQuote(archive))
+ } else {
+ stop(paste('Type of archive',archive,'is unknown.'))
+ }
+ ret = system(cmd)
+ setwd(wd)
+ if (ret != 0) {
+ stop(paste('Extraction of archive',archive,'failed.'))
+ }
+ pkg <- pairlist()
+ pkg$name = pkgname
+ pkg$archive = archive
+ pkg$path = sub("_\\.(zip|tar\\.gz)", ""
+ ,gsub(.standard_regexps()$valid_package_version, ""
+ ,archive))
+ if (!file.info(pkg$path)[,'isdir']) {
+ stop(paste(pkg$path,'is not a directory and should be.'))
+ }
+ pkg$description = read.dcf(file.path(pkg$path,'DESCRIPTION'))
+ pkg$repoURL = available[pkgname,'Repository']
+ pkg$version = pkg$description[1,'Version']
+ pkg$is_bundle = 'Bundle' %in% names(pkg$description[1,])
+ # note subtly of short circuit operators (no absorption)
+ if ((!pkg$is_bundle && pkg$description[1,'Package'] != pkg$name) ||
+ ( pkg$is_bundle && pkg$description[1,'Bundle'] != pkg$name)) {
+ stop(paste('package name mismatch'))
+ }
+ return(pkg)
+}
+
--- /dev/null
+debian_ok_licenses=c('GPL','LGPL','AGPL','ARTISTIC' #,'UNLIMITED'
+ ,'BSD','MIT','APACHE','X11','MPL')
+
+is_acceptable_license <- function(license) {
+ # determine if license is acceptable
+
+ # compress spaces into a single space
+ license = gsub('[[:blank:]]+',' ',license)
+ # make all characters upper case
+ license = toupper(license)
+ # don't care about versions of licenses
+ license = chomp(sub('\\( ?[<=>!]+ ?[0-9.-]+ ?\\)',''
+ ,sub('-[0-9.-]+','',license)))
+ if (license %in% debian_ok_licenses) {
+ return(T)
+ }
+ # uninteresting urls
+ license = gsub('HTTP://WWW.GNU.ORG/[A-Z/._-]*','',license)
+ license = gsub('HTTP://WWW.X.ORG/[A-Z/._-]*','',license)
+ license = gsub('HTTP://WWW.OPENSOURCE.ORG/[A-Z/._-]*','',license)
+ # remove all punctuation
+ license = gsub('[[:punct:]]+','',license)
+ # remove any extra space introduced
+ license = chomp(gsub('[[:space:]]+',' ',license))
+ # redundant
+ license = gsub('THE','',license)
+ license = gsub('SEE','',license)
+ license = gsub('STANDARD','',license)
+ license = gsub('LICEN[SC]E','',license)
+ license = gsub('(GNU )?(GPL|GENERAL PUBLIC)','GPL',license)
+ license = gsub('(MOZILLA )?(MPL|MOZILLA PUBLIC)','MPL',license)
+ # remove any extra space introduced
+ license = chomp(gsub('[[:space:]]+',' ',license))
+ if (license %in% debian_ok_licenses) {
+ message(paste('W: Accepted wild license as',license,'. FIX THE PACKAGE!'))
+ return(T)
+ }
+ # remove everything that looks like a version specification
+ license = gsub('(VER?SION|V)? *[0-9.-]+ *(OR *(HIGHER|LATER|NEWER|GREATER|ABOVE))?',''
+ ,license)
+ # remove any extra space introduced
+ license = chomp(gsub('[[:space:]]+',' ',license))
+ if (license %in% debian_ok_licenses) {
+ message(paste('W: Accepted wild license as',license,'. FIX THE PACKAGE!'))
+ return(T)
+ }
+ # TODO: put debian_ok_licenses in DB
+ # TODO: file {LICENSE,LICENCE} (+ maybe COPYING?)
+ message(paste('E: Wild license',license,'did not match'))
+ return(F)
+}
+
+accept.license <- function(pkg) {
+ # check the license
+ if (!('License' %in% names(pkg$description[1,]))) {
+ stop('package has no License: field in description!')
+ }
+ accept=NULL
+ for (license in strsplit(chomp(pkg$description[1,'License'])
+ ,'[[:space:]]*\\|[[:space:]]*')[[1]]) {
+ if (is_acceptable_license(license)) {
+ accept=license
+ break
+ }
+ }
+ if (is.null(accept)) {
+ stop(paste('No acceptable license:',pkg$description[1,'License']))
+ } else {
+ message(paste('N: Auto-accepted license',accept))
+ }
+ if (accept == 'Unlimited') {
+ # definition of Unlimited from ``Writing R extensions''
+ accept=paste('Unlimited (no restrictions on distribution or'
+ ,'use other than those imposed by relevant laws)')
+ }
+ return(accept)
+}
--- /dev/null
+
+r.bundle.of <- function(pkgname) {
+ # returns the bundle containing pkgname or NA
+ bundles <- names(available[!is.na(available[, 'Bundle']), 'Contains'])
+ # use the first bundle
+ for (bundle in bundles) {
+ if (pkgname %in% r.bundle.contains(bundle)) {
+ return(bundle)
+ }
+ }
+ return(NA)
+}
+
+r.bundle.contains <- function(bundlename) {
+ return(strsplit(available[bundlename,'Contains'],'[[:space:]]+')[[1]])
+}
+
+r.requiring <- function(names) {
+ for (name in names) {
+ if (!(name %in% base_pkgs) && !(name %in% rownames(available))) {
+ bundle <- r.bundle.of(name)
+ if (is.na(bundle)) {
+ stop(paste('package',name,'is not available'))
+ }
+ names <- c(names,r.bundle.contains(bundle))
+ }
+ }
+ # approximately prune first into a smaller availability
+ candidates <- available[sapply(rownames(available)
+ ,function(name)
+ length(grep(paste(names,sep='|')
+ ,available[name,r_depend_fields])) > 0)
+ ,r_depend_fields
+ ,drop=F]
+ if (length(candidates) == 0) {
+ return(c())
+ }
+ # find a logical index into available of every package/bundle
+ # whose dependency field contains at least one element of names.
+ # (this is not particularly easy to read---sorry---but is much faster than
+ # the alternatives i could think of)
+ prereq=c()
+ dep_matches <- function(dep) chomp(gsub('\\([^\\)]+\\)','',dep)) %in% names
+ any_dep_matches <- function(name,field=NA)
+ any(sapply(strsplit(chomp(candidates[name,field])
+ ,'[[:space:]]*,[[:space:]]*')
+ ,dep_matches))
+
+ for (field in r_depend_fields) {
+ matches = sapply(rownames(candidates), any_dep_matches, field=field)
+ if (length(matches) > 0) {
+ prereq = c(prereq,rownames(candidates[matches,]))
+ }
+ }
+ return(unique(prereq))
+}
+
+r.dependencies.of <- function(name=NULL,description=NULL) {
+ # find the immediate dependencies (children in the dependency graph) of an
+ # R package
+ if (!is.null(name) && (name == 'R' || name %in% base_pkgs)) {
+ return(data.frame())
+ }
+ if (is.null(description) && is.null(name)) {
+ stop('must specify either a description or a name.')
+ }
+ if (is.null(description)) {
+ if (!(name %in% rownames(available))) {
+ bundle <- r.bundle.of(name)
+ if (is.na(bundle)) {
+ stop(paste('package',name,'is not available'))
+ }
+ name <- bundle
+ }
+ description <- data.frame()
+ # keep only the interesting fields
+ for (field in r_depend_fields) {
+ if (!(field %in% names(available[name,]))) {
+ next
+ }
+ description[1,field] = available[name,field]
+ }
+ }
+ # extract the dependencies from the description
+ deps <- data.frame()
+ for (field in r_depend_fields) {
+ if (!(field %in% names(description[1,]))) {
+ next
+ }
+ new_deps <- lapply(strsplit(chomp(description[1,field])
+ ,'[[:space:]]*,[[:space:]]*')[[1]]
+ ,r.parse.dep.field)
+ deps <- iterate(lapply(new_deps[!is.na(new_deps)],rbind),deps,rbind)
+ }
+ return (deps)
+}
+
+r.parse.dep.field <- function(dep) {
+ if (is.na(dep)) {
+ return(NA)
+ }
+ # remove other comments
+ dep = gsub('(\\(\\)|\\([[:space:]]*[^<=>!].*\\))','',dep)
+ # squish spaces
+ dep = chomp(gsub('[[:space:]]+',' ',dep))
+ # parse version
+ pat = '^([^ ()]+) ?(\\( ?([<=>!]+ ?[0-9.-]+) ?\\))?$'
+ if (!length(grep(pat,dep))) {
+ stop(paste('R dependency',dep,'does not appear to be well-formed'))
+ }
+ version = sub(pat,'\\3',dep)
+ dep = sub(pat,'\\1',dep)
+ if (!(dep %in% rownames(available))) {
+ depb <- r.bundle.of(dep)
+ if (!is.na(depb)) {
+ dep <- depb
+ }
+ }
+ return(list(name=dep,version=version))
+}
+
+r.dependency.closure <- function(fringe, forward_arcs=T) {
+ # find the transitive closure of the dependencies/prerequisites of some R
+ # packages
+ closure <- list()
+ if (is.data.frame(fringe)) {
+ fringe <- levels(fringe$name)
+ }
+ fun = function(x) levels(r.dependencies.of(name=x)$name)
+ if (!forward_arcs) {
+ fun = r.requiring
+ }
+ while(length(fringe) > 0) {
+ # pop off the top
+ top <- fringe[[1]]
+ if (length(fringe) > 1) {
+ fringe <- fringe[2:length(fringe)]
+ } else {
+ fringe <- list()
+ }
+ src <- pkgname.as.debian(top,binary=F)
+ if (!length(grep('^r-',src)) || length(grep('^r-base',src))) {
+ next
+ }
+ newdeps <- fun(top)
+ closure=c(closure,top)
+ fringe=c(fringe,newdeps)
+ }
+ # build order
+ return(rev(unique(closure,fromLast=T)))
+}
+
--- /dev/null
+iterate <- function(xs,z,fun) {
+ y <- z
+ for (x in xs)
+ y <- fun(y,x)
+ return(y)
+}
+
+chomp <- function(x) {
+ # remove leading and trailing spaces
+ return(sub('^[[:space:]]+','',sub('[[:space:]]+$','',x)))
+}
+
+host.arch <- function() {
+ # return the host system architecture
+ system('dpkg-architecture -qDEB_HOST_ARCH',intern=T)
+}
+
--- /dev/null
+version.new <- function(rver,debian_revision=1, debian_epoch=0) {
+ # generate a string representation of the Debian version of an
+ # R version of a package
+ pkgver = rver
+
+ # ``Writing R extensions'' says that the version consists of at least two
+ # non-negative integers, separated by . or -
+ if (!length(grep('^([0-9]+[.-])+[0-9]+$',rver))) {
+ stop(paste('Not a valid R package version',rver))
+ }
+
+ # Debian policy says that an upstream version should start with a digit and
+ # may only contain ASCII alphanumerics and '.+-:~'
+ if (!length(grep('^[0-9][A-Za-z0-9.+:~-]*$',rver))) {
+ stop(paste('R package version',rver
+ ,'does not obviously translate into a valid Debian version.'))
+ }
+
+ # if rver contains a : then the Debian version must also have a colon
+ if (debian_epoch == 0 && length(grep(':',pkgver)))
+ debian_epoch = 1
+
+ # if the epoch is non-zero then include it
+ if (debian_epoch != 0)
+ pkgver = paste(debian_epoch,':',pkgver,sep='')
+
+ # always add the '-1' Debian release; nothing is lost and rarely will R
+ # packages be Debian packages without modification.
+ return(paste(pkgver,'-',debian_revision,sep=''))
+}
+
+version.epoch <- function(pkgver) {
+ # return the Debian epoch of a Debian package version
+ if (!length(grep(':',pkgver)))
+ return(0)
+ return(as.integer(sub('^([0-9]+):.*','\\1',pkgver)))
+}
+# version.epoch . version.new(x,y) = id
+# version.epoch(version.new(x,y)) = 0
+
+version.revision <- function(pkgver) {
+ # return the Debian revision of a Debian package version
+ return(as.integer(sub('.*-([0-9]+)$','\\1',pkgver)))
+}
+# version.revision . version.new(x) = id
+# version.revision(version.new(x)) = 1
+
+version.upstream <- function(pkgver) {
+ # return the upstream version of a Debian package version
+ return(sub('-[0-9]+$','',sub('^[0-9]+:','',pkgver)))
+}
+# version.upstream . version.new = id
+
+version.update <- function(rver, prev_pkgver) {
+ # return the next debian package version
+ prev_rver <- version.upstream(prev_pkgver)
+ if (prev_rver == rver) {
+ # increment the Debian revision
+ return(version.new(rver
+ ,debian_revision = version.revision(prev_pkgver)+1
+ ,debian_epoch = version.epoch(prev_pkgver)
+ ))
+ }
+ # new release
+ # TODO: implement Debian ordering over version and then autoincrement
+ # Debian epoch when upstream version does not increment.
+ return(version.new(rver
+ ,debian_epoch = version.epoch(prev_pkgver)
+ ))
+}
--- /dev/null
+
+changesfile <- function(srcname,version='*') {
+ return(file.path(pbuilder_results
+ ,paste(srcname,'_',version,'_'
+ ,host.arch(),'.changes',sep='')))
+}
+
+maintainer <- 'cran2deb buildbot <cran2deb@example.org>'
+root <- system.file('')
+pbuilder_results <- file.path(root,'var/results')
+pbuilder_config <- file.path(root,'etc/pbuilderrc')
+dput_config <- file.path(root,'etc/dput.cf')
+dinstall_config <- file.path(root,'etc/mini-dinstall.conf')
+dinstall_archive <- file.path(root,'var/archive')
+r_depend_fields <- c('Depends','Imports') # Suggests, Enhances
+
+# we cache the list of available packages
+# should be pulled in already
+#load(file.path(root,'var/cache/available.cache.Rd'))
+
+++ /dev/null
-#!/usr/bin/env rc
-
-for (ctv in `{./cranpkgs query}) {
- echo task view $ctv...
- if (![ -e ctv/$ctv ]) {
- ./build_some $ctv
- mkdir -p ctv/$ctv
- mv warn fail ctv/$ctv
- }
-}
-
+++ /dev/null
-#!/usr/bin/rc
-
-mkdir -p warn fail
-./cranpkgs $* >all_pkgs
-for (pkg in `{cat all_pkgs}) {
- if (~ $pkg *..* */*) {
- echo bad name $pkg >>fail/ERROR
- } else {
- echo .. package $pkg
- fail=0
- ./cran2deb $pkg >fail/$pkg >[2=1] || fail=1
- if (~ $fail 0) {
- grep '^[WE]:' fail/$pkg >warn/$pkg
- if (~ `{stat -c '%s' warn/$pkg} 0) {
- rm -f warn/$pkg
- }
- rm -f fail/$pkg
- }
- }
-}
+++ /dev/null
-#!/usr/bin/rc
-kwords='copyright|warranty|redistribution|modification|patent|trademark|licen[cs]e|permission'
-nl=`` () {printf '\n'}
-ifs=$nl {
- files=`{find $1 ! -path '*debian*' -type f}
- lines=()
- for (file in $files) {
- notices=`{grep -H '(C)' $file}
- notices=($notices `{grep -HEi $kwords $file})
- lines=($lines `{{for (notice in $notices) echo $notice} | sort -u})
- }
- # let's hope no file has a : in it
- ifs=() { seen_files=`{{for (line in $lines) echo $line} | cut -d: -f1} }
- missing_copyright=()
- for (file in $files) {
- if (echo -n $seen_files | grep -q '^'^$file^'$') {
- } else {
- missing_copyright=($missing_copyright $file)
- }
- }
- echo 'Suspect copyright notices:'
- for (line in $lines) echo ' '$line
- echo 'Files without *suspect* copyright notices:'
- for (missing in $missing_copyright) {
- echo ' '$missing
- echo ' type: '`{file $missing}
- echo ' chars: '`{wc -c $missing | awk '{print $1}'}
- echo ' lines: '`{wc -l $missing | awk '{print $1}'}
- }
-}
+++ /dev/null
-#!/usr/bin/env r
-
-maintainer <- 'cran2deb buildbot <cran2deb@example.org>'
-root <- '/home/cb/work/gsoc/cran2deb'
-pbuilder_results <- file.path(root,'var/results')
-pbuilder_config <- file.path(root,'etc/pbuilderrc')
-dput_config <- file.path(root,'etc/dput.cf')
-dinstall_config <- file.path(root,'etc/mini-dinstall.conf')
-dinstall_archive <- file.path(root,'var/archive')
-r_depend_fields <- c('Depends','Imports') # Suggests, Enhances
-
-# we cache the list of available packages
-load(file.path(root,'var/cache/available.cache.Rd'))
-
-version.new <- function(rver,debian_revision=1, debian_epoch=0) {
- # generate a string representation of the Debian version of an
- # R version of a package
- pkgver = rver
-
- # ``Writing R extensions'' says that the version consists of at least two
- # non-negative integers, separated by . or -
- if (!length(grep('^([0-9]+[.-])+[0-9]+$',rver))) {
- stop(paste('Not a valid R package version',rver))
- }
-
- # Debian policy says that an upstream version should start with a digit and
- # may only contain ASCII alphanumerics and '.+-:~'
- if (!length(grep('^[0-9][A-Za-z0-9.+:~-]*$',rver))) {
- stop(paste('R package version',rver
- ,'does not obviously translate into a valid Debian version.'))
- }
-
- # if rver contains a : then the Debian version must also have a colon
- if (debian_epoch == 0 && length(grep(':',pkgver)))
- debian_epoch = 1
-
- # if the epoch is non-zero then include it
- if (debian_epoch != 0)
- pkgver = paste(debian_epoch,':',pkgver,sep='')
-
- # always add the '-1' Debian release; nothing is lost and rarely will R
- # packages be Debian packages without modification.
- return(paste(pkgver,'-',debian_revision,sep=''))
-}
-
-version.epoch <- function(pkgver) {
- # return the Debian epoch of a Debian package version
- if (!length(grep(':',pkgver)))
- return(0)
- return(as.integer(sub('^([0-9]+):.*','\\1',pkgver)))
-}
-# version.epoch . version.new(x,y) = id
-# version.epoch(version.new(x,y)) = 0
-
-version.revision <- function(pkgver) {
- # return the Debian revision of a Debian package version
- return(as.integer(sub('.*-([0-9]+)$','\\1',pkgver)))
-}
-# version.revision . version.new(x) = id
-# version.revision(version.new(x)) = 1
-
-version.upstream <- function(pkgver) {
- # return the upstream version of a Debian package version
- return(sub('-[0-9]+$','',sub('^[0-9]+:','',pkgver)))
-}
-# version.upstream . version.new = id
-
-version.update <- function(rver, prev_pkgver) {
- # return the next debian package version
- prev_rver <- version.upstream(prev_pkgver)
- if (prev_rver == rver) {
- # increment the Debian revision
- return(version.new(rver
- ,debian_revision = version.revision(prev_pkgver)+1
- ,debian_epoch = version.epoch(prev_pkgver)
- ))
- }
- # new release
- # TODO: implement Debian ordering over version and then autoincrement
- # Debian epoch when upstream version does not increment.
- return(version.new(rver
- ,debian_epoch = version.epoch(prev_pkgver)
- ))
-}
-
-# sudo pbuilder --execute r -e 'rownames(installed.packages())'
-# XXX: has to be a better way of doing this
-base_pkgs=c('base', 'datasets','grDevices','graphics','grid', 'methods'
- ,'splines','stats', 'stats4', 'tcltk', 'tools','utils')
-# found in R source directory:
-# 'profile', 'datasets'
-
-repourl.as.debian <- function(url) {
- # map the url to a repository onto its name in debian package naming
- if (length(grep('cran',url))) {
- return('cran')
- }
- if (length(grep('bioc',url))) {
- return('bioc')
- }
- stop(paste('unknown repository',url))
-}
-
-pkgname.as.debian <- function(name,repopref=NULL,version=NULL,binary=T) {
- # generate the debian package name corresponding to the R package name
- if (name %in% base_pkgs) {
- name = 'R'
- }
- if (name == 'R') {
- # R is special.
- if (binary) {
- debname='r-base-core'
- } else {
- debname='r-base-dev'
- }
- } else {
- # XXX: data.frame rownames are unique, so always override repopref for
- # now.
- if (!(name %in% rownames(available))) {
- bundle <- r.bundle.of(name)
- if (is.na(bundle)) {
- stop(paste('package',name,'is not available'))
- }
- name <- bundle
- }
- repopref <- repourl.as.debian(available[name,'Repository'])
- debname = paste('r',tolower(repopref),tolower(name),sep='-')
- }
- if (!is.null(version) && length(version) > 1) {
- debname = paste(debname,' (',version,')',sep='')
- }
- return(debname)
-}
-
-setup <- function() {
- # set up the working directory
- tmp <- tempfile('cran2deb')
- dir.create(tmp)
- return (tmp)
-}
-
-cleanup <- function(dir) {
- # remove the working directory
- unlink(dir,recursive=T)
- invisible()
-}
-
-r.bundle.of <- function(pkgname) {
- # returns the bundle containing pkgname or NA
- bundles <- names(available[!is.na(available[, 'Bundle']), 'Contains'])
- # use the first bundle
- for (bundle in bundles) {
- if (pkgname %in% r.bundle.contains(bundle)) {
- return(bundle)
- }
- }
- return(NA)
-}
-
-r.bundle.contains <- function(bundlename) {
- return(strsplit(available[bundlename,'Contains'],'[[:space:]]+')[[1]])
-}
-
-prepare.pkg <- function(dir, pkgname) {
- # download and extract an R package named pkgname
- # OR the bundle containing pkgname
-
- # based loosely on library/utils/R/packages2.R::install.packages
- # should do nothing Debian specific
-
- # first a little trick; change pkgname if pkgname is contained in a bundle
- if (!(pkgname %in% rownames(available))) {
- bundle <- r.bundle.of(pkgname)
- if (is.na(bundle)) {
- stop(paste('package',pkgname,'is unavailable'))
- }
- pkgname <- bundle
- }
- archive <- download.packages(pkgname, dir, available=available, repos='', type="source")[1,2]
- if (length(grep('\\.\\.',archive)) || normalizePath(archive) != archive) {
- stop(paste('funny looking path',archive))
- }
- wd <- getwd()
- setwd(dir)
- if (length(grep('\\.zip$',archive))) {
- cmd = paste('unzip',shQuote(archive))
- } else if (length(grep('\\.tar\\.gz$',archive))) {
- cmd = paste('tar','xzf',shQuote(archive))
- } else {
- stop(paste('Type of archive',archive,'is unknown.'))
- }
- ret = system(cmd)
- setwd(wd)
- if (ret != 0) {
- stop(paste('Extraction of archive',archive,'failed.'))
- }
- pkg <- pairlist()
- pkg$name = pkgname
- pkg$archive = archive
- pkg$path = sub("_\\.(zip|tar\\.gz)", ""
- ,gsub(.standard_regexps()$valid_package_version, ""
- ,archive))
- if (!file.info(pkg$path)[,'isdir']) {
- stop(paste(pkg$path,'is not a directory and should be.'))
- }
- pkg$description = read.dcf(file.path(pkg$path,'DESCRIPTION'))
- pkg$repoURL = available[pkgname,'Repository']
- pkg$version = pkg$description[1,'Version']
- pkg$is_bundle = 'Bundle' %in% names(pkg$description[1,])
- # note subtly of short circuit operators (no absorption)
- if ((!pkg$is_bundle && pkg$description[1,'Package'] != pkg$name) ||
- ( pkg$is_bundle && pkg$description[1,'Bundle'] != pkg$name)) {
- stop(paste('package name mismatch'))
- }
- return(pkg)
-}
-
-debian_ok_licenses=c('GPL','LGPL','AGPL','ARTISTIC' #,'UNLIMITED'
- ,'BSD','MIT','APACHE','X11','MPL')
-
-is_acceptable_license <- function(license) {
- # determine if license is acceptable
-
- # compress spaces into a single space
- license = gsub('[[:blank:]]+',' ',license)
- # make all characters upper case
- license = toupper(license)
- # don't care about versions of licenses
- license = chomp(sub('\\( ?[<=>!]+ ?[0-9.-]+ ?\\)',''
- ,sub('-[0-9.-]+','',license)))
- if (license %in% debian_ok_licenses) {
- return(T)
- }
- # uninteresting urls
- license = gsub('HTTP://WWW.GNU.ORG/[A-Z/._-]*','',license)
- license = gsub('HTTP://WWW.X.ORG/[A-Z/._-]*','',license)
- license = gsub('HTTP://WWW.OPENSOURCE.ORG/[A-Z/._-]*','',license)
- # remove all punctuation
- license = gsub('[[:punct:]]+','',license)
- # remove any extra space introduced
- license = chomp(gsub('[[:space:]]+',' ',license))
- # redundant
- license = gsub('THE','',license)
- license = gsub('SEE','',license)
- license = gsub('STANDARD','',license)
- license = gsub('LICEN[SC]E','',license)
- license = gsub('(GNU )?(GPL|GENERAL PUBLIC)','GPL',license)
- license = gsub('(MOZILLA )?(MPL|MOZILLA PUBLIC)','MPL',license)
- # remove any extra space introduced
- license = chomp(gsub('[[:space:]]+',' ',license))
- if (license %in% debian_ok_licenses) {
- message(paste('W: Accepted wild license as',license,'. FIX THE PACKAGE!'))
- return(T)
- }
- # remove everything that looks like a version specification
- license = gsub('(VER?SION|V)? *[0-9.-]+ *(OR *(HIGHER|LATER|NEWER|GREATER|ABOVE))?',''
- ,license)
- # remove any extra space introduced
- license = chomp(gsub('[[:space:]]+',' ',license))
- if (license %in% debian_ok_licenses) {
- message(paste('W: Accepted wild license as',license,'. FIX THE PACKAGE!'))
- return(T)
- }
- # TODO: put debian_ok_licenses in DB
- # TODO: file {LICENSE,LICENCE} (+ maybe COPYING?)
- message(paste('E: Wild license',license,'did not match'))
- return(F)
-}
-
-iterate <- function(xs,z,fun) {
- y <- z
- for (x in xs)
- y <- fun(y,x)
- return(y)
-}
-
-chomp <- function(x) {
- # remove leading and trailing spaces
- return(sub('^[[:space:]]+','',sub('[[:space:]]+$','',x)))
-}
-
-host.arch <- function() {
- # return the host system architecture
- system('dpkg-architecture -qDEB_HOST_ARCH',intern=T)
-}
-
-r.requiring <- function(names) {
- for (name in names) {
- if (!(name %in% base_pkgs) && !(name %in% rownames(available))) {
- bundle <- r.bundle.of(name)
- if (is.na(bundle)) {
- stop(paste('package',name,'is not available'))
- }
- names <- c(names,r.bundle.contains(bundle))
- }
- }
- # approximately prune first into a smaller availability
- candidates <- available[sapply(rownames(available)
- ,function(name)
- length(grep(paste(names,sep='|')
- ,available[name,r_depend_fields])) > 0)
- ,r_depend_fields
- ,drop=F]
- if (length(candidates) == 0) {
- return(c())
- }
- # find a logical index into available of every package/bundle
- # whose dependency field contains at least one element of names.
- # (this is not particularly easy to read---sorry---but is much faster than
- # the alternatives i could think of)
- prereq=c()
- dep_matches <- function(dep) chomp(gsub('\\([^\\)]+\\)','',dep)) %in% names
- any_dep_matches <- function(name,field=NA)
- any(sapply(strsplit(chomp(candidates[name,field])
- ,'[[:space:]]*,[[:space:]]*')
- ,dep_matches))
-
- for (field in r_depend_fields) {
- matches = sapply(rownames(candidates), any_dep_matches, field=field)
- if (length(matches) > 0) {
- prereq = c(prereq,rownames(candidates[matches,]))
- }
- }
- return(unique(prereq))
-}
-
-r.dependencies.of <- function(name=NULL,description=NULL) {
- # find the immediate dependencies (children in the dependency graph) of an
- # R package
- if (!is.null(name) && (name == 'R' || name %in% base_pkgs)) {
- return(data.frame())
- }
- if (is.null(description) && is.null(name)) {
- stop('must specify either a description or a name.')
- }
- if (is.null(description)) {
- if (!(name %in% rownames(available))) {
- bundle <- r.bundle.of(name)
- if (is.na(bundle)) {
- stop(paste('package',name,'is not available'))
- }
- name <- bundle
- }
- description <- data.frame()
- # keep only the interesting fields
- for (field in r_depend_fields) {
- if (!(field %in% names(available[name,]))) {
- next
- }
- description[1,field] = available[name,field]
- }
- }
- # extract the dependencies from the description
- deps <- data.frame()
- for (field in r_depend_fields) {
- if (!(field %in% names(description[1,]))) {
- next
- }
- new_deps <- lapply(strsplit(chomp(description[1,field])
- ,'[[:space:]]*,[[:space:]]*')[[1]]
- ,r.parse.dep.field)
- deps <- iterate(lapply(new_deps[!is.na(new_deps)],rbind),deps,rbind)
- }
- return (deps)
-}
-
-r.parse.dep.field <- function(dep) {
- if (is.na(dep)) {
- return(NA)
- }
- # remove other comments
- dep = gsub('(\\(\\)|\\([[:space:]]*[^<=>!].*\\))','',dep)
- # squish spaces
- dep = chomp(gsub('[[:space:]]+',' ',dep))
- # parse version
- pat = '^([^ ()]+) ?(\\( ?([<=>!]+ ?[0-9.-]+) ?\\))?$'
- if (!length(grep(pat,dep))) {
- stop(paste('R dependency',dep,'does not appear to be well-formed'))
- }
- version = sub(pat,'\\3',dep)
- dep = sub(pat,'\\1',dep)
- if (!(dep %in% rownames(available))) {
- depb <- r.bundle.of(dep)
- if (!is.na(depb)) {
- dep <- depb
- }
- }
- return(list(name=dep,version=version))
-}
-
-r.dependency.closure <- function(fringe, forward_arcs=T) {
- # find the transitive closure of the dependencies/prerequisites of some R
- # packages
- closure <- list()
- if (is.data.frame(fringe)) {
- fringe <- levels(fringe$name)
- }
- fun = function(x) levels(r.dependencies.of(name=x)$name)
- if (!forward_arcs) {
- fun = r.requiring
- }
- while(length(fringe) > 0) {
- # pop off the top
- top <- fringe[[1]]
- if (length(fringe) > 1) {
- fringe <- fringe[2:length(fringe)]
- } else {
- fringe <- list()
- }
- src <- pkgname.as.debian(top,binary=F)
- if (!length(grep('^r-',src)) || length(grep('^r-base',src))) {
- next
- }
- newdeps <- fun(top)
- closure=c(closure,top)
- fringe=c(fringe,newdeps)
- }
- # build order
- return(rev(unique(closure,fromLast=T)))
-}
-
-accept.license <- function(pkg) {
- # check the license
- if (!('License' %in% names(pkg$description[1,]))) {
- stop('package has no License: field in description!')
- }
- accept=NULL
- for (license in strsplit(chomp(pkg$description[1,'License'])
- ,'[[:space:]]*\\|[[:space:]]*')[[1]]) {
- if (is_acceptable_license(license)) {
- accept=license
- break
- }
- }
- if (is.null(accept)) {
- stop(paste('No acceptable license:',pkg$description[1,'License']))
- } else {
- message(paste('N: Auto-accepted license',accept))
- }
- if (accept == 'Unlimited') {
- # definition of Unlimited from ``Writing R extensions''
- accept=paste('Unlimited (no restrictions on distribution or'
- ,'use other than those imposed by relevant laws)')
- }
- return(accept)
-}
-
-get.dependencies <- function(pkg,extra_deps) {
- if ('SystemRequirements' %in% colnames(pkg$description)) {
- stop(paste('Unsupported SystemRequirements:',pkg$description[1,'SystemRequirements']))
- }
-
- # determine dependencies
- dependencies <- r.dependencies.of(description=pkg$description)
- depends <- list()
- # these are used for generating the Depends fields
- as.deb <- function(r,binary) {
- return(pkgname.as.debian(paste(dependencies[r,]$name)
- ,version=dependencies[r,]$version
- ,repopref=pkg$repo
- ,binary=binary))
- }
- depends$bin <- lapply(rownames(dependencies), as.deb, binary=T)
- depends$build <- lapply(rownames(dependencies), as.deb, binary=F)
- # add the command line dependencies
- depends$bin = c(extra_deps$deb,depends$bin)
- depends$build = c(extra_deps$deb,depends$build)
-
- # make sure we depend upon R in some way...
- if (!length(grep('^r-base',depends$build))) {
- depends$build = c(depends$build,pkgname.as.debian('R',version='>= 2.7.0',binary=F))
- depends$bin = c(depends$bin, pkgname.as.debian('R',version='>= 2.7.0',binary=T))
- }
- # also include stuff to allow tcltk to build (suggested by Dirk)
- depends$build = c(depends$build,'xvfb','xauth','xfont-base')
-
- # remove duplicates
- depends <- lapply(depends,unique)
-
- # append the Debian dependencies
- depends$build=c(depends$build,'debhelper (>> 4.1.0)','cdbs')
- if (pkg$archdep) {
- depends$bin=c(depends$bin,'${shlibs:Depends}')
- }
-
- # the names of dependent source packages (to find the .changes file to
- # upload via dput). these can be found recursively.
- depends$r = lapply(r.dependency.closure(dependencies)
- ,tolower)
- # append command line dependencies
- depends$r = c(extra_deps$r, depends$r)
- return(depends)
-}
-
-generate.changelog <- function(pkg) {
- # construct a dummy changelog
- # TODO: ``Writing R extensions'' mentions that a package may also have
- # {NEWS,ChangeLog} files.
- cat(paste(paste(pkg$srcname,' (',pkg$debversion,') unstable; urgency=low',sep='')
- ,'' ,' * Initial release.',''
- ,paste(' --',maintainer,'',format(Sys.time(),'%a, %d %b %Y %H:%M:%S %z'))
- ,'',sep='\n'),file=pkg$debfile('changelog.in'))
-}
-
-generate.rules <- function(pkg) {
- cat(paste('#!/usr/bin/make -f'
- ,paste('debRreposname :=',pkg$repo)
- ,'include /usr/share/R/debian/r-cran.mk'
- ,'',sep='\n')
- ,file=pkg$debfile('rules'))
- Sys.chmod(pkg$debfile('rules'),'0700')
-}
-
-generate.copyright <- function(pkg) {
- # generate copyright file; we trust DESCRIPTION
- writeLines(strwrap(
- paste('This Debian package of the GNU R package',pkg$name
- ,'was generated automatically using cran2deb by'
- ,paste(maintainer,'.',sep='')
- ,''
- ,'The original GNU R package is Copyright (C) '
- # TODO: copyright start date, true copyright date
- ,format(Sys.time(),'%Y')
- ,pkg$description[1,'Author']
- ,'and possibly others.'
- ,''
- ,'The original GNU R package is maintained by'
- ,pkg$description[1,'Maintainer'],'and was obtained from:'
- ,''
- ,pkg$repoURL
- ,''
- ,''
- ,'The GNU R package DESCRIPTION offers a'
- ,'Copyright licenses under the terms of the',pkg$license
- ,'license. On a Debian GNU/Linux system, common'
- ,'licenses are included in the directory'
- ,'/usr/share/common-licenses/.'
- ,''
- ,'The DESCRIPTION file for the original GNU R package '
- ,'can be found in '
- ,file.path('/usr/lib/R/site-library'
- ,pkg$debname
- ,'DESCRIPTION'
- )
- ,sep='\n'), width=72), con=pkg$debfile('copyright.in'))
-}
-
-generate.control <- function(pkg) {
- # construct control file
- control = data.frame()
- control[1,'Source'] = pkg$srcname
- control[1,'Section'] = 'math'
- control[1,'Priority'] = 'optional'
- control[1,'Maintainer'] = maintainer
- control[1,'Build-Depends'] = paste(pkg$depends$build,collapse=', ')
- control[1,'Standards-Version'] = '3.8.0'
-
- control[2,'Package'] = pkg$debname
- control[2,'Architecture'] = 'all'
- if (pkg$archdep) {
- control[2,'Architecture'] = 'any'
- }
- control[2,'Depends'] = paste(pkg$depends$bin,collapse=', ')
-
- # bundles provide virtual packages of their contents
- if (pkg$is_bundle) {
- control[2,'Provides'] = paste(
- lapply(r.bundle.contains(pkg$name)
- ,function(name) return(pkgname.as.debian(paste(name)
- ,repopref=pkg$repo
- ,binary=T)))
- ,collapse=', ')
- }
-
- # generate the description
- descr = 'GNU R package "'
- if ('Title' %in% colnames(pkg$description)) {
- descr = paste(descr,pkg$description[1,'Title'],sep='')
- } else {
- descr = paste(descr,pkg$name,sep='')
- }
- if (pkg$is_bundle) {
- long_descr <- pkg$description[1,'BundleDescription']
- } else {
- long_descr <- pkg$description[1,'Description']
- }
- # using \n\n.\n\n is not very nice, but is necessary to make sure
- # the longer description does not begin on the synopsis line --- R's
- # write.dcf does not appear to have a nicer way of doing this.
- descr = paste(descr,'"\n\n', long_descr, sep='')
- if ('URL' %in% colnames(pkg$description)) {
- descr = paste(descr,'\n\nURL: ',pkg$description[1,'URL'],sep='')
- }
- control[2,'Description'] = descr
-
- # Debian policy says 72 char width; indent minimally
- write.dcf(control,file=pkg$debfile('control.in'),indent=1,width=72)
- write.dcf(control,indent=1,width=72)
-}
-
-prepare.new.debian <- function(pkg,extra_deps) {
- # generate Debian version and name
- pkg$repo = repourl.as.debian(pkg$repoURL)
- pkg$debversion = version.new(pkg$version)
- if (!length(grep('^[A-Za-z0-9][A-Za-z0-9+.-]+$',pkg$name))) {
- stop(paste('Cannot convert package name into a Debian name',pkg$name))
- }
- pkg$srcname = tolower(pkg$name)
- pkg$debname = pkgname.as.debian(pkg$name,repo=pkg$repo)
-
- if (!length(grep('\\.tar\\.gz',pkg$archive))) {
- stop('archive is not tarball')
- }
-
- # re-pack into a Debian-named archive with a Debian-named directory.
- debpath = file.path(dirname(pkg$archive)
- ,paste(pkg$srcname,'-'
- ,pkg$version
- ,sep=''))
- file.rename(pkg$path, debpath)
- pkg$path = debpath
- debarchive = file.path(dirname(pkg$archive)
- ,paste(pkg$srcname,'_'
- ,pkg$version,'.orig.tar.gz'
- ,sep=''))
- wd <- getwd()
- setwd(dirname(pkg$path))
- # remove them pesky +x files
- system(paste('find',shQuote(basename(pkg$path))
- ,'-type f -exec chmod -x {} \\;'))
- # tar it all back up
- system(paste('tar -czf',shQuote(debarchive),shQuote(basename(pkg$path))))
- setwd(wd)
- file.remove(pkg$archive)
- pkg$archive = debarchive
-
- # make the debian/ directory
- debdir <- file.path(pkg$path,'debian')
- pkg$debfile <- function(x) { file.path(debdir,x) }
- unlink(debdir,recursive=T)
- dir.create(debdir)
-
- # see if this is an architecture-dependent package.
- # heuristic: if /src/ exists in pkg$path, then this is an
- # architecture-dependent package.
- # CRAN2DEB.pm is a bit fancier about this but ``Writing R extensions''
- # says: ``The sources and headers for the compiled code are in src, plus
- # optionally file Makevars or Makefile.'' It seems unlikely that
- # architecture independent code would end up here.
- if (pkg$is_bundle) {
- # if it's a bundle, check each of the packages
- pkg$archdep = F
- for (pkgname in r.bundle.contains(pkg$name)) {
- pkg$archdep = file.exists(file.path(pkg$path,pkgname,'src'))
- if (pkg$archdep) {
- break
- }
- }
- } else {
- pkg$archdep = file.exists(file.path(pkg$path,'src'))
- }
- pkg$arch <- 'all'
- if (pkg$archdep) {
- pkg$arch <- host.arch()
- }
-
- pkg$license <- accept.license(pkg)
- pkg$depends <- get.dependencies(pkg,extra_deps)
- generate.changelog(pkg)
- generate.rules(pkg)
- generate.copyright(pkg)
- generate.control(pkg)
-
- # TODO: debian/watch from pkg$repoURL
-
- # convert text to utf8 (who knows what the original character set is --
- # let's hope iconv DTRT).
- for (file in c('control','changelog','copyright')) {
- system(paste('iconv -o ',shQuote(pkg$debfile(file))
- ,' -t utf8 '
- ,shQuote(pkg$debfile(paste(file,'in',sep='.')))))
- file.remove(pkg$debfile(paste(file,'in',sep='.')))
- }
- return(pkg)
-}
-
-build.debian <- function(pkg) {
- wd <- getwd()
- setwd(pkg$path)
- message(paste('N: building Debian package'
- ,pkg$debname
- ,paste('(',pkg$debversion,')',sep='')
- ,'...'))
- ret = system(paste('pdebuild --configfile',pbuilder_config))
- setwd(wd)
- if (ret != 0) {
- stop('Failed to build package.')
- }
-}
-
-changesfile <- function(srcname,version='*') {
- return(file.path(pbuilder_results
- ,paste(srcname,'_',version,'_'
- ,host.arch(),'.changes',sep='')))
-}
-
-go <- function(name,extra_deps) {
- dir <- setup()
- pkg <- try((function() {
- pkg <- prepare.new.debian(prepare.pkg(dir,name),extra_deps)
- if (file.exists(changesfile(pkg$srcname,pkg$debversion))) {
- message(paste('N: already built',pkg$srcname,'version',pkg$debversion))
- return(pkg)
- }
-
- # delete the current archive (XXX: assumes mini-dinstall)
- for (subdir in c('mini-dinstall','unstable')) {
- path = file.path(dinstall_archive,subdir)
- if (file.exists(path)) {
- unlink(path,recursive=T)
- }
- }
-
- # delete notes of upload
- file.remove(Sys.glob(file.path(pbuilder_results,'*.upload')))
-
- # make mini-dinstall generate the skeleton of the archive
- ret = system(paste('umask 022;mini-dinstall --batch -c',dinstall_config))
- if (ret != 0) {
- stop('failed to create archive')
- }
-
- # pull in all the R dependencies
- message(paste('N: dependencies:',paste(pkg$depends$r,collapse=', ')))
- for (dep in pkg$depends$r) {
- message(paste('N: uploading',dep))
- ret = system(paste('umask 022;dput','-c',shQuote(dput_config),'local'
- ,changesfile(dep)))
- if (ret != 0) {
- stop('upload of dependency failed! maybe you did not build it first?')
- }
- }
- build.debian(pkg)
-
- # upload the package
- ret = system(paste('umask 022;dput','-c',shQuote(dput_config),'local'
- ,changesfile(pkg$srcname,pkg$debversion)))
- if (ret != 0) {
- stop('upload failed!')
- }
-
- return(pkg)
- })())
- cleanup(dir)
- if (inherits(pkg,'try-error')) {
- stop(call.=F)
- }
- return(pkg)
-}
-
-if (exists('argv')) { # check for littler
- argc <- length(argv)
- extra_deps = list()
- extra_deps$deb = c()
- extra_deps$r = c()
- opts = c('-D','-R')
- for (i in 1:argc) {
- if (!(argv[i] %in% opts)) {
- if (argc >= i) {
- argv <- argv[i:argc]
- } else {
- argv <- list()
- }
- argc = argc - i + 1
- break
- }
- if (i == argc) {
- message('E: missing argument')
- q(save='no')
- }
- if (argv[i] == '-D') {
- extra_deps$deb = c(extra_deps$deb,strsplit(chomp(argv[i+1]),',')[[1]])
- }
- if (argv[i] == '-R') {
- extra_deps$r = c(extra_deps$r,strsplit(chomp(argv[i+1]),',')[[1]])
- extra_deps$deb = c(extra_deps$deb,lapply(extra_deps$r,pkgname.as.debian))
- }
- }
- if (argc == 0) {
- message('E: usage: cran2deb [-D extra_dep1,extra_dep2,...] package package ...')
- q(save='no')
- }
- build_order <- r.dependency.closure(c(extra_deps$r,argv))
- message(paste('N: build order',paste(build_order,collapse=', ')))
- for (pkg in build_order) {
- go(pkg,extra_deps)
- }
-}
+++ /dev/null
-#!/usr/bin/env r
-
-root <- '/home/cb/work/gsoc/cran2deb'
-# we cache the list of available packages
-load(file.path(root,'var/cache/available.cache.Rd'))
-
-if (length(argv) == 0) {
- writeLines(sample(dimnames(available)[[1]],800))
- #writeLines(dimnames(available)[[1]])
-} else {
- if (argv[1] == 'query') {
- for (ctv in ctv.available) {
- writeLines(ctv$name)
- }
- q(save='no')
- }
- # list of task lists
- for (ctv in ctv.available) {
- if (ctv$name %in% argv) {
- writeLines(ctv$packagelist$name)
- }
- }
-}
+++ /dev/null
-#!/usr/bin/rc
-
-#success=`{ls var/results/*.deb | wc -l}
-#echo $success successful packages
-#total=$success
-total=0
-
-fn count_dup { sort | uniq -c | sort -n}# | awk '$1 > 1{print}' }
-fn collapse { a=`{echo $^* | sed -e 's/ | /|/g'}; echo $^a }
-echo 'warnings:'
-{for (x in (warn/* /dev/null)) cut -d: -f3- <$x | sort -u} | awk '{print $1}' | count_dup
-echo
-
-faildep=('^Error: package ''.*'' could not be loaded'
- '|' '^ERROR: lazy loading failed for package ''.*'''
- '|' '^[[:space:]]*package .* is not available'
- '|' 'there is no package called ''.*''')
-faildeb='Unsupported SystemRequirements:'
-faillic=('No acceptable license: ')
-failspc=': No space left on device'
-failhdr='error: .*\.hp?p?: No such file or directory'
-faildep=`{collapse $faildep}
-faildep=$^faildep
-faillic=`{collapse $faillic}
-faillic=$^faillic
-other=''
-
-nfaildep=`{grep -El $faildep fail/* /dev/null | wc -l}
-echo $nfaildep failed R dependencies.
-grep -Eh $faildep fail/* | count_dup
-other=$faildep
-#total=$total+$nfaildep
-echo
-
-nfaillic=`{grep -El $faillic `{grep -EL $other fail/*} /dev/null | wc -l}
-echo $nfaillic failed licenses.
-grep -Eh $faillic `{grep -EL $other fail/*} | count_dup
-other=$other^'|'^$faillic
-total=$total+$nfaillic
-echo
-
-nfailspc=`{grep -El $failspc `{grep -EL $other fail/*} /dev/null | wc -l}
-echo $nfailspc out of space
-other=$other^'|'^$failspc
-total=$total+$nfailspc
-echo
-
-nfailhdr=`{grep -El $failhdr `{grep -EL $other fail/*} /dev/null | wc -l}
-echo $nfailhdr missing C header
-grep -Eh $failhdr `{grep -EL $other fail/* /dev/null} | count_dup
-other=$other^'|'^$failhdr
-total=$total+$nfailhdr
-echo
-
-nfaildeb=`{grep -El $faildeb `{grep -EL $other fail/*} /dev/null | wc -l}
-echo $nfaildeb system requirement failures.
-grep -Eh $faildeb `{grep -EL $other fail/* /dev/null} | count_dup
-other=$other^'|'^$faildeb
-total=$total+$nfaildeb
-echo
-
-nfailother=`{hoc -e `{grep -EL $other fail/* /dev/null | wc -l}^-1}
-echo $nfailother other failures.
-
-#total=`{hoc -e $total}
-#succrate=`{hoc -e $success/'('$total')*100'}
-#echo $succrate% success rate '('$total' total)'
-#total=`{hoc -e $total-$nfaillic-$nfailspc-$nfailhdr}
-#succrate=`{hoc -e $success/'('$total')*100'}
-#echo $succrate% success rate without licensing, space and Debian deps issues '('$total' total)'
-grep -EL $other fail/* /dev/null | xargs tail -n 20
-
+++ /dev/null
-#!/usr/bin/env rc
-{for (x in ctv/*) {echo;echo;echo $x: ; cd $x && ../../diagnose && cd ../..}} >ctv.results
+++ /dev/null
-[local]
-method = local
-incoming = @ROOT@/var/archive/mini-dinstall/incoming
-allow_non-us_software = 1
-run_dinstall = 0
-run_lintian = 1
-post_upload_command = /usr/bin/mini-dinstall --batch -c @ROOT@/etc/mini-dinstall.conf
-allow_unsigned_uploads = 1
+++ /dev/null
-#!/bin/bash
-# example file to be used with --hookdir
-#
-# run lintian on generated deb files
-apt-get install -y --force-yes lintian
-lintian /tmp/buildd/*.deb
+++ /dev/null
-#!/bin/bash
-# example file to be used with --hookdir
-#
-# try to install the resulting debs.
-
-echo "Trying to install resulting packages and test upgrades"
-set -ex
-
-
-PKGNAMES=$(cd /tmp/buildd && ls -1 *.deb | sed 's/_.*$//' )
-
-# install-remove check
-dpkg -i /tmp/buildd/*.deb
-dpkg --remove $PKGNAMES
-
-# install-purge check
-dpkg -i /tmp/buildd/*.deb
-dpkg --purge $PKGNAMES
-
-# upgrade-remove check
-apt-get install -y --force-yes $PKGNAMES || true
-dpkg -i /tmp/buildd/*.deb
-dpkg --remove $PKGNAMES
-
-# upgrade-purge check
-apt-get install -y --force-yes $PKGNAMES || true
-dpkg -i /tmp/buildd/*.deb
-dpkg --purge $PKGNAMES
+++ /dev/null
-#!/bin/bash
-# example file to be used with --hookdir
-#
-# run tests. Current directory is top of source-code.
-#
-# 2005, 2007 Junichi Uekawa
-#
-set -e
-
-echo "Installing the prerequisites"
-for PKG in $(ls /tmp/buildd/*.deb | sed -e's,.*/,,;s,_.*,,' ); do
- apt-get install -y --force-yes "$PKG" || true
- apt-get remove -y "$PKG" || true
-done
-# ignore the failures since they are not the prime interest
-
-dpkg -i /tmp/buildd/*.deb
-
-if chmod a+x /tmp/buildd/*/debian/pbuilder-test/*; then
- :
-else
- echo "W: no pbuilder-test script found, skipping"
- exit 0
-fi
-
-SUCCESS=0
-COUNT=0
-unset FAIL || true
-NOFAIL=1
-
-# The current directory is the top of the source-tree.
-cd /tmp/buildd/*/debian/..
-
-for SCRIPT in $(run-parts --test /tmp/buildd/*/debian/pbuilder-test) ; do
- echo "--- BEGIN test: ${SCRIPT##*/}"
- if "${SCRIPT}"; then
- echo SUCCESS
- ((SUCCESS=SUCCESS+1))
- else
- echo FAIL
- FAIL[${#FAIL[@]}]="${SCRIPT##*/}"
- NOFAIL=0
- fi
- echo "--- END test: ${SCRIPT##*/}"
- ((COUNT=COUNT+1))
-done
-
-echo "Summary:"
-echo "=== $SUCCESS out of $COUNT tests passed"
-echo "${FAIL[@]/#/ failed }"
-echo "-- end of testsuite."
-
+++ /dev/null
-/usr/bin/apt-get update
+++ /dev/null
-[DEFAULT]
-architectures = all, i386
-use_dnotify = 0
-verify_sigs = 0
-mail_on_success = 0
-archive_style = simple-subdir
-mail_log_level = NONE
-archivedir = @ROOT@/var/archive
-logfile = @ROOT@/var/mini-dinstall.log
-
-[unstable]
-
+++ /dev/null
-HOOKDIR=@ROOT@/etc/hook
-BUILDRESULT=@ROOT@/var/results
-EXTRAPACKAGES='debhelper r-base-dev cdbs r-base-core lintian xauth xfont-base xvfb'
-DISTRIBUTION=lenny
-OTHERMIRROR='deb http://localhost/users/cb/cran2deb/ unstable/$(ARCH)/ | deb http://localhost/users/cb/cran2deb/ unstable/all/'
-MIRRORSITE='http://ftp.debian.org/debian/'
-APTCACHE=''
-PBUILDERSATISFYDEPENDSCMD='/usr/lib/pbuilder/pbuilder-satisfydepends-classic'
--- /dev/null
+#!/usr/bin/env rc
+
+for (ctv in `{./cranpkgs query}) {
+ echo task view $ctv...
+ if (![ -e ctv/$ctv ]) {
+ ./build_some $ctv
+ mkdir -p ctv/$ctv
+ mv warn fail ctv/$ctv
+ }
+}
+
--- /dev/null
+#!/usr/bin/rc
+
+mkdir -p warn fail
+./cranpkgs $* >all_pkgs
+for (pkg in `{cat all_pkgs}) {
+ if (~ $pkg *..* */*) {
+ echo bad name $pkg >>fail/ERROR
+ } else {
+ echo .. package $pkg
+ fail=0
+ ./cran2deb $pkg >fail/$pkg >[2=1] || fail=1
+ if (~ $fail 0) {
+ grep '^[WE]:' fail/$pkg >warn/$pkg
+ if (~ `{stat -c '%s' warn/$pkg} 0) {
+ rm -f warn/$pkg
+ }
+ rm -f fail/$pkg
+ }
+ }
+}
--- /dev/null
+#!/usr/bin/rc
+kwords='copyright|warranty|redistribution|modification|patent|trademark|licen[cs]e|permission'
+nl=`` () {printf '\n'}
+ifs=$nl {
+ files=`{find $1 ! -path '*debian*' -type f}
+ lines=()
+ for (file in $files) {
+ notices=`{grep -H '(C)' $file}
+ notices=($notices `{grep -HEi $kwords $file})
+ lines=($lines `{{for (notice in $notices) echo $notice} | sort -u})
+ }
+ # let's hope no file has a : in it
+ ifs=() { seen_files=`{{for (line in $lines) echo $line} | cut -d: -f1} }
+ missing_copyright=()
+ for (file in $files) {
+ if (echo -n $seen_files | grep -q '^'^$file^'$') {
+ } else {
+ missing_copyright=($missing_copyright $file)
+ }
+ }
+ echo 'Suspect copyright notices:'
+ for (line in $lines) echo ' '$line
+ echo 'Files without *suspect* copyright notices:'
+ for (missing in $missing_copyright) {
+ echo ' '$missing
+ echo ' type: '`{file $missing}
+ echo ' chars: '`{wc -c $missing | awk '{print $1}'}
+ echo ' lines: '`{wc -l $missing | awk '{print $1}'}
+ }
+}
--- /dev/null
+#!/usr/bin/env r
+library(cran2deb)
+go <- function(name,extra_deps) {
+ dir <- setup()
+ pkg <- try((function() {
+ pkg <- prepare.new.debian(prepare.pkg(dir,name),extra_deps)
+ if (file.exists(changesfile(pkg$srcname,pkg$debversion))) {
+ message(paste('N: already built',pkg$srcname,'version',pkg$debversion))
+ return(pkg)
+ }
+
+ # delete the current archive (XXX: assumes mini-dinstall)
+ for (subdir in c('mini-dinstall','unstable')) {
+ path = file.path(dinstall_archive,subdir)
+ if (file.exists(path)) {
+ unlink(path,recursive=T)
+ }
+ }
+
+ # delete notes of upload
+ file.remove(Sys.glob(file.path(pbuilder_results,'*.upload')))
+
+ # make mini-dinstall generate the skeleton of the archive
+ ret = system(paste('umask 022;mini-dinstall --batch -c',dinstall_config))
+ if (ret != 0) {
+ stop('failed to create archive')
+ }
+
+ # pull in all the R dependencies
+ message(paste('N: dependencies:',paste(pkg$depends$r,collapse=', ')))
+ for (dep in pkg$depends$r) {
+ message(paste('N: uploading',dep))
+ ret = system(paste('umask 022;dput','-c',shQuote(dput_config),'local'
+ ,changesfile(dep)))
+ if (ret != 0) {
+ stop('upload of dependency failed! maybe you did not build it first?')
+ }
+ }
+ build.debian(pkg)
+
+ # upload the package
+ ret = system(paste('umask 022;dput','-c',shQuote(dput_config),'local'
+ ,changesfile(pkg$srcname,pkg$debversion)))
+ if (ret != 0) {
+ stop('upload failed!')
+ }
+
+ return(pkg)
+ })())
+ cleanup(dir)
+ if (inherits(pkg,'try-error')) {
+ stop(call.=F)
+ }
+ return(pkg)
+}
+
+if (exists('argv')) { # check for littler
+ argc <- length(argv)
+ extra_deps = list()
+ extra_deps$deb = c()
+ extra_deps$r = c()
+ opts = c('-D','-R')
+ for (i in 1:argc) {
+ if (!(argv[i] %in% opts)) {
+ if (argc >= i) {
+ argv <- argv[i:argc]
+ } else {
+ argv <- list()
+ }
+ argc = argc - i + 1
+ break
+ }
+ if (i == argc) {
+ message('E: missing argument')
+ q(save='no')
+ }
+ if (argv[i] == '-D') {
+ extra_deps$deb = c(extra_deps$deb,strsplit(chomp(argv[i+1]),',')[[1]])
+ }
+ if (argv[i] == '-R') {
+ extra_deps$r = c(extra_deps$r,strsplit(chomp(argv[i+1]),',')[[1]])
+ extra_deps$deb = c(extra_deps$deb,lapply(extra_deps$r,pkgname.as.debian))
+ }
+ }
+ if (argc == 0) {
+ message('E: usage: cran2deb [-D extra_dep1,extra_dep2,...] package package ...')
+ q(save='no')
+ }
+ build_order <- r.dependency.closure(c(extra_deps$r,argv))
+ message(paste('N: build order',paste(build_order,collapse=', ')))
+ for (pkg in build_order) {
+ go(pkg,extra_deps)
+ }
+}
--- /dev/null
+#!/usr/bin/env r
+
+library(cran2deb)
+
+if (length(argv) == 0) {
+ writeLines(sample(dimnames(available)[[1]],800))
+ #writeLines(dimnames(available)[[1]])
+} else {
+ if (argv[1] == 'query') {
+ for (ctv in ctv.available) {
+ writeLines(ctv$name)
+ }
+ q(save='no')
+ }
+ # list of task lists
+ for (ctv in ctv.available) {
+ if (ctv$name %in% argv) {
+ writeLines(ctv$packagelist$name)
+ }
+ }
+}
--- /dev/null
+#!/usr/bin/rc
+
+#success=`{ls var/results/*.deb | wc -l}
+#echo $success successful packages
+#total=$success
+total=0
+
+fn count_dup { sort | uniq -c | sort -n}# | awk '$1 > 1{print}' }
+fn collapse { a=`{echo $^* | sed -e 's/ | /|/g'}; echo $^a }
+echo 'warnings:'
+{for (x in (warn/* /dev/null)) cut -d: -f3- <$x | sort -u} | awk '{print $1}' | count_dup
+echo
+
+faildep=('^Error: package ''.*'' could not be loaded'
+ '|' '^ERROR: lazy loading failed for package ''.*'''
+ '|' '^[[:space:]]*package .* is not available'
+ '|' 'there is no package called ''.*''')
+faildeb='Unsupported SystemRequirements:'
+faillic=('No acceptable license: ')
+failspc=': No space left on device'
+failhdr='error: .*\.hp?p?: No such file or directory'
+faildep=`{collapse $faildep}
+faildep=$^faildep
+faillic=`{collapse $faillic}
+faillic=$^faillic
+other=''
+
+nfaildep=`{grep -El $faildep fail/* /dev/null | wc -l}
+echo $nfaildep failed R dependencies.
+grep -Eh $faildep fail/* | count_dup
+other=$faildep
+#total=$total+$nfaildep
+echo
+
+nfaillic=`{grep -El $faillic `{grep -EL $other fail/*} /dev/null | wc -l}
+echo $nfaillic failed licenses.
+grep -Eh $faillic `{grep -EL $other fail/*} | count_dup
+other=$other^'|'^$faillic
+total=$total+$nfaillic
+echo
+
+nfailspc=`{grep -El $failspc `{grep -EL $other fail/*} /dev/null | wc -l}
+echo $nfailspc out of space
+other=$other^'|'^$failspc
+total=$total+$nfailspc
+echo
+
+nfailhdr=`{grep -El $failhdr `{grep -EL $other fail/*} /dev/null | wc -l}
+echo $nfailhdr missing C header
+grep -Eh $failhdr `{grep -EL $other fail/* /dev/null} | count_dup
+other=$other^'|'^$failhdr
+total=$total+$nfailhdr
+echo
+
+nfaildeb=`{grep -El $faildeb `{grep -EL $other fail/*} /dev/null | wc -l}
+echo $nfaildeb system requirement failures.
+grep -Eh $faildeb `{grep -EL $other fail/* /dev/null} | count_dup
+other=$other^'|'^$faildeb
+total=$total+$nfaildeb
+echo
+
+nfailother=`{hoc -e `{grep -EL $other fail/* /dev/null | wc -l}^-1}
+echo $nfailother other failures.
+
+#total=`{hoc -e $total}
+#succrate=`{hoc -e $success/'('$total')*100'}
+#echo $succrate% success rate '('$total' total)'
+#total=`{hoc -e $total-$nfaillic-$nfailspc-$nfailhdr}
+#succrate=`{hoc -e $success/'('$total')*100'}
+#echo $succrate% success rate without licensing, space and Debian deps issues '('$total' total)'
+grep -EL $other fail/* /dev/null | xargs tail -n 20
+
--- /dev/null
+#!/usr/bin/env rc
+{for (x in ctv/*) {echo;echo;echo $x: ; cd $x && ../../diagnose && cd ../..}} >ctv.results
--- /dev/null
+#!/usr/bin/rc
+umask 022
+root=`{r -e 'library(cran2deb);cat(system.file('''',package=''cran2deb''),file=stdout())'}
+for (x in `{find etc -type f -name '*.in'}) {
+ y=`{echo $x | sed -e 's,.in$,,'}
+ sed -e 's:@ROOT@:'^$root^':g' <$x >$y
+}
+mkdir -p var/results
+if ([ ! -e var/archive ]) {
+ # I symbolically link this into /var/www/
+ mkdir var/archive
+}
+mini-dinstall --batch -c $root/etc/mini-dinstall.conf || exit 1
+mode=create
+if ([ -e /var/cache/pbuilder/base.tgz ]) {
+ mode=update
+}
+sudo pbuilder $mode --override-config --configfile $root/etc/pbuilderrc
+./update_available
--- /dev/null
+#!/usr/bin/env r
+#mirror <- 'http://cran.uk.r-project.org/'
+mirror <- 'http://cran.r-project.org/'
+message('updating list of available R packages...')
+available <- available.packages(contrib.url(mirror))
+available <- rbind(available,available.packages(contrib.url('http://www.bioconductor.org/')))
+message('updating list of available R task views...')
+library(ctv)
+ctv.available <- available.views(repo=mirror)
+library(cran2deb)
+save(available, ctv.available, file=system.file('R/sysdata.rda',package='cran2deb'),eval.promises=T)
--- /dev/null
+[local]
+method = local
+incoming = @ROOT@/var/archive/mini-dinstall/incoming
+allow_non-us_software = 1
+run_dinstall = 0
+run_lintian = 1
+post_upload_command = /usr/bin/mini-dinstall --batch -c @ROOT@/etc/mini-dinstall.conf
+allow_unsigned_uploads = 1
--- /dev/null
+#!/bin/bash
+# example file to be used with --hookdir
+#
+# run lintian on generated deb files
+apt-get install -y --force-yes lintian
+lintian /tmp/buildd/*.deb
--- /dev/null
+#!/bin/bash
+# example file to be used with --hookdir
+#
+# try to install the resulting debs.
+
+echo "Trying to install resulting packages and test upgrades"
+set -ex
+
+
+PKGNAMES=$(cd /tmp/buildd && ls -1 *.deb | sed 's/_.*$//' )
+
+# install-remove check
+dpkg -i /tmp/buildd/*.deb
+dpkg --remove $PKGNAMES
+
+# install-purge check
+dpkg -i /tmp/buildd/*.deb
+dpkg --purge $PKGNAMES
+
+# upgrade-remove check
+apt-get install -y --force-yes $PKGNAMES || true
+dpkg -i /tmp/buildd/*.deb
+dpkg --remove $PKGNAMES
+
+# upgrade-purge check
+apt-get install -y --force-yes $PKGNAMES || true
+dpkg -i /tmp/buildd/*.deb
+dpkg --purge $PKGNAMES
--- /dev/null
+#!/bin/bash
+# example file to be used with --hookdir
+#
+# run tests. Current directory is top of source-code.
+#
+# 2005, 2007 Junichi Uekawa
+#
+set -e
+
+echo "Installing the prerequisites"
+for PKG in $(ls /tmp/buildd/*.deb | sed -e's,.*/,,;s,_.*,,' ); do
+ apt-get install -y --force-yes "$PKG" || true
+ apt-get remove -y "$PKG" || true
+done
+# ignore the failures since they are not the prime interest
+
+dpkg -i /tmp/buildd/*.deb
+
+if chmod a+x /tmp/buildd/*/debian/pbuilder-test/*; then
+ :
+else
+ echo "W: no pbuilder-test script found, skipping"
+ exit 0
+fi
+
+SUCCESS=0
+COUNT=0
+unset FAIL || true
+NOFAIL=1
+
+# The current directory is the top of the source-tree.
+cd /tmp/buildd/*/debian/..
+
+for SCRIPT in $(run-parts --test /tmp/buildd/*/debian/pbuilder-test) ; do
+ echo "--- BEGIN test: ${SCRIPT##*/}"
+ if "${SCRIPT}"; then
+ echo SUCCESS
+ ((SUCCESS=SUCCESS+1))
+ else
+ echo FAIL
+ FAIL[${#FAIL[@]}]="${SCRIPT##*/}"
+ NOFAIL=0
+ fi
+ echo "--- END test: ${SCRIPT##*/}"
+ ((COUNT=COUNT+1))
+done
+
+echo "Summary:"
+echo "=== $SUCCESS out of $COUNT tests passed"
+echo "${FAIL[@]/#/ failed }"
+echo "-- end of testsuite."
+
--- /dev/null
+/usr/bin/apt-get update
--- /dev/null
+[DEFAULT]
+architectures = all, i386
+use_dnotify = 0
+verify_sigs = 0
+mail_on_success = 0
+archive_style = simple-subdir
+mail_log_level = NONE
+archivedir = @ROOT@/var/archive
+logfile = @ROOT@/var/mini-dinstall.log
+
+[unstable]
+
--- /dev/null
+HOOKDIR=@ROOT@/etc/hook
+BUILDRESULT=@ROOT@/var/results
+EXTRAPACKAGES='debhelper r-base-dev cdbs r-base-core lintian xauth xfont-base xvfb'
+DISTRIBUTION=lenny
+OTHERMIRROR='deb http://localhost/users/cb/cran2deb/ unstable/$(ARCH)/ | deb http://localhost/users/cb/cran2deb/ unstable/all/'
+MIRRORSITE='http://ftp.debian.org/debian/'
+APTCACHE=''
+PBUILDERSATISFYDEPENDSCMD='/usr/lib/pbuilder/pbuilder-satisfydepends-classic'
+++ /dev/null
-#!/usr/bin/rc
-umask 022
-root=`pwd
-for (x in `{find etc -type f -name '*.in'}) {
- y=`{echo $x | sed -e 's,.in$,,'}
- sed -e 's:@ROOT@:'^$root^':g' <$x >$y
-}
-mkdir -p var/results
-if ([ ! -e var/archive ]) {
- # I symbolically link this into /var/www/
- mkdir var/archive
-}
-mini-dinstall --batch -c $root/etc/mini-dinstall.conf || exit 1
-mode=create
-if ([ -e /var/cache/pbuilder/base.tgz ]) {
- mode=update
-}
-sudo pbuilder $mode --override-config --configfile $root/etc/pbuilderrc
-./update_available
+++ /dev/null
-#!/usr/bin/env r
-#mirror <- 'http://cran.uk.r-project.org/'
-mirror <- 'http://cran.r-project.org/'
-message('updating list of available R packages...')
-available <- available.packages(contrib.url(mirror))
-available <- rbind(available,available.packages(contrib.url('http://www.bioconductor.org/')))
-message('updating list of available R task views...')
-library(ctv)
-ctv.available <- available.views(repo=mirror)
-save(available, ctv.available, file='var/cache/available.cache.Rd',eval.promises=T)