beatrina 0.8.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +92 -0
- package/NOTICES +72 -0
- package/README.md +124 -0
- package/bin/beatrina.mjs +223 -0
- package/bin/cli.mjs +80 -0
- package/bin/failsafe.mjs +74 -0
- package/bin/identity.mjs +45 -0
- package/bin/prova-post.mjs +51 -0
- package/bin/sessions.mjs +95 -0
- package/bin/shortcut.mjs +151 -0
- package/bin/update-check.mjs +55 -0
- package/bin/upgrade.mjs +76 -0
- package/build-info.json +1 -0
- package/carmar_V0.8.6.html +1310 -0
- package/check/acceptance.mjs +278 -0
- package/check/session.mjs +215 -0
- package/engines/js/document-exec.mjs +82 -0
- package/engines/js/persist.mjs +214 -0
- package/engines/js/worker.mjs +424 -0
- package/engines/python/adapter.py +577 -0
- package/engines/python/analyze.py +814 -0
- package/engines/python/bootstrap.py +309 -0
- package/engines/python/dataview.py +735 -0
- package/engines/python/debugger.py +346 -0
- package/engines/python/document_exec.py +158 -0
- package/engines/python/engine.json +28 -0
- package/engines/python/handoff.py +118 -0
- package/engines/python/worker.py +564 -0
- package/engines/r/engine.json +25 -0
- package/engines/r/handoff.R +92 -0
- package/failsafe/ai-policy.R +255 -0
- package/failsafe/ai-store.R +373 -0
- package/failsafe/cite.R +418 -0
- package/failsafe/journal.R +684 -0
- package/failsafe/plugins.R +809 -0
- package/failsafe/serve.R +5500 -0
- package/host/ai-policy.mjs +218 -0
- package/host/deployment.mjs +160 -0
- package/host/engine-js.mjs +98 -0
- package/host/engine-pool.mjs +383 -0
- package/host/engine-python.mjs +228 -0
- package/host/engine-r.mjs +206 -0
- package/host/engine-stdio.mjs +401 -0
- package/host/journal-store.mjs +749 -0
- package/host/main.mjs +503 -0
- package/host/planes/README.md +41 -0
- package/host/planes/ai-store.mjs +327 -0
- package/host/planes/ai.mjs +467 -0
- package/host/planes/analyze.mjs +397 -0
- package/host/planes/cite.mjs +517 -0
- package/host/planes/files.mjs +0 -0
- package/host/planes/jobs.mjs +704 -0
- package/host/planes/journal.mjs +53 -0
- package/host/planes/latex.mjs +201 -0
- package/host/planes/mcp.mjs +493 -0
- package/host/planes/pair.mjs +325 -0
- package/host/planes/pipe-term.mjs +122 -0
- package/host/planes/plugins.mjs +112 -0
- package/host/planes/proc-tree.mjs +76 -0
- package/host/planes/sessions.mjs +434 -0
- package/host/planes/settings.mjs +164 -0
- package/host/planes/terminal.mjs +286 -0
- package/host/planes/test-file.mjs +80 -0
- package/host/planes/update.mjs +214 -0
- package/host/plugin-store.mjs +838 -0
- package/host/server.mjs +441 -0
- package/host/settings.mjs +379 -0
- package/host/update-record.mjs +59 -0
- package/host/user-dirs.mjs +117 -0
- package/host/windows-runtime.mjs +145 -0
- package/host/worker-plane.mjs +713 -0
- package/host/ws.mjs +190 -0
- package/kernel/analyze.R +668 -0
- package/kernel/deployment.R +165 -0
- package/kernel/examples/NOTICE.md +38 -0
- package/kernel/examples/tna-complete-tutorial.Rmd +210 -0
- package/kernel/fileio.R +656 -0
- package/kernel/index.html +96 -0
- package/kernel/job-run.R +391 -0
- package/kernel/jobs.R +276 -0
- package/kernel/kernel-protocol +1 -0
- package/kernel/kernel-version +1 -0
- package/kernel/kernel.R +671 -0
- package/kernel/knitr-run.R +245 -0
- package/kernel/latex.R +609 -0
- package/kernel/mcp/carmar-mcp.mjs +516 -0
- package/kernel/notebook-page.R +67 -0
- package/kernel/plugins/csl/apa/apa.csl +2273 -0
- package/kernel/plugins/csl/apa/plugin.json +19 -0
- package/kernel/plugins/csl/chicago-author-date/chicago-author-date.csl +4216 -0
- package/kernel/plugins/csl/chicago-author-date/plugin.json +19 -0
- package/kernel/plugins/csl/harvard-cite-them-right/harvard-cite-them-right.csl +316 -0
- package/kernel/plugins/csl/harvard-cite-them-right/plugin.json +19 -0
- package/kernel/plugins/csl/ieee/ieee.csl +519 -0
- package/kernel/plugins/csl/ieee/plugin.json +19 -0
- package/kernel/plugins/csl/modern-language-association/modern-language-association.csl +1184 -0
- package/kernel/plugins/csl/modern-language-association/plugin.json +19 -0
- package/kernel/plugins/csl/nature/nature.csl +189 -0
- package/kernel/plugins/csl/nature/plugin.json +19 -0
- package/kernel/plugins/latex/apa7/apa7.json +14 -0
- package/kernel/plugins/latex/apa7/plugin.json +19 -0
- package/kernel/plugins/latex/elsarticle/elsarticle.json +14 -0
- package/kernel/plugins/latex/elsarticle/plugin.json +19 -0
- package/kernel/plugins/latex/ieeetran/ieeetran.json +10 -0
- package/kernel/plugins/latex/ieeetran/plugin.json +19 -0
- package/kernel/project.R +131 -0
- package/kernel/settings.R +410 -0
- package/kernel/sniff.R +769 -0
- package/kernel/worker-boot.R +22 -0
- package/kernel/worker.R +3496 -0
- package/lib/agent-authoring-contract.js +547 -0
- package/lib/cell-kinds.js +108 -0
- package/lib/engine-labels.js +324 -0
- package/package.json +32 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "modern-language-association",
|
|
3
|
+
"kind": "csl",
|
|
4
|
+
"name": "MLA Handbook 9th edition (in-text citations)",
|
|
5
|
+
"version": "2026-02-03",
|
|
6
|
+
"file": "modern-language-association.csl",
|
|
7
|
+
"files": [
|
|
8
|
+
"modern-language-association.csl"
|
|
9
|
+
],
|
|
10
|
+
"requires": [],
|
|
11
|
+
"license": "CC BY-SA 3.0",
|
|
12
|
+
"source": "https://www.zotero.org/styles/modern-language-association",
|
|
13
|
+
"digest": "sha256",
|
|
14
|
+
"sha256": {
|
|
15
|
+
"modern-language-association.csl": "e1432698ef28938d044b06bd45ddcc57d6b974cec25f71007075646a11f99484"
|
|
16
|
+
},
|
|
17
|
+
"bytes": 44381,
|
|
18
|
+
"installed": ""
|
|
19
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" demote-non-dropping-particle="sort-only" default-locale="en-GB">
|
|
3
|
+
<info>
|
|
4
|
+
<title>Nature</title>
|
|
5
|
+
<id>http://www.zotero.org/styles/nature</id>
|
|
6
|
+
<link href="http://www.zotero.org/styles/nature" rel="self"/>
|
|
7
|
+
<link href="https://www.nature.com/nature/for-authors/formatting-guide" rel="documentation"/>
|
|
8
|
+
<author>
|
|
9
|
+
<name>Michael Berkowitz</name>
|
|
10
|
+
<email>mberkowi@gmu.edu</email>
|
|
11
|
+
</author>
|
|
12
|
+
<contributor>
|
|
13
|
+
<name>Patrick O'Brien</name>
|
|
14
|
+
<email>citationstyler@gmail.com</email>
|
|
15
|
+
</contributor>
|
|
16
|
+
<category citation-format="numeric"/>
|
|
17
|
+
<category field="science"/>
|
|
18
|
+
<category field="generic-base"/>
|
|
19
|
+
<issn>0028-0836</issn>
|
|
20
|
+
<eissn>1476-4687</eissn>
|
|
21
|
+
<updated>2026-08-07T18:26:21+00:00</updated>
|
|
22
|
+
<rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>
|
|
23
|
+
</info>
|
|
24
|
+
<macro name="title">
|
|
25
|
+
<choose>
|
|
26
|
+
<if type="bill book graphic legal_case legislation motion_picture report song" match="any">
|
|
27
|
+
<text variable="title" font-style="italic" text-case="title"/>
|
|
28
|
+
</if>
|
|
29
|
+
<else>
|
|
30
|
+
<text variable="title"/>
|
|
31
|
+
</else>
|
|
32
|
+
</choose>
|
|
33
|
+
</macro>
|
|
34
|
+
<macro name="author">
|
|
35
|
+
<names variable="author">
|
|
36
|
+
<name sort-separator=", " delimiter=", " and="symbol" initialize-with=". " delimiter-precedes-last="never" name-as-sort-order="all"/>
|
|
37
|
+
<label form="short" prefix=", "/>
|
|
38
|
+
<et-al font-style="italic"/>
|
|
39
|
+
</names>
|
|
40
|
+
</macro>
|
|
41
|
+
<macro name="access">
|
|
42
|
+
<choose>
|
|
43
|
+
<if variable="volume" type="article dataset software" match="any"/>
|
|
44
|
+
<else-if variable="DOI">
|
|
45
|
+
<text variable="DOI" prefix="doi:"/>
|
|
46
|
+
</else-if>
|
|
47
|
+
</choose>
|
|
48
|
+
</macro>
|
|
49
|
+
<macro name="access-data">
|
|
50
|
+
<choose>
|
|
51
|
+
<if type="dataset software" match="any">
|
|
52
|
+
<text variable="DOI" prefix="https://doi.org/"/>
|
|
53
|
+
</if>
|
|
54
|
+
</choose>
|
|
55
|
+
</macro>
|
|
56
|
+
<macro name="issuance">
|
|
57
|
+
<choose>
|
|
58
|
+
<if type="bill book graphic legal_case legislation motion_picture song thesis chapter paper-conference" match="any">
|
|
59
|
+
<group delimiter="; " suffix=".">
|
|
60
|
+
<group delimiter=", " prefix="(" suffix=")">
|
|
61
|
+
<text variable="publisher" form="long"/>
|
|
62
|
+
<text variable="publisher-place"/>
|
|
63
|
+
<date variable="issued">
|
|
64
|
+
<date-part name="year"/>
|
|
65
|
+
</date>
|
|
66
|
+
</group>
|
|
67
|
+
</group>
|
|
68
|
+
</if>
|
|
69
|
+
<else-if type="article">
|
|
70
|
+
<group delimiter=" ">
|
|
71
|
+
<choose>
|
|
72
|
+
<if variable="genre" match="any">
|
|
73
|
+
<text variable="genre" text-case="capitalize-first"/>
|
|
74
|
+
</if>
|
|
75
|
+
<else>
|
|
76
|
+
<text term="preprint" text-case="capitalize-first"/>
|
|
77
|
+
</else>
|
|
78
|
+
</choose>
|
|
79
|
+
<text term="at"/>
|
|
80
|
+
<choose>
|
|
81
|
+
<if variable="DOI" match="any">
|
|
82
|
+
<text variable="DOI" prefix="https://doi.org/"/>
|
|
83
|
+
</if>
|
|
84
|
+
<else>
|
|
85
|
+
<text variable="URL"/>
|
|
86
|
+
</else>
|
|
87
|
+
</choose>
|
|
88
|
+
<date date-parts="year" form="text" variable="issued" prefix="(" suffix=")"/>
|
|
89
|
+
</group>
|
|
90
|
+
</else-if>
|
|
91
|
+
<else-if type="dataset software" match="any">
|
|
92
|
+
<group delimiter=" ">
|
|
93
|
+
<text variable="publisher"/>
|
|
94
|
+
<text macro="access-data"/>
|
|
95
|
+
<date date-parts="year" form="text" variable="issued" prefix="(" suffix=")"/>
|
|
96
|
+
</group>
|
|
97
|
+
</else-if>
|
|
98
|
+
<else-if type="report webpage post post-weblog" match="any">
|
|
99
|
+
<group delimiter=" ">
|
|
100
|
+
<text variable="URL"/>
|
|
101
|
+
<date date-parts="year" form="text" variable="issued" prefix="(" suffix=")"/>
|
|
102
|
+
</group>
|
|
103
|
+
</else-if>
|
|
104
|
+
<else-if type="article-journal" match="any">
|
|
105
|
+
<group delimiter=" ">
|
|
106
|
+
<choose>
|
|
107
|
+
<if match="none" variable="volume page">
|
|
108
|
+
<choose>
|
|
109
|
+
<if match="any" variable="DOI">
|
|
110
|
+
<text variable="DOI" prefix="https://doi.org/"/>
|
|
111
|
+
</if>
|
|
112
|
+
<else>
|
|
113
|
+
<text variable="URL"/>
|
|
114
|
+
</else>
|
|
115
|
+
</choose>
|
|
116
|
+
</if>
|
|
117
|
+
</choose>
|
|
118
|
+
<date date-parts="year" form="text" variable="issued" prefix="(" suffix=")"/>
|
|
119
|
+
</group>
|
|
120
|
+
</else-if>
|
|
121
|
+
<else>
|
|
122
|
+
<date variable="issued" prefix="(" suffix=")">
|
|
123
|
+
<date-part name="year"/>
|
|
124
|
+
</date>
|
|
125
|
+
</else>
|
|
126
|
+
</choose>
|
|
127
|
+
</macro>
|
|
128
|
+
<macro name="container-title">
|
|
129
|
+
<choose>
|
|
130
|
+
<if type="article-journal">
|
|
131
|
+
<text variable="container-title" font-style="italic" form="short"/>
|
|
132
|
+
</if>
|
|
133
|
+
<else>
|
|
134
|
+
<text variable="container-title" font-style="italic"/>
|
|
135
|
+
</else>
|
|
136
|
+
</choose>
|
|
137
|
+
</macro>
|
|
138
|
+
<macro name="editor">
|
|
139
|
+
<choose>
|
|
140
|
+
<if type="chapter paper-conference" match="any">
|
|
141
|
+
<names variable="editor" prefix="(" suffix=")">
|
|
142
|
+
<label form="short" suffix=" "/>
|
|
143
|
+
<name and="symbol" delimiter-precedes-last="never" initialize-with=". " name-as-sort-order="all"/>
|
|
144
|
+
</names>
|
|
145
|
+
</if>
|
|
146
|
+
</choose>
|
|
147
|
+
</macro>
|
|
148
|
+
<macro name="volume">
|
|
149
|
+
<choose>
|
|
150
|
+
<if type="article-journal" match="any">
|
|
151
|
+
<text variable="volume" font-weight="bold" suffix=","/>
|
|
152
|
+
</if>
|
|
153
|
+
<else>
|
|
154
|
+
<group delimiter=" ">
|
|
155
|
+
<label variable="volume" form="short"/>
|
|
156
|
+
<text variable="volume"/>
|
|
157
|
+
</group>
|
|
158
|
+
</else>
|
|
159
|
+
</choose>
|
|
160
|
+
</macro>
|
|
161
|
+
<citation collapse="citation-number">
|
|
162
|
+
<sort>
|
|
163
|
+
<key variable="citation-number"/>
|
|
164
|
+
</sort>
|
|
165
|
+
<layout vertical-align="sup" delimiter=",">
|
|
166
|
+
<text variable="citation-number"/>
|
|
167
|
+
</layout>
|
|
168
|
+
</citation>
|
|
169
|
+
<bibliography et-al-min="6" et-al-use-first="1" second-field-align="flush" entry-spacing="0" line-spacing="2">
|
|
170
|
+
<layout suffix=".">
|
|
171
|
+
<text variable="citation-number" suffix=". "/>
|
|
172
|
+
<group delimiter=" ">
|
|
173
|
+
<text macro="author" suffix="."/>
|
|
174
|
+
<text macro="title" suffix="."/>
|
|
175
|
+
<choose>
|
|
176
|
+
<if type="chapter paper-conference" match="any">
|
|
177
|
+
<text term="in"/>
|
|
178
|
+
</if>
|
|
179
|
+
</choose>
|
|
180
|
+
<text macro="container-title"/>
|
|
181
|
+
<text macro="editor"/>
|
|
182
|
+
<text macro="volume"/>
|
|
183
|
+
<text variable="page"/>
|
|
184
|
+
<text macro="issuance"/>
|
|
185
|
+
<text macro="access"/>
|
|
186
|
+
</group>
|
|
187
|
+
</layout>
|
|
188
|
+
</bibliography>
|
|
189
|
+
</style>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "nature",
|
|
3
|
+
"kind": "csl",
|
|
4
|
+
"name": "Nature",
|
|
5
|
+
"version": "2026-08-07",
|
|
6
|
+
"file": "nature.csl",
|
|
7
|
+
"files": [
|
|
8
|
+
"nature.csl"
|
|
9
|
+
],
|
|
10
|
+
"requires": [],
|
|
11
|
+
"license": "CC BY-SA 3.0",
|
|
12
|
+
"source": "https://www.zotero.org/styles/nature",
|
|
13
|
+
"digest": "sha256",
|
|
14
|
+
"sha256": {
|
|
15
|
+
"nature.csl": "cb69522b83d8eee0eab9a06d1255ea40fe2cc1bbd85b22bbf94097129119dc0e"
|
|
16
|
+
},
|
|
17
|
+
"bytes": 6445,
|
|
18
|
+
"installed": ""
|
|
19
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"label": "APA 7th edition",
|
|
3
|
+
"description": "apa7 journal manuscript. biblatex's commands, loaded with APA's own style.",
|
|
4
|
+
"documentclass": "apa7",
|
|
5
|
+
"classOptions": [
|
|
6
|
+
"man",
|
|
7
|
+
"11pt"
|
|
8
|
+
],
|
|
9
|
+
"citeStyle": "biblatex",
|
|
10
|
+
"citePackage": "\\usepackage[style=apa]{biblatex}",
|
|
11
|
+
"topLevel": "section",
|
|
12
|
+
"preamble": [],
|
|
13
|
+
"version": "1.0"
|
|
14
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "apa7",
|
|
3
|
+
"kind": "latex",
|
|
4
|
+
"name": "APA 7th edition",
|
|
5
|
+
"version": "1.0",
|
|
6
|
+
"file": "apa7.json",
|
|
7
|
+
"files": [
|
|
8
|
+
"apa7.json"
|
|
9
|
+
],
|
|
10
|
+
"requires": [],
|
|
11
|
+
"license": "",
|
|
12
|
+
"source": "",
|
|
13
|
+
"digest": "sha256",
|
|
14
|
+
"sha256": {
|
|
15
|
+
"apa7.json": "ac40dcaad103fba6e01bfbd9b61c2a7c5c13b8a7988860c5daefefff2abcc264"
|
|
16
|
+
},
|
|
17
|
+
"bytes": 345,
|
|
18
|
+
"installed": ""
|
|
19
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"label": "Elsevier article",
|
|
3
|
+
"description": "elsarticle, the class Elsevier journals ask for. Line numbers on, for review.",
|
|
4
|
+
"documentclass": "elsarticle",
|
|
5
|
+
"classOptions": ["review", "3p", "times"],
|
|
6
|
+
"citeStyle": "natbib",
|
|
7
|
+
"topLevel": "section",
|
|
8
|
+
"preamble": [
|
|
9
|
+
"\\usepackage{lineno}",
|
|
10
|
+
"\\modulolinenumbers[5]",
|
|
11
|
+
"\\linenumbers"
|
|
12
|
+
],
|
|
13
|
+
"version": "1.0"
|
|
14
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "elsarticle",
|
|
3
|
+
"kind": "latex",
|
|
4
|
+
"name": "Elsevier article",
|
|
5
|
+
"version": "1.0",
|
|
6
|
+
"file": "elsarticle.json",
|
|
7
|
+
"files": [
|
|
8
|
+
"elsarticle.json"
|
|
9
|
+
],
|
|
10
|
+
"requires": [],
|
|
11
|
+
"license": "",
|
|
12
|
+
"source": "",
|
|
13
|
+
"digest": "sha256",
|
|
14
|
+
"sha256": {
|
|
15
|
+
"elsarticle.json": "26735bb4cec577a105ff801f471592818b9e455f7ec3135f4348627323f1b548"
|
|
16
|
+
},
|
|
17
|
+
"bytes": 379,
|
|
18
|
+
"installed": ""
|
|
19
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"label": "IEEE conference or journal",
|
|
3
|
+
"description": "IEEEtran, two-column. IEEE's own bibliography macros, so plain \\cite.",
|
|
4
|
+
"documentclass": "IEEEtran",
|
|
5
|
+
"classOptions": ["conference"],
|
|
6
|
+
"citeStyle": "plain",
|
|
7
|
+
"topLevel": "section",
|
|
8
|
+
"preamble": [],
|
|
9
|
+
"version": "1.0"
|
|
10
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "ieeetran",
|
|
3
|
+
"kind": "latex",
|
|
4
|
+
"name": "IEEE conference or journal",
|
|
5
|
+
"version": "1.0",
|
|
6
|
+
"file": "ieeetran.json",
|
|
7
|
+
"files": [
|
|
8
|
+
"ieeetran.json"
|
|
9
|
+
],
|
|
10
|
+
"requires": [],
|
|
11
|
+
"license": "",
|
|
12
|
+
"source": "",
|
|
13
|
+
"digest": "sha256",
|
|
14
|
+
"sha256": {
|
|
15
|
+
"ieeetran.json": "d8c7db78e804fac0abd98c0ec41c8b55e1478e140ee56436acd983f22692868d"
|
|
16
|
+
},
|
|
17
|
+
"bytes": 287,
|
|
18
|
+
"installed": ""
|
|
19
|
+
}
|
package/kernel/project.R
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# project.R — inspect and restore a project's package environment without
|
|
2
|
+
# requiring terminal commands. Pure status logic is separate from worker.R so
|
|
3
|
+
# lockfile edge cases and organisation-mirror policy can be tested directly.
|
|
4
|
+
|
|
5
|
+
carmar_project_or <- function(value, fallback) if (is.null(value)) fallback else value
|
|
6
|
+
|
|
7
|
+
carmar_repository_display <- function(value) {
|
|
8
|
+
value <- as.character(carmar_project_or(value, ""))[[1L]]
|
|
9
|
+
value <- sub("^([A-Za-z]+://)[^/@]+@", "\\1", value)
|
|
10
|
+
sub("[?#].*$", "", value)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
carmar_project_status <- function(path = getwd(), env = Sys.getenv,
|
|
14
|
+
installed = NULL, repos = getOption("repos"),
|
|
15
|
+
renv_available = NULL, libraries = .libPaths()) {
|
|
16
|
+
root <- normalizePath(path, winslash = "/", mustWork = FALSE)
|
|
17
|
+
lockfile <- file.path(root, "renv.lock")
|
|
18
|
+
has_lock <- file.exists(lockfile)
|
|
19
|
+
project_files <- list.files(root, pattern = "[.]Rproj$", ignore.case = TRUE)
|
|
20
|
+
has_quarto <- any(file.exists(file.path(root, c("_quarto.yml", "_quarto.yaml"))))
|
|
21
|
+
managed_raw <- trimws(env("CARMAR_CRAN_MIRROR", ""))
|
|
22
|
+
mirror_error <- if (nzchar(managed_raw) && !grepl("^https://", managed_raw))
|
|
23
|
+
"The administrator's package mirror must use HTTPS." else ""
|
|
24
|
+
cran <- if (length(repos) && "CRAN" %in% names(repos)) unname(repos[["CRAN"]]) else ""
|
|
25
|
+
repository <- if (nzchar(managed_raw)) managed_raw else cran
|
|
26
|
+
repository <- carmar_repository_display(repository)
|
|
27
|
+
if (is.null(renv_available)) renv_available <- requireNamespace("renv", quietly = TRUE)
|
|
28
|
+
active_project <- trimws(env("RENV_PROJECT", ""))
|
|
29
|
+
active <- nzchar(active_project) && identical(
|
|
30
|
+
normalizePath(active_project, winslash = "/", mustWork = FALSE), root)
|
|
31
|
+
if (!active) {
|
|
32
|
+
prefix <- paste0(root, "/renv/library/")
|
|
33
|
+
active <- any(startsWith(normalizePath(libraries, winslash = "/", mustWork = FALSE), prefix))
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
locked <- character()
|
|
37
|
+
wanted <- character()
|
|
38
|
+
lock_error <- ""
|
|
39
|
+
if (has_lock) {
|
|
40
|
+
size <- file.info(lockfile)$size[[1L]]
|
|
41
|
+
if (is.na(size) || size > 10 * 1024 * 1024) {
|
|
42
|
+
lock_error <- "renv.lock is too large to inspect safely."
|
|
43
|
+
} else {
|
|
44
|
+
parsed <- tryCatch(jsonlite::fromJSON(lockfile, simplifyVector = FALSE),
|
|
45
|
+
error = function(e) e)
|
|
46
|
+
if (inherits(parsed, "error") || !is.list(parsed$Packages)) {
|
|
47
|
+
lock_error <- "renv.lock is not valid JSON package metadata."
|
|
48
|
+
} else {
|
|
49
|
+
locked <- names(parsed$Packages)
|
|
50
|
+
wanted <- vapply(parsed$Packages, function(record) {
|
|
51
|
+
value <- carmar_project_or(record$Version, "")
|
|
52
|
+
if (is.character(value) && length(value) == 1L) value else ""
|
|
53
|
+
}, character(1))
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (is.null(installed)) {
|
|
59
|
+
matrix <- utils::installed.packages()[, c("Package", "Version"), drop = FALSE]
|
|
60
|
+
installed <- stats::setNames(as.character(matrix[, "Version"]), matrix[, "Package"])
|
|
61
|
+
}
|
|
62
|
+
installed <- stats::setNames(as.character(installed), names(installed))
|
|
63
|
+
missing <- setdiff(locked, names(installed))
|
|
64
|
+
shared <- intersect(locked, names(installed))
|
|
65
|
+
different <- shared[nzchar(wanted[shared]) & installed[shared] != wanted[shared]]
|
|
66
|
+
list(
|
|
67
|
+
project = length(project_files) > 0L || has_quarto || has_lock,
|
|
68
|
+
rproj = length(project_files) > 0L,
|
|
69
|
+
quarto = has_quarto,
|
|
70
|
+
lockfile = has_lock,
|
|
71
|
+
lock_error = lock_error,
|
|
72
|
+
renv_available = isTRUE(renv_available),
|
|
73
|
+
active = isTRUE(active),
|
|
74
|
+
packages = length(locked),
|
|
75
|
+
missing = length(missing),
|
|
76
|
+
different = length(different),
|
|
77
|
+
missing_names = I(as.character(utils::head(missing, 12L))),
|
|
78
|
+
different_names = I(as.character(utils::head(different, 12L))),
|
|
79
|
+
managed_mirror = nzchar(managed_raw),
|
|
80
|
+
repository = repository,
|
|
81
|
+
mirror_error = mirror_error,
|
|
82
|
+
can_restore = has_lock && !nzchar(lock_error) && !nzchar(mirror_error)
|
|
83
|
+
&& isTRUE(renv_available)
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
carmar_project_action <- function(action, path = getwd(), env = Sys.getenv,
|
|
88
|
+
install = NULL, restore = NULL,
|
|
89
|
+
available = function() requireNamespace("renv", quietly = TRUE)) {
|
|
90
|
+
action <- if (is.character(action) && length(action) == 1L) action else ""
|
|
91
|
+
if (!action %in% c("bootstrap", "restore")) stop("unknown project environment action")
|
|
92
|
+
state <- carmar_project_status(path = path, env = env,
|
|
93
|
+
renv_available = isTRUE(available()))
|
|
94
|
+
if (nzchar(state$mirror_error)) stop(state$mirror_error)
|
|
95
|
+
managed <- trimws(env("CARMAR_CRAN_MIRROR", ""))
|
|
96
|
+
repos <- getOption("repos")
|
|
97
|
+
if (nzchar(managed)) repos <- c(CRAN = managed)
|
|
98
|
+
|
|
99
|
+
if (identical(action, "bootstrap")) {
|
|
100
|
+
if (isTRUE(state$renv_available)) {
|
|
101
|
+
return(list(ok = TRUE, message = "renv is already installed.", restart = FALSE))
|
|
102
|
+
}
|
|
103
|
+
if (is.null(install)) install <- function(repositories) {
|
|
104
|
+
writable <- .libPaths()[file.access(.libPaths(), 2L) == 0L]
|
|
105
|
+
if (!length(writable)) stop("This R session has no writable package library.")
|
|
106
|
+
suppressWarnings(utils::install.packages("renv", lib = writable[[1L]],
|
|
107
|
+
repos = repositories, dependencies = NA, quiet = TRUE))
|
|
108
|
+
}
|
|
109
|
+
install(repos)
|
|
110
|
+
if (!isTRUE(available())) stop("renv installation did not complete.")
|
|
111
|
+
return(list(ok = TRUE, message = "renv was installed from the configured package repository.",
|
|
112
|
+
restart = FALSE))
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (!isTRUE(state$lockfile)) stop("This project has no renv.lock to restore.")
|
|
116
|
+
if (nzchar(state$lock_error)) stop(state$lock_error)
|
|
117
|
+
if (!isTRUE(state$renv_available)) stop("renv is not installed. Install renv first.")
|
|
118
|
+
if (is.null(restore)) restore <- function(project) {
|
|
119
|
+
renv::restore(project = project, prompt = FALSE, clean = FALSE)
|
|
120
|
+
}
|
|
121
|
+
old_override <- Sys.getenv("RENV_CONFIG_REPOS_OVERRIDE", unset = NA_character_)
|
|
122
|
+
on.exit({
|
|
123
|
+
if (is.na(old_override)) Sys.unsetenv("RENV_CONFIG_REPOS_OVERRIDE")
|
|
124
|
+
else Sys.setenv(RENV_CONFIG_REPOS_OVERRIDE = old_override)
|
|
125
|
+
}, add = TRUE)
|
|
126
|
+
if (nzchar(managed)) Sys.setenv(RENV_CONFIG_REPOS_OVERRIDE = managed)
|
|
127
|
+
restore(normalizePath(path, winslash = "/", mustWork = TRUE))
|
|
128
|
+
list(ok = TRUE,
|
|
129
|
+
message = "The packages recorded in renv.lock were restored from the configured repository.",
|
|
130
|
+
restart = !isTRUE(state$active))
|
|
131
|
+
}
|