libdragon 10.4.2 → 10.7.0
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/CHANGELOG.md +75 -0
- package/index.js +17 -119
- package/modules/actions/destroy.js +34 -0
- package/modules/actions/disasm.js +121 -0
- package/modules/actions/docker-utils.js +8 -0
- package/modules/actions/exec.js +97 -39
- package/modules/actions/help.js +29 -84
- package/modules/actions/index.js +8 -17
- package/modules/actions/init.js +46 -41
- package/modules/actions/install.js +10 -4
- package/modules/actions/make.js +24 -0
- package/modules/actions/npm-utils.js +122 -0
- package/modules/actions/start.js +17 -15
- package/modules/actions/stop.js +9 -3
- package/modules/actions/update.js +13 -9
- package/modules/actions/utils.js +42 -162
- package/modules/actions/version.js +17 -0
- package/modules/helpers.js +117 -45
- package/modules/parameters.js +129 -0
- package/modules/project-info.js +62 -33
- package/package.json +1 -1
- package/skeleton/Makefile +8 -7
package/modules/actions/help.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
2
|
const commandLineUsage = require('command-line-usage');
|
|
3
3
|
|
|
4
|
-
const {
|
|
4
|
+
const { print } = require('../helpers');
|
|
5
5
|
|
|
6
|
-
const printUsage = (
|
|
6
|
+
const printUsage = (info) => {
|
|
7
|
+
const actions = require('./');
|
|
7
8
|
const globalOptionDefinitions = [
|
|
8
9
|
{
|
|
9
10
|
name: 'verbose',
|
|
@@ -11,7 +12,6 @@ const printUsage = (_, actionArr) => {
|
|
|
11
12
|
'Be verbose. This will print all commands dispatched and their outputs as well. Will also start printing error stack traces.',
|
|
12
13
|
alias: 'v',
|
|
13
14
|
typeLabel: ' ',
|
|
14
|
-
group: 'global',
|
|
15
15
|
},
|
|
16
16
|
];
|
|
17
17
|
|
|
@@ -26,7 +26,7 @@ const printUsage = (_, actionArr) => {
|
|
|
26
26
|
},
|
|
27
27
|
{
|
|
28
28
|
name: 'directory',
|
|
29
|
-
description: `Directory where libdragon files are expected. It must be
|
|
29
|
+
description: `Directory where libdragon files are expected. It must be inside the libdragon project as it will be mounted on the docker container. The cli will create and manage it when using a non-manual strategy. Defaults to \`./libdragon\` if not provided.\n`,
|
|
30
30
|
alias: 'd',
|
|
31
31
|
typeLabel: '<path>',
|
|
32
32
|
group: 'vendoring',
|
|
@@ -42,107 +42,48 @@ const printUsage = (_, actionArr) => {
|
|
|
42
42
|
You can always switch to manual by re-running \`init\` with \`--strategy manual\`, though you will be responsible for managing the existing submodule/subtree. Also it is not possible to automatically switch back.
|
|
43
43
|
|
|
44
44
|
With the \`manual\` strategy, it is still recommended to have a git repository at project root such that container actions can execute faster by caching the container id inside the \`.git\` folder.\n`,
|
|
45
|
-
alias: '
|
|
45
|
+
alias: 's',
|
|
46
46
|
typeLabel: '<strategy>',
|
|
47
47
|
group: 'vendoring',
|
|
48
48
|
},
|
|
49
49
|
];
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
summary: 'Display this help information or details for the given action.',
|
|
57
|
-
},
|
|
58
|
-
init: {
|
|
59
|
-
name: 'init',
|
|
60
|
-
summary: 'Create a libdragon project in the current directory.',
|
|
61
|
-
description: `Creates a libdragon project in the current directory. Every libdragon project will have its own docker container instance. If you are in a git repository or an NPM project, libdragon will be initialized at their root also marking there with a \`.libdragon\` folder. Do not remove the \`.libdragon\` folder and commit its contents if you are using source control, as it keeps persistent libdragon project information.
|
|
62
|
-
|
|
63
|
-
By default, a git repository and a submodule at \`./libdragon\` will be created to automatically update the vendored libdragon files on subsequent \`update\`s. If you intend to opt-out from this feature, see the \`--strategy manual\` flag to provide your self-managed libdragon copy. The default behaviour is intended for users who primarily want to consume libdragon as is.
|
|
64
|
-
|
|
65
|
-
If this is the first time you are creating a libdragon project at that location, this action will also create skeleton project files to kickstart things with the given image, if provided. For subsequent runs, it will act like \`start\` thus can be used to revive an existing project without modifying it.`,
|
|
66
|
-
group: ['docker', 'vendoring'],
|
|
67
|
-
},
|
|
68
|
-
make: {
|
|
69
|
-
name: 'make [params]',
|
|
70
|
-
summary: 'Run the libdragon build system in the current directory.',
|
|
71
|
-
description: `Runs the libdragon build system in the current directory. It will mirror your current working directory to the container.
|
|
72
|
-
|
|
73
|
-
Must be run in an initialized libdragon project. This action is a shortcut to the \`exec\` action under the hood.`,
|
|
74
|
-
},
|
|
75
|
-
exec: {
|
|
76
|
-
name: 'exec <command>',
|
|
77
|
-
summary: 'Execute given command in the current directory.',
|
|
78
|
-
description: `Executes the given command in the container passing down any arguments provided. If you change your host working directory, the command will be executed in the corresponding folder in the container as well.
|
|
79
|
-
|
|
80
|
-
This action will first try to execute the command in the container and if the container is not accessible, it will attempt a complete \`start\` cycle.
|
|
81
|
-
|
|
82
|
-
This will properly passthrough your TTY if you have one. So by running \`libdragon exec bash\` you can start an interactive bash session with full TTY support.
|
|
83
|
-
|
|
84
|
-
Must be run in an initialized libdragon project.`,
|
|
85
|
-
},
|
|
86
|
-
start: {
|
|
87
|
-
name: 'start',
|
|
88
|
-
summary: 'Start the container for current project.',
|
|
89
|
-
description: `Start the container assigned to the current libdragon project. Will first attempt to start an existing container if found, followed by a new container run and installation similar to the \`install\` action. Will always print out the container id on success.
|
|
90
|
-
|
|
91
|
-
Must be run in an initialized libdragon project.`,
|
|
92
|
-
},
|
|
93
|
-
name: {
|
|
94
|
-
name: 'stop',
|
|
95
|
-
summary: 'Stop the container for current project.',
|
|
96
|
-
description: `Stop the container assigned to the current libdragon project.
|
|
97
|
-
|
|
98
|
-
Must be run in an initialized libdragon project.`,
|
|
99
|
-
},
|
|
100
|
-
install: {
|
|
101
|
-
name: 'install',
|
|
102
|
-
summary: 'Vendor libdragon as is.',
|
|
103
|
-
description: `Attempts to build and install everything libdragon related into the container. This includes all the tools and third parties used by libdragon except for the toolchain. If you have made changes to libdragon, you can execute this action to build everything based on your changes. Requires you to have an intact vendoring target (also see the \`--directory\` flag). If you are not working on libdragon itself, you can just use the \`update\` action instead.
|
|
104
|
-
|
|
105
|
-
Must be run in an initialized libdragon project. This can be useful to recover from a half-baked container.`,
|
|
106
|
-
},
|
|
107
|
-
update: {
|
|
108
|
-
name: 'update',
|
|
109
|
-
summary: 'Update libdragon and do an install.',
|
|
110
|
-
description: `Will update the docker image and if you are using auto-vendoring (see \`--strategy\`), will also update the submodule/subtree from the remote branch (\`trunk\`) with a merge/squash strategy and then perform a \`libdragon install\`. You can use the \`install\` action to only update all libdragon related artifacts in the container.
|
|
111
|
-
|
|
112
|
-
Must be run in an initialized libdragon project.`,
|
|
113
|
-
group: ['docker'],
|
|
114
|
-
},
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
const actionsToShow = actionArr
|
|
118
|
-
?.filter((action) => Object.keys(actions).includes(action))
|
|
119
|
-
.filter((action) => !['help'].includes(action));
|
|
51
|
+
const actionsToShow =
|
|
52
|
+
info?.options.EXTRA_PARAMS?.filter(
|
|
53
|
+
(action) =>
|
|
54
|
+
Object.keys(actions).includes(action) && !['help'].includes(action)
|
|
55
|
+
) ?? (info ? [info.options.CURRENT_ACTION.name] : []);
|
|
120
56
|
|
|
121
57
|
const sections = [
|
|
122
58
|
{
|
|
123
59
|
header: chalk.green('Usage:'),
|
|
124
|
-
content:
|
|
60
|
+
content: `libdragon [flags] <action>
|
|
61
|
+
|
|
62
|
+
Joining flags not supported, provide them separately like \`-v -i\` `,
|
|
125
63
|
},
|
|
126
64
|
...(actionsToShow?.length
|
|
127
65
|
? actionsToShow.flatMap((action) => [
|
|
128
66
|
{
|
|
129
67
|
header: chalk.green(`${action} action:`),
|
|
130
|
-
content: actions[action].description,
|
|
68
|
+
content: actions[action].usage.description,
|
|
131
69
|
},
|
|
132
|
-
actions[action].group
|
|
70
|
+
actions[action].usage.group || actions[action].usage.optionList
|
|
133
71
|
? {
|
|
134
72
|
header: `accepted flags:`,
|
|
135
|
-
optionList:
|
|
136
|
-
|
|
73
|
+
optionList: [
|
|
74
|
+
...(actions[action].usage.group ? optionDefinitions : []),
|
|
75
|
+
...(actions[action].usage.optionList ?? []),
|
|
76
|
+
],
|
|
77
|
+
group: actions[action].usage.group,
|
|
137
78
|
}
|
|
138
79
|
: {},
|
|
139
80
|
])
|
|
140
81
|
: [
|
|
141
82
|
{
|
|
142
83
|
header: chalk.green('Available Commands:'),
|
|
143
|
-
content: Object.values(actions).map((
|
|
144
|
-
name:
|
|
145
|
-
summary:
|
|
84
|
+
content: Object.values(actions).map(({ usage }) => ({
|
|
85
|
+
name: usage.name,
|
|
86
|
+
summary: usage.summary,
|
|
146
87
|
})),
|
|
147
88
|
},
|
|
148
89
|
]),
|
|
@@ -152,12 +93,16 @@ const printUsage = (_, actionArr) => {
|
|
|
152
93
|
},
|
|
153
94
|
];
|
|
154
95
|
const usage = commandLineUsage(sections);
|
|
155
|
-
|
|
96
|
+
print(usage);
|
|
156
97
|
};
|
|
157
98
|
|
|
158
99
|
module.exports = {
|
|
159
100
|
name: 'help',
|
|
160
101
|
fn: printUsage,
|
|
161
|
-
showStatus: true,
|
|
162
102
|
forwardsRestParams: true,
|
|
103
|
+
mustHaveProject: false,
|
|
104
|
+
usage: {
|
|
105
|
+
name: 'help [action]',
|
|
106
|
+
summary: 'Display this help information or details for the given action.',
|
|
107
|
+
},
|
|
163
108
|
};
|
package/modules/actions/index.js
CHANGED
|
@@ -1,25 +1,16 @@
|
|
|
1
|
-
const { fn: exec } = require('./exec');
|
|
2
|
-
|
|
3
|
-
const make = async (libdragonInfo, params) => {
|
|
4
|
-
await exec(libdragonInfo, ['make', ...params]);
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
// TODO: separate into files
|
|
8
1
|
module.exports = {
|
|
9
|
-
start: require('./start'),
|
|
10
|
-
stop: require('./stop'),
|
|
11
2
|
init: require('./init'),
|
|
3
|
+
make: require('./make'),
|
|
12
4
|
|
|
5
|
+
update: require('./update'),
|
|
13
6
|
exec: require('./exec'),
|
|
14
|
-
|
|
15
|
-
name: 'make',
|
|
16
|
-
fn: make,
|
|
17
|
-
forwardsRestParams: true,
|
|
18
|
-
showStatus: true,
|
|
19
|
-
},
|
|
20
|
-
|
|
7
|
+
disasm: require('./disasm'),
|
|
21
8
|
install: require('./install'),
|
|
22
|
-
|
|
9
|
+
|
|
10
|
+
start: require('./start'),
|
|
11
|
+
stop: require('./stop'),
|
|
23
12
|
|
|
24
13
|
help: require('./help'),
|
|
14
|
+
version: require('./version'),
|
|
15
|
+
destroy: require('./destroy'),
|
|
25
16
|
};
|
package/modules/actions/init.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
const fs = require('fs/promises');
|
|
2
2
|
const path = require('path');
|
|
3
3
|
|
|
4
|
-
const chalk = require('chalk');
|
|
4
|
+
const chalk = require('chalk').stderr;
|
|
5
5
|
|
|
6
6
|
const { fn: install } = require('./install');
|
|
7
7
|
const { start } = require('./start');
|
|
8
8
|
const {
|
|
9
9
|
installDependencies,
|
|
10
|
-
|
|
10
|
+
initGitAndCacheContainerId,
|
|
11
11
|
updateImage,
|
|
12
12
|
runGitMaybeHost,
|
|
13
13
|
} = require('./utils');
|
|
@@ -24,8 +24,9 @@ const {
|
|
|
24
24
|
CommandError,
|
|
25
25
|
ParameterError,
|
|
26
26
|
ValidationError,
|
|
27
|
+
toPosixPath,
|
|
28
|
+
toNativePath,
|
|
27
29
|
} = require('../helpers');
|
|
28
|
-
const { setProjectInfoToSave } = require('../project-info');
|
|
29
30
|
|
|
30
31
|
const autoVendor = async (libdragonInfo) => {
|
|
31
32
|
await runGitMaybeHost(libdragonInfo, ['init']);
|
|
@@ -79,10 +80,10 @@ const autoVendor = async (libdragonInfo) => {
|
|
|
79
80
|
* Initialize a new libdragon project in current working directory
|
|
80
81
|
* Also downloads the image
|
|
81
82
|
*/
|
|
82
|
-
async function init(
|
|
83
|
-
log(`Initializing a libdragon project at ${
|
|
83
|
+
async function init(info) {
|
|
84
|
+
log(`Initializing a libdragon project at ${info.root}`);
|
|
84
85
|
|
|
85
|
-
let newInfo =
|
|
86
|
+
let newInfo = info;
|
|
86
87
|
|
|
87
88
|
// Validate manifest
|
|
88
89
|
const manifestPath = path.join(newInfo.root, LIBDRAGON_PROJECT_MANIFEST);
|
|
@@ -105,31 +106,29 @@ async function init(libdragonInfo) {
|
|
|
105
106
|
newInfo.vendorStrategy !== newInfo.options.VENDOR_STRAT
|
|
106
107
|
) {
|
|
107
108
|
throw new ParameterError(
|
|
108
|
-
`Requested strategy switch: ${newInfo.vendorStrategy} -> ${newInfo.options.VENDOR_STRAT} It is not possible to switch vendoring strategy after initializing a project. You can always switch to manual and handle libdragon yourself
|
|
109
|
+
`Requested strategy switch: ${newInfo.vendorStrategy} -> ${newInfo.options.VENDOR_STRAT} It is not possible to switch vendoring strategy after initializing a project. You can always switch to manual and handle libdragon yourself.`,
|
|
110
|
+
info.options.CURRENT_ACTION.name
|
|
109
111
|
);
|
|
110
112
|
}
|
|
111
113
|
|
|
112
114
|
// Update the strategy information for the project if the flag is provided
|
|
113
115
|
if (newInfo.options.VENDOR_STRAT) {
|
|
114
|
-
newInfo =
|
|
115
|
-
...newInfo,
|
|
116
|
-
vendorStrategy: newInfo.options.VENDOR_STRAT,
|
|
117
|
-
});
|
|
116
|
+
newInfo.vendorStrategy = newInfo.options.VENDOR_STRAT;
|
|
118
117
|
}
|
|
119
118
|
|
|
120
119
|
// Update the directory information for the project if the flag is provided
|
|
121
120
|
if (newInfo.options.VENDOR_DIR) {
|
|
121
|
+
const relativeVendorDir = path.relative(info.root, info.options.VENDOR_DIR);
|
|
122
122
|
// Validate vendoring path
|
|
123
|
-
if (
|
|
123
|
+
if (relativeVendorDir.startsWith('..')) {
|
|
124
124
|
throw new ParameterError(
|
|
125
|
-
|
|
125
|
+
`\`--directory=${info.options.VENDOR_DIR}\` is outside the project directory.`,
|
|
126
|
+
info.options.CURRENT_ACTION.name
|
|
126
127
|
);
|
|
127
128
|
}
|
|
128
129
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
vendorDirectory: newInfo.options.VENDOR_DIR,
|
|
132
|
-
});
|
|
130
|
+
// Immeditately convert it to a posix and relative path
|
|
131
|
+
newInfo.vendorDirectory = toPosixPath(relativeVendorDir);
|
|
133
132
|
}
|
|
134
133
|
|
|
135
134
|
if (newInfo.haveProjectConfig) {
|
|
@@ -145,57 +144,63 @@ async function init(libdragonInfo) {
|
|
|
145
144
|
);
|
|
146
145
|
}
|
|
147
146
|
// TODO: we may make sure git and submodule is initialized here
|
|
148
|
-
await install(newInfo);
|
|
149
|
-
return;
|
|
147
|
+
return await install(newInfo);
|
|
150
148
|
}
|
|
151
149
|
|
|
152
|
-
newInfo.imageName
|
|
153
|
-
|
|
150
|
+
await updateImage(newInfo, newInfo.imageName);
|
|
151
|
+
|
|
154
152
|
// Download image and start it
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
153
|
+
newInfo.containerId = await start(newInfo);
|
|
154
|
+
|
|
155
|
+
// We have created a new container, save the new info ASAP
|
|
156
|
+
await initGitAndCacheContainerId(newInfo);
|
|
159
157
|
|
|
160
|
-
let vendorAndGitReadyPromise = containerReadyPromise;
|
|
161
158
|
if (newInfo.vendorStrategy !== 'manual') {
|
|
162
|
-
const vendorTarget = path.relative(
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
159
|
+
const vendorTarget = path.relative(
|
|
160
|
+
newInfo.root,
|
|
161
|
+
toNativePath(newInfo.vendorDirectory)
|
|
162
|
+
);
|
|
163
|
+
const vendorTargetExists = await fs.stat(vendorTarget).catch((e) => {
|
|
164
|
+
if (e.code !== 'ENOENT') throw e;
|
|
165
|
+
return false;
|
|
166
|
+
});
|
|
170
167
|
|
|
171
168
|
if (vendorTargetExists) {
|
|
172
169
|
throw new ValidationError(
|
|
173
170
|
`${path.resolve(
|
|
174
|
-
|
|
175
|
-
newInfo.vendorDirectory
|
|
171
|
+
vendorTarget
|
|
176
172
|
)} already exists. That is the libdragon vendoring target, please remove and retry.`
|
|
177
173
|
);
|
|
178
174
|
}
|
|
179
175
|
|
|
180
|
-
|
|
176
|
+
newInfo = await autoVendor(newInfo);
|
|
181
177
|
}
|
|
182
178
|
|
|
183
179
|
log(`Preparing project files...`);
|
|
184
180
|
const skeletonFolder = path.join(__dirname, '../../skeleton');
|
|
185
181
|
|
|
186
182
|
await Promise.all([
|
|
187
|
-
|
|
188
|
-
vendorAndGitReadyPromise.then(tryCacheContainerId),
|
|
189
|
-
vendorAndGitReadyPromise.then(installDependencies),
|
|
183
|
+
installDependencies(newInfo),
|
|
190
184
|
// node copy functions does not work with pkg
|
|
191
185
|
copyDirContents(skeletonFolder, newInfo.root),
|
|
192
186
|
]);
|
|
193
187
|
|
|
194
188
|
log(chalk.green(`libdragon ready at \`${newInfo.root}\`.`));
|
|
189
|
+
return newInfo;
|
|
195
190
|
}
|
|
196
191
|
|
|
197
192
|
module.exports = {
|
|
198
193
|
name: 'init',
|
|
199
194
|
fn: init,
|
|
200
|
-
|
|
195
|
+
mustHaveProject: false,
|
|
196
|
+
usage: {
|
|
197
|
+
name: 'init',
|
|
198
|
+
summary: 'Create a libdragon project in the current directory.',
|
|
199
|
+
description: `Creates a libdragon project in the current directory. Every libdragon project will have its own docker container instance. If you are in a git repository or an NPM project, libdragon will be initialized at their root also marking there with a \`.libdragon\` folder. Do not remove the \`.libdragon\` folder and commit its contents if you are using source control, as it keeps persistent libdragon project information.
|
|
200
|
+
|
|
201
|
+
By default, a git repository and a submodule at \`./libdragon\` will be created to automatically update the vendored libdragon files on subsequent \`update\`s. If you intend to opt-out from this feature, see the \`--strategy manual\` flag to provide your self-managed libdragon copy. The default behaviour is intended for users who primarily want to consume libdragon as is.
|
|
202
|
+
|
|
203
|
+
If this is the first time you are creating a libdragon project at that location, this action will also create skeleton project files to kickstart things with the given image, if provided. For subsequent runs, it will act like \`start\` thus can be used to revive an existing project without modifying it.`,
|
|
204
|
+
group: ['docker', 'vendoring'],
|
|
205
|
+
},
|
|
201
206
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const chalk = require('chalk');
|
|
1
|
+
const chalk = require('chalk').stderr;
|
|
2
2
|
|
|
3
|
-
const { installDependencies
|
|
3
|
+
const { installDependencies } = require('./utils');
|
|
4
4
|
const { start } = require('./start');
|
|
5
5
|
const { updateAndStart } = require('./update-and-start');
|
|
6
6
|
const { log } = require('../helpers');
|
|
@@ -17,7 +17,6 @@ const { log } = require('../helpers');
|
|
|
17
17
|
* we still keep that logic but with a deprecation warning.
|
|
18
18
|
*/
|
|
19
19
|
const install = async (libdragonInfo, skipUpdate) => {
|
|
20
|
-
await mustHaveProject(libdragonInfo);
|
|
21
20
|
let updatedInfo = libdragonInfo;
|
|
22
21
|
const imageName = libdragonInfo.options.DOCKER_IMAGE;
|
|
23
22
|
// If an image is provided, attempt to install
|
|
@@ -39,10 +38,17 @@ const install = async (libdragonInfo, skipUpdate) => {
|
|
|
39
38
|
// Re-install vendors on new image
|
|
40
39
|
// TODO: skip this if unnecessary
|
|
41
40
|
await installDependencies(updatedInfo);
|
|
41
|
+
return updatedInfo;
|
|
42
42
|
};
|
|
43
43
|
|
|
44
44
|
module.exports = {
|
|
45
45
|
name: 'install',
|
|
46
46
|
fn: install,
|
|
47
|
-
|
|
47
|
+
usage: {
|
|
48
|
+
name: 'install',
|
|
49
|
+
summary: 'Vendor libdragon as is.',
|
|
50
|
+
description: `Attempts to build and install everything libdragon related into the container. This includes all the tools and third parties used by libdragon except for the toolchain. If you have made changes to libdragon, you can execute this action to build everything based on your changes. Requires you to have an intact vendoring target (also see the \`--directory\` flag). If you are not working on libdragon itself, you can just use the \`update\` action instead.
|
|
51
|
+
|
|
52
|
+
Must be run in an initialized libdragon project. This can be useful to recover from a half-baked container.`,
|
|
53
|
+
},
|
|
48
54
|
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const { fn: exec } = require('./exec');
|
|
2
|
+
|
|
3
|
+
const make = async (info) => {
|
|
4
|
+
return await exec({
|
|
5
|
+
...info,
|
|
6
|
+
options: {
|
|
7
|
+
...info.options,
|
|
8
|
+
EXTRA_PARAMS: ['make', ...info.options.EXTRA_PARAMS],
|
|
9
|
+
},
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
module.exports = {
|
|
14
|
+
name: 'make',
|
|
15
|
+
fn: make,
|
|
16
|
+
forwardsRestParams: true,
|
|
17
|
+
usage: {
|
|
18
|
+
name: 'make [params]',
|
|
19
|
+
summary: 'Run the libdragon build system in the current directory.',
|
|
20
|
+
description: `Runs the libdragon build system in the current directory. It will mirror your current working directory to the container.
|
|
21
|
+
|
|
22
|
+
Must be run in an initialized libdragon project. This action is a shortcut to the \`exec\` action under the hood.`,
|
|
23
|
+
},
|
|
24
|
+
};
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const fsClassic = require('fs');
|
|
3
|
+
|
|
4
|
+
const _ = require('lodash');
|
|
5
|
+
|
|
6
|
+
const { dockerHostUserParams } = require('./docker-utils');
|
|
7
|
+
|
|
8
|
+
const { CONTAINER_TARGET_PATH } = require('../constants');
|
|
9
|
+
const {
|
|
10
|
+
fileExists,
|
|
11
|
+
toPosixPath,
|
|
12
|
+
spawnProcess,
|
|
13
|
+
dockerExec,
|
|
14
|
+
ValidationError,
|
|
15
|
+
} = require('../helpers');
|
|
16
|
+
|
|
17
|
+
async function findNPMRoot() {
|
|
18
|
+
try {
|
|
19
|
+
const root = path.resolve((await runNPM(['root'])).trim(), '..');
|
|
20
|
+
// Only report if package.json really exists. npm fallbacks to cwd
|
|
21
|
+
if (await fileExists(path.join(root, 'package.json'))) {
|
|
22
|
+
return root;
|
|
23
|
+
}
|
|
24
|
+
} catch {
|
|
25
|
+
// User does not have and does not care about NPM if it didn't work
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Install other NPM dependencies if this is an NPM project
|
|
31
|
+
const installNPMDependencies = async (libdragonInfo) => {
|
|
32
|
+
const npmRoot = await findNPMRoot();
|
|
33
|
+
if (npmRoot) {
|
|
34
|
+
const packageJsonPath = path.join(npmRoot, 'package.json');
|
|
35
|
+
|
|
36
|
+
const { dependencies, devDependencies } = require(packageJsonPath);
|
|
37
|
+
|
|
38
|
+
const deps = await Promise.all(
|
|
39
|
+
Object.keys({
|
|
40
|
+
...dependencies,
|
|
41
|
+
...devDependencies,
|
|
42
|
+
})
|
|
43
|
+
.filter((dep) => dep !== 'libdragon')
|
|
44
|
+
.map(async (dep) => {
|
|
45
|
+
const npmPath = await runNPM(['ls', dep, '--parseable=true']);
|
|
46
|
+
return {
|
|
47
|
+
name: dep,
|
|
48
|
+
paths: _.uniq(npmPath.split('\n').filter((f) => f)),
|
|
49
|
+
};
|
|
50
|
+
})
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
await Promise.all(
|
|
54
|
+
deps.map(({ name, paths }) => {
|
|
55
|
+
return new Promise((resolve, reject) => {
|
|
56
|
+
fsClassic.access(
|
|
57
|
+
path.join(paths[0], 'Makefile'),
|
|
58
|
+
fsClassic.F_OK,
|
|
59
|
+
async (e) => {
|
|
60
|
+
if (e) {
|
|
61
|
+
// File does not exist - skip
|
|
62
|
+
resolve();
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (paths.length > 1) {
|
|
67
|
+
reject(
|
|
68
|
+
new ValidationError(
|
|
69
|
+
`Using same dependency with different versions is not supported! ${name}`
|
|
70
|
+
)
|
|
71
|
+
);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
const relativePath = toPosixPath(
|
|
77
|
+
path.relative(libdragonInfo.root, paths[0])
|
|
78
|
+
);
|
|
79
|
+
const containerPath = path.posix.join(
|
|
80
|
+
CONTAINER_TARGET_PATH,
|
|
81
|
+
relativePath
|
|
82
|
+
);
|
|
83
|
+
const makePath = path.posix.join(containerPath, 'Makefile');
|
|
84
|
+
|
|
85
|
+
await dockerExec(
|
|
86
|
+
libdragonInfo,
|
|
87
|
+
[...dockerHostUserParams(libdragonInfo)],
|
|
88
|
+
[
|
|
89
|
+
'/bin/bash',
|
|
90
|
+
'-c',
|
|
91
|
+
'[ -f ' +
|
|
92
|
+
makePath +
|
|
93
|
+
' ] && make -C ' +
|
|
94
|
+
containerPath +
|
|
95
|
+
' && make -C ' +
|
|
96
|
+
containerPath +
|
|
97
|
+
' install',
|
|
98
|
+
]
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
resolve();
|
|
102
|
+
} catch (e) {
|
|
103
|
+
reject(e);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
);
|
|
107
|
+
});
|
|
108
|
+
})
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
function runNPM(params) {
|
|
114
|
+
return spawnProcess(
|
|
115
|
+
/^win/.test(process.platform) ? 'npm.cmd' : 'npm',
|
|
116
|
+
params
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
module.exports = {
|
|
120
|
+
installNPMDependencies,
|
|
121
|
+
findNPMRoot,
|
|
122
|
+
};
|
package/modules/actions/start.js
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
const chalk = require('chalk');
|
|
1
|
+
const chalk = require('chalk').stderr;
|
|
2
2
|
|
|
3
3
|
const { CONTAINER_TARGET_PATH } = require('../constants');
|
|
4
|
-
const { spawnProcess, log, dockerExec } = require('../helpers');
|
|
5
|
-
const { setProjectInfoToSave } = require('../project-info');
|
|
4
|
+
const { spawnProcess, log, print, dockerExec } = require('../helpers');
|
|
6
5
|
|
|
7
6
|
const {
|
|
8
7
|
checkContainerAndClean,
|
|
9
8
|
checkContainerRunning,
|
|
10
9
|
destroyContainer,
|
|
11
|
-
mustHaveProject,
|
|
12
10
|
} = require('./utils');
|
|
13
11
|
|
|
14
12
|
/**
|
|
@@ -18,7 +16,7 @@ const initContainer = async (libdragonInfo) => {
|
|
|
18
16
|
let newId;
|
|
19
17
|
try {
|
|
20
18
|
// Create a new container
|
|
21
|
-
|
|
19
|
+
log('Creating new container...');
|
|
22
20
|
newId = (
|
|
23
21
|
await spawnProcess('docker', [
|
|
24
22
|
'run',
|
|
@@ -71,18 +69,12 @@ const initContainer = async (libdragonInfo) => {
|
|
|
71
69
|
'{{.Name}}',
|
|
72
70
|
]);
|
|
73
71
|
|
|
74
|
-
|
|
75
|
-
log(
|
|
76
|
-
chalk.green(`Successfully initialized docker container: ${name.trim()}`)
|
|
77
|
-
);
|
|
72
|
+
log(chalk.green(`Successfully initialized docker container: ${name.trim()}`));
|
|
78
73
|
|
|
79
|
-
// Schedule an update to write image name
|
|
80
|
-
setProjectInfoToSave(libdragonInfo);
|
|
81
74
|
return newId;
|
|
82
75
|
};
|
|
83
76
|
|
|
84
|
-
const start = async (libdragonInfo
|
|
85
|
-
!skipProjectCheck && (await mustHaveProject(libdragonInfo));
|
|
77
|
+
const start = async (libdragonInfo) => {
|
|
86
78
|
const running =
|
|
87
79
|
libdragonInfo.containerId &&
|
|
88
80
|
(await checkContainerRunning(libdragonInfo.containerId));
|
|
@@ -108,7 +100,17 @@ const start = async (libdragonInfo, skipProjectCheck) => {
|
|
|
108
100
|
|
|
109
101
|
module.exports = {
|
|
110
102
|
name: 'start',
|
|
111
|
-
fn: async (libdragonInfo) =>
|
|
103
|
+
fn: async (libdragonInfo) => {
|
|
104
|
+
const containerId = await start(libdragonInfo);
|
|
105
|
+
print(containerId);
|
|
106
|
+
return { ...libdragonInfo, containerId };
|
|
107
|
+
},
|
|
112
108
|
start,
|
|
113
|
-
|
|
109
|
+
usage: {
|
|
110
|
+
name: 'start',
|
|
111
|
+
summary: 'Start the container for current project.',
|
|
112
|
+
description: `Start the container assigned to the current libdragon project. Will first attempt to start an existing container if found, followed by a new container run and installation similar to the \`install\` action. Will always print out the container id to stdout on success except when verbose is set.
|
|
113
|
+
|
|
114
|
+
Must be run in an initialized libdragon project.`,
|
|
115
|
+
},
|
|
114
116
|
};
|
package/modules/actions/stop.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
const { spawnProcess } = require('../helpers');
|
|
2
2
|
|
|
3
|
-
const { checkContainerRunning
|
|
3
|
+
const { checkContainerRunning } = require('./utils');
|
|
4
4
|
|
|
5
5
|
const stop = async (libdragonInfo) => {
|
|
6
|
-
await mustHaveProject(libdragonInfo);
|
|
7
6
|
const running =
|
|
8
7
|
libdragonInfo.containerId &&
|
|
9
8
|
(await checkContainerRunning(libdragonInfo.containerId));
|
|
@@ -12,10 +11,17 @@ const stop = async (libdragonInfo) => {
|
|
|
12
11
|
}
|
|
13
12
|
|
|
14
13
|
await spawnProcess('docker', ['container', 'stop', running]);
|
|
14
|
+
return libdragonInfo;
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
module.exports = {
|
|
18
18
|
name: 'stop',
|
|
19
19
|
fn: stop,
|
|
20
|
-
|
|
20
|
+
usage: {
|
|
21
|
+
name: 'stop',
|
|
22
|
+
summary: 'Stop the container for current project.',
|
|
23
|
+
description: `Stop the container assigned to the current libdragon project.
|
|
24
|
+
|
|
25
|
+
Must be run in an initialized libdragon project.`,
|
|
26
|
+
},
|
|
21
27
|
};
|