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.
@@ -0,0 +1,129 @@
1
+ const chalk = require('chalk').stderr;
2
+
3
+ const { log } = require('./helpers');
4
+ const actions = require('./actions');
5
+ const { fn: printUsage } = require('./actions/help');
6
+ const { STATUS_BAD_PARAM } = require('./constants');
7
+ const { globals } = require('./globals');
8
+
9
+ const parseParameters = async (argv) => {
10
+ const options = {
11
+ EXTRA_PARAMS: [],
12
+ CURRENT_ACTION: undefined,
13
+ };
14
+
15
+ for (let i = 2; i < argv.length; i++) {
16
+ const val = argv[i];
17
+
18
+ if (['--verbose', '-v'].includes(val)) {
19
+ options.VERBOSE = true;
20
+ globals.verbose = true;
21
+ continue;
22
+ }
23
+
24
+ // TODO: we might move these to actions as well.
25
+ if (['--image', '-i'].includes(val)) {
26
+ options.DOCKER_IMAGE = argv[++i];
27
+ continue;
28
+ } else if (val.indexOf('--image=') === 0) {
29
+ options.DOCKER_IMAGE = val.split('=')[1];
30
+ continue;
31
+ }
32
+
33
+ if (['--directory', '-d'].includes(val)) {
34
+ options.VENDOR_DIR = argv[++i];
35
+ continue;
36
+ } else if (val.indexOf('--directory=') === 0) {
37
+ options.VENDOR_DIR = val.split('=')[1];
38
+ continue;
39
+ }
40
+
41
+ if (['--strategy', '-s'].includes(val)) {
42
+ options.VENDOR_STRAT = argv[++i];
43
+ continue;
44
+ } else if (val.indexOf('--strategy=') === 0) {
45
+ options.VENDOR_STRAT = val.split('=')[1];
46
+ continue;
47
+ }
48
+
49
+ if (['--file', '-f'].includes(val)) {
50
+ options.FILE = argv[++i];
51
+ continue;
52
+ } else if (val.indexOf('--file=') === 0) {
53
+ options.FILE = val.split('=')[1];
54
+ continue;
55
+ }
56
+
57
+ if (val.indexOf('-') == 0) {
58
+ log(chalk.red(`Invalid flag \`${val}\``));
59
+ printUsage();
60
+ process.exit(STATUS_BAD_PARAM);
61
+ }
62
+
63
+ if (options.CURRENT_ACTION) {
64
+ log(chalk.red(`Expected only a single action, found: \`${val}\``));
65
+ printUsage();
66
+ process.exit(STATUS_BAD_PARAM);
67
+ }
68
+
69
+ options.CURRENT_ACTION = actions[val];
70
+
71
+ if (!options.CURRENT_ACTION) {
72
+ log(chalk.red(`Invalid action \`${val}\``));
73
+ printUsage();
74
+ process.exit(STATUS_BAD_PARAM);
75
+ }
76
+
77
+ if (options.CURRENT_ACTION.forwardsRestParams) {
78
+ options.EXTRA_PARAMS = argv.slice(i + 1);
79
+ break;
80
+ }
81
+ }
82
+
83
+ if (!options.CURRENT_ACTION) {
84
+ log(chalk.red('No action provided'));
85
+ printUsage();
86
+ process.exit(STATUS_BAD_PARAM);
87
+ }
88
+
89
+ if (
90
+ options.CURRENT_ACTION === actions.exec &&
91
+ options.EXTRA_PARAMS.length === 0
92
+ ) {
93
+ log(chalk.red('You should provide a command to exec'));
94
+ printUsage(undefined, [options.CURRENT_ACTION.name]);
95
+ process.exit(STATUS_BAD_PARAM);
96
+ }
97
+
98
+ if (
99
+ ![actions.init, actions.install, actions.update].includes(
100
+ options.CURRENT_ACTION
101
+ ) &&
102
+ options.DOCKER_IMAGE
103
+ ) {
104
+ log(chalk.red('Invalid flag: image'));
105
+ printUsage(undefined, [options.CURRENT_ACTION.name]);
106
+ process.exit(STATUS_BAD_PARAM);
107
+ }
108
+
109
+ if (
110
+ options.VENDOR_STRAT &&
111
+ !['submodule', 'subtree', 'manual'].includes(options.VENDOR_STRAT)
112
+ ) {
113
+ log(chalk.red(`Invalid strategy \`${options.VENDOR_STRAT}\``));
114
+ printUsage();
115
+ process.exit(STATUS_BAD_PARAM);
116
+ }
117
+
118
+ if (![actions.disasm].includes(options.CURRENT_ACTION) && options.FILE) {
119
+ log(chalk.red('Invalid flag: file'));
120
+ printUsage(undefined, [options.CURRENT_ACTION.name]);
121
+ process.exit(STATUS_BAD_PARAM);
122
+ }
123
+
124
+ return { options };
125
+ };
126
+
127
+ module.exports = {
128
+ parseParameters,
129
+ };
@@ -4,11 +4,11 @@ const fs = require('fs/promises');
4
4
 
