1 | import { SoftwarePackage } from '@stencila/schema'
|
2 |
|
3 | import PackageGenerator from './PackageGenerator'
|
4 | import IUrlFetcher from './IUrlFetcher'
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | export default class RGenerator extends PackageGenerator {
|
10 |
|
11 | |
12 |
|
13 |
|
14 | date: string
|
15 |
|
16 | constructor (urlFetcher: IUrlFetcher, pkg: SoftwarePackage, folder?: string) {
|
17 | super(urlFetcher, pkg, folder)
|
18 |
|
19 |
|
20 |
|
21 | let date = this.package.datePublished
|
22 | if (!date) date = (new Date(Date.now() - 24 * 3600 * 1000)).toISOString().substring(0,10)
|
23 | this.date = date
|
24 | }
|
25 |
|
26 |
|
27 |
|
28 |
|
29 | applies (): boolean {
|
30 | return this.package.runtimePlatform === 'R'
|
31 | }
|
32 |
|
33 | envVars (sysVersion: string): Array<[string, string]> {
|
34 | return [
|
35 |
|
36 |
|
37 | ['TZ', 'Etc/UTC']
|
38 | ]
|
39 | }
|
40 |
|
41 | aptKeysCommand (sysVersion: string): string {
|
42 | return 'apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 51716619E084DAB9'
|
43 | }
|
44 |
|
45 | aptRepos (base: string): Array<string> {
|
46 | let version = this.baseVersionName(base)
|
47 |
|
48 |
|
49 |
|
50 | if (version === 'bionic') version += '-cran35'
|
51 | return [
|
52 | `deb https://mran.microsoft.com/snapshot/${this.date}/bin/linux/ubuntu ${version}/`
|
53 | ]
|
54 | }
|
55 |
|
56 | aptPackages (sysVersion: string): Array<string> {
|
57 | let pkgs: Array<string> = [
|
58 | 'r-base'
|
59 | ]
|
60 |
|
61 | |
62 |
|
63 |
|
64 | function find (pkg: any) {
|
65 | if (pkg.runtimePlatform !== 'R' || !pkg.softwareRequirements) return
|
66 | for (let subpkg of pkg.softwareRequirements) {
|
67 | if (subpkg.runtimePlatform === 'deb') pkgs.push(subpkg.name || '')
|
68 | else find(subpkg)
|
69 | }
|
70 | }
|
71 | find(this.package)
|
72 |
|
73 | return pkgs
|
74 | }
|
75 |
|
76 | stencilaInstall (sysVersion: string): string | undefined {
|
77 | return `apt-get update \\
|
78 | && apt-get install -y zlib1g-dev libxml2-dev pkg-config \\
|
79 | && apt-get autoremove -y \\
|
80 | && apt-get clean \\
|
81 | && rm -rf /var/lib/apt/lists/* \\
|
82 | && Rscript -e 'install.packages("devtools")' \\
|
83 | && Rscript -e 'source("https://bioconductor.org/biocLite.R"); biocLite("graph")' \\
|
84 | && Rscript -e 'devtools::install_github("r-lib/pkgbuild")' \\
|
85 | && Rscript -e 'devtools::install_github("stencila/r")'`
|
86 | }
|
87 |
|
88 | installFiles (sysVersion: string): Array<[string, string]> {
|
89 |
|
90 | if (this.exists('install.R')) return [['install.R', 'install.R']]
|
91 | if (this.exists('DESCRIPTION')) return [['DESCRIPTION', 'DESCRIPTION']]
|
92 |
|
93 |
|
94 | const name = (this.package.name || 'unnamed').replace(/[^a-zA-Z0-9]/,'')
|
95 | const pkgs = this.filterPackages('R').map(pkg => pkg.name)
|
96 | let desc = `Package: ${name}
|
97 | Version: 1.0.0
|
98 | Date: ${this.date}
|
99 | Description: Generated by Dockter ${new Date().toISOString()}.
|
100 | To stop Dockter generating this file and start editing it yourself, rename it to "DESCRIPTION".
|
101 | `
|
102 | if (pkgs.length) desc += `Imports:\n ${pkgs.join(',\n ')}\n`
|
103 |
|
104 | this.write('.DESCRIPTION', desc)
|
105 | return [['.DESCRIPTION', 'DESCRIPTION']]
|
106 | }
|
107 |
|
108 | installCommand (sysVersion: string): string | undefined {
|
109 | if (this.exists('install.R')) {
|
110 |
|
111 | return `Rscript install.R`
|
112 | } else if (this.exists('DESCRIPTION') || this.exists('.DESCRIPTION')) {
|
113 |
|
114 |
|
115 | return `bash -c "Rscript <(curl -sL https://unpkg.com/@stencila/dockter/src/install.R)"`
|
116 | }
|
117 | }
|
118 |
|
119 | |
120 |
|
121 |
|
122 |
|
123 |
|
124 | projectFiles (): Array<[string, string]> {
|
125 | const rfiles = this.glob('**/*.R')
|
126 | return rfiles.map(file => [file, file]) as Array<[string, string]>
|
127 | }
|
128 |
|
129 | |
130 |
|
131 |
|
132 |
|
133 |
|
134 |
|
135 | runCommand (): string | undefined {
|
136 | const rfiles = this.glob('**/*.R')
|
137 | if (rfiles.length === 0) return
|
138 | let script
|
139 | if (rfiles.includes('main.R')) script = 'main.R'
|
140 | else if (rfiles.includes('cmd.R')) script = 'cmd.R'
|
141 | else script = rfiles[0]
|
142 | return `Rscript ${script}`
|
143 | }
|
144 | }
|