2 r.bundle.of <- function(pkgname) {
3 # returns the bundle containing pkgname or NA
4 bundles <- names(available[!is.na(available[, 'Bundle']), 'Contains'])
6 for (bundle in bundles) {
7 if (pkgname %in% r.bundle.contains(bundle)) {
14 r.bundle.contains <- function(bundlename) {
15 return(strsplit(available[bundlename,'Contains'],'[[:space:]]+')[[1]])
18 r.requiring <- function(names) {
20 if (!(name %in% base_pkgs) && !(name %in% rownames(available))) {
21 bundle <- r.bundle.of(name)
23 stop(paste('package',name,'is not available'))
25 names <- c(names,r.bundle.contains(bundle))
28 # approximately prune first into a smaller availability
29 candidates <- available[sapply(rownames(available)
31 length(grep(paste(names,sep='|')
32 ,available[name,r_depend_fields])) > 0)
35 if (length(candidates) == 0) {
38 # find a logical index into available of every package/bundle
39 # whose dependency field contains at least one element of names.
40 # (this is not particularly easy to read---sorry---but is much faster than
41 # the alternatives i could think of)
43 dep_matches <- function(dep) chomp(gsub('\\([^\\)]+\\)','',dep)) %in% names
44 any_dep_matches <- function(name,field=NA)
45 any(sapply(strsplit(chomp(candidates[name,field])
46 ,'[[:space:]]*,[[:space:]]*')
49 for (field in r_depend_fields) {
50 matches = sapply(rownames(candidates), any_dep_matches, field=field)
51 if (length(matches) > 0) {
52 prereq = c(prereq,rownames(candidates[matches,]))
55 return(unique(prereq))
58 r.dependencies.of <- function(name=NULL,description=NULL) {
59 # find the immediate dependencies (children in the dependency graph) of an
61 if (!is.null(name) && (name == 'R' || name %in% base_pkgs)) {
64 if (is.null(description) && is.null(name)) {
65 stop('must specify either a description or a name.')
67 if (is.null(description)) {
68 if (!(name %in% rownames(available))) {
69 bundle <- r.bundle.of(name)
71 stop(paste('package',name,'is not available'))
75 description <- data.frame()
76 # keep only the interesting fields
77 for (field in r_depend_fields) {
78 if (!(field %in% names(available[name,]))) {
81 description[1,field] = available[name,field]
84 # extract the dependencies from the description
86 for (field in r_depend_fields) {
87 if (!(field %in% names(description[1,]))) {
90 new_deps <- lapply(strsplit(chomp(description[1,field])
91 ,'[[:space:]]*,[[:space:]]*')[[1]]
93 deps <- iterate(lapply(new_deps[!is.na(new_deps)],rbind),deps,rbind)
98 r.parse.dep.field <- function(dep) {
102 # remove other comments
103 dep = gsub('(\\(\\)|\\([[:space:]]*[^<=>!].*\\))','',dep)
105 dep = chomp(gsub('[[:space:]]+',' ',dep))
107 pat = '^([^ ()]+) ?(\\( ?([<=>!]+ ?[0-9.-]+) ?\\))?$'
108 if (!length(grep(pat,dep))) {
109 stop(paste('R dependency',dep,'does not appear to be well-formed'))
111 version = sub(pat,'\\3',dep)
112 dep = sub(pat,'\\1',dep)
113 if (!(dep %in% rownames(available))) {
114 depb <- r.bundle.of(dep)
119 return(list(name=dep,version=version))
122 r.dependency.closure <- function(fringe, forward_arcs=T) {
123 # find the transitive closure of the dependencies/prerequisites of some R
126 if (is.data.frame(fringe)) {
127 fringe <- as.list(fringe$name)
129 fun = function(x) r.dependencies.of(name=x)$name
133 while(length(fringe) > 0) {
136 if (length(fringe) > 1) {
137 fringe <- fringe[2:length(fringe)]
141 src <- pkgname.as.debian(top,binary=F)
142 if (!length(grep('^r-',src)) || length(grep('^r-base',src))) {
146 closure=c(closure,top)
147 fringe=c(fringe,newdeps)
150 return(rev(unique(closure,fromLast=T)))