5
5
  const {
6
6
  checkContainerAndClean,
7
- findNPMRoot,
8
- runGitMaybeHost,
9
- tryCacheContainerId,
7
+ initGitAndCacheContainerId,
10
8
  } = require('./actions/utils');
11
9
 
10
+ const { findNPMRoot } = require('./actions/npm-utils');
11
+
12
12
  const {
13
13
  LIBDRAGON_PROJECT_MANIFEST,
14
14
  CONFIG_FILE,
@@ -20,7 +20,17 @@ const {
20
20
  CONTAINER_TARGET_PATH,
21
21
  } = require('./constants');
22
22
 
23
- const { fileExists, log, spawnProcess, toPosixPath } = require('./helpers');
23
+ const {
24
+ fileExists,
25
+ log,
26
+ spawnProcess,
27
+ toPosixPath,
28
+ assert,
29
+ ParameterError,
30
+ } = require('./helpers');
31
+
32
+ const initAction = require('./actions/init');
33
+ const destroyAction = require('./actions/destroy');
24
34
 
25
35
  async function findContainerId(libdragonInfo) {
26
36
  const idFile = path.join(libdragonInfo.root, '.git', CACHED_CONTAINER_FILE);
@@ -42,7 +52,13 @@ async function findContainerId(libdragonInfo) {
42
52
  ])
43
53
  )
44
54
  .split('\n')
45
- .filter((s) => s.includes(`${libdragonInfo.root} `));
55
+ // docker seem to save paths with posix separators but make sure we look for
56
+ // both, just in case
57
+ .filter(
58
+ (s) =>
59
+ s.includes(`${toPosixPath(libdragonInfo.root)} `) ||
60
+ s.includes(`${libdragonInfo.root} `)
61
+ );
46
62
 
47
63
  if (candidates.length > 0) {
48
64
  const str = candidates[0];
@@ -50,11 +66,12 @@ async function findContainerId(libdragonInfo) {
50
66
  const idIndex = str.indexOf(shortId);
51
67
  const longId = str.slice(idIndex, idIndex + 64);
52
68
  if (longId.length === 64) {
53
- // If there is managed vendoring, make sure we have a git repo
54
- if (libdragonInfo.vendorStrategy !== 'manual') {
55
- await runGitMaybeHost(libdragonInfo, ['init']);
56
- }
57
- await tryCacheContainerId({ ...libdragonInfo, containerId: longId });
69
+ const newInfo = { ...libdragonInfo, containerId: longId };
70
+ // This shouldn't happen but if the user somehow deleted the .git folder
71
+ // (we don't have the container id file at this point) we can recover the
72
+ // project. `git init` is safe anyways and it is not executed if strategy
73
+ // is `manual`
74
+ await initGitAndCacheContainerId(newInfo);
58
75
  return longId;
59
76
  }
60
77
  }
@@ -83,20 +100,42 @@ async function findGitRoot() {
83
100
  }
84
101
  }
85
102
 
