libdragon 10.8.0 → 10.8.2
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/README.md +149 -34
- package/index.js +22 -1
- package/modules/actions/destroy.js +6 -3
- package/modules/actions/disasm.js +10 -2
- package/modules/actions/docker-utils.js +4 -0
- package/modules/actions/exec.js +48 -16
- package/modules/actions/help.js +9 -6
- package/modules/actions/init.js +49 -19
- package/modules/actions/install.js +4 -8
- package/modules/actions/make.js +5 -2
- package/modules/actions/npm-utils.js +57 -49
- package/modules/actions/start.js +10 -3
- package/modules/actions/stop.js +7 -2
- package/modules/actions/update-and-start.js +3 -0
- package/modules/actions/update.js +6 -2
- package/modules/actions/utils.js +24 -3
- package/modules/actions/version.js +3 -3
- package/modules/constants.js +9 -2
- package/modules/helpers.js +185 -49
- package/modules/parameters.js +45 -14
- package/modules/project-info.js +67 -24
- package/package.json +9 -5
package/README.md
CHANGED
|
@@ -1,12 +1,65 @@
|
|
|
1
1
|
# Docker Libdragon
|
|
2
2
|
|
|
3
|
-
[](https://github.com/anacierdem/libdragon-docker/actions/workflows/release.yml)
|
|
4
4
|
|
|
5
|
-
This is a wrapper for a docker container to make managing the libdragon toolchain easier.
|
|
5
|
+
This is a wrapper for a docker container to make managing the libdragon toolchain easier. It has the additional advantage that libdragon toolchain and library can be installed on a per-project basis instead of managing system-wide installations.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Prerequisites
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
You should have [docker](https://www.docker.com/products/docker-desktop) (`>= 18`) installed on your system.
|
|
10
|
+
|
|
11
|
+
`git` is not strictly required to use the tool. Still, it is highly recommended to have git on your host machine as it will be used instead of the one in the container.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
This is primarily a node.js script which is also packaged as an executable. You have two options:
|
|
16
|
+
|
|
17
|
+
### pre-built
|
|
18
|
+
|
|
19
|
+
Download the [pre-built executable](https://github.com/anacierdem/libdragon-docker/releases/latest) for your system and put it somewhere on your PATH. It is discouraged to put it in your project folder.
|
|
20
|
+
|
|
21
|
+
<details>
|
|
22
|
+
<summary>Windows instructions</summary>
|
|
23
|
+
|
|
24
|
+
- Download the Windows executable and copy it to `C:\bin`
|
|
25
|
+
- Press `Windows + R` key combination and then enter `rundll32 sysdm.cpl,EditEnvironmentVariables`
|
|
26
|
+
- In the `Environment Variables` window find the `Path` variable under `User variables for <your user name>`
|
|
27
|
+
- Double click it and add a new entry as `C:\bin`
|
|
28
|
+
- Restart your computer.
|
|
29
|
+
- You should now be able to use the `libdragon` on a command line or PowerShell.
|
|
30
|
+
- To update it with a new version, just replace the file in `C:\bin`
|
|
31
|
+
|
|
32
|
+
</details>
|
|
33
|
+
|
|
34
|
+
<details>
|
|
35
|
+
<summary>MacOS instructions</summary>
|
|
36
|
+
|
|
37
|
+
- Download the MacOS executable and copy it to `/usr/local/bin`
|
|
38
|
+
- Right click it and choose `Open`.
|
|
39
|
+
- It will show a warning, approve it by clicking `Open` again. You can close the newly opened terminal window.
|
|
40
|
+
- You should now be able to use the `libdragon` command.
|
|
41
|
+
- To update it with a new version, replace the file in `/usr/local/bin` and repeat the other steps.
|
|
42
|
+
|
|
43
|
+
</details>
|
|
44
|
+
|
|
45
|
+
<details>
|
|
46
|
+
<summary>Linux instructions</summary>
|
|
47
|
+
|
|
48
|
+
- You should already know this :)
|
|
49
|
+
|
|
50
|
+
</details>
|
|
51
|
+
|
|
52
|
+
### via NPM
|
|
53
|
+
|
|
54
|
+
Install [node.js](https://nodejs.org/en/download/) (`>= 14`) and install `libdragon` as a global NPM package;
|
|
55
|
+
|
|
56
|
+
npm install -g libdragon
|
|
57
|
+
|
|
58
|
+
To update the tool to the latest, do `npm i -g libdragon@latest`.
|
|
59
|
+
|
|
60
|
+
## Quick Guide
|
|
61
|
+
|
|
62
|
+
Navigate to the folder you want to initialize your project and invoke libdragon;
|
|
10
63
|
|
|
11
64
|
libdragon init
|
|
12
65
|
|
|
@@ -22,21 +75,60 @@ To update the library and rebuild/install all the artifacts;
|
|
|
22
75
|
|
|
23
76
|
libdragon update
|
|
24
77
|
|
|
25
|
-
|
|
78
|
+
In general, you can invoke libdragon as follows;
|
|
26
79
|
|
|
27
|
-
|
|
80
|
+
libdragon [flags] <action>
|
|
28
81
|
|
|
29
|
-
|
|
82
|
+
Run `libdragon help [action]` for more details on individual actions.
|
|
30
83
|
|
|
31
|
-
|
|
84
|
+
## Recipes
|
|
32
85
|
|
|
33
|
-
|
|
86
|
+
### Using a different branch of libdragon
|
|
34
87
|
|
|
35
|
-
|
|
88
|
+
Initialize your project as usual:
|
|
36
89
|
|
|
37
|
-
libdragon
|
|
90
|
+
libdragon init
|
|
38
91
|
|
|
39
|
-
|
|
92
|
+
Then switch the submodule to the desired branch:
|
|
93
|
+
|
|
94
|
+
cd ./libdragon
|
|
95
|
+
git checkout opengl
|
|
96
|
+
cd ..
|
|
97
|
+
libdragon install
|
|
98
|
+
|
|
99
|
+
If your changes are on a different remote, then you will need to manage your git remotes as usual.
|
|
100
|
+
|
|
101
|
+
### Testing changes on libdragon
|
|
102
|
+
|
|
103
|
+
As libdragon is an actively developed library, you may find yourself at a position where you want to change a few things on it and see how it works. In general, if you modify the files in `libdragon` folder of your project, you can install that version to the docker container by simply running:
|
|
104
|
+
|
|
105
|
+
libdragon install
|
|
106
|
+
|
|
107
|
+
This will update all the artifacts in your container and your new code will start linking against the new version when you re-build it via `libdragon make`. The build system should pick up the change in the library and re-compile the dependent files.
|
|
108
|
+
|
|
109
|
+
Instead of depending on the above command, you can re-build the library by making it a make dependency in your project:
|
|
110
|
+
|
|
111
|
+
```makefile
|
|
112
|
+
libdragon-install: libdragon
|
|
113
|
+
$(MAKE) -C ./libdragon install
|
|
114
|
+
|
|
115
|
+
libdragon:
|
|
116
|
+
$(MAKE) -C ./libdragon
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
If your build now depends on `libdragon-install`, it will force an install (which should be pretty quick if you don't have changes) and force the build system to rebuild your project when necessary.
|
|
120
|
+
|
|
121
|
+
If you clone this repository, this setup is pretty much ready for you. Make sure you have a working libdragon setup and you get the submodules (e.g `git submodule update --init`). Then you can run `libdragon make bench` to execute the code in `./src` with your library changes. Also see [test bench](#local-test-bench).
|
|
122
|
+
|
|
123
|
+
When managing your changes to the library, you have a few options:
|
|
124
|
+
|
|
125
|
+
#### **Using `submodule` vendor strategy.**
|
|
126
|
+
|
|
127
|
+
To be able to share your project with the library change, you would need to push it somewhere public and make sure it is cloned properly by your contributors. This is not recommended for keeping track of your changes but is very useful if you plan to contribute it back to upstream. In the latter case, you can push your submodule branch to your fork and easily open a PR.
|
|
128
|
+
|
|
129
|
+
#### **Using `subtree` vendor strategy.**
|
|
130
|
+
|
|
131
|
+
To be able to share your project with the library change, you just commit your changes. This is very useful for keeping track of your changes specific to your project. On the other hand this is not recommended if you plan to contribute it back to upstream because you will need to make sure your libdragon commits are isolated and do the juggling when pushing it somewhere via `git subtree push`.
|
|
40
132
|
|
|
41
133
|
## Working on this repository
|
|
42
134
|
|
|
@@ -86,15 +178,40 @@ This repository also uses [ed64](https://github.com/anacierdem/ed64), so you can
|
|
|
86
178
|
|
|
87
179
|
There are also additional vscode launch configurations to build libdragon examples and tests based on the currently built and installed libdragon in the docker container. Most of these will always rebuild so that they will use the latest if you made and installed an alternative libdragon. The test bench itself and a few examples (that use the new build system) will already rebuild and reinstall libdragon automatically. These will always produce a rom image using the latest libdragon code in the active repository via its make dependencies. You can clean everything with the `clean` task (open the command palette and choose `Run Task -> clean`).
|
|
88
180
|
|
|
181
|
+
### Developing the tool itself
|
|
182
|
+
|
|
183
|
+
For a quick development loop it really helps linking the code in this repository as the global libdragon installation. To do this run;
|
|
184
|
+
|
|
185
|
+
npm link
|
|
186
|
+
|
|
187
|
+
in the root of the repository. Once you do this, running `libdragon` will use the code here rather than the actual npm installation. Then you can test your changes in the libdragon project here or elsewhere on your computer.
|
|
188
|
+
|
|
189
|
+
When you are happy with your changes, you can verify you conform to the coding standards via:
|
|
190
|
+
|
|
191
|
+
npm run format-check
|
|
192
|
+
npm run lint-check
|
|
193
|
+
|
|
194
|
+
You can auto-fix applicable errors by running `format` and `lint` scripts instead. Additionally, typescript is used as the type system. To be able to get away with transpiling the code during development, jsDoc flavor of types are used instead of inline ones. To check your types, run:
|
|
195
|
+
|
|
196
|
+
npm run tsc
|
|
197
|
+
|
|
198
|
+
This repository uses [`semantic-release`](https://github.com/semantic-release/semantic-release) and manages releases from specially formatted commit messages. To simplify creating them you can use:
|
|
199
|
+
|
|
200
|
+
npx cz
|
|
201
|
+
|
|
202
|
+
It will create a `semantic-release` compatible commit from your current staged changes.
|
|
203
|
+
|
|
89
204
|
## As an NPM dependency
|
|
90
205
|
|
|
91
206
|
You can install libdragon as an NPM dependency by `npm install libdragon --save` in order to use docker in your N64 projects. A `libdragon` command similar to global intallation is provided that can be used in your NPM scripts as follows;
|
|
92
207
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
208
|
+
```json
|
|
209
|
+
"scripts": {
|
|
210
|
+
"prepare": "libdragon init"
|
|
211
|
+
"build": "libdragon make",
|
|
212
|
+
"clean": "libdragon make clean"
|
|
213
|
+
}
|
|
214
|
+
```
|
|
98
215
|
|
|
99
216
|
See [here](https://github.com/anacierdem/ed64-example) for a full example.
|
|
100
217
|
|
|
@@ -104,29 +221,27 @@ You can make an NPM package that a `libdragon` project can depend on. Just inclu
|
|
|
104
221
|
|
|
105
222
|
For example this `package.json` in the dependent project;
|
|
106
223
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
224
|
+
```json
|
|
225
|
+
{
|
|
226
|
+
"name": "libdragonDependentProject",
|
|
227
|
+
"version": "1.0.0",
|
|
228
|
+
"description": "...",
|
|
229
|
+
"scripts": {
|
|
230
|
+
"build": "libdragon make",
|
|
231
|
+
"clean": "libdragon make clean",
|
|
232
|
+
"prepare": "libdragon init"
|
|
233
|
+
},
|
|
234
|
+
"dependencies": {
|
|
235
|
+
"libdragon": <version>,
|
|
236
|
+
"ed64": <version>
|
|
120
237
|
}
|
|
238
|
+
}
|
|
239
|
+
```
|
|
121
240
|
|
|
122
241
|
will init the container for this project and run `make && make install` for `ed64` upon running `npm install`. To develop a dependency [this](https://github.com/anacierdem/libdragon-dependency) is a good starting point.
|
|
123
242
|
|
|
124
243
|
This is an experimental dependency management.
|
|
125
244
|
|
|
126
|
-
## TODOS
|
|
127
|
-
|
|
128
|
-
- [ ] Skip CI checks for irrelevant changes.
|
|
129
|
-
|
|
130
245
|
## Funding
|
|
131
246
|
|
|
132
247
|
If this tool helped you, consider supporting its development by sponsoring it!
|
package/index.js
CHANGED
|
@@ -18,9 +18,30 @@ const {
|
|
|
18
18
|
const { parseParameters } = require('./modules/parameters');
|
|
19
19
|
const { readProjectInfo, writeProjectInfo } = require('./modules/project-info');
|
|
20
20
|
|
|
21
|
+
// Note: it is not possible to merge these type definitions in a single comment
|
|
22
|
+
/**
|
|
23
|
+
* @template {any} [U=any]
|
|
24
|
+
* @typedef {(U extends any ? (k: U)=>void : never) extends ((k: infer I)=>void) ? I : never} UnionToIntersection
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* @template {any} [K=any]
|
|
28
|
+
* never does not break the call `info.options.CURRENT_ACTION.fn`
|
|
29
|
+
* @typedef {[K] extends [UnionToIntersection<K>] ? any : unknown} NoUnion
|
|
30
|
+
* @typedef {NoUnion<Exclude<Parameters<import('./modules/parameters').Actions[import('./modules/project-info').ActionsNoProject]['fn']>[0], undefined>>} EitherCLIOrLibdragonInfo
|
|
31
|
+
*/
|
|
32
|
+
|
|
21
33
|
parseParameters(process.argv)
|
|
22
34
|
.then(readProjectInfo)
|
|
23
|
-
.then((info) =>
|
|
35
|
+
.then((info) => {
|
|
36
|
+
return info.options.CURRENT_ACTION.fn(
|
|
37
|
+
/** @type {EitherCLIOrLibdragonInfo} */ (info)
|
|
38
|
+
);
|
|
39
|
+
// This type make sure a similar restriction to this code block is enforced
|
|
40
|
+
// without adding unnecessary javascript.
|
|
41
|
+
// return isProjectAction(info)
|
|
42
|
+
// ? info.options.CURRENT_ACTION.fn(info)
|
|
43
|
+
// : info.options.CURRENT_ACTION.fn(info);
|
|
44
|
+
})
|
|
24
45
|
.catch((e) => {
|
|
25
46
|
if (e instanceof ParameterError) {
|
|
26
47
|
log(chalk.red(e.message));
|
|
@@ -6,6 +6,9 @@ const { CONFIG_FILE, LIBDRAGON_PROJECT_MANIFEST } = require('../constants');
|
|
|
6
6
|
const { fileExists, dirExists, log } = require('../helpers');
|
|
7
7
|
const chalk = require('chalk');
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* @param {import('../project-info').LibdragonInfo} libdragonInfo
|
|
11
|
+
*/
|
|
9
12
|
const destroy = async (libdragonInfo) => {
|
|
10
13
|
await destroyContainer(libdragonInfo);
|
|
11
14
|
|
|
@@ -22,13 +25,13 @@ const destroy = async (libdragonInfo) => {
|
|
|
22
25
|
log(chalk.green('Done cleanup.'));
|
|
23
26
|
};
|
|
24
27
|
|
|
25
|
-
module.exports = {
|
|
28
|
+
module.exports = /** @type {const} */ ({
|
|
26
29
|
name: 'destroy',
|
|
27
30
|
fn: destroy,
|
|
28
|
-
|
|
31
|
+
forwardsRestParams: false,
|
|
29
32
|
usage: {
|
|
30
33
|
name: 'destroy',
|
|
31
34
|
summary: 'Do clean-up for current project.',
|
|
32
35
|
description: `Removes libdragon configuration from current project and removes any known containers but will not touch previously vendored files. \`libdragon\` will not work anymore for this project.`,
|
|
33
36
|
},
|
|
34
|
-
};
|
|
37
|
+
});
|
|
@@ -10,6 +10,11 @@ const {
|
|
|
10
10
|
ParameterError,
|
|
11
11
|
} = require('../helpers');
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* @param {string} stop
|
|
15
|
+
* @param {string} start
|
|
16
|
+
* @returns {Promise<string>}
|
|
17
|
+
*/
|
|
13
18
|
const findElf = async (stop, start = '.') => {
|
|
14
19
|
start = path.resolve(start);
|
|
15
20
|
|
|
@@ -43,6 +48,9 @@ const findElf = async (stop, start = '.') => {
|
|
|
43
48
|
}
|
|
44
49
|
};
|
|
45
50
|
|
|
51
|
+
/**
|
|
52
|
+
* @param {import('../project-info').LibdragonInfo} info
|
|
53
|
+
*/
|
|
46
54
|
const disasm = async (info) => {
|
|
47
55
|
let elfPath;
|
|
48
56
|
if (info.options.FILE) {
|
|
@@ -89,7 +97,7 @@ const disasm = async (info) => {
|
|
|
89
97
|
});
|
|
90
98
|
};
|
|
91
99
|
|
|
92
|
-
module.exports = {
|
|
100
|
+
module.exports = /** @type {const} */ ({
|
|
93
101
|
name: 'disasm',
|
|
94
102
|
fn: disasm,
|
|
95
103
|
forwardsRestParams: true,
|
|
@@ -118,4 +126,4 @@ module.exports = {
|
|
|
118
126
|
},
|
|
119
127
|
],
|
|
120
128
|
},
|
|
121
|
-
};
|
|
129
|
+
});
|
package/modules/actions/exec.js
CHANGED
|
@@ -8,12 +8,16 @@ const {
|
|
|
8
8
|
toPosixPath,
|
|
9
9
|
fileExists,
|
|
10
10
|
dirExists,
|
|
11
|
+
CommandError,
|
|
11
12
|
} = require('../helpers');
|
|
12
13
|
|
|
13
14
|
const { start } = require('./start');
|
|
14
15
|
const { dockerHostUserParams } = require('./docker-utils');
|
|
15
16
|
const { installDependencies } = require('./utils');
|
|
16
17
|
|
|
18
|
+
/**
|
|
19
|
+
* @param {import('../project-info').LibdragonInfo} libdragonInfo
|
|
20
|
+
*/
|
|
17
21
|
function dockerRelativeWorkdir(libdragonInfo) {
|
|
18
22
|
return (
|
|
19
23
|
CONTAINER_TARGET_PATH +
|
|
@@ -22,10 +26,16 @@ function dockerRelativeWorkdir(libdragonInfo) {
|
|
|
22
26
|
);
|
|
23
27
|
}
|
|
24
28
|
|
|
29
|
+
/**
|
|
30
|
+
* @param {import('../project-info').LibdragonInfo} libdragonInfo
|
|
31
|
+
*/
|
|
25
32
|
function dockerRelativeWorkdirParams(libdragonInfo) {
|
|
26
33
|
return ['--workdir', dockerRelativeWorkdir(libdragonInfo)];
|
|
27
34
|
}
|
|
28
35
|
|
|
36
|
+
/**
|
|
37
|
+
* @param {import('../project-info').LibdragonInfo} info
|
|
38
|
+
*/
|
|
29
39
|
const exec = async (info) => {
|
|
30
40
|
const parameters = info.options.EXTRA_PARAMS.slice(1);
|
|
31
41
|
log(
|
|
@@ -37,21 +47,32 @@ const exec = async (info) => {
|
|
|
37
47
|
|
|
38
48
|
const stdin = new PassThrough();
|
|
39
49
|
|
|
40
|
-
|
|
41
|
-
|
|
50
|
+
/** @type {string[]} */
|
|
51
|
+
const paramsWithConvertedPaths = await Promise.all(
|
|
52
|
+
parameters.map(async (item) => {
|
|
53
|
+
if (item.startsWith('-')) {
|
|
54
|
+
return item;
|
|
55
|
+
}
|
|
56
|
+
if (
|
|
57
|
+
item.includes(path.sep) &&
|
|
58
|
+
((await fileExists(item)) || (await dirExists(item)))
|
|
59
|
+
) {
|
|
60
|
+
return toPosixPath(
|
|
61
|
+
path.isAbsolute(item) ? path.relative(process.cwd(), item) : item
|
|
62
|
+
);
|
|
63
|
+
}
|
|
42
64
|
return item;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return toPosixPath(
|
|
46
|
-
path.isAbsolute(item) ? path.relative(process.cwd(), item) : item
|
|
47
|
-
);
|
|
48
|
-
}
|
|
49
|
-
return item;
|
|
50
|
-
});
|
|
65
|
+
})
|
|
66
|
+
);
|
|
51
67
|
|
|
68
|
+
/**
|
|
69
|
+
*
|
|
70
|
+
* @param {import('../project-info').LibdragonInfo} libdragonInfo
|
|
71
|
+
* @param {import('../helpers').SpawnOptions} opts
|
|
72
|
+
* @returns
|
|
73
|
+
*/
|
|
52
74
|
const tryCmd = (libdragonInfo, opts = {}) => {
|
|
53
75
|
const enableTTY = Boolean(process.stdout.isTTY && process.stdin.isTTY);
|
|
54
|
-
|
|
55
76
|
return (
|
|
56
77
|
libdragonInfo.containerId &&
|
|
57
78
|
dockerExec(
|
|
@@ -80,6 +101,9 @@ const exec = async (info) => {
|
|
|
80
101
|
};
|
|
81
102
|
|
|
82
103
|
let started = false;
|
|
104
|
+
/**
|
|
105
|
+
* @param {import('fs').ReadStream=} stdin
|
|
106
|
+
*/
|
|
83
107
|
const startOnceAndCmd = async (stdin) => {
|
|
84
108
|
if (!started) {
|
|
85
109
|
const newId = await start(info);
|
|
@@ -121,22 +145,30 @@ const exec = async (info) => {
|
|
|
121
145
|
inheritStderr: false,
|
|
122
146
|
// In the first run, pass the stdin to the process if it is not a TTY
|
|
123
147
|
// o/w we loose a user input unnecesarily somehow.
|
|
124
|
-
stdin:
|
|
148
|
+
stdin:
|
|
149
|
+
(!process.stdin.isTTY || undefined) &&
|
|
150
|
+
/** @type {import('fs').ReadStream} */ (
|
|
151
|
+
/** @type {unknown} */ (process.stdin)
|
|
152
|
+
),
|
|
125
153
|
});
|
|
126
154
|
} catch (e) {
|
|
155
|
+
if (!(e instanceof CommandError)) {
|
|
156
|
+
throw e;
|
|
157
|
+
}
|
|
127
158
|
if (
|
|
128
|
-
!e.out ||
|
|
129
159
|
// TODO: is there a better way?
|
|
130
160
|
!e.out.toString().includes(info.containerId)
|
|
131
161
|
) {
|
|
132
162
|
throw e;
|
|
133
163
|
}
|
|
134
|
-
await startOnceAndCmd(
|
|
164
|
+
await startOnceAndCmd(
|
|
165
|
+
/** @type {import('fs').ReadStream} */ (/** @type {unknown} */ (stdin))
|
|
166
|
+
);
|
|
135
167
|
}
|
|
136
168
|
return info;
|
|
137
169
|
};
|
|
138
170
|
|
|
139
|
-
module.exports = {
|
|
171
|
+
module.exports = /** @type {const} */ ({
|
|
140
172
|
name: 'exec',
|
|
141
173
|
fn: exec,
|
|
142
174
|
forwardsRestParams: true,
|
|
@@ -152,4 +184,4 @@ module.exports = {
|
|
|
152
184
|
|
|
153
185
|
Must be run in an initialized libdragon project.`,
|
|
154
186
|
},
|
|
155
|
-
};
|
|
187
|
+
});
|
package/modules/actions/help.js
CHANGED
|
@@ -3,7 +3,10 @@ const commandLineUsage = require('command-line-usage');
|
|
|
3
3
|
|
|
4
4
|
const { print } = require('../helpers');
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* @param {import('../project-info').CLIInfo} info
|
|
8
|
+
*/
|
|
9
|
+
const printUsage = async (info) => {
|
|
7
10
|
const actions = require('./');
|
|
8
11
|
const globalOptionDefinitions = [
|
|
9
12
|
{
|
|
@@ -48,11 +51,12 @@ const printUsage = (info) => {
|
|
|
48
51
|
},
|
|
49
52
|
];
|
|
50
53
|
|
|
51
|
-
const actionsToShow =
|
|
54
|
+
const actionsToShow = /** @type {(keyof actions)[]} */ (
|
|
52
55
|
info?.options.EXTRA_PARAMS?.filter(
|
|
53
56
|
(action) =>
|
|
54
57
|
Object.keys(actions).includes(action) && !['help'].includes(action)
|
|
55
|
-
) ?? (info ? [info.options.CURRENT_ACTION.name] : [])
|
|
58
|
+
) ?? (info ? [info.options.CURRENT_ACTION.name] : [])
|
|
59
|
+
);
|
|
56
60
|
|
|
57
61
|
const sections = [
|
|
58
62
|
{
|
|
@@ -96,13 +100,12 @@ const printUsage = (info) => {
|
|
|
96
100
|
print(usage);
|
|
97
101
|
};
|
|
98
102
|
|
|
99
|
-
module.exports = {
|
|
103
|
+
module.exports = /** @type {const} */ ({
|
|
100
104
|
name: 'help',
|
|
101
105
|
fn: printUsage,
|
|
102
106
|
forwardsRestParams: true,
|
|
103
|
-
mustHaveProject: false,
|
|
104
107
|
usage: {
|
|
105
108
|
name: 'help [action]',
|
|
106
109
|
summary: 'Display this help information or details for the given action.',
|
|
107
110
|
},
|
|
108
|
-
};
|
|
111
|
+
});
|
package/modules/actions/init.js
CHANGED
|
@@ -3,7 +3,6 @@ const path = require('path');
|
|
|
3
3
|
|
|
4
4
|
const chalk = require('chalk').stderr;
|
|
5
5
|
|
|
6
|
-
const { fn: install } = require('./install');
|
|
7
6
|
const { start } = require('./start');
|
|
8
7
|
const {
|
|
9
8
|
installDependencies,
|
|
@@ -29,6 +28,10 @@ const {
|
|
|
29
28
|
} = require('../helpers');
|
|
30
29
|
const { syncImageAndStart } = require('./update-and-start');
|
|
31
30
|
|
|
31
|
+
/**
|
|
32
|
+
* @param {import('../project-info').LibdragonInfo} info
|
|
33
|
+
* @returns {Promise<"submodule" | "subtree" | undefined>}
|
|
34
|
+
*/
|
|
32
35
|
const autoDetect = async (info) => {
|
|
33
36
|
const vendorTarget = path.relative(
|
|
34
37
|
info.root,
|
|
@@ -60,15 +63,25 @@ const autoDetect = async (info) => {
|
|
|
60
63
|
inheritStdin: false,
|
|
61
64
|
inheritStdout: false,
|
|
62
65
|
inheritStderr: false,
|
|
66
|
+
}).catch((e) => {
|
|
67
|
+
if (!(e instanceof CommandError)) {
|
|
68
|
+
throw e;
|
|
69
|
+
}
|
|
63
70
|
});
|
|
64
71
|
|
|
65
|
-
if (
|
|
72
|
+
if (
|
|
73
|
+
gitLogs &&
|
|
74
|
+
gitLogs.includes(`git-subtree-dir: ${info.vendorDirectory}`)
|
|
75
|
+
) {
|
|
66
76
|
log(`${info.vendorDirectory} is a subtree.`);
|
|
67
77
|
return 'subtree';
|
|
68
78
|
}
|
|
69
79
|
}
|
|
70
80
|
};
|
|
71
81
|
|
|
82
|
+
/**
|
|
83
|
+
* @param {import('../project-info').LibdragonInfo} info
|
|
84
|
+
*/
|
|
72
85
|
const autoVendor = async (info) => {
|
|
73
86
|
// Update the strategy information for the project if the flag is provided
|
|
74
87
|
if (info.options.VENDOR_STRAT) {
|
|
@@ -96,6 +109,8 @@ const autoVendor = async (info) => {
|
|
|
96
109
|
}
|
|
97
110
|
|
|
98
111
|
await runGitMaybeHost(info, ['init']);
|
|
112
|
+
|
|
113
|
+
// TODO: TS thinks this is already defined
|
|
99
114
|
const detectedStrategy = await autoDetect(info);
|
|
100
115
|
|
|
101
116
|
if (
|
|
@@ -114,22 +129,32 @@ const autoVendor = async (info) => {
|
|
|
114
129
|
);
|
|
115
130
|
return {
|
|
116
131
|
...info,
|
|
117
|
-
vendorStrategy:
|
|
132
|
+
vendorStrategy: /** @type {import('../parameters').VendorStrategy} */ (
|
|
133
|
+
detectedStrategy
|
|
134
|
+
),
|
|
118
135
|
};
|
|
119
136
|
}
|
|
120
137
|
|
|
121
138
|
if (info.vendorStrategy === 'submodule') {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
139
|
+
try {
|
|
140
|
+
await runGitMaybeHost(info, [
|
|
141
|
+
'submodule',
|
|
142
|
+
'add',
|
|
143
|
+
'--force',
|
|
144
|
+
'--name',
|
|
145
|
+
LIBDRAGON_SUBMODULE,
|
|
146
|
+
'--branch',
|
|
147
|
+
LIBDRAGON_BRANCH,
|
|
148
|
+
LIBDRAGON_GIT,
|
|
149
|
+
info.vendorDirectory,
|
|
150
|
+
]);
|
|
151
|
+
} catch (e) {
|
|
152
|
+
if (!(e instanceof CommandError)) throw e;
|
|
153
|
+
// We speculate this is caused by the user, so replace it with a more useful error message.
|
|
154
|
+
e.message = `Unable to create submodule. If you have copied the executable in your project folder or you have a file named ${info.vendorDirectory}, removing it might solve this issue. Original error:\n${e.message}`;
|
|
155
|
+
throw e;
|
|
156
|
+
}
|
|
157
|
+
|
|
133
158
|
return info;
|
|
134
159
|
}
|
|
135
160
|
|
|
@@ -163,11 +188,14 @@ const autoVendor = async (info) => {
|
|
|
163
188
|
]);
|
|
164
189
|
return info;
|
|
165
190
|
}
|
|
191
|
+
|
|
192
|
+
return info;
|
|
166
193
|
};
|
|
167
194
|
|
|
168
195
|
/**
|
|
169
196
|
* Initialize a new libdragon project in current working directory
|
|
170
197
|
* Also downloads the image
|
|
198
|
+
* @param {import('../project-info').LibdragonInfo} info
|
|
171
199
|
*/
|
|
172
200
|
async function init(info) {
|
|
173
201
|
log(`Initializing a libdragon project at ${info.root}`);
|
|
@@ -176,7 +204,7 @@ async function init(info) {
|
|
|
176
204
|
const manifestPath = path.join(info.root, LIBDRAGON_PROJECT_MANIFEST);
|
|
177
205
|
const manifestStats = await fs.stat(manifestPath).catch((e) => {
|
|
178
206
|
if (e.code !== 'ENOENT') throw e;
|
|
179
|
-
return false;
|
|
207
|
+
return /** @type {const} */ (false);
|
|
180
208
|
});
|
|
181
209
|
|
|
182
210
|
if (manifestStats && !manifestStats.isDirectory()) {
|
|
@@ -216,7 +244,9 @@ async function init(info) {
|
|
|
216
244
|
info.containerId = await start(info);
|
|
217
245
|
|
|
218
246
|
// We have created a new container, save the new info ASAP
|
|
219
|
-
await initGitAndCacheContainerId(
|
|
247
|
+
await initGitAndCacheContainerId(
|
|
248
|
+
/** @type Parameters<initGitAndCacheContainerId>[0] */ (info)
|
|
249
|
+
);
|
|
220
250
|
|
|
221
251
|
info = await autoVendor(info);
|
|
222
252
|
|
|
@@ -233,10 +263,10 @@ async function init(info) {
|
|
|
233
263
|
return info;
|
|
234
264
|
}
|
|
235
265
|
|
|
236
|
-
module.exports = {
|
|
266
|
+
module.exports = /** @type {const} */ ({
|
|
237
267
|
name: 'init',
|
|
238
268
|
fn: init,
|
|
239
|
-
|
|
269
|
+
forwardsRestParams: false,
|
|
240
270
|
usage: {
|
|
241
271
|
name: 'init',
|
|
242
272
|
summary: 'Create a libdragon project in the current directory.',
|
|
@@ -249,4 +279,4 @@ module.exports = {
|
|
|
249
279
|
If you have an existing project with an already vendored submodule or subtree libdragon copy, \`init\` will automatically detect it at the provided \`--directory\`.`,
|
|
250
280
|
group: ['docker', 'vendoring'],
|
|
251
281
|
},
|
|
252
|
-
};
|
|
282
|
+
});
|