shilo-cli 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/commands/propuestas.js +5 -4
- package/src/commands/push.js +8 -5
- package/src/commands/status.js +5 -4
- package/src/viewer.js +17 -0
package/package.json
CHANGED
|
@@ -9,6 +9,7 @@ const sync = require('../sync');
|
|
|
9
9
|
const prompt = require('../prompt');
|
|
10
10
|
const textdiff = require('../textdiff');
|
|
11
11
|
const { resolveContext } = require('../context');
|
|
12
|
+
const { puedeAplicar } = require('../viewer');
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* shilo propuestas [ver|bajar|aplicar|descartar] [id] [opciones]
|
|
@@ -147,7 +148,7 @@ async function ver(ctx, { proposal: resumen, viewer }, args) {
|
|
|
147
148
|
chequeos: d.chequeos,
|
|
148
149
|
usee: d.usee,
|
|
149
150
|
blocked_by: d.blockedBy,
|
|
150
|
-
puedo_aplicar:
|
|
151
|
+
puedo_aplicar: puedeAplicar(viewer),
|
|
151
152
|
changes: d.changes.map((c) => ({
|
|
152
153
|
...c,
|
|
153
154
|
...(args.contenido ? { contenido_base: texto(c.base), contenido_propuesta: texto(c.head) } : {}),
|
|
@@ -222,7 +223,7 @@ async function ver(ctx, { proposal: resumen, viewer }, args) {
|
|
|
222
223
|
ui.info('');
|
|
223
224
|
const id8 = p.id.slice(0, 8);
|
|
224
225
|
if (!args.diff) ui.info(ui.c.dim(`Diferencias: shilo propuestas ver ${id8} --diff`));
|
|
225
|
-
if (viewer
|
|
226
|
+
if (puedeAplicar(viewer)) {
|
|
226
227
|
ui.info(ui.c.dim(d.conflicts.length > 0
|
|
227
228
|
? `Resolver: shilo propuestas aplicar ${id8} --propuesta <ruta> --actual <ruta> (o --todo propuesta)`
|
|
228
229
|
: `Aplicar: shilo propuestas aplicar ${id8}`));
|
|
@@ -362,8 +363,8 @@ async function aplicar(ctx, { proposal: resumen, viewer }, args) {
|
|
|
362
363
|
ui.error(`Esa propuesta ya está ${resumen.state}.`);
|
|
363
364
|
return 1;
|
|
364
365
|
}
|
|
365
|
-
if (viewer && !viewer
|
|
366
|
-
ui.error('
|
|
366
|
+
if (viewer && !puedeAplicar(viewer)) {
|
|
367
|
+
ui.error('Para aplicar una propuesta hace falta ser el dueño o tener el permiso de aprobar propuestas.');
|
|
367
368
|
return 1;
|
|
368
369
|
}
|
|
369
370
|
|
package/src/commands/push.js
CHANGED
|
@@ -22,6 +22,7 @@ const {
|
|
|
22
22
|
MAX_FILE_BYTES,
|
|
23
23
|
} = require('../textguard');
|
|
24
24
|
const { ShiloClient } = require('../ShiloClient');
|
|
25
|
+
const { puedeAplicar } = require('../viewer');
|
|
25
26
|
|
|
26
27
|
const DEFAULT_BASE_URL = 'https://www.shilo.city';
|
|
27
28
|
const COMMIT_BATCH = 100; // máximo de archivos por commit (límite del backend, camino anterior)
|
|
@@ -1412,11 +1413,12 @@ async function push(args) {
|
|
|
1412
1413
|
|
|
1413
1414
|
config.persistCredsIfChanged(cfg, mgr.current);
|
|
1414
1415
|
|
|
1415
|
-
// 9b) Si quien sube
|
|
1416
|
-
// mismo en vez de ir a la web a
|
|
1416
|
+
// 9b) Si quien sube puede aprobar (dueño o permiso `approve_proposals`), lo
|
|
1417
|
+
// que quedó abierto lo puede aplicar ahora mismo en vez de ir a la web a
|
|
1418
|
+
// aprobarse a sí mismo.
|
|
1417
1419
|
const failures = failedWrites.length + plan.failed.length;
|
|
1418
1420
|
let openShown = false;
|
|
1419
|
-
if (open.length > 0 && failures === 0 && viewer &&
|
|
1421
|
+
if (open.length > 0 && failures === 0 && puedeAplicar(viewer) && !args.yes && process.stdin.isTTY) {
|
|
1420
1422
|
const res = await offerOwnerApply(open);
|
|
1421
1423
|
if (res.applied.length > 0) {
|
|
1422
1424
|
committed += res.applied.reduce((n, o) => n + o.paths.length, 0);
|
|
@@ -1492,7 +1494,7 @@ async function push(args) {
|
|
|
1492
1494
|
const pendingFiles = open.reduce((n, o) => n + o.paths.length, 0);
|
|
1493
1495
|
const owner = projectInfo && projectInfo.owner;
|
|
1494
1496
|
const ownerName = owner ? owner.display_name || owner.username : null;
|
|
1495
|
-
const approver = viewer
|
|
1497
|
+
const approver = puedeAplicar(viewer) ? 'tu aprobación' : ownerName ? `la aprobación de ${ownerName}` : 'la aprobación del dueño del proyecto';
|
|
1496
1498
|
ui.success(
|
|
1497
1499
|
`Tus ${pendingFiles} cambio(s) están guardados en Shilo y esperan ${approver}.` +
|
|
1498
1500
|
(committed > 0 ? ` (Otros ${committed} ya son parte de la versión actual.)` : '')
|
|
@@ -1516,7 +1518,8 @@ async function push(args) {
|
|
|
1516
1518
|
ui.info('');
|
|
1517
1519
|
for (const o of list) reportOpen(o);
|
|
1518
1520
|
openShown = true;
|
|
1519
|
-
|
|
1521
|
+
const quien = viewer && viewer.is_owner ? 'Sos el dueño del proyecto' : 'Tenés permiso de aprobar propuestas';
|
|
1522
|
+
ui.info(`${quien}: podés aplicar estos ${files} cambio(s) ahora, sin pasar por la web.`);
|
|
1520
1523
|
if (conflicted > 0) {
|
|
1521
1524
|
ui.info(
|
|
1522
1525
|
`En ${conflicted} archivo(s) que también cambiaron en el proyecto se va a quedar ` +
|
package/src/commands/status.js
CHANGED
|
@@ -5,6 +5,7 @@ const ui = require('../ui');
|
|
|
5
5
|
const sync = require('../sync');
|
|
6
6
|
const remote = require('../remote');
|
|
7
7
|
const { resolveContext } = require('../context');
|
|
8
|
+
const { puedeAplicar } = require('../viewer');
|
|
8
9
|
|
|
9
10
|
// A partir de cuántos días sin sincronizar se recuerda hacerlo.
|
|
10
11
|
const STALE_DAYS = 30;
|
|
@@ -126,11 +127,11 @@ async function status(args) {
|
|
|
126
127
|
};
|
|
127
128
|
};
|
|
128
129
|
|
|
129
|
-
// 4b) Propuestas abiertas: las mías (esperan aprobación) y, si
|
|
130
|
-
// las de los demás
|
|
130
|
+
// 4b) Propuestas abiertas: las mías (esperan aprobación) y, si puedo aprobar
|
|
131
|
+
// (dueño o permiso `approve_proposals`), las de los demás.
|
|
131
132
|
const openProposals = listed ? listed.proposals : [];
|
|
132
133
|
const mineOpen = me ? openProposals.filter((p) => p.author_id === me) : [];
|
|
133
|
-
const othersOpen = viewer
|
|
134
|
+
const othersOpen = puedeAplicar(viewer) ? openProposals.filter((p) => p.author_id !== me) : [];
|
|
134
135
|
const projectInfo = (listed && listed.project) || null;
|
|
135
136
|
const owner = projectInfo && projectInfo.owner;
|
|
136
137
|
const ownerName = owner ? owner.display_name || owner.username : null;
|
|
@@ -217,7 +218,7 @@ async function status(args) {
|
|
|
217
218
|
/** Propuestas abiertas: lo primero que hay que saber, antes que la lista de archivos. */
|
|
218
219
|
const reportProposals = () => {
|
|
219
220
|
if (mineOpen.length > 0) {
|
|
220
|
-
const who = viewer
|
|
221
|
+
const who = puedeAplicar(viewer) ? 'tu aprobación' : ownerName ? `la aprobación de ${ownerName}` : 'aprobación';
|
|
221
222
|
ui.info(ui.c.bold(`Tenés ${mineOpen.length} propuesta(s) esperando ${who}:`));
|
|
222
223
|
for (const p of mineOpen) {
|
|
223
224
|
const link = linkTo(p);
|
package/src/viewer.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Si quien pregunta puede aplicar propuestas en el proyecto: el dueño o un
|
|
5
|
+
* colaborador con el permiso `approve_proposals` (migración 021).
|
|
6
|
+
*
|
|
7
|
+
* Lo dice el servidor en `viewer.can_apply`. Un servidor anterior a la 021 no
|
|
8
|
+
* lo manda y sólo el dueño podía aplicar, así que sin el campo se usa
|
|
9
|
+
* `is_owner`. Es sólo para mostrar u ofrecer: el servidor decide igual.
|
|
10
|
+
*/
|
|
11
|
+
function puedeAplicar(viewer) {
|
|
12
|
+
if (!viewer) return false;
|
|
13
|
+
if (typeof viewer.can_apply === 'boolean') return viewer.can_apply;
|
|
14
|
+
return !!viewer.is_owner;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
module.exports = { puedeAplicar };
|