libdragon 11.4.4 → 12.0.1

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 CHANGED
@@ -6,9 +6,7 @@ This is a wrapper for a docker container to make managing the libdragon toolchai
6
6
 
7
7
  ## Prerequisites
8
8
 
9
- You should have [docker](https://www.docker.com/products/docker-desktop) (`>= 27.2.0`) 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.
9
+ You should have [docker](https://www.docker.com/products/docker-desktop) (`>= 27.2.0`) and [git](https://git-scm.com/downloads) installed on your system.
12
10
 
13
11
  ## Installation
14
12
 
@@ -65,7 +63,7 @@ Download the [pre-built executable](https://github.com/anacierdem/libdragon-dock
65
63
 
66
64
  ### via NPM
67
65
 
68
- Install [node.js](https://nodejs.org/en/download/) (`>= 18`) and install `libdragon` as a global NPM package;
66
+ Install [node.js](https://nodejs.org/en/download/) (`>= 22`) and install `libdragon` as a global NPM package;
69
67
 
70
68
  ```bash
71
69
  npm install -g libdragon
@@ -291,15 +289,9 @@ To create your own dev container backed project, you can use the contents of the
291
289
  - It will prepare the container and open it in the editor.
292
290
  </details>
293
291
 
294
- ## Dependency management
295
-
296
- > [!WARNING]
297
- > This is an experimental feature.
298
-
299
- ### As an NPM dependency
300
-
301
- 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;
292
+ ## As an NPM dependency
302
293
 
294
+ 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 installation is provided that can be used in your NPM scripts as follows;
303
295
  ```json
304
296
  "scripts": {
305
297
  "prepare": "libdragon init"
@@ -308,33 +300,6 @@ You can install libdragon as an NPM dependency by `npm install libdragon --save`
308
300
  }
309
301
  ```
310
302
 
311
- See [here](https://github.com/anacierdem/ed64-example) for a full example.
312
-
313
- ### Developing a dependency
314
-
315
- You can make an NPM package that a `libdragon` project can depend on. Just include a `Makefile` on the repository root with a default recipe and an `install` recipe. On the depending project, after installing libdragon and the dependency with `npm install <dep name> --save`, one can install libdragon dependencies on the current docker container using `package.json` scripts.
316
-
317
- For example this `package.json` in the dependent project;
318
-
319
- ```json
320
- {
321
- "name": "libdragonDependentProject",
322
- "version": "1.0.0",
323
- "description": "...",
324
- "scripts": {
325
- "build": "libdragon make",
326
- "clean": "libdragon make clean",
327
- "prepare": "libdragon init"
328
- },
329
- "dependencies": {
330
- "libdragon": <version>,
331
- "ed64": <version>
332
- }
333
- }
334
- ```
335
-
336
- 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.
337
-
338
303
  ## Funding
339
304
 
340
305
  If this tool helped you, consider supporting its development by sponsoring it!
package/index.js CHANGED
@@ -33,7 +33,7 @@ const { readProjectInfo, writeProjectInfo } = require('./modules/project-info');
33
33
  // This is overridden when building for SEA. When running from local or NPM,
34
34
  // the package.json version is used by the version action. esbuild will give
35
35
  // a warning for this assignment, but it works as expected.
36
- globalThis.VERSION = "";
36
+ globalThis.VERSION = '';
37
37
 
38
38
  parseParameters(process.argv)
39
39
  .then(readProjectInfo)
@@ -10,7 +10,7 @@ const {
10
10
  installDependencies,
11
11
  initGitAndCacheContainerId,
12
12
  updateImage,
13
- runGitMaybeHost,
13
+ runGit,
14
14
  destroyContainer,
15
15
  ensureGit,
16
16
  } = require('../utils');
@@ -61,15 +61,11 @@ const autoDetect = async (info) => {
61
61
 
62
62
  if (
63
63
  vendorTargetExists &&
64
- (await runGitMaybeHost(
65
- info,
66
- ['submodule', 'status', info.vendorDirectory],
67
- {
68
- inheritStdin: false,
69
- inheritStdout: false,
70
- inheritStderr: false,
71
- }
72
- ).catch((e) => {
64
+ (await runGit(info, ['submodule', 'status', info.vendorDirectory], {
65
+ inheritStdin: false,
66
+ inheritStdout: false,
67
+ inheritStderr: false,
68
+ }).catch((e) => {
73
69
  if (!(e instanceof CommandError)) {
74
70
  throw e;
75
71
  }
@@ -80,7 +76,7 @@ const autoDetect = async (info) => {
80
76
  }
81
77
 
82
78
  if (vendorTargetExists) {
83
- const gitLogs = await runGitMaybeHost(info, ['log'], {
79
+ const gitLogs = await runGit(info, ['log'], {
84
80
  inheritStdin: false,
85
81
  inheritStdout: false,
86
82
  inheritStderr: false,
@@ -161,7 +157,7 @@ const autoVendor = async (info) => {
161
157
 
162
158
  if (info.vendorStrategy === 'submodule') {
163
159
  try {
164
- await runGitMaybeHost(info, [
160
+ await runGit(info, [
165
161
  'submodule',
166
162
  'add',
167
163
  '--force',
@@ -188,7 +184,7 @@ const autoVendor = async (info) => {
188
184
  if (info.vendorStrategy === 'subtree') {
189
185
  // Create a commit if it does not exist. This is required for subtree.
190
186
  try {
191
- await runGitMaybeHost(info, ['rev-parse', 'HEAD']);
187
+ await runGit(info, ['rev-parse', 'HEAD']);
192
188
  } catch (e) {
193
189
  if (!(e instanceof CommandError)) throw e;
194
190
 
@@ -197,16 +193,16 @@ const autoVendor = async (info) => {
197
193
  // git on the host machine.
198
194
  // TODO: this is probably creating an unnecessary commit for someone who
199
195
  // just created a git repo and knows what they are doing.
200
- await runGitMaybeHost(info, [
196
+ await runGit(info, [
201
197
  'commit',
202
198
  '--allow-empty',
203
199
  '-n',
204
200
  '-m',
205
- 'Initial commit.',
201
+ '"Initial commit."',
206
202
  ]);
207
203
  }
208
204
 
209
- await runGitMaybeHost(info, [
205
+ await runGit(info, [
210
206
  'subtree',
211
207
  'add',
212
208
  '--prefix',
@@ -321,7 +317,7 @@ async function init(info) {
321
317
 
322
318
  if ((await autoDetect(info)) === 'submodule') {
323
319
  try {
324
- const existingBranchName = await runGitMaybeHost(
320
+ const existingBranchName = await runGit(
325
321
  info,
326
322
  [
327
323
  '-C',
@@ -58,7 +58,16 @@ const initContainer = async (libdragonInfo) => {
58
58
  '-R',
59
59
  `${uid >= 0 ? uid : ''}:${gid >= 0 ? gid : ''}`,
60
60
  '/n64_toolchain',
61
- ]
61
+ ],
62
+ {
63
+ userCommand: false,
64
+ inheritStdin: true,
65
+ inheritStdout: false,
66
+ inheritStderr: false,
67
+ spawnOptions: {
68
+ shell: true,
69
+ },
70
+ }
62
71
  );
63
72
  } catch (e) {
64
73
  // Dispose the invalid container, clean and exit
@@ -1,7 +1,7 @@
1
1
  const { log, assert } = require('../helpers');
2
2
  const { LIBDRAGON_GIT } = require('../constants');
3
3
  const {
4
- runGitMaybeHost,
4
+ runGit,
5
5
  installDependencies,
6
6
  updateImage,
7
7
  destroyContainer,
@@ -55,7 +55,7 @@ const update = async (info) => {
55
55
  }
56
56
 
57
57
  if (info.vendorStrategy === 'submodule') {
58
- await runGitMaybeHost(info, [
58
+ await runGit(info, [
59
59
  'submodule',
60
60
  'update',
61
61
  '--remote',
@@ -63,7 +63,7 @@ const update = async (info) => {
63
63
  info.vendorDirectory,
64
64
  ]);
65
65
  } else if (info.vendorStrategy === 'subtree') {
66
- await runGitMaybeHost(info, [
66
+ await runGit(info, [
67
67
  'subtree',
68
68
  'pull',
69
69
  '--prefix',
@@ -124,11 +124,12 @@ async function dirExists(path) {
124
124
  * }} SpawnOptions
125
125
  */
126
126
 
127
- // A simple Promise wrapper for child_process.spawn. Return the err/out streams
128
- // from the process by default. Specify inheritStdout / inheritStderr to disable
129
- // this and inherit the parent process's stream, passing through the TTY if any.
130
127
  /**
131
- *
128
+ * A simple Promise wrapper for child_process.spawn. Return the err/out streams
129
+ * from the process by default. Specify inheritStdout / inheritStderr to disable
130
+ * this and inherit the parent process's stream, passing through the TTY if any.
131
+ * Runs everything in a shell, so be careful with user input. By default, we get
132
+ * the input from user but this is the whole idea of most of the logic here.
132
133
  * @param {string} cmd
133
134
  * @param {string[]} params
134
135
  * @param {SpawnOptions} options
@@ -183,6 +184,10 @@ function spawnProcess(
183
184
  enableOutTTY ? 'inherit' : 'pipe',
184
185
  enableErrorTTY ? 'inherit' : 'pipe',
185
186
  ],
187
+ env: {
188
+ // Prevent the annoying docker "What's next?" message. It messes up everything.
189
+ DOCKER_CLI_HINTS: 'false',
190
+ },
186
191
  ...spawnOptions,
187
192
  });
188
193
 
@@ -348,17 +353,7 @@ const dockerExec = /** @type {DockerExec} */ (
348
353
  libdragonInfo.containerId,
349
354
  ...finalCmdWithParams,
350
355
  ],
351
- {
352
- ...options,
353
- spawnOptions: {
354
- env: {
355
- // Prevent the annoyin docker "What's next?" message. It messes up everything.
356
- DOCKER_CLI_HINTS: 'false',
357
- ...options?.spawnOptions?.env,
358
- },
359
- ...options?.spawnOptions,
360
- },
361
- }
356
+ options
362
357
  );
363
358
  }
364
359
  );
@@ -1,20 +1,6 @@
1
1
  const path = require('path');
2
- const fsClassic = require('fs');
3
- const fs = require('fs/promises');
4
2
 
5
- // TODO: stop using lodash just for a simple uniq function
6
- const _ = require('lodash');
7
-
8
- const { dockerHostUserParams } = require('./docker-utils');
9
-
10
- const { CONTAINER_TARGET_PATH } = require('./constants');
11
- const {
12
- fileExists,
13
- toPosixPath,
14
- spawnProcess,
15
- dockerExec,
16
- ValidationError,
17
- } = require('./helpers');
3
+ const { fileExists, spawnProcess } = require('./helpers');
18
4
 
19
5
  async function findNPMRoot() {
20
6
  try {
@@ -29,115 +15,15 @@ async function findNPMRoot() {
29
15
  }
30
16
  }
31
17
 
32
- /**
33
- * Install other NPM dependencies if this is an NPM project
34
- * @param {import('./project-info').LibdragonInfo} libdragonInfo
35
- */
36
- const installNPMDependencies = async (libdragonInfo) => {
37
- const npmRoot = await findNPMRoot();
38
- if (npmRoot) {
39
- const packageJsonPath = path.join(npmRoot, 'package.json');
40
-
41
- const { dependencies, devDependencies } = JSON.parse(
42
- await fs.readFile(packageJsonPath, { encoding: 'utf8' })
43
- );
44
-
45
- const deps = await Promise.all(
46
- Object.keys({
47
- ...dependencies,
48
- ...devDependencies,
49
- })
50
- .filter((dep) => dep !== 'libdragon')
51
- .map(async (dep) => {
52
- const npmPath = await runNPM(['ls', dep, '--parseable=true']);
53
- return {
54
- name: dep,
55
- paths: _.uniq(npmPath.split('\n').filter((f) => f)),
56
- };
57
- })
58
- );
59
-
60
- await Promise.all(
61
- deps.map(({ name, paths }) => {
62
- return /** @type Promise<void> */ (
63
- new Promise((resolve, reject) => {
64
- fsClassic.access(
65
- path.join(paths[0], 'Makefile'),
66
- fsClassic.constants.F_OK,
67
- async (e) => {
68
- if (e) {
69
- // File does not exist - skip
70
- resolve();
71
- return;
72
- }
73
-
74
- if (paths.length > 1) {
75
- reject(
76
- new ValidationError(
77
- `Using same dependency with different versions is not supported! ${name}`
78
- )
79
- );
80
- return;
81
- }
82
-
83
- try {
84
- const relativePath = toPosixPath(
85
- path.relative(libdragonInfo.root, paths[0])
86
- );
87
- const containerPath = path.posix.join(
88
- CONTAINER_TARGET_PATH,
89
- relativePath
90
- );
91
- const makePath = path.posix.join(containerPath, 'Makefile');
92
-
93
- await dockerExec(
94
- libdragonInfo,
95
- [...dockerHostUserParams(libdragonInfo)],
96
- [
97
- '/bin/bash',
98
- '-c',
99
- '[ -f ' +
100
- makePath +
101
- ' ] && make -C ' +
102
- containerPath +
103
- ' && make -C ' +
104
- containerPath +
105
- ' install',
106
- ]
107
- );
108
-
109
- resolve();
110
- } catch (e) {
111
- reject(e);
112
- }
113
- }
114
- );
115
- })
116
- );
117
- })
118
- );
119
- }
120
- };
121
-
122
18
  /**
123
19
  * @param {string[]} params
124
20
  */
125
21
  function runNPM(params) {
126
22
  return spawnProcess(
127
23
  /^win/.test(process.platform) ? 'npm.cmd' : 'npm',
128
- params,
129
- {
130
- userCommand: false,
131
- inheritStdin: true,
132
- inheritStdout: false,
133
- inheritStderr: false,
134
- spawnOptions: {
135
- shell: true,
136
- },
137
- }
24
+ params
138
25
  );
139
26
  }
140
27
  module.exports = {
141
- installNPMDependencies,
142
28
  findNPMRoot,
143
29
  };
package/modules/utils.js CHANGED
@@ -10,13 +10,11 @@ const {
10
10
  dockerExec,
11
11
  dirExists,
12
12
  assert,
13
- CommandError,
14
13
  ValidationError,
15
14
  toNativePath,
16
15
  } = require('./helpers');
17
16
 
18
17
  const { dockerHostUserParams } = require('./docker-utils');
19
- const { installNPMDependencies } = require('./npm-utils');
20
18
 
21
19
  /**
22
20
  * @param {import('./project-info').LibdragonInfo} libdragonInfo
@@ -42,10 +40,17 @@ const installDependencies = async (libdragonInfo) => {
42
40
  CONTAINER_TARGET_PATH + '/' + libdragonInfo.vendorDirectory,
43
41
  ...dockerHostUserParams(libdragonInfo),
44
42
  ],
45
- ['/bin/bash', './build.sh']
43
+ ['/bin/bash', './build.sh'],
44
+ {
45
+ userCommand: false,
46
+ inheritStdin: true,
47
+ inheritStdout: false,
48
+ inheritStderr: false,
49
+ spawnOptions: {
50
+ shell: true,
51
+ },
52
+ }
46
53
  );
47
-
48
- await installNPMDependencies(libdragonInfo);
49
54
  };
50
55
 
51
56
  /**
@@ -119,8 +124,7 @@ const destroyContainer = async (libdragonInfo) => {
119
124
  };
120
125
 
121
126
  /**
122
- * Invokes host git with provided params. If host does not have git, falls back
123
- * to the docker git, with the nix user set to the user running libdragon.
127
+ * Invokes host git with provided params.
124
128
  */
125
129
 
126
130
  /**
@@ -129,43 +133,23 @@ const destroyContainer = async (libdragonInfo) => {
129
133
  * @param {string[]} params
130
134
  * @param {import('./helpers').SpawnOptions} options
131
135
  */
132
- async function runGitMaybeHost(libdragonInfo, params, options = {}) {
136
+ async function runGit(libdragonInfo, params, options = {}) {
133
137
  assert(
134
138
  libdragonInfo.vendorStrategy !== 'manual',
135
139
  new Error('Should never run git if vendoring strategy is manual.')
136
140
  );
137
- try {
138
- const isWin = /^win/.test(process.platform);
139
-
140
- return await spawnProcess(
141
- 'git',
142
- ['-C', libdragonInfo.root, ...params],
143
- // Windows git is breaking the TTY somehow - disable TTY for now
144
- // We are not able to display progress for the initial clone b/c of this
145
- // Enable progress otherwise.
146
- isWin
147
- ? { inheritStdin: false, ...options }
148
- : { inheritStdout: true, inheritStderr: true, ...options }
149
- );
150
- } catch (e) {
151
- if (e instanceof CommandError) {
152
- throw e;
153
- }
154
-
155
- assert(
156
- !process.env.DOCKER_CONTAINER,
157
- new Error('[runGitMaybeHost] Native git should exist in a container.')
158
- );
159
-
160
- return await dockerExec(
161
- libdragonInfo,
162
- // Use the host user when initializing git as we will need access
163
- [...dockerHostUserParams(libdragonInfo)],
164
- ['git', ...params],
165
- // Let's enable tty here to show the progress
166
- { inheritStdout: true, inheritStderr: true, ...options }
167
- );
168
- }
141
+ const isWin = /^win/.test(process.platform);
142
+
143
+ return await spawnProcess(
144
+ 'git',
145
+ ['-C', libdragonInfo.root, ...params],
146
+ // Windows git is breaking the TTY somehow - disable TTY for now
147
+ // We are not able to display progress for the initial clone b/c of this
148
+ // Enable progress otherwise.
149
+ isWin
150
+ ? { inheritStdin: false, ...options }
151
+ : { inheritStdout: true, inheritStderr: true, ...options }
152
+ );
169
153
  }
170
154
 
171
155
  /**
@@ -267,7 +251,7 @@ async function initGitAndCacheContainerId(libdragonInfo) {
267
251
  */
268
252
  async function ensureGit(info) {
269
253
  const gitRoot = (
270
- await runGitMaybeHost(info, ['rev-parse', '--show-toplevel'], {
254
+ await runGit(info, ['rev-parse', '--show-toplevel'], {
271
255
  inheritStdin: false,
272
256
  inheritStdout: false,
273
257
  inheritStderr: false,
@@ -283,7 +267,7 @@ async function ensureGit(info) {
283
267
  // where there is a git working tree higher in the host filesystem, which
284
268
  // the container does not have access to.
285
269
  if (!gitRoot) {
286
- await runGitMaybeHost(info, ['init']);
270
+ await runGit(info, ['init']);
287
271
  }
288
272
  }
289
273
 
@@ -294,6 +278,6 @@ module.exports = {
294
278
  checkContainerRunning,
295
279
  checkContainerAndClean,
296
280
  initGitAndCacheContainerId,
297
- runGitMaybeHost,
281
+ runGit,
298
282
  ensureGit,
299
283
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "libdragon",
3
- "version": "11.4.4",
3
+ "version": "12.0.1",
4
4
  "description": "This is a docker wrapper for libdragon",
5
5
  "main": "index.js",
6
6
  "engines": {
@@ -41,7 +41,6 @@
41
41
  "dependencies": {
42
42
  "chalk": "^4.1.0",
43
43
  "command-line-usage": "^6.1.1",
44
- "lodash": "^4.17.20",
45
44
  "zx": "^8.1.8"
46
45
  },
47
46
  "devDependencies": {
@@ -49,11 +48,9 @@
49
48
  "@semantic-release/exec": "^6.0.3",
50
49
  "@semantic-release/git": "^10.0.1",
51
50
  "@types/command-line-usage": "^5.0.2",
52
- "@types/lodash": "^4.14.182",
53
51
  "commitizen": "^4.2.4",
54
52
  "cz-conventional-changelog": "^3.3.0",
55
53
  "esbuild": "^0.20.0",
56
- "ed64": "^2.0.4",
57
54
  "eslint": "^9.11.0",
58
55
  "jest": "^29.5.0",
59
56
  "postject": "^1.0.0-alpha.6",