docker-client-mx 1.43.0 → 1.44.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.
Files changed (70) hide show
  1. package/dist/docker-desktop-mx/browser/{chunk-CjySsWe4.js → chunk-5u_BJ6JX.js} +1 -1
  2. package/dist/docker-desktop-mx/browser/{chunk-yYm_2q6C.js → chunk-6988XP3w.js} +1 -1
  3. package/dist/docker-desktop-mx/browser/{chunk-qxDOm16k.js → chunk-7mU3uVaN.js} +1 -1
  4. package/dist/docker-desktop-mx/browser/{chunk-Bxte2YBm.js → chunk-B23Afk52.js} +1 -1
  5. package/dist/docker-desktop-mx/browser/{chunk-xmDwFpQl.js → chunk-B7xGbGa9.js} +1 -1
  6. package/dist/docker-desktop-mx/browser/{chunk-Cx-uRg2m.js → chunk-B8Uu84pE.js} +1 -1
  7. package/dist/docker-desktop-mx/browser/{chunk-k-zsJmvX.js → chunk-BCYusaqm.js} +1 -1
  8. package/dist/docker-desktop-mx/browser/{chunk-B1xjyPnV.js → chunk-BEtYD0_3.js} +1 -1
  9. package/dist/docker-desktop-mx/browser/{chunk-DS3iAefP.js → chunk-BG-O4Nb_.js} +1 -1
  10. package/dist/docker-desktop-mx/browser/{chunk-DnY7-enP.js → chunk-BJsftgmt.js} +1 -1
  11. package/dist/docker-desktop-mx/browser/{chunk-CUSsr_nJ.js → chunk-Bho6QLGs.js} +1 -1
  12. package/dist/docker-desktop-mx/browser/{chunk-hJqozYgS.js → chunk-C1Nu6ZjD.js} +1 -1
  13. package/dist/docker-desktop-mx/browser/chunk-C3hTwhog.js +4 -0
  14. package/dist/docker-desktop-mx/browser/chunk-C52HI2A-.js +1 -0
  15. package/dist/docker-desktop-mx/browser/chunk-CGKsmblG.js +6 -0
  16. package/dist/docker-desktop-mx/browser/{chunk-BE5ctn7s.js → chunk-CMi-ZnXy.js} +1 -1
  17. package/dist/docker-desktop-mx/browser/{chunk-vPeKxmUB.js → chunk-CYFxPPxo2.js} +1 -1
  18. package/dist/docker-desktop-mx/browser/{chunk-DdTfHpyK.js → chunk-Cl4e4J9q.js} +1 -1
  19. package/dist/docker-desktop-mx/browser/{chunk-CjAbzLl3.js → chunk-Cr28jI1A.js} +1 -1
  20. package/dist/docker-desktop-mx/browser/{chunk-Cpz4zP5G.js → chunk-CzkAHty9.js} +1 -1
  21. package/dist/docker-desktop-mx/browser/{chunk-D2SM5E9h.js → chunk-D1tQa5OM.js} +1 -1
  22. package/dist/docker-desktop-mx/browser/{chunk-75uKIulV.js → chunk-D3PaEk7L.js} +1 -1
  23. package/dist/docker-desktop-mx/browser/chunk-DApzx4cc2.js +1 -0
  24. package/dist/docker-desktop-mx/browser/{chunk-BpQVP_gf.js → chunk-DNiq9JXI.js} +1 -1
  25. package/dist/docker-desktop-mx/browser/{chunk-BsTDUJ3m.js → chunk-DSfTqCF0.js} +1 -1
  26. package/dist/docker-desktop-mx/browser/{chunk-VC5gaeEq.js → chunk-DeEfJWMH2.js} +1 -1
  27. package/dist/docker-desktop-mx/browser/{chunk-DCYTwazU.js → chunk-DeROY6LN.js} +1 -1
  28. package/dist/docker-desktop-mx/browser/{chunk-hXmaVpBu2.js → chunk-DffEUxgS.js} +1 -1
  29. package/dist/docker-desktop-mx/browser/chunk-Di7dDUYN2.js +6 -0
  30. package/dist/docker-desktop-mx/browser/{chunk-Q3Ig-PJ6.js → chunk-DiB8MPYS.js} +1 -1
  31. package/dist/docker-desktop-mx/browser/{chunk-DLpC_2HL.js → chunk-Dp9UsDfH.js} +16 -16
  32. package/dist/docker-desktop-mx/browser/{chunk-Cau4mGeC.js → chunk-DtM-X5Eh.js} +1 -1
  33. package/dist/docker-desktop-mx/browser/{chunk-D5njuWRz.js → chunk-DtY6mcWb.js} +1 -1
  34. package/dist/docker-desktop-mx/browser/{chunk-D86K3m6W.js → chunk-DtbAIphi.js} +1 -1
  35. package/dist/docker-desktop-mx/browser/{chunk-CaR7Z77S2.js → chunk-DvJZmDzM2.js} +1 -1
  36. package/dist/docker-desktop-mx/browser/{chunk-CpNGhf9S.js → chunk-Dy3d-reD.js} +1 -1
  37. package/dist/docker-desktop-mx/browser/chunk-DzyPSjiy2.js +1 -0
  38. package/dist/docker-desktop-mx/browser/{chunk-CphQt55R.js → chunk-MyEYCSP-.js} +1 -1
  39. package/dist/docker-desktop-mx/browser/{chunk-DNfiG-TG.js → chunk-bSfpBwIa.js} +1 -1
  40. package/dist/docker-desktop-mx/browser/{chunk-BNz89YmT2.js → chunk-e16wEMMK.js} +1 -1
  41. package/dist/docker-desktop-mx/browser/{chunk-C7c_wFw-.js → chunk-eoU2TjRt.js} +1 -1
  42. package/dist/docker-desktop-mx/browser/{chunk-gHmeiJFn.js → chunk-xPy8hpGV.js} +1 -1
  43. package/dist/docker-desktop-mx/browser/index.html +2 -2
  44. package/dist/docker-desktop-mx/browser/main-WTPCDZAO.js +1 -0
  45. package/dist/docker-desktop-mx/browser/styles-2WH7TMRX.css +1 -0
  46. package/dist-electron/channels.js +4 -0
  47. package/dist-electron/channels.js.map +1 -1
  48. package/dist-electron/container-adjust.js +182 -0
  49. package/dist-electron/container-adjust.js.map +1 -0
  50. package/dist-electron/exec.js +78 -7
  51. package/dist-electron/exec.js.map +1 -1
  52. package/dist-electron/file-edit.js +206 -0
  53. package/dist-electron/file-edit.js.map +1 -0
  54. package/dist-electron/ipc.js +28 -5
  55. package/dist-electron/ipc.js.map +1 -1
  56. package/dist-electron/log-export.js +5 -4
  57. package/dist-electron/log-export.js.map +1 -1
  58. package/dist-electron/logs.js +26 -10
  59. package/dist-electron/logs.js.map +1 -1
  60. package/dist-electron/preload.js +12 -4
  61. package/dist-electron/preload.js.map +1 -1
  62. package/package.json +1 -1
  63. package/dist/docker-desktop-mx/browser/chunk-B-8njY4y.js +0 -1
  64. package/dist/docker-desktop-mx/browser/chunk-BYBsnx9-2.js +0 -1
  65. package/dist/docker-desktop-mx/browser/chunk-CpIMiI_l.js +0 -4
  66. package/dist/docker-desktop-mx/browser/chunk-DGnxa3ti2.js +0 -1
  67. package/dist/docker-desktop-mx/browser/chunk-iWbUoQd52.js +0 -6
  68. package/dist/docker-desktop-mx/browser/chunk-sxrgZH0E.js +0 -3
  69. package/dist/docker-desktop-mx/browser/main-UUO74KHR.js +0 -1
  70. package/dist/docker-desktop-mx/browser/styles-IM2TO7ZD.css +0 -1
