mirror of
https://github.com/Nezumi-2711/9router.git
synced 2026-09-22 13:38:31 +00:00
feat(rtk): add JS-native git-log filter (#2423)
Compress git log output via dedicated RTK filter: keep commit headers, Author/Date, subject; drop body padding, decoration, embedded diff lines. Wire into autodetect (git-log prioritized before git-diff) and registry. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
committed by
decolua
co-authored by
Cursor
parent
bbae990b92
commit
19281b5524
@@ -1,9 +1,10 @@
|
||||
// Port of auto_detect_filter (rtk/src/cmds/system/pipe_cmd.rs:132-188) + JS extras
|
||||
// Order: git-diff → git-status → build-output → grep → find → tree → ls → search-list
|
||||
// → read-numbered → dedup-log → smart-truncate → null
|
||||
// Detection order: git-log → git-diff → git-status → build-output → grep → find → tree → ls → search-list
|
||||
// → read-numbered → dedup-log → smart-truncate → null
|
||||
import { DETECT_WINDOW, READ_NUMBERED_MIN_HIT_RATIO, SMART_TRUNCATE_MIN_LINES } from "./constants.js";
|
||||
import { gitDiff } from "./filters/gitDiff.js";
|
||||
import { gitStatus } from "./filters/gitStatus.js";
|
||||
import { gitLog } from "./filters/gitLog.js";
|
||||
import { buildOutput } from "./filters/buildOutput.js";
|
||||
import { grep } from "./filters/grep.js";
|
||||
import { find } from "./filters/find.js";
|
||||
@@ -17,6 +18,7 @@ import { searchList, SEARCH_LIST_HEADER_RE } from "./filters/searchList.js";
|
||||
const RE_GIT_DIFF = /^diff --git /m;
|
||||
const RE_GIT_DIFF_HUNK = /^@@ /m;
|
||||
const RE_GIT_STATUS = /^On branch |^nothing to commit|^Changes (not |to be )|^Untracked files:/m;
|
||||
const RE_GIT_LOG = /^[*|/\\ ]*commit [0-9a-f]{7,40}$/m;
|
||||
const RE_PORCELAIN = /^[ MADRCU?!][ MADRCU?!] \S/m;
|
||||
const RE_BUILD_OUTPUT = /^(npm (warn|error|ERR!)|yarn (warn|error)|\s*Compiling\s+\S+|\s*Downloading\s+\S+|added \d+ package|\[ERROR\]|BUILD (SUCCESS|FAILED)|\s*Finished\s+|Successfully (installed|built)|ERROR:)/im;
|
||||
const RE_TREE_GLYPH = /[├└]──|│ /;
|
||||
@@ -27,6 +29,7 @@ export function autoDetectFilter(text) {
|
||||
// Rust: floor_char_boundary to avoid UTF-8 split — JS .slice() by char is safe
|
||||
const head = text.length > DETECT_WINDOW ? text.slice(0, DETECT_WINDOW) : text;
|
||||
|
||||
if (RE_GIT_LOG.test(head)) return gitLog;
|
||||
if (RE_GIT_DIFF.test(head) || RE_GIT_DIFF_HUNK.test(head)) return gitDiff;
|
||||
if (RE_GIT_STATUS.test(head)) return gitStatus;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ export const MIN_COMPRESS_SIZE = 500; // bytes; skip tiny blobs
|
||||
export const DETECT_WINDOW = 1024; // autodetect peeks first N chars
|
||||
export const GIT_DIFF_HUNK_MAX_LINES = 100; // per-hunk line cap
|
||||
export const GIT_DIFF_CONTEXT_KEEP = 3; // context lines around changes
|
||||
export const GIT_LOG_MAX_LINES = 200; // gitLog line cap
|
||||
export const DEDUP_LINE_MAX = 2000; // dedupLog truncation cap
|
||||
|
||||
// Rust pipe_cmd.rs parity caps
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
// JS-native git-log filter
|
||||
// Compresses `git log` output: keeps commit headers, subjects, Author/Date;
|
||||
// drops body padding, decoration, embedded diff lines.
|
||||
import { GIT_LOG_MAX_LINES } from "../constants.js";
|
||||
|
||||
export function gitLog(text, maxLines = GIT_LOG_MAX_LINES) {
|
||||
if (!text) return "";
|
||||
|
||||
const input = String(text);
|
||||
const lines = input.split("\n");
|
||||
const out = [];
|
||||
let skipped = 0;
|
||||
let inCommit = false;
|
||||
let subjectSeen = false;
|
||||
|
||||
function pushLine(l) {
|
||||
if (out.length < maxLines) {
|
||||
out.push(l);
|
||||
return true;
|
||||
}
|
||||
skipped++;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const raw = lines[i];
|
||||
const line = raw.trimEnd();
|
||||
const trimmed = line.trim();
|
||||
|
||||
// commit <sha> header — starts new commit entry
|
||||
// Also matched with leading graph decoration (`* commit abc1234...` — --graph without --oneline)
|
||||
if (/^commit [0-9a-f]{7,40}$/i.test(trimmed) || /^[*|/\\ ]+commit [0-9a-f]{7,40}/i.test(trimmed)) {
|
||||
inCommit = true;
|
||||
subjectSeen = false;
|
||||
pushLine(line);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (inCommit) {
|
||||
// Author / Date — keep as-is (already column 0 in raw, or graph-prefix stripped by commit-header match)
|
||||
if (/^[*|/\\ ]*(Author|Date):/i.test(trimmed)) {
|
||||
pushLine(trimmed);
|
||||
continue;
|
||||
}
|
||||
// blank — skip
|
||||
if (trimmed === "") continue;
|
||||
// indented subject (4 spaces, optionally preceded by graph decoration) — first one is subject
|
||||
if (!subjectSeen && /^[*|/\\ ]* \S/.test(line)) {
|
||||
pushLine(" Subject: " + trimmed);
|
||||
subjectSeen = true;
|
||||
continue;
|
||||
}
|
||||
// stat summary: "N file(s) changed, N insertions(+), N deletions(-)"
|
||||
if (/^\d+ file\w* changed/.test(trimmed)) {
|
||||
pushLine(" " + trimmed);
|
||||
continue;
|
||||
}
|
||||
// embedded diff header — one-line marker
|
||||
if (/^diff --git /.test(trimmed)) {
|
||||
pushLine(" ... diff body omitted");
|
||||
continue;
|
||||
}
|
||||
// everything else in commit body — drop
|
||||
continue;
|
||||
}
|
||||
|
||||
// Not in a commit block (--oneline / --graph modes):
|
||||
|
||||
// Graph decoration + sha + subject: "*|/\\ <sha7> <subject>"
|
||||
const graphMatch = trimmed.match(/^[*|/\\ ]+([0-9a-f]{7,40}\s+.+)/i);
|
||||
if (graphMatch) {
|
||||
pushLine(graphMatch[1]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Plain oneline: "<sha7> <subject>"
|
||||
if (/^[0-9a-f]{7,40}\s+/.test(trimmed)) {
|
||||
pushLine(trimmed);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Pure graph decoration (no sha) — drop
|
||||
if (/^[*|/\\ ]+$/.test(trimmed) && /[*|/\\]/.test(trimmed)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// catch-all pass-through
|
||||
pushLine(trimmed);
|
||||
}
|
||||
|
||||
if (skipped > 0) out.push(`... (${skipped} more lines)`);
|
||||
|
||||
const result = out.join("\n");
|
||||
if (!result && input) return input;
|
||||
if (result.length > input.length) return input;
|
||||
return result;
|
||||
}
|
||||
|
||||
gitLog.filterName = "git-log";
|
||||
@@ -1,6 +1,7 @@
|
||||
import { FILTERS } from "./constants.js";
|
||||
import { gitDiff } from "./filters/gitDiff.js";
|
||||
import { gitStatus } from "./filters/gitStatus.js";
|
||||
import { gitLog } from "./filters/gitLog.js";
|
||||
import { grep } from "./filters/grep.js";
|
||||
import { find } from "./filters/find.js";
|
||||
import { dedupLog } from "./filters/dedupLog.js";
|
||||
@@ -13,6 +14,7 @@ import { searchList } from "./filters/searchList.js";
|
||||
const REGISTRY = {
|
||||
[FILTERS.GIT_DIFF]: gitDiff,
|
||||
[FILTERS.GIT_STATUS]: gitStatus,
|
||||
[FILTERS.GIT_LOG]: gitLog,
|
||||
[FILTERS.GREP]: grep,
|
||||
[FILTERS.FIND]: find,
|
||||
[FILTERS.DEDUP_LOG]: dedupLog,
|
||||
|
||||
Reference in New Issue
Block a user