@c4a/extract 0.5.41-beta.4 → 0.5.41-beta.6

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.
@@ -13891,11 +13891,11 @@ class ExtractionPluginRegistry {
13891
13891
  }
13892
13892
 
13893
13893
  // src/scanner.ts
13894
- import { exec } from "node:child_process";
13894
+ import { execFile } from "node:child_process";
13895
13895
  import { access, readdir, readFile } from "node:fs/promises";
13896
13896
  import { basename, extname, join, relative, resolve, sep } from "node:path";
13897
13897
  import { promisify } from "node:util";
13898
- var execAsync = promisify(exec);
13898
+ var execFileAsync = promisify(execFile);
13899
13899
  var isScanExcludedDir = (name) => SCAN_EXCLUDED_DIRS.has(name) || name.startsWith(".") && name !== "." || name.endsWith(".egg-info");
13900
13900
  var DEFAULT_EXCLUDED_FILE_PATTERNS = [
13901
13901
  /\.test\.ts$/i,
@@ -13906,9 +13906,18 @@ var SUPPORTED_EXTENSIONS = new Set([".ts", ".tsx"]);
13906
13906
  var toPosixPath = (value) => value.split(sep).join("/");
13907
13907
  var shouldExcludeFile = (fileName) => DEFAULT_EXCLUDED_FILE_PATTERNS.some((pattern) => pattern.test(fileName));
13908
13908
  var isSupportedSourceFile = (fileName) => SUPPORTED_EXTENSIONS.has(extname(fileName));
13909
+ var gitScopeArgs = (prefix) => {
13910
+ const scope = prefix.replace(/\/+$/u, "");
13911
+ return scope.length > 0 ? ["--", scope] : [];
13912
+ };
13913
+ var stripGitPrefix = (filePath, prefix) => {
13914
+ if (!prefix)
13915
+ return filePath;
13916
+ return filePath.startsWith(prefix) ? filePath.slice(prefix.length) : null;
13917
+ };
13909
13918
  var tryGitListFiles = async (rootDir, ref) => {
13910
13919
  try {
13911
- const { stdout: gitRootRaw } = await execAsync("git rev-parse --show-toplevel", {
13920
+ const { stdout: gitRootRaw } = await execFileAsync("git", ["rev-parse", "--show-toplevel"], {
13912
13921
  cwd: rootDir
13913
13922
  });
13914
13923
  const gitRoot = gitRootRaw.trim();
@@ -13919,33 +13928,31 @@ var tryGitListFiles = async (rootDir, ref) => {
13919
13928
  if (treeRef !== "HEAD" && !/^[0-9a-fA-F]{4,40}$/.test(treeRef)) {
13920
13929
  return null;
13921
13930
  }
13922
- const { stdout: treeOutput } = await execAsync(`git ls-tree -r --name-only ${treeRef}`, { cwd: gitRoot, maxBuffer: 64 * 1024 * 1024 });
13931
+ const scopeArgs = gitScopeArgs(prefix);
13932
+ const { stdout: treeOutput } = await execFileAsync("git", ["ls-tree", "-r", "--name-only", treeRef, ...scopeArgs], { cwd: gitRoot, maxBuffer: 64 * 1024 * 1024 });
13923
13933
  const fileSet = new Set;
13924
13934
  for (const line of treeOutput.split(`
13925
13935
  `)) {
13926
13936
  const trimmed = line.trim();
13927
13937
  if (!trimmed)
13928
13938
  continue;
13929
- if (prefix) {
13930
- if (!trimmed.startsWith(prefix))
13931
- continue;
13932
- fileSet.add(trimmed.slice(prefix.length));
13933
- } else {
13934
- fileSet.add(trimmed);
13935
- }
13939
+ const relPath = stripGitPrefix(trimmed, prefix);
13940
+ if (relPath)
13941
+ fileSet.add(relPath);
13936
13942
  }
13937
13943
  if (!ref) {
13938
- const { stdout: diffOutput } = await execAsync("git diff --name-status HEAD", { cwd: gitRoot, maxBuffer: 16 * 1024 * 1024 });
13944
+ const { stdout: diffOutput } = await execFileAsync("git", ["diff", "--name-status", "HEAD", ...scopeArgs], { cwd: gitRoot, maxBuffer: 16 * 1024 * 1024 });
13939
13945
  for (const line of diffOutput.split(`
13940
13946
  `)) {
13941
13947
  const trimmed = line.trim();
13942
13948
  if (!trimmed)
13943
13949
  continue;
13944
- const status = trimmed[0];
13945
- const filePath = trimmed.slice(1).trim();
13950
+ const parts = trimmed.split("\t");
13951
+ const status = parts[0]?.[0];
13952
+ const filePath = status === "R" || status === "C" ? parts[2] : parts[1] ?? trimmed.slice(1).trim();
13946
13953
  if (!filePath)
13947
13954
  continue;
13948
- const relPath = prefix ? filePath.startsWith(prefix) ? filePath.slice(prefix.length) : null : filePath;
13955
+ const relPath = stripGitPrefix(filePath, prefix);
13949
13956
  if (!relPath)
13950
13957
  continue;
13951
13958
  if (status === "D") {
@@ -13954,7 +13961,7 @@ var tryGitListFiles = async (rootDir, ref) => {
13954
13961
  fileSet.add(relPath);
13955
13962
  }
13956
13963
  }
13957
- const { stdout: statusOutput } = await execAsync("git status --porcelain -uall", { cwd: gitRoot, maxBuffer: 16 * 1024 * 1024 });
13964
+ const { stdout: statusOutput } = await execFileAsync("git", ["status", "--porcelain", "-uall", ...scopeArgs], { cwd: gitRoot, maxBuffer: 16 * 1024 * 1024 });
13958
13965
  for (const line of statusOutput.split(`
13959
13966
  `)) {
13960
13967
  if (!line.startsWith("?? "))
@@ -13962,7 +13969,7 @@ var tryGitListFiles = async (rootDir, ref) => {
13962
13969
  const filePath = line.slice(3).trim();
13963
13970
  if (!filePath || filePath.endsWith("/"))
13964
13971
  continue;
13965
- const relPath = prefix ? filePath.startsWith(prefix) ? filePath.slice(prefix.length) : null : filePath;
13972
+ const relPath = stripGitPrefix(filePath, prefix);
13966
13973
  if (relPath)
13967
13974
  fileSet.add(relPath);
13968
13975
  }
@@ -13972,42 +13979,51 @@ var tryGitListFiles = async (rootDir, ref) => {
13972
13979
  return null;
13973
13980
  }
13974
13981
  };
13975
- var scanSourceFiles = async (rootDir, excludeDirs, ref, pathFilter2) => {
13982
+ function filterGitSourceFiles(baseDir, gitFiles, excludeDirs, pathFilter2) {
13976
13983
  const results = [];
13977
- const baseDir = resolve(rootDir);
13978
13984
  const codePathMatcher = pathFilter2 ? createPathMatcher(pathFilter2.code) : null;
13979
13985
  const matchesCode = (relPath, fileName) => {
13980
13986
  if (codePathMatcher)
13981
13987
  return codePathMatcher(relPath);
13982
13988
  return isSupportedSourceFile(fileName) && !shouldExcludeFile(fileName);
13983
13989
  };
13984
- const gitFiles = await tryGitListFiles(baseDir, ref);
13985
- if (gitFiles && gitFiles.size > 0) {
13986
- for (const relPath of gitFiles) {
13987
- const fileName = relPath.split("/").pop() ?? "";
13988
- if (!matchesCode(relPath, fileName))
13989
- continue;
13990
- const segments = relPath.split("/");
13991
- let excluded = false;
13992
- for (let i = 0;i < segments.length - 1; i++) {
13993
- const seg = segments[i];
13994
- if (isScanExcludedDir(seg)) {
13990
+ for (const relPath of gitFiles) {
13991
+ const fileName = relPath.split("/").pop() ?? "";
13992
+ if (!matchesCode(relPath, fileName))
13993
+ continue;
13994
+ const segments = relPath.split("/");
13995
+ let excluded = false;
13996
+ for (let i = 0;i < segments.length - 1; i++) {
13997
+ const seg = segments[i];
13998
+ if (isScanExcludedDir(seg)) {
13999
+ excluded = true;
14000
+ break;
14001
+ }
14002
+ if (excludeDirs) {
14003
+ const dirPath = resolve(baseDir, segments.slice(0, i + 1).join("/"));
14004
+ if (excludeDirs.has(dirPath)) {
13995
14005
  excluded = true;
13996
14006
  break;
13997
14007
  }
13998
- if (excludeDirs) {
13999
- const dirPath = resolve(baseDir, segments.slice(0, i + 1).join("/"));
14000
- if (excludeDirs.has(dirPath)) {
14001
- excluded = true;
14002
- break;
14003
- }
14004
- }
14005
14008
  }
14006
- if (excluded)
14007
- continue;
14008
- results.push(toPosixPath(relPath));
14009
14009
  }
14010
- return results.sort();
14010
+ if (!excluded)
14011
+ results.push(toPosixPath(relPath));
14012
+ }
14013
+ return results.sort();
14014
+ }
14015
+ var scanSourceFiles = async (rootDir, excludeDirs, ref, pathFilter2) => {
14016
+ const results = [];
14017
+ const baseDir = resolve(rootDir);
14018
+ const codePathMatcher = pathFilter2 ? createPathMatcher(pathFilter2.code) : null;
14019
+ const matchesCode = (relPath, fileName) => {
14020
+ if (codePathMatcher)
14021
+ return codePathMatcher(relPath);
14022
+ return isSupportedSourceFile(fileName) && !shouldExcludeFile(fileName);
14023
+ };
14024
+ const gitFiles = await tryGitListFiles(baseDir, ref);
14025
+ if (gitFiles && gitFiles.size > 0) {
14026
+ return filterGitSourceFiles(baseDir, gitFiles, excludeDirs, pathFilter2);
14011
14027
  }
14012
14028
  const visit = async (currentDir) => {
14013
14029
  const entries = await readdir(currentDir, { withFileTypes: true });
@@ -14160,9 +14176,9 @@ var findSubModuleDirs = async (rootDir, excludeDirs, gitFiles, pathFilter2) => {
14160
14176
  await walk(root);
14161
14177
  return results;
14162
14178
  };
14163
- var buildModule = async (repoRoot, moduleDir, moduleName, childModuleDirs, ref, pathFilter2) => {
14179
+ var buildModule = async (repoRoot, moduleDir, moduleName, childModuleDirs, ref, pathFilter2, gitFiles) => {
14164
14180
  const excludes = childModuleDirs.size > 0 ? childModuleDirs : undefined;
14165
- const moduleFiles = await scanSourceFiles(moduleDir, excludes, ref, pathFilter2);
14181
+ const moduleFiles = gitFiles !== undefined && gitFiles !== null && gitFiles.size > 0 ? filterGitSourceFiles(resolve(moduleDir), gitFiles, excludes, pathFilter2) : await scanSourceFiles(moduleDir, excludes, ref, pathFilter2);
14166
14182
  const modulePath = toPosixPath(relative(repoRoot, moduleDir)) || ".";
14167
14183
  const totalLines = await Promise.all(moduleFiles.map((file) => countFileLines(join(moduleDir, file))));
14168
14184
  const files = modulePath === "." ? moduleFiles : moduleFiles.map((file) => toPosixPath(join(modulePath, file)));
@@ -14174,6 +14190,20 @@ var buildModule = async (repoRoot, moduleDir, moduleName, childModuleDirs, ref,
14174
14190
  totalLines: totalLines.reduce((sum, value) => sum + value, 0)
14175
14191
  };
14176
14192
  };
14193
+ function scopedGitFiles(gitFiles, scopeRel) {
14194
+ if (gitFiles === null)
14195
+ return null;
14196
+ const normalizedScope = toPosixPath(scopeRel).replace(/\/+$/u, "");
14197
+ if (!normalizedScope || normalizedScope === ".")
14198
+ return gitFiles;
14199
+ const prefix = `${normalizedScope}/`;
14200
+ const scoped = new Set;
14201
+ for (const file of gitFiles) {
14202
+ if (file.startsWith(prefix))
14203
+ scoped.add(file.slice(prefix.length));
14204
+ }
14205
+ return scoped;
14206
+ }
14177
14207
  var detectModules = async (repoPath, ref, pathFilter2) => {
14178
14208
  const repoRoot = resolve(repoPath);
14179
14209
  const modules = [];
@@ -14183,7 +14213,7 @@ var detectModules = async (repoPath, ref, pathFilter2) => {
14183
14213
  const rootManifest = await findManifestFile(repoRoot);
14184
14214
  if (rootManifest) {
14185
14215
  const rootName = await readModuleName(repoRoot, rootManifest) ?? basename(repoRoot);
14186
- modules.push(await buildModule(repoRoot, repoRoot, rootName, subModuleDirSet, ref, pathFilter2));
14216
+ modules.push(await buildModule(repoRoot, repoRoot, rootName, subModuleDirSet, ref, pathFilter2, gitFiles));
14187
14217
  }
14188
14218
  for (const subDir of subModuleDirs) {
14189
14219
  const manifest = await findManifestFile(subDir);
@@ -14191,11 +14221,10 @@ var detectModules = async (repoPath, ref, pathFilter2) => {
14191
14221
  continue;
14192
14222
  const name = await readModuleName(subDir, manifest) ?? basename(subDir);
14193
14223
  const subDirRel = toPosixPath(relative(repoRoot, subDir));
14194
- const subPrefix = subDirRel + "/";
14195
- const subGitFiles = gitFiles ? new Set([...gitFiles].filter((f) => f.startsWith(subPrefix)).map((f) => f.slice(subPrefix.length))) : null;
14224
+ const subGitFiles = scopedGitFiles(gitFiles, subDirRel);
14196
14225
  const nested = await findSubModuleDirs(subDir, subModuleDirSet, subGitFiles, pathFilter2);
14197
14226
  const nestedSet = new Set(nested.map((d) => resolve(d)));
14198
- modules.push(await buildModule(repoRoot, subDir, name, nestedSet, ref, pathFilter2));
14227
+ modules.push(await buildModule(repoRoot, subDir, name, nestedSet, ref, pathFilter2, subGitFiles));
14199
14228
  }
14200
14229
  return modules.sort((a, b) => a.name.localeCompare(b.name));
14201
14230
  };
@@ -14214,7 +14243,7 @@ var detectModuleAt = async (repoPath, modulePath, ref, pathFilter2) => {
14214
14243
  const gitFiles = await tryGitListFiles(moduleDir, ref);
14215
14244
  const nested = await findSubModuleDirs(moduleDir, undefined, gitFiles, pathFilter2);
14216
14245
  const nestedSet = new Set(nested.map((d) => resolve(d)));
14217
- return buildModule(repoRoot, moduleDir, name, nestedSet, ref, pathFilter2);
14246
+ return buildModule(repoRoot, moduleDir, name, nestedSet, ref, pathFilter2, gitFiles);
14218
14247
  };
14219
14248
 
14220
14249
  // src/repository.ts
package/index.js CHANGED
@@ -15468,11 +15468,11 @@ import { readFile as readFile2, readdir as readdir2, stat } from "node:fs/promis
15468
15468
  import path2 from "node:path";
15469
15469
 
15470
15470
  // src/scanner.ts
15471
- import { exec } from "node:child_process";
15471
+ import { execFile } from "node:child_process";
15472
15472
  import { access, readdir, readFile } from "node:fs/promises";
15473
15473
  import { basename, extname, join, relative, resolve, sep } from "node:path";
15474
15474
  import { promisify } from "node:util";
15475
- var execAsync = promisify(exec);
15475
+ var execFileAsync = promisify(execFile);
15476
15476
  var isScanExcludedDir = (name) => SCAN_EXCLUDED_DIRS.has(name) || name.startsWith(".") && name !== "." || name.endsWith(".egg-info");
15477
15477
  var DEFAULT_EXCLUDED_FILE_PATTERNS = [
15478
15478
  /\.test\.ts$/i,
@@ -15483,9 +15483,18 @@ var SUPPORTED_EXTENSIONS = new Set([".ts", ".tsx"]);
15483
15483
  var toPosixPath = (value) => value.split(sep).join("/");
15484
15484
  var shouldExcludeFile = (fileName) => DEFAULT_EXCLUDED_FILE_PATTERNS.some((pattern) => pattern.test(fileName));
15485
15485
  var isSupportedSourceFile = (fileName) => SUPPORTED_EXTENSIONS.has(extname(fileName));
15486
+ var gitScopeArgs = (prefix) => {
15487
+ const scope = prefix.replace(/\/+$/u, "");
15488
+ return scope.length > 0 ? ["--", scope] : [];
15489
+ };
15490
+ var stripGitPrefix = (filePath, prefix) => {
15491
+ if (!prefix)
15492
+ return filePath;
15493
+ return filePath.startsWith(prefix) ? filePath.slice(prefix.length) : null;
15494
+ };
15486
15495
  var tryGitListFiles = async (rootDir, ref) => {
15487
15496
  try {
15488
- const { stdout: gitRootRaw } = await execAsync("git rev-parse --show-toplevel", {
15497
+ const { stdout: gitRootRaw } = await execFileAsync("git", ["rev-parse", "--show-toplevel"], {
15489
15498
  cwd: rootDir
15490
15499
  });
15491
15500
  const gitRoot = gitRootRaw.trim();
@@ -15496,33 +15505,31 @@ var tryGitListFiles = async (rootDir, ref) => {
15496
15505
  if (treeRef !== "HEAD" && !/^[0-9a-fA-F]{4,40}$/.test(treeRef)) {
15497
15506
  return null;
15498
15507
  }
15499
- const { stdout: treeOutput } = await execAsync(`git ls-tree -r --name-only ${treeRef}`, { cwd: gitRoot, maxBuffer: 64 * 1024 * 1024 });
15508
+ const scopeArgs = gitScopeArgs(prefix);
15509
+ const { stdout: treeOutput } = await execFileAsync("git", ["ls-tree", "-r", "--name-only", treeRef, ...scopeArgs], { cwd: gitRoot, maxBuffer: 64 * 1024 * 1024 });
15500
15510
  const fileSet = new Set;
15501
15511
  for (const line of treeOutput.split(`
15502
15512
  `)) {
15503
15513
  const trimmed = line.trim();
15504
15514
  if (!trimmed)
15505
15515
  continue;
15506
- if (prefix) {
15507
- if (!trimmed.startsWith(prefix))
15508
- continue;
15509
- fileSet.add(trimmed.slice(prefix.length));
15510
- } else {
15511
- fileSet.add(trimmed);
15512
- }
15516
+ const relPath = stripGitPrefix(trimmed, prefix);
15517
+ if (relPath)
15518
+ fileSet.add(relPath);
15513
15519
  }
15514
15520
  if (!ref) {
15515
- const { stdout: diffOutput } = await execAsync("git diff --name-status HEAD", { cwd: gitRoot, maxBuffer: 16 * 1024 * 1024 });
15521
+ const { stdout: diffOutput } = await execFileAsync("git", ["diff", "--name-status", "HEAD", ...scopeArgs], { cwd: gitRoot, maxBuffer: 16 * 1024 * 1024 });
15516
15522
  for (const line of diffOutput.split(`
15517
15523
  `)) {
15518
15524
  const trimmed = line.trim();
15519
15525
  if (!trimmed)
15520
15526
  continue;
15521
- const status = trimmed[0];
15522
- const filePath = trimmed.slice(1).trim();
15527
+ const parts = trimmed.split("\t");
15528
+ const status = parts[0]?.[0];
15529
+ const filePath = status === "R" || status === "C" ? parts[2] : parts[1] ?? trimmed.slice(1).trim();
15523
15530
  if (!filePath)
15524
15531
  continue;
15525
- const relPath = prefix ? filePath.startsWith(prefix) ? filePath.slice(prefix.length) : null : filePath;
15532
+ const relPath = stripGitPrefix(filePath, prefix);
15526
15533
  if (!relPath)
15527
15534
  continue;
15528
15535
  if (status === "D") {
@@ -15531,7 +15538,7 @@ var tryGitListFiles = async (rootDir, ref) => {
15531
15538
  fileSet.add(relPath);
15532
15539
  }
15533
15540
  }
15534
- const { stdout: statusOutput } = await execAsync("git status --porcelain -uall", { cwd: gitRoot, maxBuffer: 16 * 1024 * 1024 });
15541
+ const { stdout: statusOutput } = await execFileAsync("git", ["status", "--porcelain", "-uall", ...scopeArgs], { cwd: gitRoot, maxBuffer: 16 * 1024 * 1024 });
15535
15542
  for (const line of statusOutput.split(`
15536
15543
  `)) {
15537
15544
  if (!line.startsWith("?? "))
@@ -15539,7 +15546,7 @@ var tryGitListFiles = async (rootDir, ref) => {
15539
15546
  const filePath = line.slice(3).trim();
15540
15547
  if (!filePath || filePath.endsWith("/"))
15541
15548
  continue;
15542
- const relPath = prefix ? filePath.startsWith(prefix) ? filePath.slice(prefix.length) : null : filePath;
15549
+ const relPath = stripGitPrefix(filePath, prefix);
15543
15550
  if (relPath)
15544
15551
  fileSet.add(relPath);
15545
15552
  }
@@ -15549,42 +15556,51 @@ var tryGitListFiles = async (rootDir, ref) => {
15549
15556
  return null;
15550
15557
  }
15551
15558
  };
15552
- var scanSourceFiles = async (rootDir, excludeDirs, ref, pathFilter2) => {
15559
+ function filterGitSourceFiles(baseDir, gitFiles, excludeDirs, pathFilter2) {
15553
15560
  const results = [];
15554
- const baseDir = resolve(rootDir);
15555
15561
  const codePathMatcher = pathFilter2 ? createPathMatcher(pathFilter2.code) : null;
15556
15562
  const matchesCode = (relPath, fileName) => {
15557
15563
  if (codePathMatcher)
15558
15564
  return codePathMatcher(relPath);
15559
15565
  return isSupportedSourceFile(fileName) && !shouldExcludeFile(fileName);
15560
15566
  };
15561
- const gitFiles = await tryGitListFiles(baseDir, ref);
15562
- if (gitFiles && gitFiles.size > 0) {
15563
- for (const relPath of gitFiles) {
15564
- const fileName = relPath.split("/").pop() ?? "";
15565
- if (!matchesCode(relPath, fileName))
15566
- continue;
15567
- const segments = relPath.split("/");
15568
- let excluded = false;
15569
- for (let i = 0;i < segments.length - 1; i++) {
15570
- const seg = segments[i];
15571
- if (isScanExcludedDir(seg)) {
15567
+ for (const relPath of gitFiles) {
15568
+ const fileName = relPath.split("/").pop() ?? "";
15569
+ if (!matchesCode(relPath, fileName))
15570
+ continue;
15571
+ const segments = relPath.split("/");
15572
+ let excluded = false;
15573
+ for (let i = 0;i < segments.length - 1; i++) {
15574
+ const seg = segments[i];
15575
+ if (isScanExcludedDir(seg)) {
15576
+ excluded = true;
15577
+ break;
15578
+ }
15579
+ if (excludeDirs) {
15580
+ const dirPath = resolve(baseDir, segments.slice(0, i + 1).join("/"));
15581
+ if (excludeDirs.has(dirPath)) {
15572
15582
  excluded = true;
15573
15583
  break;
15574
15584
  }
15575
- if (excludeDirs) {
15576
- const dirPath = resolve(baseDir, segments.slice(0, i + 1).join("/"));
15577
- if (excludeDirs.has(dirPath)) {
15578
- excluded = true;
15579
- break;
15580
- }
15581
- }
15582
15585
  }
15583
- if (excluded)
15584
- continue;
15585
- results.push(toPosixPath(relPath));
15586
15586
  }
15587
- return results.sort();
15587
+ if (!excluded)
15588
+ results.push(toPosixPath(relPath));
15589
+ }
15590
+ return results.sort();
15591
+ }
15592
+ var scanSourceFiles = async (rootDir, excludeDirs, ref, pathFilter2) => {
15593
+ const results = [];
15594
+ const baseDir = resolve(rootDir);
15595
+ const codePathMatcher = pathFilter2 ? createPathMatcher(pathFilter2.code) : null;
15596
+ const matchesCode = (relPath, fileName) => {
15597
+ if (codePathMatcher)
15598
+ return codePathMatcher(relPath);
15599
+ return isSupportedSourceFile(fileName) && !shouldExcludeFile(fileName);
15600
+ };
15601
+ const gitFiles = await tryGitListFiles(baseDir, ref);
15602
+ if (gitFiles && gitFiles.size > 0) {
15603
+ return filterGitSourceFiles(baseDir, gitFiles, excludeDirs, pathFilter2);
15588
15604
  }
15589
15605
  const visit = async (currentDir) => {
15590
15606
  const entries = await readdir(currentDir, { withFileTypes: true });
@@ -15737,9 +15753,9 @@ var findSubModuleDirs = async (rootDir, excludeDirs, gitFiles, pathFilter2) => {
15737
15753
  await walk(root);
15738
15754
  return results;
15739
15755
  };
15740
- var buildModule = async (repoRoot, moduleDir, moduleName, childModuleDirs, ref, pathFilter2) => {
15756
+ var buildModule = async (repoRoot, moduleDir, moduleName, childModuleDirs, ref, pathFilter2, gitFiles) => {
15741
15757
  const excludes = childModuleDirs.size > 0 ? childModuleDirs : undefined;
15742
- const moduleFiles = await scanSourceFiles(moduleDir, excludes, ref, pathFilter2);
15758
+ const moduleFiles = gitFiles !== undefined && gitFiles !== null && gitFiles.size > 0 ? filterGitSourceFiles(resolve(moduleDir), gitFiles, excludes, pathFilter2) : await scanSourceFiles(moduleDir, excludes, ref, pathFilter2);
15743
15759
  const modulePath = toPosixPath(relative(repoRoot, moduleDir)) || ".";
15744
15760
  const totalLines = await Promise.all(moduleFiles.map((file) => countFileLines(join(moduleDir, file))));
15745
15761
  const files = modulePath === "." ? moduleFiles : moduleFiles.map((file) => toPosixPath(join(modulePath, file)));
@@ -15751,6 +15767,20 @@ var buildModule = async (repoRoot, moduleDir, moduleName, childModuleDirs, ref,
15751
15767
  totalLines: totalLines.reduce((sum, value) => sum + value, 0)
15752
15768
  };
15753
15769
  };
15770
+ function scopedGitFiles(gitFiles, scopeRel) {
15771
+ if (gitFiles === null)
15772
+ return null;
15773
+ const normalizedScope = toPosixPath(scopeRel).replace(/\/+$/u, "");
15774
+ if (!normalizedScope || normalizedScope === ".")
15775
+ return gitFiles;
15776
+ const prefix = `${normalizedScope}/`;
15777
+ const scoped = new Set;
15778
+ for (const file of gitFiles) {
15779
+ if (file.startsWith(prefix))
15780
+ scoped.add(file.slice(prefix.length));
15781
+ }
15782
+ return scoped;
15783
+ }
15754
15784
  var detectModules = async (repoPath, ref, pathFilter2) => {
15755
15785
  const repoRoot = resolve(repoPath);
15756
15786
  const modules = [];
@@ -15760,7 +15790,7 @@ var detectModules = async (repoPath, ref, pathFilter2) => {
15760
15790
  const rootManifest = await findManifestFile(repoRoot);
15761
15791
  if (rootManifest) {
15762
15792
  const rootName = await readModuleName(repoRoot, rootManifest) ?? basename(repoRoot);
15763
- modules.push(await buildModule(repoRoot, repoRoot, rootName, subModuleDirSet, ref, pathFilter2));
15793
+ modules.push(await buildModule(repoRoot, repoRoot, rootName, subModuleDirSet, ref, pathFilter2, gitFiles));
15764
15794
  }
15765
15795
  for (const subDir of subModuleDirs) {
15766
15796
  const manifest = await findManifestFile(subDir);
@@ -15768,11 +15798,10 @@ var detectModules = async (repoPath, ref, pathFilter2) => {
15768
15798
  continue;
15769
15799
  const name = await readModuleName(subDir, manifest) ?? basename(subDir);
15770
15800
  const subDirRel = toPosixPath(relative(repoRoot, subDir));
15771
- const subPrefix = subDirRel + "/";
15772
- const subGitFiles = gitFiles ? new Set([...gitFiles].filter((f) => f.startsWith(subPrefix)).map((f) => f.slice(subPrefix.length))) : null;
15801
+ const subGitFiles = scopedGitFiles(gitFiles, subDirRel);
15773
15802
  const nested = await findSubModuleDirs(subDir, subModuleDirSet, subGitFiles, pathFilter2);
15774
15803
  const nestedSet = new Set(nested.map((d) => resolve(d)));
15775
- modules.push(await buildModule(repoRoot, subDir, name, nestedSet, ref, pathFilter2));
15804
+ modules.push(await buildModule(repoRoot, subDir, name, nestedSet, ref, pathFilter2, subGitFiles));
15776
15805
  }
15777
15806
  return modules.sort((a, b) => a.name.localeCompare(b.name));
15778
15807
  };
@@ -15791,7 +15820,7 @@ var detectModuleAt = async (repoPath, modulePath, ref, pathFilter2) => {
15791
15820
  const gitFiles = await tryGitListFiles(moduleDir, ref);
15792
15821
  const nested = await findSubModuleDirs(moduleDir, undefined, gitFiles, pathFilter2);
15793
15822
  const nestedSet = new Set(nested.map((d) => resolve(d)));
15794
- return buildModule(repoRoot, moduleDir, name, nestedSet, ref, pathFilter2);
15823
+ return buildModule(repoRoot, moduleDir, name, nestedSet, ref, pathFilter2, gitFiles);
15795
15824
  };
15796
15825
 
15797
15826
  // src/repository.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c4a/extract",
3
- "version": "0.5.41-beta.4",
3
+ "version": "0.5.41-beta.6",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "c4a-extract-code": "./bin/c4a-extract-code.js"