// src/actions/gitignore.ts
import { unlinkSync } from "node:fs";
import chalk from "chalk";

// src/pm/workspaces.ts
import { existsSync, readFileSync } from "node:fs";
import PATH from "node:path";
import { globSync } from "glob";
function readJsonFile(path) {
  if (!existsSync(path)) return void 0;
  try {
    return JSON.parse(readFileSync(path, "utf8"));
  } catch {
    return void 0;
  }
}
function readRootPackageJson(cwd = process.cwd()) {
  return readJsonFile(PATH.resolve(cwd, "package.json"));
}
function detectPackageManagerFromPackageJson(cwd = process.cwd()) {
  const packageManager = readRootPackageJson(cwd)?.packageManager;
  if (!(packageManager != null && packageManager.length > 0)) return void 0;
  return packageManager.split("@", 1)[0];
}

// src/pm/detectPackageManager.ts
import { existsSync as existsSync2 } from "node:fs";
var knownPackageManagers = /* @__PURE__ */ new Set(["bun", "npm", "pnpm", "yarn"]);
function detectPackageManager() {
  const packageManager = detectPackageManagerFromPackageJson();
  if (packageManager != null && packageManager.length > 0 && knownPackageManagers.has(packageManager)) {
    return packageManager;
  }
  if (existsSync2("pnpm-lock.yaml") || existsSync2("pnpm-workspace.yaml")) return "pnpm";
  if (existsSync2("bun.lock") || existsSync2("bun.lockb")) return "bun";
  if (existsSync2("yarn.lock") || existsSync2(".yarnrc.yml")) return "yarn";
  if (existsSync2("package-lock.json") || existsSync2("npm-shrinkwrap.json")) return "npm";
  return "yarn";
}

// src/pm/registry.ts
var implementations = /* @__PURE__ */ new Map();
function getPackageManager(name) {
  const pmName = name ?? detectPackageManager();
  const pm = implementations.get(pmName);
  if (!pm) {
    throw new Error(
      `No package manager implementation registered for "${pmName}". Ensure registerPackageManager() has been called before getPackageManager().`
    );
  }
  return pm;
}

// src/lib/file/constants.ts
var WINDOWS_NEWLINE_REGEX = /\r\n/g;
var CROSS_PLATFORM_NEWLINE = "\n";

// src/lib/file/fileLines.ts
import {
  existsSync as existsSync3,
  readFileSync as readFileSync2,
  writeFileSync
} from "node:fs";

// src/lib/string/empty.ts
var isEmpty = (value) => value?.trim().length === 0;
var isNotEmpty = (value) => !isEmpty(value);

// src/lib/string/union.ts
var union = (a, b) => /* @__PURE__ */ new Set([...new Set(a), ...new Set(b)]);

// src/lib/file/ReadFileSyncOptions.ts
var defaultReadFileSyncOptions = { encoding: "utf8" };

// src/lib/file/fileLines.ts
var readLines = (uri, options = defaultReadFileSyncOptions) => existsSync3(uri) ? readFileSync2(uri, options).replace(WINDOWS_NEWLINE_REGEX, () => CROSS_PLATFORM_NEWLINE).split(CROSS_PLATFORM_NEWLINE) : [];
var readNonEmptyLines = (uri, options = defaultReadFileSyncOptions) => readLines(uri, options).filter(isNotEmpty);
var writeLines = (uri, lines, options = defaultReadFileSyncOptions) => {
  const existing = existsSync3(uri) ? readFileSync2(uri, options) : void 0;
  const desired = lines.join(CROSS_PLATFORM_NEWLINE);
  if (existing !== desired) writeFileSync(uri, desired, options);
};

// src/lib/initCwd.ts
function INIT_CWD() {
  return process.env.INIT_CWD ?? process.cwd();
}

// src/lib/gitignoreTemplate.ts
import { readFileSync as readFileSync3 } from "node:fs";
import { createRequire } from "node:module";
import PATH2 from "node:path";
var require2 = createRequire(import.meta.url);
var packageRoot = PATH2.dirname(require2.resolve("@xylabs/toolchain/package.json"));
var templatesDir = PATH2.resolve(packageRoot, "templates", "gitignore");
var gitignoreTemplate = () => readFileSync3(PATH2.resolve(templatesDir, "template.gitignore"), "utf8");

// src/actions/gitignore.ts
var COMMENT_PREFIX = "#";
var isComment = (line) => line.startsWith(COMMENT_PREFIX);
var isNegation = (line) => line.startsWith("!");
function parseTemplateSections(lines) {
  const sections = [];
  let current = [];
  for (const line of lines) {
    if (isComment(line)) {
      if (current.length > 0) {
        sections.push(current);
      }
      current = [line];
    } else {
      current.push(line);
    }
  }
  if (current.length > 0) {
    sections.push(current);
  }
  return sections;
}
function mergeWithTemplate(existing, templateContent) {
  const templateLines = templateContent.split("\n").filter((line) => line.trim().length > 0);
  const sections = parseTemplateSections(templateLines);
  const existingEntries = new Set(existing.filter((line) => !isComment(line)));
  const templateEntries = new Set(templateLines.filter((line) => !isComment(line)));
  const customEntries = [...existingEntries].filter((entry) => !templateEntries.has(entry));
  const result = [];
  for (const section of sections) {
    for (const line of section) {
      result.push(line);
    }
    result.push("");
  }
  if (customEntries.length > 0) {
    result.push("# Custom");
    const sorted = [...union(customEntries, [])].toSorted((a, b) => {
      if (isNegation(a) && !isNegation(b)) return 1;
      if (!isNegation(a) && isNegation(b)) return -1;
      return a.localeCompare(b);
    });
    for (const entry of sorted) {
      result.push(entry);
    }
    result.push("");
  }
  return result;
}
function removePackageGitignores(cwd) {
  let removed = 0;
  const workspaces = getPackageManager().listWorkspaces();
  for (const { location } of workspaces) {
    if (location === ".") continue;
    const filePath = `${cwd}/${location}/.gitignore`;
    try {
      unlinkSync(filePath);
      console.log(chalk.yellow(`  Removed ${location}/.gitignore`));
      removed++;
    } catch {
    }
  }
  return removed;
}
var gitignoreGen = gitignore;
function gitignore() {
  console.log(chalk.green("Generate .gitignore"));
  const cwd = INIT_CWD();
  const gitignorePath = `${cwd}/.gitignore`;
  try {
    const templateContent = gitignoreTemplate();
    const existing = readNonEmptyLines(gitignorePath);
    const merged = mergeWithTemplate(existing, templateContent);
    writeLines(gitignorePath, merged);
    console.log(chalk.green("  Root .gitignore updated"));
    const removed = removePackageGitignores(cwd);
    if (removed > 0) {
      console.log(chalk.green(`  Removed ${removed} package .gitignore file(s)`));
    }
    return 0;
  } catch (ex) {
    const error = ex;
    console.error(chalk.red(`Generate .gitignore failed: ${error.message}`));
    return 1;
  }
}
export {
  gitignore,
  gitignoreGen
};
//# sourceMappingURL=gitignore.mjs.map