86
- async function readProjectInfo() {
103
+ async function readProjectInfo(info) {
104
+ // No need to do anything here if the action does not depend on the project
105
+ // The only exception is the init and destroy actions, which do not need an
106
+ // existing project but readProjectInfo must always run to analyze the situation
107
+ const forceReadProjectInfo = [initAction, destroyAction].includes(
108
+ info.options.CURRENT_ACTION
109
+ );
110
+ if (
111
+ info.options.CURRENT_ACTION.mustHaveProject === false &&
112
+ !forceReadProjectInfo
113
+ ) {
114
+ return info;
115
+ }
116
+
87
117
  const projectRoot = await findLibdragonRoot();
88
118
 
89
- let info = {
119
+ if (!projectRoot && !forceReadProjectInfo) {
120
+ throw new ParameterError(
121
+ 'This is not a libdragon project. Initialize with `libdragon init` first.',
122
+ info.options.CURRENT_ACTION.name
123
+ );
124
+ }
125
+
126
+ info = {
127
+ ...info,
90
128
  root: projectRoot ?? (await findNPMRoot()) ?? (await findGitRoot()),
91
129
  userInfo: os.userInfo(),
92
130
 
93
131
  // Use this to discriminate if there is a project when the command is run
132
+ // Only used for the init action ATM, and it is not ideal to have this here
94
133
  haveProjectConfig: !!projectRoot,
95
134
 
96
135
  // Set the defaults immediately, these should be present at all times even
97
136
  // if we are migrating from the old config because they did not exist before
98
137
  imageName: DOCKER_HUB_IMAGE,
99
- vendorDirectory: path.join('.', LIBDRAGON_SUBMODULE),
138
+ vendorDirectory: toPosixPath(path.join('.', LIBDRAGON_SUBMODULE)),
100
139
  vendorStrategy: DEFAULT_STRATEGY,
101
140
  };
102
141
 
@@ -158,30 +197,16 @@ async function readProjectInfo() {
158
197
  log(`Active vendor directory: ${info.vendorDirectory}`, true);
159
198
  log(`Active vendor strategy: ${info.vendorStrategy}`, true);
160
199
 
161
- // Cache the latest image name
162
- setProjectInfoToSave(info);
163
200
  return info;
164
201
  }
165
202
 
166
- let projectInfoToWrite = {};
167
203
  /**
168
- * Updates project info to be written. The provided keys are overwritten without
169
- * changing the existing values. When the process exists successfully these will
170
- * get written to the configuration file. Echoes back the given info.
171
- * @param info This is only the base info without action properties like showStatus
204
+ * @param info This is only the base info without options
172
205
  * fn and command line options
173
206
  */
174
- function setProjectInfoToSave(info) {
175
- projectInfoToWrite = { ...projectInfoToWrite, ...info };
176
- return info;
177
- }
178
-
179
- /**
180
- * @param info This is only the base info without action properties like showStatus
181
- * fn and command line options
182
- */
183
- async function writeProjectInfo(info = projectInfoToWrite) {
207
+ async function writeProjectInfo(info) {
184
208
  // Do not log anything here as it may litter the output being always run on exit
209
+ if (!info) return;
185
210
 
186
211
  const projectPath = path.join(info.root, LIBDRAGON_PROJECT_MANIFEST);
187
212
 
@@ -195,13 +220,17 @@ async function writeProjectInfo(info = projectInfoToWrite) {
195
220
  await fs.mkdir(projectPath);
196
221
  }
197
222
 
223
+ assert(
224
+ toPosixPath(info.vendorDirectory) === info.vendorDirectory,
225
+ new Error('vendorDirectory should always be in posix format')
226
+ );
227
+
198
228
  await fs.writeFile(
199
229
  path.join(projectPath, CONFIG_FILE),
200
230
  JSON.stringify(
201
231
  {
202
232
  imageName: info.imageName,
203
- // Always save this in posix format
204
- vendorDirectory: toPosixPath(info.vendorDirectory),
233
+ vendorDirectory: info.vendorDirectory,
205
234
  vendorStrategy: info.vendorStrategy,
206
235
  },
207
236
  null,
@@ -211,4 +240,4 @@ async function writeProjectInfo(info = projectInfoToWrite) {
211
240
  log(`Configuration file updated`, true);
212
241
  }
213
242
 
214
- module.exports = { readProjectInfo, writeProjectInfo, setProjectInfoToSave };
243
+ module.exports = { readProjectInfo, writeProjectInfo };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "libdragon",
3
- "version": "10.4.2",
3
+ "version": "10.7.0",
4
4
  "description": "This is a docker wrapper for libdragon",
5
5
  "main": "index.js",
6
6
  "engines": {
package/skeleton/Makefile CHANGED
@@ -3,16 +3,17 @@ SOURCE_DIR=src
3
3
  BUILD_DIR=build
4
4
  include $(N64_INST)/include/n64.mk
5
5
 
6
- src=main.c
7
-
8
6
  all: hello.z64
7
+ .PHONY: all
8
+
9
+ OBJS = $(BUILD_DIR)/main.o
9
10
 
10
11
  hello.z64: N64_ROM_TITLE="Hello World"
11
- $(BUILD_DIR)/hello.elf: $(src:%.c=$(BUILD_DIR)/%.o)
12
12
 
13
- clean:
14
- rm -f $(BUILD_DIR)/* hello.z64
13
+ $(BUILD_DIR)/hello.elf: $(OBJS)
15
14
 
16
- -include $(wildcard $(BUILD_DIR)/*.d)
15
+ clean:
16
+ rm -f $(BUILD_DIR)/* *.z64
17
+ .PHONY: clean
17
18
 
18
- .PHONY: all clean
19
+ -include $(wildcard $(BUILD_DIR)/*.d)