@@ -0,0 +1,182 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toAdjustPlan = toAdjustPlan;
4
+ exports.ownAliases = ownAliases;
5
+ exports.toAdjustedOptions = toAdjustedOptions;
6
+ exports.readAdjustPlan = readAdjustPlan;
7
+ exports.adjustContainer = adjustContainer;
8
+ const containers_1 = require("./containers");
9
+ const docker_client_1 = require("./docker-client");
10
+ const i18n_1 = require("./i18n");
11
+ const port_conflicts_1 = require("./port-conflicts");
12
+ /**
13
+ * Een losse container aanpassen (fase 80): de omgevingsvariabelen, de poorten en de restart policy.
14
+ * Docker kan die niet veranderen op een bestaande container, dus: opnieuw maken onder dezelfde naam.
15
+ *
16
+ * In deze volgorde, zodat er op elk moment een weg terug is:
17
+ * 1. het origineel stoppen (anders kan de nieuwe dezelfde poort niet krijgen);
18
+ * 2. het origineel hernoemen naar `naam-oud`;
19
+ * 3. de nieuwe maken onder de oude naam, aan dezelfde netwerken, en starten;
20
+ * 4. pas dan het origineel weggooien, zonder zijn volumes.
21
+ * Mislukt 3, dan gaat de nieuwe weg, krijgt het origineel zijn naam terug en start het weer als het
22
+ * draaide.
23
+ *
24
+ * Anders dan bij dupliceren (fase 75) blijven de aliassen op een netwerk: het is dezelfde container.
25
+ * En een anoniem volume gaat expliciet mee: zonder dat krijgt de nieuwe een leeg volume, en is de
26
+ * data van bijvoorbeeld een database zonder benoemd volume weg.
27
+ *
28
+ * Alleen voor een container zonder compose: daar hoort de wijziging in het compose-bestand.
29
+ */
30
+ const COMPOSE_LABEL = /^com\.docker\.compose\./;
31
+ const RESTART_POLICIES = ['no', 'always', 'unless-stopped', 'on-failure'];
32
+ function bareName(name) {
33
+ return (name ?? '').replace(/^\//, '');
34
+ }
35
+ /** Wat de dialoog nodig heeft: de variabelen zoals ze nu zijn, de poorten en de restart policy. */
36
+ function toAdjustPlan(raw) {
37
+ const bindings = raw.HostConfig?.PortBindings;
38
+ const ports = Object.entries(bindings ?? {})
39
+ .map(([key, list]) => {
40
+ const [port, protocol] = key.split('/');
41
+ return { containerPort: Number(port), protocol: protocol === 'udp' ? 'udp' : 'tcp', hostPort: list?.[0]?.HostPort ? Number(list[0].HostPort) : null };
42
+ })
43
+ .sort((a, b) => a.containerPort - b.containerPort);
44
+ const policy = RESTART_POLICIES.find((name) => name === raw.HostConfig?.RestartPolicy?.Name) ?? 'no';
45
+ return {
46
+ name: bareName(raw.Name),
47
+ env: [...(raw.Config?.Env ?? [])],
48
+ ports,
49
+ restart: policy,
50
+ compose: Object.keys(raw.Config?.Labels ?? {}).some((label) => COMPOSE_LABEL.test(label)),
51
+ };
52
+ }
53
+ /** De aliassen die je zelf gaf; Docker zet er zelf de korte id en de naam bij, en die komen vanzelf terug. */
54
+ function ownAliases(aliases, raw) {
55
+ const automatic = new Set([bareName(raw.Name), (raw.Id ?? '').slice(0, 12)]);
56
+ return (aliases ?? []).filter((alias) => !automatic.has(alias));
57
+ }
58
+ /** De create-body van de nieuwe versie: alles van het origineel, met de aangepaste drie, en de anonieme volumes erbij. */
59
+ function toAdjustedOptions(raw, options) {
60
+ // De hostnaam laat Docker weer zelf kiezen, net als bij een nieuwe container.
61
+ const config = { ...(raw.Config ?? {}) };
62
+ delete config.Hostname;
63
+ const host = raw.HostConfig ?? {};
64
+ const exposed = { ...(config.ExposedPorts ?? {}) };
65
+ const bindings = {};
66
+ for (const port of options.ports) {
67
+ const key = `${String(port.containerPort)}/${port.protocol}`;
68
+ exposed[key] = {};
69
+ bindings[key] = [{ HostPort: port.hostPort === null ? '' : String(port.hostPort) }];
70
+ }
71
+ // Een volume zonder naam staat niet in Binds; zonder het hier te noemen krijgt de nieuwe een leeg volume.
72
+ const named = new Set((host.Binds ?? []).map((bind) => bind.split(':')[0]));
73
+ const anonymous = (raw.Mounts ?? [])
74
+ .filter((mount) => mount.Type === 'volume' && mount.Name !== undefined && mount.Destination !== undefined && !named.has(mount.Name))
75
+ .map((mount) => `${mount.Name ?? ''}:${mount.Destination ?? ''}`);
76
+ const primary = host.NetworkMode ?? '';
77
+ const aliases = ownAliases(raw.NetworkSettings?.Networks?.[primary]?.Aliases, raw);
78
+ return {
79
+ ...config,
80
+ name: bareName(raw.Name),
81
+ Env: [...options.env],
82
+ ExposedPorts: exposed,
83
+ HostConfig: {
84
+ ...host,
85
+ PortBindings: bindings,
86
+ Binds: [...(host.Binds ?? []), ...anonymous],
87
+ RestartPolicy: { Name: options.restart, MaximumRetryCount: options.restart === 'on-failure' ? (host.RestartPolicy?.MaximumRetryCount ?? 0) : 0 },
88
+ },
89
+ ...(aliases.length > 0 ? { NetworkingConfig: { EndpointsConfig: { [primary]: { Aliases: aliases } } } } : {}),
90
+ };
91
+ }
92
+ /** Wat de dialoog "Aanpassen" nodig heeft, uit inspect. */
93
+ async function readAdjustPlan(id) {
94
+ try {
95
+ const raw = (await (0, docker_client_1.getConnection)().docker.getContainer(id).inspect());
96
+ return { ok: true, plan: toAdjustPlan(raw) };
97
+ }
98
+ catch (err) {
99
+ return { ok: false, problem: (0, docker_client_1.readableError)(err, (0, docker_client_1.getConnection)().endpoint).message };
100
+ }
101
+ }
102
+ /** Een vrije naam voor het origineel zolang het aanpassen loopt: `naam-oud`, of `naam-oud-2`. */
103
+ function parkedName(name, taken) {
104
+ let candidate = `${name}-oud`;
105
+ for (let counter = 2; taken.has(candidate); counter += 1) {
106
+ candidate = `${name}-oud-${String(counter)}`;
107
+ }
108
+ return candidate;
109
+ }
110
+ /** Maakt de container opnieuw met de aangepaste instellingen; zie de uitleg bovenaan. */
111
+ async function adjustContainer(id, options) {
112
+ const { docker } = (0, docker_client_1.getConnection)();
113
+ let raw;
114
+ try {
115
+ raw = await docker.getContainer(id).inspect();
116
+ }
117
+ catch (err) {
118
+ return { ok: false, problem: (0, docker_client_1.readableError)(err, (0, docker_client_1.getConnection)().endpoint).message };
119
+ }
120
+ // Op de echte id, niet op wat binnenkwam: een naam wijst na het hernoemen naar de nieuwe container,
121
+ // en dan zou "het origineel weggooien" de nieuwe raken.
122
+ const original = docker.getContainer(raw.Id ?? id);
123
+ if (toAdjustPlan(raw).compose) {
124
+ return { ok: false, problem: (0, i18n_1.t)({
125
+ en: 'This is a compose container; change it in the compose file.',
126
+ nl: 'Dit is een compose-container; pas hem aan in het compose-bestand.',
127
+ de: 'Dies ist ein Compose-Container; ändern Sie ihn in der Compose-Datei.',
128
+ fr: 'C’est un conteneur compose ; modifiez-le dans le fichier compose.',
129
+ es: 'Es un contenedor de compose; cámbialo en el archivo compose.',
130
+ }) };
131
+ }
132
+ const name = bareName(raw.Name);
133
+ const wasRunning = raw.State?.Running === true;
134
+ let renamed = false;
135
+ let created = null;
136
+ try {
137
+ if (wasRunning) {
138
+ await original.stop();
139
+ }
140
+ const taken = new Set((await (0, containers_1.listContainers)()).map((container) => container.name));
141
+ await original.rename({ name: parkedName(name, taken) });
142
+ renamed = true;
143
+ const body = toAdjustedOptions(raw, options);
144
+ created = await docker.createContainer(body);
145
+ const primary = raw.HostConfig?.NetworkMode ?? '';
146
+ for (const [network, settings] of Object.entries(raw.NetworkSettings?.Networks ?? {})) {
147
+ if (network !== primary) {
148
+ const aliases = ownAliases(settings?.Aliases, raw);
149
+ await docker.getNetwork(network).connect({ Container: created.id, ...(aliases.length > 0 ? { EndpointConfig: { Aliases: aliases } } : {}) });
150
+ }
151
+ }
152
+ await created.start();
153
+ await original.remove({ v: false });
154
+ return { ok: true };
155
+ }
156
+ catch (err) {
157
+ // Terug naar hoe het was: de nieuwe weg, het origineel onder zijn eigen naam, en weer aan als het draaide.
158
+ await created?.remove({ force: true }).catch(() => undefined);
159
+ if (renamed) {
160
+ await original.rename({ name }).catch(() => undefined);
161
+ }
162
+ if (wasRunning) {
163
+ await original.start().catch(() => undefined);
164
+ }
165
+ const problem = (0, docker_client_1.readableError)(err, (0, docker_client_1.getConnection)().endpoint).message;
166
+ return {
167
+ ok: false,
168
+ problem: await (0, port_conflicts_1.explainPortConflict)(problem, containers_1.listContainers, {
169
+ raw: err instanceof Error ? err.message : String(err),
170
+ except: id,
171
+ lead: () => (0, i18n_1.t)({
172
+ en: `${name} could not start with the new settings, so it runs as before: one of its ports is taken.`,
173
+ nl: `${name} kon niet starten met de nieuwe instellingen, dus hij draait zoals eerst: een van zijn poorten is bezet.`,
174
+ de: `${name} konnte mit den neuen Einstellungen nicht starten und läuft wie vorher: einer seiner Ports ist belegt.`,
175
+ fr: `${name} n’a pas pu démarrer avec les nouveaux réglages, il tourne donc comme avant : l’un de ses ports est pris.`,
176
+ es: `${name} no pudo arrancar con los nuevos ajustes, así que funciona como antes: uno de sus puertos está ocupado.`,
177
+ }),
178
+ }),
179
+ };
180
+ }
181
+ }
182
+ //# sourceMappingURL=container-adjust.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container-adjust.js","sourceRoot":"","sources":["../electron/container-adjust.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EXEC_USER = exports.STOP_SCRIPT = void 0;
4
+ exports.terminalMark = terminalMark;
3
5
  exports.wrapSession = wrapSession;
4
6
  exports.openExec = openExec;
7
+ const node_crypto_1 = require("node:crypto");
5
8
  const docker_client_1 = require("./docker-client");
6
9
  const i18n_1 = require("./i18n");
7
10
  /**
@@ -12,6 +15,31 @@ const i18n_1 = require("./i18n");
12
15
  * vragen het eerst. Dat kost één korte exec, en het antwoord is eenduidig.
13
16
  */
14
17
  const PROBE = 'for c in /bin/bash /usr/bin/bash /bin/sh /usr/bin/sh /bin/ash; do [ -x "$c" ] && echo "$c" && exit 0; done; exit 1';
18
+ /**
19
+ * Ruimt de processen van één terminal op (fase 79): alles met dit kenmerk in de omgeving, dus de
20
+ * shell en wat erin gestart is. Eerst SIGHUP, zoals een terminal die ophangt; wat na een seconde nog
21
+ * leeft, SIGKILL. `$1` is het kenmerk; het script zelf heeft het niet in zijn omgeving.
22
+ */
23
+ exports.STOP_SCRIPT = [
24
+ 'm="MX_TERMINAL=$1"',
25
+ 'hit() { for p in /proc/[0-9]*; do tr \'\\000\' \'\\n\' < "$p/environ" 2>/dev/null | grep -qx "$m" && echo "${p#/proc/}"; done; }',
26
+ 'pids=$(hit); [ -z "$pids" ] && exit 0',
27
+ 'kill -HUP $pids 2>/dev/null; sleep 1',
28
+ 'pids=$(hit); [ -n "$pids" ] && kill -KILL $pids 2>/dev/null; exit 0',
29
+ ].join('\n');
30
+ /** Het kenmerk dat een terminal meekrijgt: zo vindt het opruimen precies zijn eigen processen terug. */
31
+ function terminalMark() {
32
+ return (0, node_crypto_1.randomUUID)();
33
+ }
34
+ /**
35
+ * Wat Docker als gebruiker van een exec aanneemt: een naam of een uid, eventueel met `:groep`.
36
+ * Strenger dan nodig, zodat er nooit iets anders in de API-aanroep terechtkomt.
37
+ */
38
+ exports.EXEC_USER = /^[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,31}(:[a-zA-Z0-9_][a-zA-Z0-9_.-]{0,31})?$/;
39
+ /** Alleen meegeven als er een gebruiker gekozen is; zonder `User` neemt Docker die van de image. */
40
+ function asUser(user) {
41
+ return user === null ? {} : { User: user };
42
+ }
15
43
  /** Leest de uitvoer van een korte exec uit; de shell-probe schrijft één regel. */
16
44
  function readAll(stream) {
17
45
  return new Promise((resolve) => {
@@ -22,10 +50,12 @@ function readAll(stream) {
22
50
  });
23
51
  }
24
52
  const dockerBackend = {
25
- detectShell: async (containerId) => {
53
+ detectShell: async (containerId, user) => {
26
54
  const { docker } = (0, docker_client_1.getConnection)();
27
55
  try {
56
+ // Als dezelfde gebruiker als de shell straks: een naam die er niet is, valt dan hier al op.
28
57
  const probe = await docker.getContainer(containerId).exec({
58
+ ...asUser(user),
29
59
  Cmd: ['/bin/sh', '-c', PROBE],
30
60
  AttachStdout: true,
31
61
  AttachStderr: false,
@@ -40,15 +70,18 @@ const dockerBackend = {
40
70
  return null;
41
71
  }
42
72
  },
43
- start: async (containerId, shell, size) => {
73
+ start: async (containerId, shell, size, user) => {
44
74
  const { docker } = (0, docker_client_1.getConnection)();
75
+ const mark = terminalMark();
45
76
  const exec = await docker.getContainer(containerId).exec({
77
+ ...asUser(user),
46
78
  Cmd: [shell],
47
79
  AttachStdin: true,
48
80
  AttachStdout: true,
49
81
  AttachStderr: true,
50
82
  Tty: true,
51
- Env: ['TERM=xterm-256color'],
83
+ // Het kenmerk erven ook de programma's die je in de shell start; zie STOP_SCRIPT.
84
+ Env: ['TERM=xterm-256color', `MX_TERMINAL=${mark}`],
52
85
  });
53
86
  // Drie dingen moeten hier staan, en het derde is een valkuil:
54
87
  // - hijack maakt van de HTTP-verbinding een tweerichtingskanaal in plaats van een antwoord;
@@ -65,15 +98,35 @@ const dockerBackend = {
65
98
  // Een resize op een exec die net gestopt is geeft een 404; dat is geen fout om te melden.
66
99
  void exec.resize({ h: rows, w: cols }).catch(() => undefined);
67
100
  },
101
+ // Met een TTY hangt Docker de terminal niet op als de verbinding sluit: de shell bleef dan
102
+ // draaien, ook als root (fase 79). Dus zelf opruimen, als dezelfde gebruiker.
103
+ stop: () => void stopTerminal(containerId, mark, user),
68
104
  };
69
105
  },
70
106
  };
107
+ /** Draait STOP_SCRIPT in de container. Lukt het niet (container al weg), dan is er ook niets meer op te ruimen. */
108
+ async function stopTerminal(containerId, mark, user) {
109
+ try {
110
+ const exec = await (0, docker_client_1.getConnection)().docker.getContainer(containerId).exec({
111
+ ...asUser(user),
112
+ Cmd: ['/bin/sh', '-c', exports.STOP_SCRIPT, 'mx', mark],
113
+ AttachStdout: true,
114
+ AttachStderr: true,
115
+ });
116
+ const stream = await exec.start({ hijack: true, stdin: false });
117
+ await readAll(stream);
118
+ }
119
+ catch {
120
+ // Niets aan te doen, en niets om te melden: de terminal is al dicht.
121
+ }
122
+ }
71
123
  /**
72
124
  * Maakt van een ruwe TTY-stream een sessie. `stop` ruimt op wat er naast de stream nog draait,
73
125
  * zoals de hulpcontainer van de host-shell.
74
126
  */
75
127
  function wrapSession(shell, stream, resize, onData, onEnd, stop = () => undefined) {
76
128
  let closed = false;
129
+ let destroyed = false;
77
130
  const finish = () => {
78
131
  if (!closed) {
79
132
  closed = true;
@@ -93,6 +146,11 @@ function wrapSession(shell, stream, resize, onData, onEnd, stop = () => undefine
93
146
  },
94
147
  resize,
95
148
  destroy: () => {
149
+ // Sluiten kan van twee kanten komen (de tab en het venster); opruimen hoeft maar één keer.
150
+ if (destroyed) {
151
+ return;
152
+ }
153
+ destroyed = true;
96
154
  closed = true;
97
155
  stream.destroy();
98
156
  stop();
@@ -106,8 +164,21 @@ function wrapSession(shell, stream, resize, onData, onEnd, stop = () => undefine
106
164
  * inclusief de escape-codes, want díé zijn hier juist de bedoeling. Dat is het verschil met de
107
165
  * logweergave, waar we ze er juist uit halen.
108
166
  */
109
- async function openExec(containerId, size, onData, onEnd, backend = dockerBackend) {
110
- const shell = await backend.detectShell(containerId);
167
+ async function openExec(containerId, size, onData, onEnd, backend = dockerBackend, user = null) {
168
+ const shell = await backend.detectShell(containerId, user);
169
+ // Met een gekozen gebruiker is "geen shell" meestal "geen gebruiker met die naam".
170
+ if (shell === null && user !== null) {
171
+ return {
172
+ ok: false,
173
+ problem: (0, i18n_1.t)({
174
+ en: `No shell could be started as ${user}. Does that user exist in this container?`,
175
+ nl: `Als ${user} kon geen shell gestart worden. Bestaat die gebruiker in deze container?`,
176
+ de: `Als ${user} konnte keine Shell gestartet werden. Gibt es diesen Benutzer in diesem Container?`,
177
+ fr: `Aucun shell n’a pu être démarré en tant que ${user}. Cet utilisateur existe-t-il dans ce conteneur ?`,
178
+ es: `No se ha podido iniciar un shell como ${user}. ¿Existe ese usuario en este contenedor?`,
179
+ }),
180
+ };
181
+ }
111
182
  if (shell === null) {
112
183
  return {
113
184
  ok: false,
@@ -121,8 +192,8 @@ async function openExec(containerId, size, onData, onEnd, backend = dockerBacken
121
192
  };
122
193
  }
123
194
  try {
124
- const { stream, resize } = await backend.start(containerId, shell, size);
125
- return { ok: true, session: wrapSession(shell, stream, resize, onData, onEnd) };
195
+ const { stream, resize, stop } = await backend.start(containerId, shell, size, user);
196
+ return { ok: true, session: wrapSession(shell, stream, resize, onData, onEnd, stop) };
126
197
  }
127
198
  catch (err) {
128
199
  const reason = err instanceof Error ? err.message : String(err);
@@ -1 +1 @@
1
- {"version":3,"file":"exec.js","sourceRoot":"","sources":["../electron/exec.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"exec.js","sourceRoot":"","sources":["../electron/exec.ts"],"names":[],"mappings":";;;AAsDA,oCAGC;AA8GD,kCA4CC;AAaD,4BAqDC;AArRD,6CAAyC;AAEzC,mDAAgD;AAEhD,iCAA2B;AAE3B;;;;;;GAMG;AACH,MAAM,KAAK,GAAG,oHAAoH,CAAC;AA2BnI;;;;GAIG;AACU,QAAA,WAAW,GAAG;IACzB,oBAAoB;IACpB,kIAAkI;IAClI,uCAAuC;IACvC,sCAAsC;IACtC,qEAAqE;CACtE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,wGAAwG;AACxG,SAAgB,YAAY;IAE1B,OAAO,IAAA,wBAAU,GAAE,CAAC;AACtB,CAAC;AAED;;;GAGG;AACU,QAAA,SAAS,GAAG,wEAAwE,CAAC;AAElG,oGAAoG;AACpG,SAAS,MAAM,CAAC,IAAmB;IAEjC,OAAO,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AAC7C,CAAC;AAED,kFAAkF;AAClF,SAAS,OAAO,CAAC,MAAc;IAE7B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,IAAI,IAAI,GAAG,EAAE,CAAC;QAEd,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACvE,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACtC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,aAAa,GAAgB;IACjC,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE;QACvC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAA,6BAAa,GAAE,CAAC;QAEnC,IAAI,CAAC;YACH,4FAA4F;YAC5F,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC;gBACxD,GAAG,MAAM,CAAC,IAAI,CAAC;gBACf,GAAG,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC;gBAC7B,YAAY,EAAE,IAAI;gBAClB,YAAY,EAAE,KAAK;aACpB,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;YACjE,sFAAsF;YACtF,+EAA+E;YAC/E,MAAM,KAAK,GAAG,6BAA6B,CAAC,IAAI,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;YAExE,OAAO,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC1C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;QAC9C,MAAM,EAAE,MAAM,EAAE,GAAG,IAAA,6BAAa,GAAE,CAAC;QACnC,MAAM,IAAI,GAAG,YAAY,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC;YACvD,GAAG,MAAM,CAAC,IAAI,CAAC;YACf,GAAG,EAAE,CAAC,KAAK,CAAC;YACZ,WAAW,EAAE,IAAI;YACjB,YAAY,EAAE,IAAI;YAClB,YAAY,EAAE,IAAI;YAClB,GAAG,EAAE,IAAI;YACT,kFAAkF;YAClF,GAAG,EAAE,CAAC,qBAAqB,EAAE,eAAe,IAAI,EAAE,CAAC;SACpD,CAAC,CAAC;QAEH,8DAA8D;QAC9D,4FAA4F;QAC5F,yEAAyE;QACzE,4FAA4F;QAC5F,0FAA0F;QAC1F,mFAAmF;QACnF,0EAA0E;QAC1E,MAAM,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAA6B,CAAC;QAExG,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAElD,OAAO;YACL,MAAM;YACN,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE;gBACrB,0FAA0F;gBAC1F,KAAK,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YAChE,CAAC;YACD,2FAA2F;YAC3F,8EAA8E;YAC9E,IAAI,EAAE,GAAG,EAAE,CAAC,KAAK,YAAY,CAAC,WAAW,EAAE,IAAI,EAAE,IAAI,CAAC;SACvD,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,mHAAmH;AACnH,KAAK,UAAU,YAAY,CAAC,WAAmB,EAAE,IAAY,EAAE,IAAmB;IAEhF,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,IAAA,6BAAa,GAAE,CAAC,MAAM,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC;YACvE,GAAG,MAAM,CAAC,IAAI,CAAC;YACf,GAAG,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,mBAAW,EAAE,IAAI,EAAE,IAAI,CAAC;YAC/C,YAAY,EAAE,IAAI;YAClB,YAAY,EAAE,IAAI;SACnB,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QAEhE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,qEAAqE;IACvE,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAgB,WAAW,CACzB,KAAa,EACb,MAAqB,EACrB,MAA4C,EAC5C,MAA+B,EAC/B,KAAiB,EACjB,OAAmB,GAAG,EAAE,CAAC,SAAS;IAGlC,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,MAAM,MAAM,GAAG,GAAS,EAAE;QACxB,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,GAAG,IAAI,CAAC;YACd,KAAK,EAAE,CAAC;QACV,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC7D,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACzB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC3B,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAE3B,OAAO;QACL,KAAK;QACL,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE;YACd,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;QACD,MAAM;QACN,OAAO,EAAE,GAAG,EAAE;YACZ,2FAA2F;YAC3F,IAAI,SAAS,EAAE,CAAC;gBACd,OAAO;YACT,CAAC;YAED,SAAS,GAAG,IAAI,CAAC;YACjB,MAAM,GAAG,IAAI,CAAC;YACd,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,EAAE,CAAC;QACT,CAAC;KACF,CAAC;AACJ,CAAC;AAMD;;;;;;GAMG;AACI,KAAK,UAAU,QAAQ,CAC5B,WAAmB,EACnB,IAAoC,EACpC,MAA+B,EAC/B,KAAiB,EACjB,UAAuB,aAAa,EACpC,OAAsB,IAAI;IAG1B,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAE3D,mFAAmF;IACnF,IAAI,KAAK,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QACpC,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,IAAA,QAAC,EAAC;gBACT,EAAE,EAAE,gCAAgC,IAAI,2CAA2C;gBACnF,EAAE,EAAE,OAAO,IAAI,0EAA0E;gBACzF,EAAE,EAAE,OAAO,IAAI,oFAAoF;gBACnG,EAAE,EAAE,+CAA+C,IAAI,mDAAmD;gBAC1G,EAAE,EAAE,yCAAyC,IAAI,2CAA2C;aAC7F,CAAC;SACH,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,IAAA,QAAC,EAAC;gBACT,EAAE,EAAE,0FAA0F;gBAC9F,EAAE,EAAE,2FAA2F;gBAC/F,EAAE,EAAE,4FAA4F;gBAChG,EAAE,EAAE,mGAAmG;gBACvG,EAAE,EAAE,qGAAqG;aAC1G,CAAC;SACH,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QAErF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC;IACxF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,MAAM,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAEhE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,IAAA,QAAC,EAAC;gBAC7B,EAAE,EAAE,mCAAmC,MAAM,EAAE;gBAC/C,EAAE,EAAE,qCAAqC,MAAM,EAAE;gBACjD,EAAE,EAAE,4CAA4C,MAAM,EAAE;gBACxD,EAAE,EAAE,sCAAsC,MAAM,EAAE;gBAClD,EAAE,EAAE,qCAAqC,MAAM,EAAE;aAClD,CAAC,EAAE,CAAC;IACP,CAAC;AACH,CAAC"}
@@ -0,0 +1,206 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.MAX_EDIT_BYTES = void 0;
37
+ exports.asText = asText;
38
+ exports.versionOf = versionOf;
39
+ exports.onMount = onMount;
40
+ exports.readEditableFile = readEditableFile;
41
+ exports.saveEditableFile = saveEditableFile;
42
+ const node_crypto_1 = require("node:crypto");
43
+ const path = __importStar(require("node:path"));
44
+ const tar = __importStar(require("tar-stream"));
45
+ const docker_client_1 = require("./docker-client");
46
+ const files_1 = require("./files");
47
+ const i18n_1 = require("./i18n");
48
+ /**
49
+ * Een tekstbestand in een container bewerken (fase 78): lezen, en terugzetten met dezelfde rechten
50
+ * en eigenaar. Via `getArchive` en `putArchive`, zonder shell, zoals downloaden en uploaden.
51
+ *
52
+ * Alleen tekst en alleen klein: een editor in de app is voor een configuratieregel, niet voor een
53
+ * logbestand van honderd megabyte. De versie is een hash van de inhoud; opslaan leest eerst opnieuw
54
+ * en weigert als het bestand intussen veranderd is, in plaats van het stil te overschrijven.
55
+ */
56
+ /** Groter dan dit is geen bestand om in de app te bewerken; dan blijven downloaden en uploaden. */
57
+ exports.MAX_EDIT_BYTES = 512 * 1024;
58
+ const MAX_LINK_HOPS = 8;
59
+ /** De eerste entry van een archief; de inhoud alleen als het een bestand is dat klein genoeg is. */
60
+ async function firstEntry(archive) {
61
+ const extract = tar.extract();
62
+ let found = null;
63
+ archive.pipe(extract);
64
+ for await (const entry of extract) {
65
+ const header = entry.header;
66
+ if (found === null) {
67
+ const small = header.type === 'file' && (header.size ?? 0) <= exports.MAX_EDIT_BYTES;
68
+ const chunks = [];
69
+ if (small) {
70
+ for await (const chunk of entry) {
71
+ chunks.push(chunk);
72
+ }
73
+ }
74
+ else {
75
+ entry.resume();
76
+ }
77
+ found = {
78
+ type: header.type ?? 'file',
79
+ size: header.size ?? 0,
80
+ mode: header.mode ?? 0o644,
81
+ uid: header.uid ?? 0,
82
+ gid: header.gid ?? 0,
83
+ linkname: header.linkname ?? null,
84
+ content: small ? Buffer.concat(chunks) : null,
85
+ };
86
+ }
87
+ else {
88
+ entry.resume();
89
+ }
90
+ }
91
+ return found;
92
+ }
93
+ /** Of dit tekst is die we heel terugschrijven: geen nul-bytes, en UTF-8 dat heen en terug gelijk blijft. */
94
+ function asText(content) {
95
+ if (content.includes(0)) {
96
+ return null;
97
+ }
98
+ const text = content.toString('utf8');
99
+ return Buffer.from(text, 'utf8').equals(content) ? text : null;
100
+ }
101
+ /** De versie van een bestand: een hash van de inhoud, om bij opslaan te zien of het veranderde. */
102
+ function versionOf(content) {
103
+ return (0, node_crypto_1.createHash)('sha256').update(content).digest('hex');
104
+ }
105
+ /** Of een pad onder een volume of bind mount valt; dan blijft een wijziging na "Opnieuw" staan. */
106
+ function onMount(file, destinations) {
107
+ return destinations.some((destination) => file === destination || file.startsWith(`${destination.replace(/\/$/, '')}/`));
108
+ }
109
+ /** Leest het bestand, en volgt een symlink zoals de container dat zou doen. */
110
+ async function read(id, requested) {
111
+ const container = (0, docker_client_1.getConnection)().docker.getContainer(id);
112
+ let current = (0, files_1.normalizeContainerPath)(requested);
113
+ for (let hop = 0; hop <= MAX_LINK_HOPS; hop += 1) {
114
+ const entry = await firstEntry((await container.getArchive({ path: current })));
115
+ if (entry?.type === 'symlink' && entry.linkname !== null) {
116
+ current = path.posix.resolve(path.posix.dirname(current), entry.linkname);
117
+ continue;
118
+ }
119
+ if (entry === null || entry.type !== 'file') {
120
+ return { ok: false, problem: (0, i18n_1.t)({
121
+ en: `${current} is not a file.`,
122
+ nl: `${current} is geen bestand.`,
123
+ de: `${current} ist keine Datei.`,
124
+ fr: `${current} n’est pas un fichier.`,
125
+ es: `${current} no es un archivo.`,
126
+ }) };
127
+ }
128
+ return { ok: true, path: current, entry };
129
+ }
130
+ return { ok: false, problem: (0, i18n_1.t)({
131
+ en: `too many symlinks in a row from ${requested}.`,
132
+ nl: `te veel symlinks achter elkaar vanaf ${requested}.`,
133
+ de: `zu viele Symlinks hintereinander ab ${requested}.`,
134
+ fr: `trop de liens symboliques à la suite depuis ${requested}.`,
135
+ es: `demasiados symlinks seguidos desde ${requested}.`,
136
+ }) };
137
+ }
138
+ /** Leest een tekstbestand om te bewerken, met de versie om bij opslaan tegen te controleren. */
139
+ async function readEditableFile(id, requested) {
140
+ try {
141
+ const result = await read(id, requested);
142
+ if (!result.ok) {
143
+ return result;
144
+ }
145
+ const { entry } = result;
146
+ if (entry.content === null) {
147
+ return { ok: false, problem: (0, i18n_1.t)({
148
+ en: `${result.path} is larger than ${String(exports.MAX_EDIT_BYTES / 1024)} kB; download it to edit it.`,
149
+ nl: `${result.path} is groter dan ${String(exports.MAX_EDIT_BYTES / 1024)} kB; download het om het te bewerken.`,
150
+ de: `${result.path} ist größer als ${String(exports.MAX_EDIT_BYTES / 1024)} kB; laden Sie es zum Bearbeiten herunter.`,
151
+ fr: `${result.path} dépasse ${String(exports.MAX_EDIT_BYTES / 1024)} ko ; téléchargez-le pour le modifier.`,
152
+ es: `${result.path} supera los ${String(exports.MAX_EDIT_BYTES / 1024)} kB; descárgalo para editarlo.`,
153
+ }) };
154
+ }
155
+ const text = asText(entry.content);
156
+ if (text === null) {
157
+ return { ok: false, problem: (0, i18n_1.t)({
158
+ en: `${result.path} is not text (or not UTF-8); download it to edit it.`,
159
+ nl: `${result.path} is geen tekst (of geen UTF-8); download het om het te bewerken.`,
160
+ de: `${result.path} ist kein Text (oder kein UTF-8); laden Sie es zum Bearbeiten herunter.`,
161
+ fr: `${result.path} n’est pas du texte (ou pas en UTF-8) ; téléchargez-le pour le modifier.`,
162
+ es: `${result.path} no es texto (o no es UTF-8); descárgalo para editarlo.`,
163
+ }) };
164
+ }
165
+ const inspect = (await (0, docker_client_1.getConnection)().docker.getContainer(id).inspect());
166
+ const destinations = (inspect.Mounts ?? []).map((mount) => mount.Destination ?? '').filter((destination) => destination !== '');
167
+ return { ok: true, path: result.path, text, version: versionOf(entry.content), onMount: onMount(result.path, destinations) };
168
+ }
169
+ catch (err) {
170
+ return { ok: false, problem: (0, docker_client_1.readableError)(err, (0, docker_client_1.getConnection)().endpoint).message };
171
+ }
172
+ }
173
+ /**
174
+ * Zet de tekst terug, met de rechten, eigenaar en groep die het bestand had. Is het intussen
175
+ * veranderd (een andere versie dan `version`), dan niet: `conflict` zegt dat, tenzij `force`.
176
+ */
177
+ async function saveEditableFile(id, file, text, version, force) {
178
+ try {
179
+ const current = await read(id, file);
180
+ if (!current.ok) {
181
+ return { ...current, conflict: false };
182
+ }
183
+ if (!force && (current.entry.content === null || versionOf(current.entry.content) !== version)) {
184
+ return { ok: false, conflict: true, problem: (0, i18n_1.t)({
185
+ en: `${current.path} has changed in the container since you opened it.`,
186
+ nl: `${current.path} is in de container veranderd sinds je het opende.`,
187
+ de: `${current.path} hat sich im Container geändert, seit Sie es geöffnet haben.`,
188
+ fr: `${current.path} a changé dans le conteneur depuis que vous l’avez ouvert.`,
189
+ es: `${current.path} ha cambiado en el contenedor desde que lo abriste.`,
190
+ }) };
191
+ }
192
+ const content = Buffer.from(text, 'utf8');
193
+ const pack = tar.pack();
194
+ pack.entry({ name: path.posix.basename(current.path), size: content.length, mode: current.entry.mode, uid: current.entry.uid, gid: current.entry.gid, mtime: new Date() }, content);
195
+ pack.finalize();
196
+ // `copyUIDGID`: de eigenaar en groep uit het archief, en dat zijn die van het oude bestand.
197
+ await (0, docker_client_1.getConnection)()
198
+ .docker.getContainer(id)
199
+ .putArchive(pack, { path: path.posix.dirname(current.path), copyUIDGID: '1' });
200
+ return { ok: true, version: versionOf(content) };
201
+ }
202
+ catch (err) {
203
+ return { ok: false, conflict: false, problem: (0, docker_client_1.readableError)(err, (0, docker_client_1.getConnection)().endpoint).message };
204
+ }
205
+ }
206
+ //# sourceMappingURL=file-edit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-edit.js","sourceRoot":"","sources":["../electron/file-edit.ts"],"names":[],"mappings":"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"}