| 1 | # Convert a package with custom sub-folders to a valid CRAN package |
| 2 | # @param inPath Input path: location of the package to flatten |
| 3 | # @param outPath Output path: location of the package to create |
| 4 | .pkgdev.tocran = function(inPath, outPath) { |
| 5 | |
| 6 | # Gather all R source files (no tests) |
| 7 | fullPathRfiles = c() |
| 8 | forbiddenPath = file.path(inPath,"R","tests") |
| 9 | for (fileOrDir in list.files(file.path(inPath,"R"),full.names=TRUE)) { |
| 10 | if (fileOrDir != forbiddenPath) { |
| 11 | if (file.info(fileOrDir)$isdir) { |
| 12 | fullPathRfiles = c( |
| 13 | fullPathRfiles, |
| 14 | list.files(fileOrDir,pattern="\\.[RrSsq]$", |
| 15 | recursive=TRUE,full.names=TRUE)) |
| 16 | } |
| 17 | else fullPathRfiles = c(fullPathRfiles, fileOrDir) |
| 18 | } |
| 19 | } |
| 20 | # Truncate paths: only suffix in pkgname/R/suffix is useful |
| 21 | fullPathRfiles = sub( |
| 22 | paste(inPath,.Platform$file.sep,"R",.Platform$file.sep,sep=''), |
| 23 | "", |
| 24 | fullPathRfiles, |
| 25 | fixed=TRUE) |
| 26 | |
| 27 | # Transform rFiles until no folder separator can be found |
| 28 | rFiles = fullPathRfiles |
| 29 | while (length(grep(.Platform$file.sep,rFiles)) > 0) { |
| 30 | rFiles = lowerFileDepth(rFiles) |
| 31 | } |
| 32 | |
| 33 | # Create and fill every non-sensible folder on output path |
| 34 | unlink(outPath, recursive=TRUE) #in case of [TODO: warn user] |
| 35 | dir.create(outPath, showWarnings=FALSE) |
| 36 | forbiddenPath = "R" |
| 37 | for (fileOrDir in list.files(inPath)) { |
| 38 | if (fileOrDir != forbiddenPath) { |
| 39 | if (file.info(file.path(inPath,fileOrDir))$isdir) { |
| 40 | dir.create(file.path(outPath,fileOrDir), showWarnings=FALSE, recursive=TRUE) |
| 41 | file.copy(file.path(inPath,fileOrDir), file.path(outPath),recursive=TRUE) |
| 42 | } |
| 43 | else file.copy(file.path(inPath,fileOrDir), file.path(outPath)) |
| 44 | } |
| 45 | } |
| 46 | |
| 47 | # Prepare R folder (empty for the moment) |
| 48 | dir.create( file.path(outPath,"R") ) |
| 49 | |
| 50 | # Copy "flattened" files to R/ |
| 51 | for (i in 1:length(rFiles)) { |
| 52 | file.copy( file.path(inPath,"R",fullPathRfiles[i]), |
| 53 | file.path(outPath,"R",rFiles[i]) ) |
| 54 | } |
| 55 | |
| 56 | # Optional processing if /src is present |
| 57 | if (file.exists(file.path(inPath,"src"))) { |
| 58 | |
| 59 | # Gather all C code files (NOT including headers; no tests) |
| 60 | cCodeFiles = c() |
| 61 | forbiddenPath = file.path(inPath,"src","tests") |
| 62 | for (fileOrDir in list.files(file.path(inPath,"src"),full.names=TRUE)) { |
| 63 | if (fileOrDir != forbiddenPath) { |
| 64 | if (file.info(fileOrDir)$isdir) { |
| 65 | cCodeFiles = c( |
| 66 | cCodeFiles, |
| 67 | list.files(fileOrDir,pattern="\\.[Cc]$", |
| 68 | recursive=TRUE,full.names=TRUE)) |
| 69 | } |
| 70 | else cCodeFiles = c(cCodeFiles, fileOrDir) |
| 71 | } |
| 72 | } |
| 73 | # Truncate paths: only suffix in pkgname/R/suffix is useful |
| 74 | cCodeFiles = sub( |
| 75 | paste(inPath,.Platform$file.sep,"src",.Platform$file.sep,sep=''), |
| 76 | "", |
| 77 | cCodeFiles, |
| 78 | fixed=TRUE) |
| 79 | |
| 80 | # Add a 'Makevars' file under src/ to allow compilation by R CMD INSTALL |
| 81 | makevars = paste( |
| 82 | paste("SOURCES","=",paste(cCodeFiles,sep='',collapse=' '),"\n",sep=' '), |
| 83 | paste("OBJECTS","=","$(SOURCES:.c=.o)","\n",sep=' '), |
| 84 | sep='\n') |
| 85 | writeLines(makevars, file.path(outPath,"src","Makevars")) |
| 86 | } |
| 87 | } |
| 88 | |
| 89 | # NOTE: rule = sort according to first subfolder, then place 1 for the first ...etc; |
| 90 | # for example tr1/tr2/tr3/file.c --> tr2/tr3/file_1.c --> tr3/file_12.c ...etc |
| 91 | lowerFileDepth = function(files) { |
| 92 | |
| 93 | # Sort files according to their prefix paths |
| 94 | sortedFiles = sort(files, index.return=TRUE) |
| 95 | |
| 96 | # Truncate paths if required |
| 97 | folderKount = 0 |
| 98 | lastFolder = "" |
| 99 | for (i in 1:length(files)) { |
| 100 | if (length(grep(.Platform$file.sep, sortedFiles$x[i], fixed=TRUE)) > 0) { |
| 101 | prefix = strsplit(sortedFiles$x[i], c(.Platform$file.sep))[[1]][1] |
| 102 | if (prefix != lastFolder) { |
| 103 | folderKount = folderKount + 1 |
| 104 | lastFolder = prefix |
| 105 | } |
| 106 | sortedFiles$x[i] = paste( |
| 107 | #truncate base name |
| 108 | substr(sortedFiles$x[i],nchar(prefix)+2,nchar(sortedFiles$x[i])-2), |
| 109 | #add [sub-]folder identifier |
| 110 | folderKount, |
| 111 | #add suffix (.R, .r ...) de |
| 112 | substr(sortedFiles$x[i],nchar(sortedFiles$x[i])-1,nchar(sortedFiles$x[i])), |
| 113 | sep='') |
| 114 | } |
| 115 | } |
| 116 | |
| 117 | # Return transformed files list ranked as in input (unsorted) |
| 118 | for (i in 1:length(files)) { |
| 119 | files[ sortedFiles$ix[i] ] = sortedFiles$x[i] |
| 120 | } |
| 121 | return (files) |
| 122 | } |