Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
quarto-dev
GitHub Repository: quarto-dev/quarto-cli
Path: blob/main/src/core/container.ts
3562 views
1
/*
2
* container.ts
3
*
4
* Copyright (C) 2020-2022 Posit Software, PBC
5
*/
6
7
import { existsSync, walkSync } from "../deno_ral/fs.ts";
8
import { basename, join } from "../deno_ral/path.ts";
9
10
// REES Compatible execution files
11
// from https://repo2docker.readthedocs.io/en/latest/config_files.html#config-files
12
const kExecutionFiles = [
13
"environment.yml",
14
"requirements.txt",
15
"renv.lock", // not supported by repo2docker
16
"Pipfile",
17
"Pipfile.lock",
18
"setup.py",
19
"Project.toml",
20
"REQUIRE",
21
"install.R",
22
"apt.txt",
23
"DESCRIPTION",
24
"postBuild",
25
"start",
26
"runtime.txt",
27
"default.nix",
28
"Dockerfile",
29
];
30
31
export function isReesEnvronmentFile(path: string) {
32
return kExecutionFiles.includes(basename(path));
33
}
34
35
export function codeSpacesUrl(repoUrl: string) {
36
// https://github.com/Notebooks-Now/submission-quarto-full/
37
// transforms to:
38
// https://github.com/codespaces/new/Notebooks-Now/submission-quarto-full
39
40
const containerUrl = repoUrl.replace(
41
/(https?\:\/\/github.com)\/([a-zA-Z0-9-_\.]+?)\/([a-zA-Z0-9-_\.]+?)\//,
42
"$1/codespaces/new/$2/$3?resume=1",
43
);
44
return containerUrl;
45
}
46
47
export interface BinderOptions {
48
openFile?: string;
49
editor?: "vscode" | "rstudio" | "jupyterlab";
50
}
51
52
export function binderUrl(
53
organization: string,
54
repository: string,
55
binderOptions?: BinderOptions,
56
) {
57
// https://github.com/Notebooks-Now/submission-quarto-lite
58
// https://mybinder.org/v2/gh/Notebooks-Now/submission-quarto-lite/HEAD?labpath=article.ipynb
59
const url = [`https://mybinder.org/v2/gh/${organization}/${repository}/HEAD`];
60
const params = [];
61
if (binderOptions && binderOptions.openFile) {
62
params.push(`labpath=${binderOptions.openFile}`);
63
}
64
65
if (binderOptions?.editor) {
66
switch (binderOptions.editor) {
67
case "rstudio":
68
params.push(`urlpath=rstudio`);
69
break;
70
case "vscode":
71
params.push(`urlpath=vscode`);
72
break;
73
case "jupyterlab":
74
default:
75
break;
76
}
77
}
78
79
// Add any parameters
80
if (params.length > 0) {
81
url.push("?");
82
url.push(params.join("&"));
83
}
84
85
return url.join("");
86
}
87
88
export function isDevContainerFile(relPath: string) {
89
if (relPath === join(".devcontainer", "devcontainer.json")) {
90
return true;
91
}
92
93
if (relPath === ".devcontainer.json") {
94
return true;
95
}
96
97
if (relPath.match(/^\.devcontainer[\/\\][^\/\\]+?[\/\\]devcontainer.json$/)) {
98
return true;
99
}
100
101
return false;
102
}
103
104
// Are there binder compatible environments defined
105
export function hasBinderCompatibleEnvironment(dir: string) {
106
for (const executionFile of kExecutionFiles) {
107
if (existsSync(join(dir, executionFile))) {
108
return true;
109
}
110
}
111
return false;
112
}
113
114
export function hasDevContainer(dir: string) {
115
// Devcontainer file in a hidden subdirectory
116
if (existsSync(join(dir, ".devcontainer", "devcontainer.json"))) {
117
return true;
118
}
119
120
// Devcontainer file in the root
121
if (existsSync(join(dir, ".devcontainer.json"))) {
122
return true;
123
}
124
125
// Devcontainer in a direct subdirectory child
126
const containerRootDir = join(dir, ".devcontainer");
127
if (existsSync(containerRootDir)) {
128
for (
129
const walk of walkSync(containerRootDir, {
130
maxDepth: 1,
131
includeFiles: false,
132
includeDirs: true,
133
})
134
) {
135
if (existsSync(join(containerRootDir, walk.name, "devcontainer.json"))) {
136
return true;
137
}
138
}
139
}
140
141
return false;
142
}
143
144