d6e4440322da83046e18067c1e093b24cf458cfe
[pkgdev.git] / R / tocran.R
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 }