pull-request-split-advisor 3.2.5 → 3.2.7
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/dist/cli.js +2 -7
- package/dist/git/git.js +46 -13
- package/dist/output/report.js +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -393,14 +393,9 @@ async function main() {
|
|
|
393
393
|
` git checkout ${branchFrom}`,
|
|
394
394
|
` git checkout -b ${suggestedBranch}`,
|
|
395
395
|
"",
|
|
396
|
-
"
|
|
397
|
-
"La opción --apply
|
|
396
|
+
"El análisis continúa de forma informativa.",
|
|
397
|
+
"La opción --apply está deshabilitada en esta ejecución."
|
|
398
398
|
], "red");
|
|
399
|
-
const continueAnyway = await ui.confirm("¿Deseas continuar de todas formas (solo análisis, sin aplicar)?");
|
|
400
|
-
if (!continueAnyway) {
|
|
401
|
-
closeReadlineInterface();
|
|
402
|
-
return;
|
|
403
|
-
}
|
|
404
399
|
}
|
|
405
400
|
// ─── Pipeline de análisis ────────────────────────────────────────────────
|
|
406
401
|
ui.spinner.start("Analizando cambios del working tree...");
|
package/dist/git/git.js
CHANGED
|
@@ -243,40 +243,73 @@ export function findCascadeParent(currentBranch, baseBranch) {
|
|
|
243
243
|
if (!familyMatch)
|
|
244
244
|
return null;
|
|
245
245
|
const familyPrefix = `${familyMatch[1]}/${familyMatch[2].toUpperCase()}`;
|
|
246
|
-
// Construir lista de
|
|
247
|
-
//
|
|
246
|
+
// Construir lista de candidatos desde tres fuentes (en orden de precedencia):
|
|
247
|
+
// 1. Ramas locales
|
|
248
|
+
// 2. Refs de tracking remoto ya descargadas (git branch -r)
|
|
249
|
+
// 3. Ramas que existen en el remoto pero nunca fueron descargadas (git ls-remote)
|
|
250
|
+
//
|
|
248
251
|
// Para cada entrada guardamos { name, ref }:
|
|
249
|
-
// - name: nombre
|
|
250
|
-
// - ref: ref resolvible por git (local
|
|
252
|
+
// - name: nombre sin prefijo de remoto (para mostrar al usuario y hacer checkout)
|
|
253
|
+
// - ref: ref resolvible por git (local o "origin/branch")
|
|
251
254
|
const branches = [];
|
|
252
|
-
|
|
255
|
+
const seenNames = new Set();
|
|
256
|
+
// 1. Ramas locales
|
|
253
257
|
const localRaw = shSafe("git branch --format=%(refname:short)");
|
|
254
258
|
for (const b of localRaw.split("\n").map((s) => s.trim()).filter(Boolean)) {
|
|
255
259
|
branches.push({ name: b, ref: b });
|
|
260
|
+
seenNames.add(b.toUpperCase());
|
|
256
261
|
}
|
|
257
|
-
// Ramas remotas (
|
|
258
|
-
// Se usa el nombre sin el prefijo del remoto (primer segmento hasta "/").
|
|
259
|
-
// Si ya existe la rama localmente, se omite (la ref local tiene precedencia).
|
|
262
|
+
// 2. Ramas remotas ya cacheadas localmente (git branch -r)
|
|
260
263
|
const remoteRaw = shSafe("git branch -r --format=%(refname:short)");
|
|
261
264
|
for (const b of remoteRaw.split("\n").map((s) => s.trim()).filter(Boolean)) {
|
|
262
265
|
const slash = b.indexOf("/");
|
|
263
266
|
if (slash < 0)
|
|
264
267
|
continue;
|
|
265
|
-
const name = b.slice(slash + 1);
|
|
268
|
+
const name = b.slice(slash + 1);
|
|
266
269
|
if (!name || name.startsWith("HEAD"))
|
|
267
270
|
continue;
|
|
268
|
-
if (!
|
|
269
|
-
branches.push({ name, ref: b });
|
|
271
|
+
if (!seenNames.has(name.toUpperCase())) {
|
|
272
|
+
branches.push({ name, ref: b });
|
|
273
|
+
seenNames.add(name.toUpperCase());
|
|
270
274
|
}
|
|
271
275
|
}
|
|
276
|
+
// 3. Consultar el remoto directamente con git ls-remote para descubrir
|
|
277
|
+
// ramas que existen en el servidor pero nunca fueron descargadas.
|
|
278
|
+
// Filtramos por el prefijo familia para que sea rápido incluso con
|
|
279
|
+
// repositorios que tienen cientos de ramas.
|
|
280
|
+
const remote = shSafe("git remote").split("\n")[0]?.trim() || "origin";
|
|
281
|
+
const lsRemoteRaw = shSafe(`git ls-remote --heads ${q(remote)} ${q(`refs/heads/${familyPrefix}*`)}`);
|
|
282
|
+
for (const line of lsRemoteRaw.split("\n").map((s) => s.trim()).filter(Boolean)) {
|
|
283
|
+
// Formato: "<sha>\trefs/heads/<name>"
|
|
284
|
+
const tabIdx = line.indexOf("\t");
|
|
285
|
+
if (tabIdx < 0)
|
|
286
|
+
continue;
|
|
287
|
+
const ref = line.slice(tabIdx + 1); // "refs/heads/feature/…"
|
|
288
|
+
const name = ref.replace(/^refs\/heads\//, "");
|
|
289
|
+
if (!name || seenNames.has(name.toUpperCase()))
|
|
290
|
+
continue;
|
|
291
|
+
// Usar "<remote>/<name>" como ref resolvible si el tracking existe,
|
|
292
|
+
// o la ref completa "refs/remotes/<remote>/<name>" como fallback.
|
|
293
|
+
// Para git rev-list y git log podemos usar directamente la ref completa.
|
|
294
|
+
const trackingRef = `refs/remotes/${remote}/${name}`;
|
|
295
|
+
const resolvedRef = shSafe(`git rev-parse --verify ${q(trackingRef)}`).trim()
|
|
296
|
+
? `${remote}/${name}`
|
|
297
|
+
: ref; // "refs/heads/<name>" solo funciona si fue fetched; caer en ls-remote sha
|
|
298
|
+
// Si no hay tracking local, no podemos resolver commits sin fetch.
|
|
299
|
+
// En ese caso hacemos un fetch puntual de esa única rama antes de usarla.
|
|
300
|
+
if (resolvedRef === ref) {
|
|
301
|
+
// fetch puntual y silencioso de solo esta rama para obtener su historial
|
|
302
|
+
shSafe(`git fetch ${q(remote)} ${q(`refs/heads/${name}:refs/remotes/${remote}/${name}`)} --no-tags`);
|
|
303
|
+
}
|
|
304
|
+
branches.push({ name, ref: `${remote}/${name}` });
|
|
305
|
+
seenNames.add(name.toUpperCase());
|
|
306
|
+
}
|
|
272
307
|
const candidates = branches.filter(({ name }) => name !== currentBranch &&
|
|
273
308
|
name.toUpperCase().startsWith(familyPrefix.toUpperCase()));
|
|
274
309
|
if (candidates.length === 0)
|
|
275
310
|
return null;
|
|
276
311
|
// De los candidatos, quedarnos con los que tengan commits adelantados
|
|
277
312
|
// respecto a la base y ordenarlos por committerdate descendente.
|
|
278
|
-
// Si la rama solo existe en el remoto, la ref "origin/feature/…" es
|
|
279
|
-
// resolvible directamente por git sin necesidad de checkout local.
|
|
280
313
|
const withAhead = candidates.filter(({ ref }) => {
|
|
281
314
|
const count = shSafe(`git rev-list ${q(baseBranch)}..${q(ref)} --count`);
|
|
282
315
|
return (parseInt(count, 10) || 0) > 0;
|
package/dist/output/report.js
CHANGED
|
@@ -519,7 +519,7 @@ export function renderHtmlReport(input) {
|
|
|
519
519
|
<p>${parentNote}</p>
|
|
520
520
|
<p><strong>Comandos recomendados:</strong></p>
|
|
521
521
|
<pre style="background:rgba(0,0,0,.25);padding:10px 14px;border-radius:6px;font-size:.85em;margin:8px 0 0"># Crear la siguiente rama de la cascada\ngit checkout ${esc(cw.branchFrom)}\ngit checkout -b ${esc(cw.suggestedBranch)}</pre>
|
|
522
|
-
<p class="disclaimer-footer" style="margin-top:8px">El apply
|
|
522
|
+
<p class="disclaimer-footer" style="margin-top:8px">Este reporte es informativo. El apply quedó deshabilitado en esta ejecución para preservar la integridad del plan en cascada.</p>
|
|
523
523
|
</div>
|
|
524
524
|
</section>`;
|
|
525
525
|
})() : ""}
|
package/package.json
CHANGED