mirror of
https://github.com/FlipsideCrypto/real-time-data-lag.git
synced 2026-02-06 10:46:46 +00:00
Initiate New Template Project
api_key.txt ignored
This commit is contained in:
commit
1b83d59d02
51
.gitignore
vendored
Normal file
51
.gitignore
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
# History files
|
||||
.Rhistory
|
||||
.Rapp.history
|
||||
|
||||
# Session Data files
|
||||
.RData
|
||||
.RDataTmp
|
||||
|
||||
# User-specific files
|
||||
.Ruserdata
|
||||
|
||||
# Example code in package build process
|
||||
*-Ex.R
|
||||
|
||||
# Output files from R CMD build
|
||||
/*.tar.gz
|
||||
|
||||
# Output files from R CMD check
|
||||
/*.Rcheck/
|
||||
|
||||
# RStudio files
|
||||
.Rproj.user/
|
||||
|
||||
# produced vignettes
|
||||
vignettes/*.html
|
||||
vignettes/*.pdf
|
||||
|
||||
# OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3
|
||||
.httr-oauth
|
||||
|
||||
# knitr and R markdown default cache directories
|
||||
*_cache/
|
||||
/cache/
|
||||
|
||||
# Temporary files created by R markdown
|
||||
*.utf8.md
|
||||
*.knit.md
|
||||
|
||||
# R Environment Variables
|
||||
.Renviron
|
||||
|
||||
# pkgdown site
|
||||
docs/
|
||||
|
||||
# translation temp files
|
||||
po/*~
|
||||
|
||||
# RStudio Connect folder
|
||||
rsconnect/
|
||||
|
||||
api_key.txt
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Carlos R. Mercado
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
24
README.md
Normal file
24
README.md
Normal file
@ -0,0 +1,24 @@
|
||||
# Flipside Crypto R Shiny Template
|
||||
|
||||
This is a minimalized R Shiny template app to keep Flipside Shiny apps on-brand. It includes the following:
|
||||
|
||||
- shiny_template R Project
|
||||
- app directory with the template app
|
||||
- renv lock file (includes shroomDK)
|
||||
- relevant gitignores (e.g., ignoring api_key.txt for shroomDK)
|
||||
|
||||
## App
|
||||
|
||||
The app folder serves as your template R Shiny app. It can be run as is to show filler text and a filler chart. The folder contains:
|
||||
|
||||
- www/
|
||||
- fliplogo.jpg - the Flipside icon
|
||||
- rudderstack.js - requires shinyjs; used to track clicks to the flipside website
|
||||
- styles.css - template css including a few shiny specific outputs (e.g., .container-fluid) review and take care editing
|
||||
- global.R - default global file for miscellaneous functions and objects.
|
||||
- ui.R - default user interface file, includes both critical tags (e.g., header bar) and optional template code (e.g., chart div)
|
||||
- server.R - minimized server file w/ empty server function
|
||||
|
||||
## renv
|
||||
|
||||
use `renv::restore()` (ensure you have renv downloaded) to restore the app libraries prior to testing on your machine. Note: shroomDK is in active development. This template may fall behind in shroomDK versions. Review the [documentation](https://github.com/FlipsideCrypto/sdk/tree/main/r/shroomDK) for more info.
|
||||
13
app/global.R
Normal file
13
app/global.R
Normal file
@ -0,0 +1,13 @@
|
||||
library(shinyjs)
|
||||
library(shroomDK)
|
||||
library(data.table)
|
||||
library(plotly)
|
||||
library(dplyr)
|
||||
library(reactable)
|
||||
|
||||
example_data <- data.frame(
|
||||
x = 1:100,
|
||||
y = abs(rnorm(100)),
|
||||
z = abs(ceiling(rnorm(100))),
|
||||
a = as.factor(sample(LETTERS[1:5], 100, replace = TRUE))
|
||||
)
|
||||
96
app/server.R
Normal file
96
app/server.R
Normal file
@ -0,0 +1,96 @@
|
||||
library(shiny)
|
||||
source("global.R")
|
||||
server <- function(input, output, session) {
|
||||
|
||||
# example_data in global
|
||||
|
||||
# Example SCATTERPLOT
|
||||
output$exscatter <- renderPlotly({
|
||||
plot_ly(data = example_data,
|
||||
x = ~x,
|
||||
y = ~y,
|
||||
color = ~a,
|
||||
size = ~z,
|
||||
text = ~paste("Y: ", y,
|
||||
'<br>Size:', z,
|
||||
'<br>Color:', a)
|
||||
) %>%
|
||||
layout(title = "",
|
||||
yaxis = list(title = "Y Label",
|
||||
showgrid = FALSE,
|
||||
color = "#FFF"),
|
||||
xaxis = list(title = "X Label",
|
||||
showgrid = TRUE,
|
||||
color = "#FFF",
|
||||
gridcolor = "#202933"),
|
||||
plot_bgcolor = "transparent",
|
||||
paper_bgcolor = "transparent",
|
||||
legend = list(font = list(color = '#FFFFFF'))) %>%
|
||||
# variety of useful config options to be aware of
|
||||
# https://plotly.com/r/configuration-options/
|
||||
config(scrollZoom = FALSE,
|
||||
# displayModeBar = TRUE, # default is hover
|
||||
toImageButtonOptions = list(format= 'svg', # one of png, svg, jpeg, webp
|
||||
filename= 'template_image',
|
||||
height= 500,
|
||||
width= 700,
|
||||
scale= 1),
|
||||
displaylogo = FALSE
|
||||
)
|
||||
|
||||
|
||||
})
|
||||
|
||||
# Example BARPLOT
|
||||
# more details - https://plotly.com/r/bar-charts/
|
||||
output$exbar <- renderPlotly({
|
||||
|
||||
ed <- example_data %>%
|
||||
group_by(a, z, .add = TRUE) %>%
|
||||
summarize(n = n())
|
||||
|
||||
plot_ly(data = ed,
|
||||
x = ~as.character(a),
|
||||
y = ~n,
|
||||
color = ~as.factor(z),
|
||||
text = ~paste("Letter: ", a,
|
||||
'<br>Category:', z,
|
||||
'<br>Number:', n)
|
||||
) %>%
|
||||
layout(title = "",
|
||||
yaxis = list(title = "Y Label",
|
||||
showgrid = FALSE,
|
||||
color = "#FFF"),
|
||||
xaxis = list(title = "X Label",
|
||||
showticklabels = TRUE,
|
||||
color = "#FFF",
|
||||
gridcolor = "#202933"),
|
||||
plot_bgcolor = "transparent",
|
||||
paper_bgcolor = "transparent",
|
||||
legend = list(font = list(color = '#FFFFFF'))) %>%
|
||||
# variety of useful config options to be aware of
|
||||
# https://plotly.com/r/configuration-options/
|
||||
config(scrollZoom = FALSE,
|
||||
# displayModeBar = TRUE, # default is hover
|
||||
toImageButtonOptions = list(format= 'svg', # one of png, svg, jpeg, webp
|
||||
filename= 'template_image',
|
||||
height= 500,
|
||||
width= 700,
|
||||
scale= 1),
|
||||
displaylogo = FALSE
|
||||
)
|
||||
|
||||
|
||||
})
|
||||
|
||||
# Simple reactable - see: styles.css for formatting
|
||||
output$myreactable <- renderReactable({
|
||||
reactable(example_data,
|
||||
borderless = TRUE,
|
||||
outlined = FALSE
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
|
||||
}
|
||||
165
app/ui.R
Normal file
165
app/ui.R
Normal file
@ -0,0 +1,165 @@
|
||||
library(shiny)
|
||||
source("global.R")
|
||||
|
||||
|
||||
# Define UI ------
|
||||
|
||||
shinyUI(fluidPage(
|
||||
title = 'TITLE',
|
||||
useShinyjs(),
|
||||
|
||||
tags$head(
|
||||
tags$link(rel = 'stylesheet', type = 'text/css', href = 'styles.css'),
|
||||
tags$link(rel = 'icon', href = 'fliptrans.png'),
|
||||
tags$link(rel = 'stylesheet', href = 'https://fonts.googleapis.com/css?family=Roboto+Mono'),
|
||||
tags$link(rel = 'stylesheet', href = 'https://fonts.googleapis.com/css?family=Inter')
|
||||
),
|
||||
tags$head(tags$script(src = 'rudderstack.js')),
|
||||
tags$style(type='text/css',
|
||||
'.shiny-output-error { visibility: hidden; }',
|
||||
'.shiny-output-error:before { visibility: hidden; }'
|
||||
),
|
||||
|
||||
withTags({
|
||||
header(class='top-banner',
|
||||
section(
|
||||
a(class='fs-logo', href='https://www.flipsidecrypto.com',
|
||||
'Powered by Flipside Crypto', onclick = 'rudderstack.track("ntr-click-flipside-icon")'),
|
||||
section(class='socials',
|
||||
a(class='twitter', href='https://twitter.com/flipsidecrypto',
|
||||
'Twitter', onclick = 'rudderstack.track("ntr-click-twitter-icon")'),
|
||||
a(class='linkedin', href='https://www.linkedin.com/company/flipside-crypto',
|
||||
'LinkedIn', onclick = 'rudderstack.track("ntr-click-linkedin-icon")'),
|
||||
a(class='discord', href='https://flipsidecrypto.com/discord',
|
||||
'Discord', onclick = 'rudderstack.track("ntr-click-discord-icon")'),
|
||||
a(href='https://app.flipsidecrypto.com/auth/signup/', # redirects to xyz signup
|
||||
'Sign Up', onclick = 'rudderstack.track("ntr-click-signup-icon")')
|
||||
)
|
||||
)
|
||||
)
|
||||
}),
|
||||
|
||||
# APP LABEL HERE -----------------------------------
|
||||
|
||||
withTags({
|
||||
section(class='hero',
|
||||
p("HERO IMAGE HERE"),
|
||||
h1(
|
||||
class='header',
|
||||
'TAGLINE TITLE',
|
||||
),
|
||||
p('TAGLINE'),
|
||||
)
|
||||
}),
|
||||
|
||||
# APP START HERE -----------------------------------
|
||||
|
||||
## EXAMPLE INPUTS DIV ----
|
||||
div( # re-using chart classes to make smoother outlining
|
||||
class = 'chart-container',
|
||||
div(
|
||||
class = 'chart-block',
|
||||
fluidRow(
|
||||
column(3,
|
||||
selectInput(inputId = 'selectinput',
|
||||
label = "Select Input",
|
||||
choices = c("a","b","c"),
|
||||
selected = NULL, multiple = TRUE)
|
||||
),
|
||||
column(3,
|
||||
radioButtons(inputId = 'selectinput',
|
||||
label = "Select Input",
|
||||
choices = c("a","b","c"),
|
||||
selected = NULL)
|
||||
),
|
||||
column(3,
|
||||
textAreaInput(inputId = "textarea",label = "Text Area", value = "area input")
|
||||
),
|
||||
column(3,
|
||||
textInput(inputId = "text",label = "Text", value = "text input")
|
||||
)
|
||||
),
|
||||
fluidRow(
|
||||
column(3,
|
||||
dateInput(inputId = 'selectdate',
|
||||
label = "Select Date",
|
||||
value = Sys.Date(),
|
||||
min = Sys.Date()- 100,
|
||||
max = Sys.Date() + 100)
|
||||
),
|
||||
column(3,
|
||||
dateRangeInput(inputId = "daterange",
|
||||
label = "Date Range",
|
||||
start = Sys.Date()-1,
|
||||
end = Sys.Date()+1,
|
||||
min = Sys.Date()- 100,
|
||||
max = Sys.Date() + 100)
|
||||
),
|
||||
column(3,
|
||||
numericInput(inputId = "numericinput",
|
||||
label = "Number",
|
||||
value = 1,
|
||||
min = -10,
|
||||
max = 10,
|
||||
step = 1)
|
||||
),
|
||||
column(3,
|
||||
checkboxGroupInput(inputId = 'checkboxgroup',
|
||||
label = "Checkbox Group",
|
||||
choices = c(1,2,3),
|
||||
selected = 1,
|
||||
choiceNames = c("One","Two","Three"))
|
||||
)
|
||||
)
|
||||
|
||||
)),
|
||||
|
||||
|
||||
## EXAMPLE PLOTLY Scatterplot CHART ----
|
||||
|
||||
div(
|
||||
class = 'chart-container',
|
||||
div(
|
||||
class = 'chart-block',
|
||||
div(class = 'chart-title', span('SCATTERPLOT EXAMPLE')),
|
||||
div(
|
||||
class = 'chart',
|
||||
plotlyOutput('exscatter')
|
||||
)
|
||||
)
|
||||
),
|
||||
|
||||
# EXAMPLE PLOTLY Barplot CHART ----
|
||||
|
||||
div(
|
||||
class = 'chart-container',
|
||||
div(
|
||||
class = 'chart-block',
|
||||
div(class = 'chart-title', span('BARPLOT EXAMPLE')),
|
||||
div(
|
||||
class = 'chart',
|
||||
plotlyOutput('exbar')
|
||||
)
|
||||
)
|
||||
),
|
||||
|
||||
# EXAMPLE FORM DIV
|
||||
|
||||
|
||||
# EXAMPLE REACTABLE TABLE DIV ----
|
||||
# re-using chart classes to make smoother
|
||||
div(
|
||||
class = 'chart-container',
|
||||
div(
|
||||
class = 'chart-block',
|
||||
div(class = 'chart-title', span('Reactable Table EXAMPLE')),
|
||||
reactableOutput("myreactable")
|
||||
)
|
||||
)
|
||||
|
||||
# EXAMPLE WALLET CONNECT DIV ----
|
||||
|
||||
|
||||
|
||||
) # end FluidPage
|
||||
) # end shinyUI
|
||||
BIN
app/www/fliplogo.jpg
Normal file
BIN
app/www/fliplogo.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.2 KiB |
3
app/www/rudderstack.js
Normal file
3
app/www/rudderstack.js
Normal file
@ -0,0 +1,3 @@
|
||||
!function(){var e=window.rudderanalytics=window.rudderanalytics||[];e.methods=["load","page","track","identify","alias","group","ready","reset","getAnonymousId","setAnonymousId"],e.factory=function(t){return function(){var r=Array.prototype.slice.call(arguments);return r.unshift(t),e.push(r),e}};for(var t=0;t<e.methods.length;t++){var r=e.methods[t];e[r]=e.factory(r)}e.loadJS=function(e,t){var r=document.createElement("script");r.type="text/javascript",r.async=!0,r.src="https://cdn.rudderlabs.com/v1.1/rudder-analytics.min.js";var a=document.getElementsByTagName("script")[0];a.parentNode.insertBefore(r,a)},e.loadJS(),
|
||||
e.load('29a6Pl6fLlx4iYiOdfxRt0IBad9','https://flipsidecrworumuyiulf.dataplane.rudderstack.com'),
|
||||
e.page()}();
|
||||
237
app/www/styles.css
Normal file
237
app/www/styles.css
Normal file
@ -0,0 +1,237 @@
|
||||
|
||||
/*******************/
|
||||
/*PUT CUSTOM CLASSES HERE*/
|
||||
/*******************/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*******************/
|
||||
/* GENERAL Page */
|
||||
/*******************/
|
||||
|
||||
body {
|
||||
background-color: #10151A;
|
||||
background-attachment:fixed;
|
||||
background-size: auto 100%;
|
||||
background-position: center;
|
||||
padding-left: 10%;
|
||||
padding-right: 10%;
|
||||
font-family: 'Inter';
|
||||
color: #FFFFFF;
|
||||
padding-bottom: 6rem;
|
||||
}
|
||||
|
||||
a {
|
||||
background: transparent;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 2%;
|
||||
background: #10151A;
|
||||
opacity: 0.5;
|
||||
border: 1px solid #637381;
|
||||
}
|
||||
|
||||
.container-fluid {
|
||||
background-color: #10151A;
|
||||
max-width: 1000px;
|
||||
margin: 0 auto;
|
||||
height: 100%;
|
||||
padding-top: 48px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/******************/
|
||||
/* Header Bar */
|
||||
/******************/
|
||||
.top-banner {
|
||||
background: #161E26;
|
||||
height: 48px;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
}
|
||||
.top-banner > section {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
justify-content: space-between;
|
||||
margin: 0 auto;
|
||||
padding: 0 15px;
|
||||
max-width: 1000px;
|
||||
}
|
||||
.top-banner a {
|
||||
background-color: transparent;
|
||||
}
|
||||
.top-banner a:hover, .top-banner a:active {
|
||||
color: #FFF;
|
||||
text-decoration: none;
|
||||
}
|
||||
.fs-logo {
|
||||
background: url("data:image/svg+xml,%3Csvg%20width=%2216%22%20height=%2216%22%20viewBox=%220%200%2016%2016%22%20fill=%22none%22%20xmlns=%22http://www.w3.org/2000/svg%22%3E%3Cpath%20fill-rule=%22evenodd%22%20clip-rule=%22evenodd%22%20d=%22M7.52088%2016C6.92112%2016%206.32136%2015.8477%205.78403%2015.543C4.56881%2014.8541%202.95205%2013.9375%201.73686%2013.2485C0.662092%2012.6393%200%2011.5131%200%2010.2945L0%205.70554C0%204.48686%200.662092%203.36075%201.73686%202.75144C2.95205%202.06249%204.56881%201.14593%205.78403%200.456977C6.85876%20-0.152326%208.18288%20-0.152326%209.25772%200.456977C10.4729%201.14593%2012.0896%202.06249%2013.3048%202.75144C13.8258%203.04684%2014.2499%203.46376%2014.5486%203.95377L9.23759%207.01154C8.19179%207.61937%207.52579%208.76857%207.52088%209.95417L7.52088%2016ZM15.0416%209.50549L15.0416%2010.2945C15.0416%2011.5131%2014.3796%2012.6393%2013.3048%2013.2485C12.0896%2013.9375%2010.4729%2014.8541%209.25772%2015.543C9.14451%2015.6072%209.02845%2015.6646%208.91038%2015.7153L8.91038%2014.29C8.91339%2013.5805%209.30794%2012.8961%209.9254%2012.5304C11.4418%2011.6491%2012.9692%2010.7862%2014.4855%209.90463C14.6838%209.78731%2014.8695%209.65331%2015.0416%209.50549ZM15.013%205.26806C15.0319%205.412%2015.0416%205.558%2015.0416%205.70554L15.0416%206.53731C15.0379%207.43057%2014.5405%208.27874%2013.7728%208.73349C12.2564%209.6148%2010.729%2010.4778%209.21271%2011.3591C9.10783%2011.4212%209.00693%2011.4887%208.91038%2011.5609L8.91038%209.95691C8.91333%209.23703%209.31737%208.5508%209.94293%208.1872L15.013%205.26806Z%22%20fill=%22white%22/%3E%3C/svg%3E") no-repeat left center;
|
||||
padding-left: 24px;
|
||||
}
|
||||
.socials {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
.socials a {
|
||||
display: inline-block;
|
||||
margin: 0 0.5em;
|
||||
overflow: hidden;
|
||||
text-indent: -9999px;
|
||||
white-space: nowrap;
|
||||
width: 24px;
|
||||
}
|
||||
.socials a:last-child {
|
||||
margin-right: 0;
|
||||
overflow: visible;
|
||||
text-indent: 0;
|
||||
width: auto;
|
||||
}
|
||||
.socials a:last-child::before {
|
||||
content: "|";
|
||||
margin: 0 0.5em;
|
||||
}
|
||||
.twitter {
|
||||
color: red;
|
||||
background: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8.94 18.7051C11.4989 18.7212 13.9577 17.7118 15.7672 15.9023C17.5767 14.0928 18.5861 11.634 18.57 9.0751V8.6326C19.2267 8.15147 19.7951 7.56023 20.25 6.8851C19.6316 7.15555 18.9773 7.33491 18.3075 7.4176C19.0177 6.99444 19.5506 6.32835 19.8075 5.5426C19.1456 5.93968 18.4199 6.21883 17.6625 6.3676C16.6139 5.25027 14.9461 4.97529 13.5943 5.69684C12.2425 6.41839 11.5428 7.95705 11.8875 9.4501C9.16635 9.31653 6.63036 8.03218 4.9125 5.9176C4.02372 7.46019 4.4828 9.42766 5.9625 10.4176C5.43646 10.3973 4.92259 10.2534 4.4625 9.9976V10.0351C4.45287 11.6359 5.56204 13.0263 7.125 13.3726C6.63573 13.5042 6.12322 13.5247 5.625 13.4326C6.07495 14.7902 7.33014 15.7181 8.76 15.7501C7.56691 16.7105 6.08407 17.2391 4.5525 17.2501C4.28396 17.2423 4.01606 17.2198 3.75 17.1826C5.30022 18.1703 7.1019 18.691 8.94 18.6826' fill='%23F4F6F8'/%3E%3C/svg%3E%0A") no-repeat center center;
|
||||
}
|
||||
.linkedin {
|
||||
background: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M19.6575 3.00002H4.3425C3.61669 2.99566 3.02038 3.57199 3 4.29752V19.65C3.01639 20.3773 3.61508 20.9559 4.3425 20.9475H19.6575C20.3849 20.9559 20.9836 20.3773 21 19.65V4.29752C20.9796 3.57199 20.3833 2.99566 19.6575 3.00002ZM8.3325 18.3075H5.6925V9.75002H8.3325V18.3075ZM7.0425 8.55752C6.19951 8.55777 5.51036 7.88527 5.49 7.04252C5.47516 6.6264 5.63396 6.22284 5.92839 5.92841C6.22282 5.63398 6.62638 5.47519 7.0425 5.49002C7.8561 5.54668 8.48716 6.2232 8.48716 7.03877C8.48716 7.85435 7.8561 8.53087 7.0425 8.58752V8.55752ZM18.36 18.255H15.75V14.07C15.75 13.0725 15.75 11.775 14.355 11.775C12.96 11.775 12.75 12.87 12.75 13.9725V18.21H10.08V9.75002H12.57V10.875H12.6225C13.1428 9.97149 14.1234 9.43343 15.165 9.48002C17.8575 9.48002 18.36 11.28 18.36 13.5675V18.255Z' fill='%23F4F6F8'/%3E%3C/svg%3E%0A") no-repeat center center;
|
||||
}
|
||||
.discord {
|
||||
background: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M10.2354 11.1801C10.0175 11.1617 9.79902 11.2095 9.60868 11.3172C9.41833 11.425 9.26496 11.5877 9.16863 11.7841C9.07229 11.9804 9.0375 12.2013 9.06879 12.4178C9.10008 12.6343 9.19601 12.8363 9.34401 12.9973C9.492 13.1584 9.68518 13.271 9.89825 13.3205C10.1113 13.3699 10.3344 13.3539 10.5382 13.2744C10.742 13.195 10.917 13.0559 11.0405 12.8753C11.1639 12.6948 11.2299 12.4811 11.2299 12.2624C11.2358 12.126 11.2147 11.9898 11.1678 11.8616C11.121 11.7334 11.0493 11.6157 10.957 11.5151C10.8646 11.4146 10.7533 11.3333 10.6295 11.2758C10.5057 11.2184 10.3718 11.1858 10.2354 11.1801ZM13.7942 11.1801C13.5762 11.1617 13.3578 11.2095 13.1674 11.3172C12.9771 11.425 12.8237 11.5877 12.7274 11.7841C12.631 11.9804 12.5962 12.2013 12.6275 12.4178C12.6588 12.6343 12.7548 12.8363 12.9028 12.9973C13.0508 13.1584 13.2439 13.271 13.457 13.3205C13.6701 13.3699 13.8931 13.3539 14.0969 13.2744C14.3007 13.195 14.4758 13.0559 14.5992 12.8753C14.7226 12.6948 14.7887 12.4811 14.7887 12.2624C14.7945 12.126 14.7734 11.9898 14.7266 11.8616C14.6797 11.7334 14.6081 11.6157 14.5157 11.5151C14.4234 11.4146 14.3121 11.3333 14.1883 11.2758C14.0645 11.2184 13.9306 11.1858 13.7942 11.1801Z' fill='%23F4F6F8'/%3E%3Cpath d='M18.5325 3H5.46751C5.20438 3.00063 4.94396 3.05308 4.70111 3.15436C4.45826 3.25564 4.23774 3.40376 4.05213 3.59027C3.86653 3.77678 3.71948 3.99802 3.61939 4.24136C3.51929 4.4847 3.46811 4.74538 3.46876 5.0085V18.1905C3.46811 18.4536 3.51929 18.7143 3.61939 18.9576C3.71948 19.201 3.86653 19.4222 4.05213 19.6087C4.23774 19.7952 4.45826 19.9434 4.70111 20.0446C4.94396 20.1459 5.20438 20.1984 5.46751 20.199H16.524L16.0073 18.3953L17.2553 19.5555L18.435 20.6475L20.5313 22.5V5.0085C20.5319 4.74538 20.4807 4.4847 20.3806 4.24136C20.2805 3.99802 20.1335 3.77678 19.9479 3.59027C19.7623 3.40376 19.5418 3.25564 19.2989 3.15436C19.0561 3.05308 18.7956 3.00063 18.5325 3ZM14.769 15.7335C14.769 15.7335 14.418 15.3142 14.1255 14.9437C14.8322 14.7774 15.4573 14.3664 15.8903 13.7835C15.5394 14.017 15.1633 14.21 14.769 14.3588C14.3154 14.5524 13.8411 14.693 13.3553 14.778C12.5202 14.9317 11.6638 14.9284 10.83 14.7682C10.3405 14.6725 9.86073 14.5321 9.39676 14.349C9.15219 14.255 8.91437 14.1442 8.68501 14.0175C8.65576 13.998 8.62651 13.9882 8.59726 13.9688C8.58259 13.9614 8.56937 13.9515 8.55826 13.9395C8.38276 13.842 8.28526 13.7738 8.28526 13.7738C8.70251 14.3444 9.30604 14.7514 9.99151 14.9242C9.69901 15.2948 9.33826 15.7335 9.33826 15.7335C8.75909 15.7491 8.18497 15.6221 7.66642 15.3636C7.14787 15.1052 6.70078 14.7233 6.36451 14.2515C6.39616 12.2749 6.87623 10.3313 7.76851 8.56725C8.55372 7.95055 9.51103 7.59283 10.5083 7.5435L10.6058 7.6605C9.66755 7.89268 8.79203 8.32877 8.04151 8.93775C8.04151 8.93775 8.25601 8.82075 8.61676 8.655C9.3176 8.33509 10.0645 8.12779 10.83 8.04075C10.8846 8.02945 10.94 8.02293 10.9958 8.02125C11.6491 7.93613 12.3103 7.92958 12.9653 8.00175C13.9952 8.11938 14.9922 8.43735 15.9 8.93775C15.1875 8.3578 14.36 7.93574 13.4723 7.6995L13.6088 7.5435C14.606 7.59283 15.5633 7.95055 16.3485 8.56725C17.2408 10.3313 17.7209 12.2749 17.7525 14.2515C17.4135 14.7229 16.9645 15.1043 16.4446 15.3625C15.9246 15.6208 15.3494 15.7482 14.769 15.7335Z' fill='%23F4F6F8'/%3E%3C/svg%3E%0A") no-repeat center center;
|
||||
}
|
||||
.hero {
|
||||
margin: 1.5em 0;
|
||||
text-align: center;
|
||||
}
|
||||
.hero > p {
|
||||
color: #E5E5E5;
|
||||
font-size: 20px;
|
||||
margin-top: 1em;
|
||||
}
|
||||
.header {
|
||||
margin: 0;
|
||||
color: #03FFFF;
|
||||
font-family: 'Inter', sans-serif;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
/*****************/
|
||||
/* GENERAL Forms */
|
||||
/*****************/
|
||||
|
||||
/* helps with dropdown menu conflicts w/ body */
|
||||
|
||||
.dropdown-menu {
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
padding: 10px 10px 0;
|
||||
margin: none !important;
|
||||
}
|
||||
.form-control {
|
||||
background: #10151A;
|
||||
border: 1px solid #03FFFF;
|
||||
border-radius: 4px;
|
||||
font-family: Roboto Mono !important;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
input::-webkit-outer-spin-button,
|
||||
input::-webkit-inner-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
input[type=number] {
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
|
||||
|
||||
/******************/
|
||||
/* GENERAL Charts */
|
||||
/******************/
|
||||
.chart-block {
|
||||
background: #171E25;
|
||||
border: 2px solid rgba(45, 109, 135, 0.5);
|
||||
border-radius: 16px;
|
||||
}
|
||||
.chart-block > .row > .col-sm-6 {
|
||||
padding: 0;
|
||||
}
|
||||
.col-sm-6 > .chart {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.chart-title {
|
||||
font-family: Inter;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-size: 20px;
|
||||
line-height: 150%;
|
||||
color: white;
|
||||
padding: 32px 32px 20px;
|
||||
}
|
||||
.chart {
|
||||
border-bottom-left-radius: 16px;
|
||||
border-bottom-right-radius: 16px;
|
||||
padding: 0 32px;
|
||||
background: linear-gradient(
|
||||
360deg
|
||||
, rgba(16, 21, 26, 1) 0%
|
||||
, rgba(16, 21, 26, 1) 11%
|
||||
, rgba(0, 204, 255, 0.3) 11%
|
||||
, rgba(0, 204, 255, 0) 100%
|
||||
);
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
padding: 10px 0;;
|
||||
}
|
||||
|
||||
|
||||
/******************/
|
||||
/* REACTABLE Tables */
|
||||
/******************/
|
||||
|
||||
.rt-page-button-current {
|
||||
color: #FFF;
|
||||
}
|
||||
.rt-thead {
|
||||
background-color: #10151A;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.ReactTable {
|
||||
background-color: #171e25;
|
||||
color: #C4CDD5;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.rt-th {
|
||||
border: 0px solid #000000 !important;
|
||||
padding-top: 15px;
|
||||
padding-bottom: 15px;
|
||||
font-weight: 400;
|
||||
font-family: Inter;
|
||||
}
|
||||
.rt-tr {
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
.rt-pagination {
|
||||
margin: 0;
|
||||
background: #171e25;
|
||||
opacity: 0.5;
|
||||
border-bottom: 1px solid #C4CDD5;
|
||||
border-top: 1px solid #C4CDD5;
|
||||
}
|
||||
13
real-time-data-lag.Rproj
Normal file
13
real-time-data-lag.Rproj
Normal file
@ -0,0 +1,13 @@
|
||||
Version: 1.0
|
||||
|
||||
RestoreWorkspace: Default
|
||||
SaveWorkspace: Default
|
||||
AlwaysSaveHistory: Default
|
||||
|
||||
EnableCodeIndexing: Yes
|
||||
UseSpacesForTab: Yes
|
||||
NumSpacesForTab: 2
|
||||
Encoding: UTF-8
|
||||
|
||||
RnwWeave: Sweave
|
||||
LaTeX: pdfLaTeX
|
||||
331
renv.lock
Normal file
331
renv.lock
Normal file
@ -0,0 +1,331 @@
|
||||
{
|
||||
"R": {
|
||||
"Version": "4.2.1",
|
||||
"Repositories": [
|
||||
{
|
||||
"Name": "CRAN",
|
||||
"URL": "https://cran.rstudio.com"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Packages": {
|
||||
"R6": {
|
||||
"Package": "R6",
|
||||
"Version": "2.5.1",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "470851b6d5d0ac559e9d01bb352b4021",
|
||||
"Requirements": []
|
||||
},
|
||||
"Rcpp": {
|
||||
"Package": "Rcpp",
|
||||
"Version": "1.0.9",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "e9c08b94391e9f3f97355841229124f2",
|
||||
"Requirements": []
|
||||
},
|
||||
"base64enc": {
|
||||
"Package": "base64enc",
|
||||
"Version": "0.1-3",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "543776ae6848fde2f48ff3816d0628bc",
|
||||
"Requirements": []
|
||||
},
|
||||
"bslib": {
|
||||
"Package": "bslib",
|
||||
"Version": "0.4.0",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "be5ee090716ce1671be6cd5d7c34d091",
|
||||
"Requirements": [
|
||||
"cachem",
|
||||
"htmltools",
|
||||
"jquerylib",
|
||||
"jsonlite",
|
||||
"memoise",
|
||||
"rlang",
|
||||
"sass"
|
||||
]
|
||||
},
|
||||
"cachem": {
|
||||
"Package": "cachem",
|
||||
"Version": "1.0.6",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "648c5b3d71e6a37e3043617489a0a0e9",
|
||||
"Requirements": [
|
||||
"fastmap",
|
||||
"rlang"
|
||||
]
|
||||
},
|
||||
"commonmark": {
|
||||
"Package": "commonmark",
|
||||
"Version": "1.8.0",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "2ba81b120c1655ab696c935ef33ea716",
|
||||
"Requirements": []
|
||||
},
|
||||
"crayon": {
|
||||
"Package": "crayon",
|
||||
"Version": "1.5.1",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "8dc45fd8a1ee067a92b85ef274e66d6a",
|
||||
"Requirements": []
|
||||
},
|
||||
"digest": {
|
||||
"Package": "digest",
|
||||
"Version": "0.6.29",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "cf6b206a045a684728c3267ef7596190",
|
||||
"Requirements": []
|
||||
},
|
||||
"ellipsis": {
|
||||
"Package": "ellipsis",
|
||||
"Version": "0.3.2",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "bb0eec2fe32e88d9e2836c2f73ea2077",
|
||||
"Requirements": [
|
||||
"rlang"
|
||||
]
|
||||
},
|
||||
"fastmap": {
|
||||
"Package": "fastmap",
|
||||
"Version": "1.1.0",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "77bd60a6157420d4ffa93b27cf6a58b8",
|
||||
"Requirements": []
|
||||
},
|
||||
"fontawesome": {
|
||||
"Package": "fontawesome",
|
||||
"Version": "0.3.0",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "a36c4a3eade472039a3ec8cb824e6dc4",
|
||||
"Requirements": [
|
||||
"htmltools",
|
||||
"rlang"
|
||||
]
|
||||
},
|
||||
"fs": {
|
||||
"Package": "fs",
|
||||
"Version": "1.5.2",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "7c89603d81793f0d5486d91ab1fc6f1d",
|
||||
"Requirements": []
|
||||
},
|
||||
"glue": {
|
||||
"Package": "glue",
|
||||
"Version": "1.6.2",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "4f2596dfb05dac67b9dc558e5c6fba2e",
|
||||
"Requirements": []
|
||||
},
|
||||
"htmltools": {
|
||||
"Package": "htmltools",
|
||||
"Version": "0.5.3",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "6496090a9e00f8354b811d1a2d47b566",
|
||||
"Requirements": [
|
||||
"base64enc",
|
||||
"digest",
|
||||
"fastmap",
|
||||
"rlang"
|
||||
]
|
||||
},
|
||||
"httpuv": {
|
||||
"Package": "httpuv",
|
||||
"Version": "1.6.5",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "97fe71f0a4a1c9890e6c2128afa04bc0",
|
||||
"Requirements": [
|
||||
"R6",
|
||||
"Rcpp",
|
||||
"later",
|
||||
"promises"
|
||||
]
|
||||
},
|
||||
"jquerylib": {
|
||||
"Package": "jquerylib",
|
||||
"Version": "0.1.4",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "5aab57a3bd297eee1c1d862735972182",
|
||||
"Requirements": [
|
||||
"htmltools"
|
||||
]
|
||||
},
|
||||
"jsonlite": {
|
||||
"Package": "jsonlite",
|
||||
"Version": "1.8.0",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "d07e729b27b372429d42d24d503613a0",
|
||||
"Requirements": []
|
||||
},
|
||||
"later": {
|
||||
"Package": "later",
|
||||
"Version": "1.3.0",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "7e7b457d7766bc47f2a5f21cc2984f8e",
|
||||
"Requirements": [
|
||||
"Rcpp",
|
||||
"rlang"
|
||||
]
|
||||
},
|
||||
"lifecycle": {
|
||||
"Package": "lifecycle",
|
||||
"Version": "1.0.1",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "a6b6d352e3ed897373ab19d8395c98d0",
|
||||
"Requirements": [
|
||||
"glue",
|
||||
"rlang"
|
||||
]
|
||||
},
|
||||
"magrittr": {
|
||||
"Package": "magrittr",
|
||||
"Version": "2.0.3",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "7ce2733a9826b3aeb1775d56fd305472",
|
||||
"Requirements": []
|
||||
},
|
||||
"memoise": {
|
||||
"Package": "memoise",
|
||||
"Version": "2.0.1",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "e2817ccf4a065c5d9d7f2cfbe7c1d78c",
|
||||
"Requirements": [
|
||||
"cachem",
|
||||
"rlang"
|
||||
]
|
||||
},
|
||||
"mime": {
|
||||
"Package": "mime",
|
||||
"Version": "0.12",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "18e9c28c1d3ca1560ce30658b22ce104",
|
||||
"Requirements": []
|
||||
},
|
||||
"promises": {
|
||||
"Package": "promises",
|
||||
"Version": "1.2.0.1",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "4ab2c43adb4d4699cf3690acd378d75d",
|
||||
"Requirements": [
|
||||
"R6",
|
||||
"Rcpp",
|
||||
"later",
|
||||
"magrittr",
|
||||
"rlang"
|
||||
]
|
||||
},
|
||||
"rappdirs": {
|
||||
"Package": "rappdirs",
|
||||
"Version": "0.3.3",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "5e3c5dc0b071b21fa128676560dbe94d",
|
||||
"Requirements": []
|
||||
},
|
||||
"renv": {
|
||||
"Package": "renv",
|
||||
"Version": "0.15.5",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "6a38294e7d12f5d8e656b08c5bd8ae34",
|
||||
"Requirements": []
|
||||
},
|
||||
"rlang": {
|
||||
"Package": "rlang",
|
||||
"Version": "1.0.4",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "6539dd8c651e67e3b55b5ffea106362b",
|
||||
"Requirements": []
|
||||
},
|
||||
"sass": {
|
||||
"Package": "sass",
|
||||
"Version": "0.4.2",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "1b191143d7d3444d504277843f3a95fe",
|
||||
"Requirements": [
|
||||
"R6",
|
||||
"fs",
|
||||
"htmltools",
|
||||
"rappdirs",
|
||||
"rlang"
|
||||
]
|
||||
},
|
||||
"shiny": {
|
||||
"Package": "shiny",
|
||||
"Version": "1.7.2",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "4f7970a3edb0a153ac6b376785a1944a",
|
||||
"Requirements": [
|
||||
"R6",
|
||||
"bslib",
|
||||
"cachem",
|
||||
"commonmark",
|
||||
"crayon",
|
||||
"ellipsis",
|
||||
"fastmap",
|
||||
"fontawesome",
|
||||
"glue",
|
||||
"htmltools",
|
||||
"httpuv",
|
||||
"jsonlite",
|
||||
"later",
|
||||
"lifecycle",
|
||||
"mime",
|
||||
"promises",
|
||||
"rlang",
|
||||
"sourcetools",
|
||||
"withr",
|
||||
"xtable"
|
||||
]
|
||||
},
|
||||
"sourcetools": {
|
||||
"Package": "sourcetools",
|
||||
"Version": "0.1.7",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "947e4e02a79effa5d512473e10f41797",
|
||||
"Requirements": []
|
||||
},
|
||||
"withr": {
|
||||
"Package": "withr",
|
||||
"Version": "2.5.0",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "c0e49a9760983e81e55cdd9be92e7182",
|
||||
"Requirements": []
|
||||
},
|
||||
"xtable": {
|
||||
"Package": "xtable",
|
||||
"Version": "1.8-4",
|
||||
"Source": "Repository",
|
||||
"Repository": "CRAN",
|
||||
"Hash": "b8acdf8af494d9ec19ccb2481a9b11c2",
|
||||
"Requirements": []
|
||||
}
|
||||
}
|
||||
}
|
||||
6
renv/.gitignore
vendored
Normal file
6
renv/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
library/
|
||||
local/
|
||||
cellar/
|
||||
lock/
|
||||
python/
|
||||
staging/
|
||||
942
renv/activate.R
Normal file
942
renv/activate.R
Normal file
@ -0,0 +1,942 @@
|
||||
|
||||
local({
|
||||
|
||||
# the requested version of renv
|
||||
version <- "0.15.5"
|
||||
|
||||
# the project directory
|
||||
project <- getwd()
|
||||
|
||||
# figure out whether the autoloader is enabled
|
||||
enabled <- local({
|
||||
|
||||
# first, check config option
|
||||
override <- getOption("renv.config.autoloader.enabled")
|
||||
if (!is.null(override))
|
||||
return(override)
|
||||
|
||||
# next, check environment variables
|
||||
# TODO: prefer using the configuration one in the future
|
||||
envvars <- c(
|
||||
"RENV_CONFIG_AUTOLOADER_ENABLED",
|
||||
"RENV_AUTOLOADER_ENABLED",
|
||||
"RENV_ACTIVATE_PROJECT"
|
||||
)
|
||||
|
||||
for (envvar in envvars) {
|
||||
envval <- Sys.getenv(envvar, unset = NA)
|
||||
if (!is.na(envval))
|
||||
return(tolower(envval) %in% c("true", "t", "1"))
|
||||
}
|
||||
|
||||
# enable by default
|
||||
TRUE
|
||||
|
||||
})
|
||||
|
||||
if (!enabled)
|
||||
return(FALSE)
|
||||
|
||||
# avoid recursion
|
||||
if (identical(getOption("renv.autoloader.running"), TRUE)) {
|
||||
warning("ignoring recursive attempt to run renv autoloader")
|
||||
return(invisible(TRUE))
|
||||
}
|
||||
|
||||
# signal that we're loading renv during R startup
|
||||
options(renv.autoloader.running = TRUE)
|
||||
on.exit(options(renv.autoloader.running = NULL), add = TRUE)
|
||||
|
||||
# signal that we've consented to use renv
|
||||
options(renv.consent = TRUE)
|
||||
|
||||
# load the 'utils' package eagerly -- this ensures that renv shims, which
|
||||
# mask 'utils' packages, will come first on the search path
|
||||
library(utils, lib.loc = .Library)
|
||||
|
||||
# unload renv if it's already been loaded
|
||||
if ("renv" %in% loadedNamespaces())
|
||||
unloadNamespace("renv")
|
||||
|
||||
# load bootstrap tools
|
||||
`%||%` <- function(x, y) {
|
||||
if (is.environment(x) || length(x)) x else y
|
||||
}
|
||||
|
||||
bootstrap <- function(version, library) {
|
||||
|
||||
# attempt to download renv
|
||||
tarball <- tryCatch(renv_bootstrap_download(version), error = identity)
|
||||
if (inherits(tarball, "error"))
|
||||
stop("failed to download renv ", version)
|
||||
|
||||
# now attempt to install
|
||||
status <- tryCatch(renv_bootstrap_install(version, tarball, library), error = identity)
|
||||
if (inherits(status, "error"))
|
||||
stop("failed to install renv ", version)
|
||||
|
||||
}
|
||||
|
||||
renv_bootstrap_tests_running <- function() {
|
||||
getOption("renv.tests.running", default = FALSE)
|
||||
}
|
||||
|
||||
renv_bootstrap_repos <- function() {
|
||||
|
||||
# check for repos override
|
||||
repos <- Sys.getenv("RENV_CONFIG_REPOS_OVERRIDE", unset = NA)
|
||||
if (!is.na(repos))
|
||||
return(repos)
|
||||
|
||||
# check for lockfile repositories
|
||||
repos <- tryCatch(renv_bootstrap_repos_lockfile(), error = identity)
|
||||
if (!inherits(repos, "error") && length(repos))
|
||||
return(repos)
|
||||
|
||||
# if we're testing, re-use the test repositories
|
||||
if (renv_bootstrap_tests_running())
|
||||
return(getOption("renv.tests.repos"))
|
||||
|
||||
# retrieve current repos
|
||||
repos <- getOption("repos")
|
||||
|
||||
# ensure @CRAN@ entries are resolved
|
||||
repos[repos == "@CRAN@"] <- getOption(
|
||||
"renv.repos.cran",
|
||||
"https://cloud.r-project.org"
|
||||
)
|
||||
|
||||
# add in renv.bootstrap.repos if set
|
||||
default <- c(FALLBACK = "https://cloud.r-project.org")
|
||||
extra <- getOption("renv.bootstrap.repos", default = default)
|
||||
repos <- c(repos, extra)
|
||||
|
||||
# remove duplicates that might've snuck in
|
||||
dupes <- duplicated(repos) | duplicated(names(repos))
|
||||
repos[!dupes]
|
||||
|
||||
}
|
||||
|
||||
renv_bootstrap_repos_lockfile <- function() {
|
||||
|
||||
lockpath <- Sys.getenv("RENV_PATHS_LOCKFILE", unset = "renv.lock")
|
||||
if (!file.exists(lockpath))
|
||||
return(NULL)
|
||||
|
||||
lockfile <- tryCatch(renv_json_read(lockpath), error = identity)
|
||||
if (inherits(lockfile, "error")) {
|
||||
warning(lockfile)
|
||||
return(NULL)
|
||||
}
|
||||
|
||||
repos <- lockfile$R$Repositories
|
||||
if (length(repos) == 0)
|
||||
return(NULL)
|
||||
|
||||
keys <- vapply(repos, `[[`, "Name", FUN.VALUE = character(1))
|
||||
vals <- vapply(repos, `[[`, "URL", FUN.VALUE = character(1))
|
||||
names(vals) <- keys
|
||||
|
||||
return(vals)
|
||||
|
||||
}
|
||||
|
||||
renv_bootstrap_download <- function(version) {
|
||||
|
||||
# if the renv version number has 4 components, assume it must
|
||||
# be retrieved via github
|
||||
nv <- numeric_version(version)
|
||||
components <- unclass(nv)[[1]]
|
||||
|
||||
# if this appears to be a development version of 'renv', we'll
|
||||
# try to restore from github
|
||||
dev <- length(components) == 4L
|
||||
|
||||
# begin collecting different methods for finding renv
|
||||
methods <- c(
|
||||
renv_bootstrap_download_tarball,
|
||||
if (dev)
|
||||
renv_bootstrap_download_github
|
||||
else c(
|
||||
renv_bootstrap_download_cran_latest,
|
||||
renv_bootstrap_download_cran_archive
|
||||
)
|
||||
)
|
||||
|
||||
for (method in methods) {
|
||||
path <- tryCatch(method(version), error = identity)
|
||||
if (is.character(path) && file.exists(path))
|
||||
return(path)
|
||||
}
|
||||
|
||||
stop("failed to download renv ", version)
|
||||
|
||||
}
|
||||
|
||||
renv_bootstrap_download_impl <- function(url, destfile) {
|
||||
|
||||
mode <- "wb"
|
||||
|
||||
# https://bugs.r-project.org/bugzilla/show_bug.cgi?id=17715
|
||||
fixup <-
|
||||
Sys.info()[["sysname"]] == "Windows" &&
|
||||
substring(url, 1L, 5L) == "file:"
|
||||
|
||||
if (fixup)
|
||||
mode <- "w+b"
|
||||
|
||||
utils::download.file(
|
||||
url = url,
|
||||
destfile = destfile,
|
||||
mode = mode,
|
||||
quiet = TRUE
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
renv_bootstrap_download_cran_latest <- function(version) {
|
||||
|
||||
spec <- renv_bootstrap_download_cran_latest_find(version)
|
||||
|
||||
message("* Downloading renv ", version, " ... ", appendLF = FALSE)
|
||||
|
||||
type <- spec$type
|
||||
repos <- spec$repos
|
||||
|
||||
info <- tryCatch(
|
||||
utils::download.packages(
|
||||
pkgs = "renv",
|
||||
destdir = tempdir(),
|
||||
repos = repos,
|
||||
type = type,
|
||||
quiet = TRUE
|
||||
),
|
||||
condition = identity
|
||||
)
|
||||
|
||||
if (inherits(info, "condition")) {
|
||||
message("FAILED")
|
||||
return(FALSE)
|
||||
}
|
||||
|
||||
# report success and return
|
||||
message("OK (downloaded ", type, ")")
|
||||
info[1, 2]
|
||||
|
||||
}
|
||||
|
||||
renv_bootstrap_download_cran_latest_find <- function(version) {
|
||||
|
||||
# check whether binaries are supported on this system
|
||||
binary <-
|
||||
getOption("renv.bootstrap.binary", default = TRUE) &&
|
||||
!identical(.Platform$pkgType, "source") &&
|
||||
!identical(getOption("pkgType"), "source") &&
|
||||
Sys.info()[["sysname"]] %in% c("Darwin", "Windows")
|
||||
|
||||
types <- c(if (binary) "binary", "source")
|
||||
|
||||
# iterate over types + repositories
|
||||
for (type in types) {
|
||||
for (repos in renv_bootstrap_repos()) {
|
||||
|
||||
# retrieve package database
|
||||
db <- tryCatch(
|
||||
as.data.frame(
|
||||
utils::available.packages(type = type, repos = repos),
|
||||
stringsAsFactors = FALSE
|
||||
),
|
||||
error = identity
|
||||
)
|
||||
|
||||
if (inherits(db, "error"))
|
||||
next
|
||||
|
||||
# check for compatible entry
|
||||
entry <- db[db$Package %in% "renv" & db$Version %in% version, ]
|
||||
if (nrow(entry) == 0)
|
||||
next
|
||||
|
||||
# found it; return spec to caller
|
||||
spec <- list(entry = entry, type = type, repos = repos)
|
||||
return(spec)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
# if we got here, we failed to find renv
|
||||
fmt <- "renv %s is not available from your declared package repositories"
|
||||
stop(sprintf(fmt, version))
|
||||
|
||||
}
|
||||
|
||||
renv_bootstrap_download_cran_archive <- function(version) {
|
||||
|
||||
name <- sprintf("renv_%s.tar.gz", version)
|
||||
repos <- renv_bootstrap_repos()
|
||||
urls <- file.path(repos, "src/contrib/Archive/renv", name)
|
||||
destfile <- file.path(tempdir(), name)
|
||||
|
||||
message("* Downloading renv ", version, " ... ", appendLF = FALSE)
|
||||
|
||||
for (url in urls) {
|
||||
|
||||
status <- tryCatch(
|
||||
renv_bootstrap_download_impl(url, destfile),
|
||||
condition = identity
|
||||
)
|
||||
|
||||
if (identical(status, 0L)) {
|
||||
message("OK")
|
||||
return(destfile)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
message("FAILED")
|
||||
return(FALSE)
|
||||
|
||||
}
|
||||
|
||||
renv_bootstrap_download_tarball <- function(version) {
|
||||
|
||||
# if the user has provided the path to a tarball via
|
||||
# an environment variable, then use it
|
||||
tarball <- Sys.getenv("RENV_BOOTSTRAP_TARBALL", unset = NA)
|
||||
if (is.na(tarball))
|
||||
return()
|
||||
|
||||
# allow directories
|
||||
info <- file.info(tarball, extra_cols = FALSE)
|
||||
if (identical(info$isdir, TRUE)) {
|
||||
name <- sprintf("renv_%s.tar.gz", version)
|
||||
tarball <- file.path(tarball, name)
|
||||
}
|
||||
|
||||
# bail if it doesn't exist
|
||||
if (!file.exists(tarball)) {
|
||||
|
||||
# let the user know we weren't able to honour their request
|
||||
fmt <- "* RENV_BOOTSTRAP_TARBALL is set (%s) but does not exist."
|
||||
msg <- sprintf(fmt, tarball)
|
||||
warning(msg)
|
||||
|
||||
# bail
|
||||
return()
|
||||
|
||||
}
|
||||
|
||||
fmt <- "* Bootstrapping with tarball at path '%s'."
|
||||
msg <- sprintf(fmt, tarball)
|
||||
message(msg)
|
||||
|
||||
tarball
|
||||
|
||||
}
|
||||
|
||||
renv_bootstrap_download_github <- function(version) {
|
||||
|
||||
enabled <- Sys.getenv("RENV_BOOTSTRAP_FROM_GITHUB", unset = "TRUE")
|
||||
if (!identical(enabled, "TRUE"))
|
||||
return(FALSE)
|
||||
|
||||
# prepare download options
|
||||
pat <- Sys.getenv("GITHUB_PAT")
|
||||
if (nzchar(Sys.which("curl")) && nzchar(pat)) {
|
||||
fmt <- "--location --fail --header \"Authorization: token %s\""
|
||||
extra <- sprintf(fmt, pat)
|
||||
saved <- options("download.file.method", "download.file.extra")
|
||||
options(download.file.method = "curl", download.file.extra = extra)
|
||||
on.exit(do.call(base::options, saved), add = TRUE)
|
||||
} else if (nzchar(Sys.which("wget")) && nzchar(pat)) {
|
||||
fmt <- "--header=\"Authorization: token %s\""
|
||||
extra <- sprintf(fmt, pat)
|
||||
saved <- options("download.file.method", "download.file.extra")
|
||||
options(download.file.method = "wget", download.file.extra = extra)
|
||||
on.exit(do.call(base::options, saved), add = TRUE)
|
||||
}
|
||||
|
||||
message("* Downloading renv ", version, " from GitHub ... ", appendLF = FALSE)
|
||||
|
||||
url <- file.path("https://api.github.com/repos/rstudio/renv/tarball", version)
|
||||
name <- sprintf("renv_%s.tar.gz", version)
|
||||
destfile <- file.path(tempdir(), name)
|
||||
|
||||
status <- tryCatch(
|
||||
renv_bootstrap_download_impl(url, destfile),
|
||||
condition = identity
|
||||
)
|
||||
|
||||
if (!identical(status, 0L)) {
|
||||
message("FAILED")
|
||||
return(FALSE)
|
||||
}
|
||||
|
||||
message("OK")
|
||||
return(destfile)
|
||||
|
||||
}
|
||||
|
||||
renv_bootstrap_install <- function(version, tarball, library) {
|
||||
|
||||
# attempt to install it into project library
|
||||
message("* Installing renv ", version, " ... ", appendLF = FALSE)
|
||||
dir.create(library, showWarnings = FALSE, recursive = TRUE)
|
||||
|
||||
# invoke using system2 so we can capture and report output
|
||||
bin <- R.home("bin")
|
||||
exe <- if (Sys.info()[["sysname"]] == "Windows") "R.exe" else "R"
|
||||
r <- file.path(bin, exe)
|
||||
|
||||
args <- c(
|
||||
"--vanilla", "CMD", "INSTALL", "--no-multiarch",
|
||||
"-l", shQuote(path.expand(library)),
|
||||
shQuote(path.expand(tarball))
|
||||
)
|
||||
|
||||
output <- system2(r, args, stdout = TRUE, stderr = TRUE)
|
||||
message("Done!")
|
||||
|
||||
# check for successful install
|
||||
status <- attr(output, "status")
|
||||
if (is.numeric(status) && !identical(status, 0L)) {
|
||||
header <- "Error installing renv:"
|
||||
lines <- paste(rep.int("=", nchar(header)), collapse = "")
|
||||
text <- c(header, lines, output)
|
||||
writeLines(text, con = stderr())
|
||||
}
|
||||
|
||||
status
|
||||
|
||||
}
|
||||
|
||||
renv_bootstrap_platform_prefix <- function() {
|
||||
|
||||
# construct version prefix
|
||||
version <- paste(R.version$major, R.version$minor, sep = ".")
|
||||
prefix <- paste("R", numeric_version(version)[1, 1:2], sep = "-")
|
||||
|
||||
# include SVN revision for development versions of R
|
||||
# (to avoid sharing platform-specific artefacts with released versions of R)
|
||||
devel <-
|
||||
identical(R.version[["status"]], "Under development (unstable)") ||
|
||||
identical(R.version[["nickname"]], "Unsuffered Consequences")
|
||||
|
||||
if (devel)
|
||||
prefix <- paste(prefix, R.version[["svn rev"]], sep = "-r")
|
||||
|
||||
# build list of path components
|
||||
components <- c(prefix, R.version$platform)
|
||||
|
||||
# include prefix if provided by user
|
||||
prefix <- renv_bootstrap_platform_prefix_impl()
|
||||
if (!is.na(prefix) && nzchar(prefix))
|
||||
components <- c(prefix, components)
|
||||
|
||||
# build prefix
|
||||
paste(components, collapse = "/")
|
||||
|
||||
}
|
||||
|
||||
renv_bootstrap_platform_prefix_impl <- function() {
|
||||
|
||||
# if an explicit prefix has been supplied, use it
|
||||
prefix <- Sys.getenv("RENV_PATHS_PREFIX", unset = NA)
|
||||
if (!is.na(prefix))
|
||||
return(prefix)
|
||||
|
||||
# if the user has requested an automatic prefix, generate it
|
||||
auto <- Sys.getenv("RENV_PATHS_PREFIX_AUTO", unset = NA)
|
||||
if (auto %in% c("TRUE", "True", "true", "1"))
|
||||
return(renv_bootstrap_platform_prefix_auto())
|
||||
|
||||
# empty string on failure
|
||||
""
|
||||
|
||||
}
|
||||
|
||||
renv_bootstrap_platform_prefix_auto <- function() {
|
||||
|
||||
prefix <- tryCatch(renv_bootstrap_platform_os(), error = identity)
|
||||
if (inherits(prefix, "error") || prefix %in% "unknown") {
|
||||
|
||||
msg <- paste(
|
||||
"failed to infer current operating system",
|
||||
"please file a bug report at https://github.com/rstudio/renv/issues",
|
||||
sep = "; "
|
||||
)
|
||||
|
||||
warning(msg)
|
||||
|
||||
}
|
||||
|
||||
prefix
|
||||
|
||||
}
|
||||
|
||||
renv_bootstrap_platform_os <- function() {
|
||||
|
||||
sysinfo <- Sys.info()
|
||||
sysname <- sysinfo[["sysname"]]
|
||||
|
||||
# handle Windows + macOS up front
|
||||
if (sysname == "Windows")
|
||||
return("windows")
|
||||
else if (sysname == "Darwin")
|
||||
return("macos")
|
||||
|
||||
# check for os-release files
|
||||
for (file in c("/etc/os-release", "/usr/lib/os-release"))
|
||||
if (file.exists(file))
|
||||
return(renv_bootstrap_platform_os_via_os_release(file, sysinfo))
|
||||
|
||||
# check for redhat-release files
|
||||
if (file.exists("/etc/redhat-release"))
|
||||
return(renv_bootstrap_platform_os_via_redhat_release())
|
||||
|
||||
"unknown"
|
||||
|
||||
}
|
||||
|
||||
renv_bootstrap_platform_os_via_os_release <- function(file, sysinfo) {
|
||||
|
||||
# read /etc/os-release
|
||||
release <- utils::read.table(
|
||||
file = file,
|
||||
sep = "=",
|
||||
quote = c("\"", "'"),
|
||||
col.names = c("Key", "Value"),
|
||||
comment.char = "#",
|
||||
stringsAsFactors = FALSE
|
||||
)
|
||||
|
||||
vars <- as.list(release$Value)
|
||||
names(vars) <- release$Key
|
||||
|
||||
# get os name
|
||||
os <- tolower(sysinfo[["sysname"]])
|
||||
|
||||
# read id
|
||||
id <- "unknown"
|
||||
for (field in c("ID", "ID_LIKE")) {
|
||||
if (field %in% names(vars) && nzchar(vars[[field]])) {
|
||||
id <- vars[[field]]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
# read version
|
||||
version <- "unknown"
|
||||
for (field in c("UBUNTU_CODENAME", "VERSION_CODENAME", "VERSION_ID", "BUILD_ID")) {
|
||||
if (field %in% names(vars) && nzchar(vars[[field]])) {
|
||||
version <- vars[[field]]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
# join together
|
||||
paste(c(os, id, version), collapse = "-")
|
||||
|
||||
}
|
||||
|
||||
renv_bootstrap_platform_os_via_redhat_release <- function() {
|
||||
|
||||
# read /etc/redhat-release
|
||||
contents <- readLines("/etc/redhat-release", warn = FALSE)
|
||||
|
||||
# infer id
|
||||
id <- if (grepl("centos", contents, ignore.case = TRUE))
|
||||
"centos"
|
||||
else if (grepl("redhat", contents, ignore.case = TRUE))
|
||||
"redhat"
|
||||
else
|
||||
"unknown"
|
||||
|
||||
# try to find a version component (very hacky)
|
||||
version <- "unknown"
|
||||
|
||||
parts <- strsplit(contents, "[[:space:]]")[[1L]]
|
||||
for (part in parts) {
|
||||
|
||||
nv <- tryCatch(numeric_version(part), error = identity)
|
||||
if (inherits(nv, "error"))
|
||||
next
|
||||
|
||||
version <- nv[1, 1]
|
||||
break
|
||||
|
||||
}
|
||||
|
||||
paste(c("linux", id, version), collapse = "-")
|
||||
|
||||
}
|
||||
|
||||
renv_bootstrap_library_root_name <- function(project) {
|
||||
|
||||
# use project name as-is if requested
|
||||
asis <- Sys.getenv("RENV_PATHS_LIBRARY_ROOT_ASIS", unset = "FALSE")
|
||||
if (asis)
|
||||
return(basename(project))
|
||||
|
||||
# otherwise, disambiguate based on project's path
|
||||
id <- substring(renv_bootstrap_hash_text(project), 1L, 8L)
|
||||
paste(basename(project), id, sep = "-")
|
||||
|
||||
}
|
||||
|
||||
renv_bootstrap_library_root <- function(project) {
|
||||
|
||||
prefix <- renv_bootstrap_profile_prefix()
|
||||
|
||||
path <- Sys.getenv("RENV_PATHS_LIBRARY", unset = NA)
|
||||
if (!is.na(path))
|
||||
return(paste(c(path, prefix), collapse = "/"))
|
||||
|
||||
path <- renv_bootstrap_library_root_impl(project)
|
||||
if (!is.null(path)) {
|
||||
name <- renv_bootstrap_library_root_name(project)
|
||||
return(paste(c(path, prefix, name), collapse = "/"))
|
||||
}
|
||||
|
||||
renv_bootstrap_paths_renv("library", project = project)
|
||||
|
||||
}
|
||||
|
||||
renv_bootstrap_library_root_impl <- function(project) {
|
||||
|
||||
root <- Sys.getenv("RENV_PATHS_LIBRARY_ROOT", unset = NA)
|
||||
if (!is.na(root))
|
||||
return(root)
|
||||
|
||||
type <- renv_bootstrap_project_type(project)
|
||||
if (identical(type, "package")) {
|
||||
userdir <- renv_bootstrap_user_dir()
|
||||
return(file.path(userdir, "library"))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
renv_bootstrap_validate_version <- function(version) {
|
||||
|
||||
loadedversion <- utils::packageDescription("renv", fields = "Version")
|
||||
if (version == loadedversion)
|
||||
return(TRUE)
|
||||
|
||||
# assume four-component versions are from GitHub; three-component
|
||||
# versions are from CRAN
|
||||
components <- strsplit(loadedversion, "[.-]")[[1]]
|
||||
remote <- if (length(components) == 4L)
|
||||
paste("rstudio/renv", loadedversion, sep = "@")
|
||||
else
|
||||
paste("renv", loadedversion, sep = "@")
|
||||
|
||||
fmt <- paste(
|
||||
"renv %1$s was loaded from project library, but this project is configured to use renv %2$s.",
|
||||
"Use `renv::record(\"%3$s\")` to record renv %1$s in the lockfile.",
|
||||
"Use `renv::restore(packages = \"renv\")` to install renv %2$s into the project library.",
|
||||
sep = "\n"
|
||||
)
|
||||
|
||||
msg <- sprintf(fmt, loadedversion, version, remote)
|
||||
warning(msg, call. = FALSE)
|
||||
|
||||
FALSE
|
||||
|
||||
}
|
||||
|
||||
renv_bootstrap_hash_text <- function(text) {
|
||||
|
||||
hashfile <- tempfile("renv-hash-")
|
||||
on.exit(unlink(hashfile), add = TRUE)
|
||||
|
||||
writeLines(text, con = hashfile)
|
||||
tools::md5sum(hashfile)
|
||||
|
||||
}
|
||||
|
||||
renv_bootstrap_load <- function(project, libpath, version) {
|
||||
|
||||
# try to load renv from the project library
|
||||
if (!requireNamespace("renv", lib.loc = libpath, quietly = TRUE))
|
||||
return(FALSE)
|
||||
|
||||
# warn if the version of renv loaded does not match
|
||||
renv_bootstrap_validate_version(version)
|
||||
|
||||
# load the project
|
||||
renv::load(project)
|
||||
|
||||
TRUE
|
||||
|
||||
}
|
||||
|
||||
renv_bootstrap_profile_load <- function(project) {
|
||||
|
||||
# if RENV_PROFILE is already set, just use that
|
||||
profile <- Sys.getenv("RENV_PROFILE", unset = NA)
|
||||
if (!is.na(profile) && nzchar(profile))
|
||||
return(profile)
|
||||
|
||||
# check for a profile file (nothing to do if it doesn't exist)
|
||||
path <- renv_bootstrap_paths_renv("profile", profile = FALSE)
|
||||
if (!file.exists(path))
|
||||
return(NULL)
|
||||
|
||||
# read the profile, and set it if it exists
|
||||
contents <- readLines(path, warn = FALSE)
|
||||
if (length(contents) == 0L)
|
||||
return(NULL)
|
||||
|
||||
# set RENV_PROFILE
|
||||
profile <- contents[[1L]]
|
||||
if (!profile %in% c("", "default"))
|
||||
Sys.setenv(RENV_PROFILE = profile)
|
||||
|
||||
profile
|
||||
|
||||
}
|
||||
|
||||
renv_bootstrap_profile_prefix <- function() {
|
||||
profile <- renv_bootstrap_profile_get()
|
||||
if (!is.null(profile))
|
||||
return(file.path("profiles", profile, "renv"))
|
||||
}
|
||||
|
||||
renv_bootstrap_profile_get <- function() {
|
||||
profile <- Sys.getenv("RENV_PROFILE", unset = "")
|
||||
renv_bootstrap_profile_normalize(profile)
|
||||
}
|
||||
|
||||
renv_bootstrap_profile_set <- function(profile) {
|
||||
profile <- renv_bootstrap_profile_normalize(profile)
|
||||
if (is.null(profile))
|
||||
Sys.unsetenv("RENV_PROFILE")
|
||||
else
|
||||
Sys.setenv(RENV_PROFILE = profile)
|
||||
}
|
||||
|
||||
renv_bootstrap_profile_normalize <- function(profile) {
|
||||
|
||||
if (is.null(profile) || profile %in% c("", "default"))
|
||||
return(NULL)
|
||||
|
||||
profile
|
||||
|
||||
}
|
||||
|
||||
renv_bootstrap_path_absolute <- function(path) {
|
||||
|
||||
substr(path, 1L, 1L) %in% c("~", "/", "\\") || (
|
||||
substr(path, 1L, 1L) %in% c(letters, LETTERS) &&
|
||||
substr(path, 2L, 3L) %in% c(":/", ":\\")
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
renv_bootstrap_paths_renv <- function(..., profile = TRUE, project = NULL) {
|
||||
renv <- Sys.getenv("RENV_PATHS_RENV", unset = "renv")
|
||||
root <- if (renv_bootstrap_path_absolute(renv)) NULL else project
|
||||
prefix <- if (profile) renv_bootstrap_profile_prefix()
|
||||
components <- c(root, renv, prefix, ...)
|
||||
paste(components, collapse = "/")
|
||||
}
|
||||
|
||||
renv_bootstrap_project_type <- function(path) {
|
||||
|
||||
descpath <- file.path(path, "DESCRIPTION")
|
||||
if (!file.exists(descpath))
|
||||
return("unknown")
|
||||
|
||||
desc <- tryCatch(
|
||||
read.dcf(descpath, all = TRUE),
|
||||
error = identity
|
||||
)
|
||||
|
||||
if (inherits(desc, "error"))
|
||||
return("unknown")
|
||||
|
||||
type <- desc$Type
|
||||
if (!is.null(type))
|
||||
return(tolower(type))
|
||||
|
||||
package <- desc$Package
|
||||
if (!is.null(package))
|
||||
return("package")
|
||||
|
||||
"unknown"
|
||||
|
||||
}
|
||||
|
||||
renv_bootstrap_user_dir <- function() {
|
||||
dir <- renv_bootstrap_user_dir_impl()
|
||||
path.expand(chartr("\\", "/", dir))
|
||||
}
|
||||
|
||||
renv_bootstrap_user_dir_impl <- function() {
|
||||
|
||||
# use local override if set
|
||||
override <- getOption("renv.userdir.override")
|
||||
if (!is.null(override))
|
||||
return(override)
|
||||
|
||||
# use R_user_dir if available
|
||||
tools <- asNamespace("tools")
|
||||
if (is.function(tools$R_user_dir))
|
||||
return(tools$R_user_dir("renv", "cache"))
|
||||
|
||||
# try using our own backfill for older versions of R
|
||||
envvars <- c("R_USER_CACHE_DIR", "XDG_CACHE_HOME")
|
||||
for (envvar in envvars) {
|
||||
root <- Sys.getenv(envvar, unset = NA)
|
||||
if (!is.na(root))
|
||||
return(file.path(root, "R/renv"))
|
||||
}
|
||||
|
||||
# use platform-specific default fallbacks
|
||||
if (Sys.info()[["sysname"]] == "Windows")
|
||||
file.path(Sys.getenv("LOCALAPPDATA"), "R/cache/R/renv")
|
||||
else if (Sys.info()[["sysname"]] == "Darwin")
|
||||
"~/Library/Caches/org.R-project.R/R/renv"
|
||||
else
|
||||
"~/.cache/R/renv"
|
||||
|
||||
}
|
||||
|
||||
|
||||
renv_json_read <- function(file = NULL, text = NULL) {
|
||||
|
||||
text <- paste(text %||% read(file), collapse = "\n")
|
||||
|
||||
# find strings in the JSON
|
||||
pattern <- '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
|
||||
locs <- gregexpr(pattern, text, perl = TRUE)[[1]]
|
||||
|
||||
# if any are found, replace them with placeholders
|
||||
replaced <- text
|
||||
strings <- character()
|
||||
replacements <- character()
|
||||
|
||||
if (!identical(c(locs), -1L)) {
|
||||
|
||||
# get the string values
|
||||
starts <- locs
|
||||
ends <- locs + attr(locs, "match.length") - 1L
|
||||
strings <- substring(text, starts, ends)
|
||||
|
||||
# only keep those requiring escaping
|
||||
strings <- grep("[[\\]{}:]", strings, perl = TRUE, value = TRUE)
|
||||
|
||||
# compute replacements
|
||||
replacements <- sprintf('"\032%i\032"', seq_along(strings))
|
||||
|
||||
# replace the strings
|
||||
mapply(function(string, replacement) {
|
||||
replaced <<- sub(string, replacement, replaced, fixed = TRUE)
|
||||
}, strings, replacements)
|
||||
|
||||
}
|
||||
|
||||
# transform the JSON into something the R parser understands
|
||||
transformed <- replaced
|
||||
transformed <- gsub("[[{]", "list(", transformed)
|
||||
transformed <- gsub("[]}]", ")", transformed)
|
||||
transformed <- gsub(":", "=", transformed, fixed = TRUE)
|
||||
text <- paste(transformed, collapse = "\n")
|
||||
|
||||
# parse it
|
||||
json <- parse(text = text, keep.source = FALSE, srcfile = NULL)[[1L]]
|
||||
|
||||
# construct map between source strings, replaced strings
|
||||
map <- as.character(parse(text = strings))
|
||||
names(map) <- as.character(parse(text = replacements))
|
||||
|
||||
# convert to list
|
||||
map <- as.list(map)
|
||||
|
||||
# remap strings in object
|
||||
remapped <- renv_json_remap(json, map)
|
||||
|
||||
# evaluate
|
||||
eval(remapped, envir = baseenv())
|
||||
|
||||
}
|
||||
|
||||
renv_json_remap <- function(json, map) {
|
||||
|
||||
# fix names
|
||||
if (!is.null(names(json))) {
|
||||
lhs <- match(names(json), names(map), nomatch = 0L)
|
||||
rhs <- match(names(map), names(json), nomatch = 0L)
|
||||
names(json)[rhs] <- map[lhs]
|
||||
}
|
||||
|
||||
# fix values
|
||||
if (is.character(json))
|
||||
return(map[[json]] %||% json)
|
||||
|
||||
# handle true, false, null
|
||||
if (is.name(json)) {
|
||||
text <- as.character(json)
|
||||
if (text == "true")
|
||||
return(TRUE)
|
||||
else if (text == "false")
|
||||
return(FALSE)
|
||||
else if (text == "null")
|
||||
return(NULL)
|
||||
}
|
||||
|
||||
# recurse
|
||||
if (is.recursive(json)) {
|
||||
for (i in seq_along(json)) {
|
||||
json[i] <- list(renv_json_remap(json[[i]], map))
|
||||
}
|
||||
}
|
||||
|
||||
json
|
||||
|
||||
}
|
||||
|
||||
# load the renv profile, if any
|
||||
renv_bootstrap_profile_load(project)
|
||||
|
||||
# construct path to library root
|
||||
root <- renv_bootstrap_library_root(project)
|
||||
|
||||
# construct library prefix for platform
|
||||
prefix <- renv_bootstrap_platform_prefix()
|
||||
|
||||
# construct full libpath
|
||||
libpath <- file.path(root, prefix)
|
||||
|
||||
# attempt to load
|
||||
if (renv_bootstrap_load(project, libpath, version))
|
||||
return(TRUE)
|
||||
|
||||
# load failed; inform user we're about to bootstrap
|
||||
prefix <- paste("# Bootstrapping renv", version)
|
||||
postfix <- paste(rep.int("-", 77L - nchar(prefix)), collapse = "")
|
||||
header <- paste(prefix, postfix)
|
||||
message(header)
|
||||
|
||||
# perform bootstrap
|
||||
bootstrap(version, libpath)
|
||||
|
||||
# exit early if we're just testing bootstrap
|
||||
if (!is.na(Sys.getenv("RENV_BOOTSTRAP_INSTALL_ONLY", unset = NA)))
|
||||
return(TRUE)
|
||||
|
||||
# try again to load
|
||||
if (requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) {
|
||||
message("* Successfully installed and loaded renv ", version, ".")
|
||||
return(renv::load())
|
||||
}
|
||||
|
||||
# failed to download or load renv; warn the user
|
||||
msg <- c(
|
||||
"Failed to find an renv installation: the project will not be loaded.",
|
||||
"Use `renv::activate()` to re-initialize the project."
|
||||
)
|
||||
|
||||
warning(paste(msg, collapse = "\n"), call. = FALSE)
|
||||
|
||||
})
|
||||
10
renv/settings.dcf
Normal file
10
renv/settings.dcf
Normal file
@ -0,0 +1,10 @@
|
||||
bioconductor.version:
|
||||
external.libraries:
|
||||
ignored.packages:
|
||||
package.dependency.fields: Imports, Depends, LinkingTo
|
||||
r.version:
|
||||
snapshot.type: implicit
|
||||
use.cache: TRUE
|
||||
vcs.ignore.cellar: TRUE
|
||||
vcs.ignore.library: TRUE
|
||||
vcs.ignore.local: TRUE
|
||||
Loading…
Reference in New Issue
Block a user