"use strict";
/* Socket Lib - Built with esbuild */
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var git_exports = {};
__export(git_exports, {
  findGitRoot: () => findGitRoot,
  getChangedFiles: () => getChangedFiles,
  getChangedFilesSync: () => getChangedFilesSync,
  getStagedFiles: () => getStagedFiles,
  getStagedFilesSync: () => getStagedFilesSync,
  getUnstagedFiles: () => getUnstagedFiles,
  getUnstagedFilesSync: () => getUnstagedFilesSync,
  isChanged: () => isChanged,
  isChangedSync: () => isChangedSync,
  isStaged: () => isStaged,
  isStagedSync: () => isStagedSync,
  isUnstaged: () => isUnstaged,
  isUnstagedSync: () => isUnstagedSync
});
module.exports = __toCommonJS(git_exports);
var import_path = __toESM(require("path"));
var import_debug = require("./debug");
var import_globs = require("./globs");
var import_normalize = require("./paths/normalize");
var import_spawn = require("./spawn");
var import_strings = require("./strings");
const gitDiffCache = /* @__PURE__ */ new Map();
let _fs;
// @__NO_SIDE_EFFECTS__
function getFs() {
  if (_fs === void 0) {
    _fs = require("node:fs");
  }
  return _fs;
}
let _path;
// @__NO_SIDE_EFFECTS__
function getPath() {
  if (_path === void 0) {
    _path = require("node:path");
  }
  return _path;
}
function getGitPath() {
  return "git";
}
function getCwd() {
  return (/* @__PURE__ */ getFs()).realpathSync(process.cwd());
}
function getGitDiffSpawnArgs(cwd) {
  const resolvedCwd = cwd ? (/* @__PURE__ */ getFs()).realpathSync(cwd) : getCwd();
  return {
    all: [
      getGitPath(),
      ["status", "--porcelain"],
      {
        cwd: resolvedCwd
      }
    ],
    unstaged: [
      getGitPath(),
      ["diff", "--name-only"],
      {
        cwd: resolvedCwd
      }
    ],
    staged: [
      getGitPath(),
      ["diff", "--cached", "--name-only"],
      {
        cwd: resolvedCwd
      }
    ]
  };
}
async function innerDiff(args, options) {
  const { cache = true, ...parseOptions } = { __proto__: null, ...options };
  const cacheKey = cache ? JSON.stringify({ args, parseOptions }) : void 0;
  if (cache && cacheKey) {
    const result2 = gitDiffCache.get(cacheKey);
    if (result2) {
      return result2;
    }
  }
  let result;
  try {
    const spawnResult = await (0, import_spawn.spawn)(args[0], args[1], {
      ...args[2],
      stdioString: false
    });
    const stdout = Buffer.isBuffer(spawnResult.stdout) ? spawnResult.stdout.toString("utf8") : String(spawnResult.stdout);
    const spawnCwd = typeof args[2]["cwd"] === "string" ? args[2]["cwd"] : void 0;
    result = parseGitDiffStdout(stdout, parseOptions, spawnCwd);
  } catch (e) {
    (0, import_debug.debugNs)(
      "git",
      `Git command failed (${args[0]} ${args[1].join(" ")}): ${e.message}`
    );
    return [];
  }
  if (cache && cacheKey) {
    gitDiffCache.set(cacheKey, result);
  }
  return result;
}
function innerDiffSync(args, options) {
  const { cache = true, ...parseOptions } = { __proto__: null, ...options };
  const cacheKey = cache ? JSON.stringify({ args, parseOptions }) : void 0;
  if (cache && cacheKey) {
    const result2 = gitDiffCache.get(cacheKey);
    if (result2) {
      return result2;
    }
  }
  let result;
  try {
    const spawnResult = (0, import_spawn.spawnSync)(args[0], args[1], {
      ...args[2],
      stdioString: false
    });
    const stdout = Buffer.isBuffer(spawnResult.stdout) ? spawnResult.stdout.toString("utf8") : String(spawnResult.stdout);
    const spawnCwd = typeof args[2]["cwd"] === "string" ? args[2]["cwd"] : void 0;
    result = parseGitDiffStdout(stdout, parseOptions, spawnCwd);
  } catch (e) {
    (0, import_debug.debugNs)(
      "git",
      `Git command failed (${args[0]} ${args[1].join(" ")}): ${e.message}`
    );
    return [];
  }
  if (cache && cacheKey) {
    gitDiffCache.set(cacheKey, result);
  }
  return result;
}
function findGitRoot(startPath) {
  const fs = /* @__PURE__ */ getFs();
  const path2 = /* @__PURE__ */ getPath();
  let currentPath = startPath;
  while (true) {
    try {
      const gitPath = path2.join(currentPath, ".git");
      if (fs.existsSync(gitPath)) {
        return currentPath;
      }
    } catch {
    }
    const parentPath = path2.dirname(currentPath);
    if (parentPath === currentPath) {
      return startPath;
    }
    currentPath = parentPath;
  }
}
function parseGitDiffStdout(stdout, options, spawnCwd) {
  const defaultRoot = spawnCwd ? findGitRoot(spawnCwd) : getCwd();
  const {
    absolute = false,
    cwd: cwdOption = defaultRoot,
    porcelain = false,
    ...matcherOptions
  } = { __proto__: null, ...options };
  const cwd = cwdOption === defaultRoot ? defaultRoot : (/* @__PURE__ */ getFs()).realpathSync(cwdOption);
  const rootPath = defaultRoot;
  let rawFiles = stdout ? (0, import_strings.stripAnsi)(stdout).split("\n").map((line) => line.trimEnd()).filter((line) => line) : [];
  if (porcelain) {
    rawFiles = rawFiles.map((line) => {
      return line.length > 3 ? line.substring(3) : line;
    });
  }
  const files = absolute ? rawFiles.map((relPath2) => (0, import_normalize.normalizePath)(import_path.default.join(rootPath, relPath2))) : rawFiles.map((relPath2) => (0, import_normalize.normalizePath)(relPath2));
  if (cwd === rootPath) {
    return files;
  }
  const relPath = (0, import_normalize.normalizePath)(import_path.default.relative(rootPath, cwd));
  const matcher = (0, import_globs.getGlobMatcher)([`${relPath}/**`], {
    ...matcherOptions,
    absolute,
    cwd: rootPath
  });
  const filtered = [];
  for (const filepath of files) {
    if (matcher(filepath)) {
      filtered.push(filepath);
    }
  }
  return filtered;
}
async function getChangedFiles(options) {
  const args = getGitDiffSpawnArgs(options?.cwd).all;
  return await innerDiff(args, {
    __proto__: null,
    ...options,
    porcelain: true
  });
}
function getChangedFilesSync(options) {
  const args = getGitDiffSpawnArgs(options?.cwd).all;
  return innerDiffSync(args, {
    __proto__: null,
    ...options,
    porcelain: true
  });
}
async function getUnstagedFiles(options) {
  const args = getGitDiffSpawnArgs(options?.cwd).unstaged;
  return await innerDiff(args, options);
}
function getUnstagedFilesSync(options) {
  const args = getGitDiffSpawnArgs(options?.cwd).unstaged;
  return innerDiffSync(args, options);
}
async function getStagedFiles(options) {
  const args = getGitDiffSpawnArgs(options?.cwd).staged;
  return await innerDiff(args, options);
}
function getStagedFilesSync(options) {
  const args = getGitDiffSpawnArgs(options?.cwd).staged;
  return innerDiffSync(args, options);
}
async function isChanged(pathname, options) {
  const files = await getChangedFiles({
    __proto__: null,
    ...options,
    absolute: false
  });
  const resolvedPathname = (/* @__PURE__ */ getFs()).realpathSync(pathname);
  const baseCwd = options?.cwd ? (/* @__PURE__ */ getFs()).realpathSync(options["cwd"]) : getCwd();
  const relativePath = (0, import_normalize.normalizePath)(import_path.default.relative(baseCwd, resolvedPathname));
  return files.includes(relativePath);
}
function isChangedSync(pathname, options) {
  const files = getChangedFilesSync({
    __proto__: null,
    ...options,
    absolute: false
  });
  const resolvedPathname = (/* @__PURE__ */ getFs()).realpathSync(pathname);
  const baseCwd = options?.cwd ? (/* @__PURE__ */ getFs()).realpathSync(options["cwd"]) : getCwd();
  const relativePath = (0, import_normalize.normalizePath)(import_path.default.relative(baseCwd, resolvedPathname));
  return files.includes(relativePath);
}
async function isUnstaged(pathname, options) {
  const files = await getUnstagedFiles({
    __proto__: null,
    ...options,
    absolute: false
  });
  const resolvedPathname = (/* @__PURE__ */ getFs()).realpathSync(pathname);
  const baseCwd = options?.cwd ? (/* @__PURE__ */ getFs()).realpathSync(options["cwd"]) : getCwd();
  const relativePath = (0, import_normalize.normalizePath)(import_path.default.relative(baseCwd, resolvedPathname));
  return files.includes(relativePath);
}
function isUnstagedSync(pathname, options) {
  const files = getUnstagedFilesSync({
    __proto__: null,
    ...options,
    absolute: false
  });
  const resolvedPathname = (/* @__PURE__ */ getFs()).realpathSync(pathname);
  const baseCwd = options?.cwd ? (/* @__PURE__ */ getFs()).realpathSync(options["cwd"]) : getCwd();
  const relativePath = (0, import_normalize.normalizePath)(import_path.default.relative(baseCwd, resolvedPathname));
  return files.includes(relativePath);
}
async function isStaged(pathname, options) {
  const files = await getStagedFiles({
    __proto__: null,
    ...options,
    absolute: false
  });
  const resolvedPathname = (/* @__PURE__ */ getFs()).realpathSync(pathname);
  const baseCwd = options?.cwd ? (/* @__PURE__ */ getFs()).realpathSync(options["cwd"]) : getCwd();
  const relativePath = (0, import_normalize.normalizePath)(import_path.default.relative(baseCwd, resolvedPathname));
  return files.includes(relativePath);
}
function isStagedSync(pathname, options) {
  const files = getStagedFilesSync({
    __proto__: null,
    ...options,
    absolute: false
  });
  const resolvedPathname = (/* @__PURE__ */ getFs()).realpathSync(pathname);
  const baseCwd = options?.cwd ? (/* @__PURE__ */ getFs()).realpathSync(options["cwd"]) : getCwd();
  const relativePath = (0, import_normalize.normalizePath)(import_path.default.relative(baseCwd, resolvedPathname));
  return files.includes(relativePath);
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  findGitRoot,
  getChangedFiles,
  getChangedFilesSync,
  getStagedFiles,
  getStagedFilesSync,
  getUnstagedFiles,
  getUnstagedFilesSync,
  isChanged,
  isChangedSync,
  isStaged,
  isStagedSync,
  isUnstaged,
  isUnstagedSync
});
