@dimm-city/print-md 0.4.1-beta.6 → 0.5.0-rc.1

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.
Files changed (2) hide show
  1. package/dist/cli.js +461 -211
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -22693,7 +22693,7 @@ var package_default;
22693
22693
  var init_package = __esm(() => {
22694
22694
  package_default = {
22695
22695
  name: "@dimm-city/print-md-lib",
22696
- version: "0.4.1-beta.6",
22696
+ version: "0.5.0-rc.1",
22697
22697
  private: true,
22698
22698
  type: "module",
22699
22699
  main: "dist/index.js",
@@ -22724,6 +22724,7 @@ var init_package = __esm(() => {
22724
22724
  },
22725
22725
  dependencies: {
22726
22726
  chokidar: "^5.0.0",
22727
+ diff3: "0.0.3",
22727
22728
  glob: "^13.0.0",
22728
22729
  htmlhint: "^1.9.2",
22729
22730
  "isomorphic-git": "^1.38.4",
@@ -94379,6 +94380,69 @@ var init_diagnostics = __esm(() => {
94379
94380
  });
94380
94381
 
94381
94382
  // ../lib/src/lib/project-source.ts
94383
+ import { stat as stat5, readFile as readFile21 } from "node:fs/promises";
94384
+ import path9 from "node:path";
94385
+ async function isDirectory2(target) {
94386
+ try {
94387
+ return (await stat5(target)).isDirectory();
94388
+ } catch {
94389
+ return false;
94390
+ }
94391
+ }
94392
+ function parseRemoteUrl(configText) {
94393
+ const sectionRe = /\[remote\s+"([^"]+)"\]([^[]*)/g;
94394
+ let firstUrl;
94395
+ let originUrl;
94396
+ let match;
94397
+ while ((match = sectionRe.exec(configText)) !== null) {
94398
+ const name = match[1];
94399
+ const body = match[2] ?? "";
94400
+ const urlMatch = /^\s*url\s*=\s*(.+?)\s*$/m.exec(body);
94401
+ if (!urlMatch)
94402
+ continue;
94403
+ const url = urlMatch[1];
94404
+ if (!url)
94405
+ continue;
94406
+ if (firstUrl === undefined)
94407
+ firstUrl = url;
94408
+ if (name === "origin") {
94409
+ originUrl = url;
94410
+ break;
94411
+ }
94412
+ }
94413
+ return originUrl ?? firstUrl;
94414
+ }
94415
+ function parseHeadBranch(headText) {
94416
+ const match = /^ref:\s*refs\/heads\/(.+?)\s*$/m.exec(headText);
94417
+ return match ? match[1] : undefined;
94418
+ }
94419
+ async function detectProjectSource(folderPath) {
94420
+ const gitDir = path9.join(folderPath, ".git");
94421
+ if (!await isDirectory2(gitDir)) {
94422
+ return { type: "local-folder", path: folderPath };
94423
+ }
94424
+ let remoteUrl;
94425
+ try {
94426
+ const configText = await readFile21(path9.join(gitDir, "config"), "utf8");
94427
+ remoteUrl = parseRemoteUrl(configText);
94428
+ } catch {
94429
+ remoteUrl = undefined;
94430
+ }
94431
+ let branch;
94432
+ try {
94433
+ const headText = await readFile21(path9.join(gitDir, "HEAD"), "utf8");
94434
+ branch = parseHeadBranch(headText);
94435
+ } catch {
94436
+ branch = undefined;
94437
+ }
94438
+ return {
94439
+ type: "local-git-folder",
94440
+ path: folderPath,
94441
+ hasRemote: remoteUrl !== undefined,
94442
+ ...remoteUrl !== undefined ? { remoteUrl } : {},
94443
+ ...branch !== undefined ? { branch } : {}
94444
+ };
94445
+ }
94382
94446
  function capabilitiesFor(source) {
94383
94447
  switch (source.type) {
94384
94448
  case "local-folder":
@@ -96412,20 +96476,20 @@ var require_ignore = __commonJS((exports, module) => {
96412
96476
  var throwError = (message, Ctor) => {
96413
96477
  throw new Ctor(message);
96414
96478
  };
96415
- var checkPath = (path9, originalPath, doThrow) => {
96416
- if (!isString2(path9)) {
96479
+ var checkPath = (path10, originalPath, doThrow) => {
96480
+ if (!isString2(path10)) {
96417
96481
  return doThrow(`path must be a string, but got \`${originalPath}\``, TypeError);
96418
96482
  }
96419
- if (!path9) {
96483
+ if (!path10) {
96420
96484
  return doThrow(`path must not be empty`, TypeError);
96421
96485
  }
96422
- if (checkPath.isNotRelative(path9)) {
96486
+ if (checkPath.isNotRelative(path10)) {
96423
96487
  const r = "`path.relative()`d";
96424
96488
  return doThrow(`path should be a ${r} string, but got "${originalPath}"`, RangeError);
96425
96489
  }
96426
96490
  return true;
96427
96491
  };
96428
- var isNotRelative = (path9) => REGEX_TEST_INVALID_PATH.test(path9);
96492
+ var isNotRelative = (path10) => REGEX_TEST_INVALID_PATH.test(path10);
96429
96493
  checkPath.isNotRelative = isNotRelative;
96430
96494
  checkPath.convert = (p10) => p10;
96431
96495
 
@@ -96468,7 +96532,7 @@ var require_ignore = __commonJS((exports, module) => {
96468
96532
  addPattern(pattern) {
96469
96533
  return this.add(pattern);
96470
96534
  }
96471
- _testOne(path9, checkUnignored) {
96535
+ _testOne(path10, checkUnignored) {
96472
96536
  let ignored = false;
96473
96537
  let unignored = false;
96474
96538
  this._rules.forEach((rule2) => {
@@ -96476,7 +96540,7 @@ var require_ignore = __commonJS((exports, module) => {
96476
96540
  if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
96477
96541
  return;
96478
96542
  }
96479
- const matched = rule2.regex.test(path9);
96543
+ const matched = rule2.regex.test(path10);
96480
96544
  if (matched) {
96481
96545
  ignored = !negative;
96482
96546
  unignored = negative;
@@ -96488,39 +96552,39 @@ var require_ignore = __commonJS((exports, module) => {
96488
96552
  };
96489
96553
  }
96490
96554
  _test(originalPath, cache2, checkUnignored, slices) {
96491
- const path9 = originalPath && checkPath.convert(originalPath);
96492
- checkPath(path9, originalPath, this._allowRelativePaths ? RETURN_FALSE : throwError);
96493
- return this._t(path9, cache2, checkUnignored, slices);
96555
+ const path10 = originalPath && checkPath.convert(originalPath);
96556
+ checkPath(path10, originalPath, this._allowRelativePaths ? RETURN_FALSE : throwError);
96557
+ return this._t(path10, cache2, checkUnignored, slices);
96494
96558
  }
96495
- _t(path9, cache2, checkUnignored, slices) {
96496
- if (path9 in cache2) {
96497
- return cache2[path9];
96559
+ _t(path10, cache2, checkUnignored, slices) {
96560
+ if (path10 in cache2) {
96561
+ return cache2[path10];
96498
96562
  }
96499
96563
  if (!slices) {
96500
- slices = path9.split(SLASH);
96564
+ slices = path10.split(SLASH);
96501
96565
  }
96502
96566
  slices.pop();
96503
96567
  if (!slices.length) {
96504
- return cache2[path9] = this._testOne(path9, checkUnignored);
96568
+ return cache2[path10] = this._testOne(path10, checkUnignored);
96505
96569
  }
96506
96570
  const parent = this._t(slices.join(SLASH) + SLASH, cache2, checkUnignored, slices);
96507
- return cache2[path9] = parent.ignored ? parent : this._testOne(path9, checkUnignored);
96571
+ return cache2[path10] = parent.ignored ? parent : this._testOne(path10, checkUnignored);
96508
96572
  }
96509
- ignores(path9) {
96510
- return this._test(path9, this._ignoreCache, false).ignored;
96573
+ ignores(path10) {
96574
+ return this._test(path10, this._ignoreCache, false).ignored;
96511
96575
  }
96512
96576
  createFilter() {
96513
- return (path9) => !this.ignores(path9);
96577
+ return (path10) => !this.ignores(path10);
96514
96578
  }
96515
96579
  filter(paths) {
96516
96580
  return makeArray(paths).filter(this.createFilter());
96517
96581
  }
96518
- test(path9) {
96519
- return this._test(path9, this._testCache, true);
96582
+ test(path10) {
96583
+ return this._test(path10, this._testCache, true);
96520
96584
  }
96521
96585
  }
96522
96586
  var factory = (options) => new Ignore(options);
96523
- var isPathValid = (path9) => checkPath(path9 && checkPath.convert(path9), path9, RETURN_FALSE);
96587
+ var isPathValid = (path10) => checkPath(path10 && checkPath.convert(path10), path10, RETURN_FALSE);
96524
96588
  factory.isPathValid = isPathValid;
96525
96589
  factory.default = factory;
96526
96590
  module.exports = factory;
@@ -96528,7 +96592,7 @@ var require_ignore = __commonJS((exports, module) => {
96528
96592
  const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
96529
96593
  checkPath.convert = makePosix;
96530
96594
  const REGIX_IS_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
96531
- checkPath.isNotRelative = (path9) => REGIX_IS_WINDOWS_PATH_ABSOLUTE.test(path9) || isNotRelative(path9);
96595
+ checkPath.isNotRelative = (path10) => REGIX_IS_WINDOWS_PATH_ABSOLUTE.test(path10) || isNotRelative(path10);
96532
96596
  }
96533
96597
  });
96534
96598
 
@@ -96565,7 +96629,7 @@ var require_lib3 = __commonJS((exports, module) => {
96565
96629
  // ../../node_modules/.bun/diff3@0.0.3/node_modules/diff3/onp.js
96566
96630
  var require_onp = __commonJS((exports, module) => {
96567
96631
  module.exports = function(a_, b_) {
96568
- var a = a_, b = b_, m = a.length, n = b.length, reverse = false, ed2 = null, offset = m + 1, path9 = [], pathposi = [], ses = [], lcs = "", SES_DELETE = -1, SES_COMMON = 0, SES_ADD = 1;
96632
+ var a = a_, b = b_, m = a.length, n = b.length, reverse = false, ed2 = null, offset = m + 1, path10 = [], pathposi = [], ses = [], lcs = "", SES_DELETE = -1, SES_COMMON = 0, SES_ADD = 1;
96569
96633
  var tmp1, tmp2;
96570
96634
  var init = function() {
96571
96635
  if (m >= n) {
@@ -96595,9 +96659,9 @@ var require_onp = __commonJS((exports, module) => {
96595
96659
  var snake = function(k, p10, pp2) {
96596
96660
  var r, x, y;
96597
96661
  if (p10 > pp2) {
96598
- r = path9[k - 1 + offset];
96662
+ r = path10[k - 1 + offset];
96599
96663
  } else {
96600
- r = path9[k + 1 + offset];
96664
+ r = path10[k + 1 + offset];
96601
96665
  }
96602
96666
  y = Math.max(p10, pp2);
96603
96667
  x = y - k;
@@ -96605,7 +96669,7 @@ var require_onp = __commonJS((exports, module) => {
96605
96669
  ++x;
96606
96670
  ++y;
96607
96671
  }
96608
- path9[k + offset] = pathposi.length;
96672
+ path10[k + offset] = pathposi.length;
96609
96673
  pathposi[pathposi.length] = new P(x, y, r);
96610
96674
  return y;
96611
96675
  };
@@ -96663,7 +96727,7 @@ var require_onp = __commonJS((exports, module) => {
96663
96727
  fp2 = {};
96664
96728
  for (i = 0;i < size; ++i) {
96665
96729
  fp2[i] = -1;
96666
- path9[i] = -1;
96730
+ path10[i] = -1;
96667
96731
  }
96668
96732
  p10 = -1;
96669
96733
  do {
@@ -96677,7 +96741,7 @@ var require_onp = __commonJS((exports, module) => {
96677
96741
  fp2[delta + offset] = snake(delta, fp2[delta - 1 + offset] + 1, fp2[delta + 1 + offset]);
96678
96742
  } while (fp2[delta + offset] !== n);
96679
96743
  ed2 = delta + 2 * p10;
96680
- r = path9[delta + offset];
96744
+ r = path10[delta + offset];
96681
96745
  epc = [];
96682
96746
  while (r !== -1) {
96683
96747
  epc[epc.length] = new P(pathposi[r].x, pathposi[r].y, null);
@@ -97307,17 +97371,17 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
97307
97371
  const length = Math.ceil((62 + bpath.length + 1) / 8) * 8;
97308
97372
  const written = Buffer.alloc(length);
97309
97373
  const writer = new BufferCursor(written);
97310
- const stat5 = normalizeStats(entry);
97311
- writer.writeUInt32BE(stat5.ctimeSeconds);
97312
- writer.writeUInt32BE(stat5.ctimeNanoseconds);
97313
- writer.writeUInt32BE(stat5.mtimeSeconds);
97314
- writer.writeUInt32BE(stat5.mtimeNanoseconds);
97315
- writer.writeUInt32BE(stat5.dev);
97316
- writer.writeUInt32BE(stat5.ino);
97317
- writer.writeUInt32BE(stat5.mode);
97318
- writer.writeUInt32BE(stat5.uid);
97319
- writer.writeUInt32BE(stat5.gid);
97320
- writer.writeUInt32BE(stat5.size);
97374
+ const stat6 = normalizeStats(entry);
97375
+ writer.writeUInt32BE(stat6.ctimeSeconds);
97376
+ writer.writeUInt32BE(stat6.ctimeNanoseconds);
97377
+ writer.writeUInt32BE(stat6.mtimeSeconds);
97378
+ writer.writeUInt32BE(stat6.mtimeNanoseconds);
97379
+ writer.writeUInt32BE(stat6.dev);
97380
+ writer.writeUInt32BE(stat6.ino);
97381
+ writer.writeUInt32BE(stat6.mode);
97382
+ writer.writeUInt32BE(stat6.uid);
97383
+ writer.writeUInt32BE(stat6.gid);
97384
+ writer.writeUInt32BE(stat6.size);
97321
97385
  writer.write(entry.oid, 20, "hex");
97322
97386
  writer.writeUInt16BE(renderCacheEntryFlags(entry));
97323
97387
  writer.write(entry.path, bpath.length, "utf8");
@@ -97362,13 +97426,13 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
97362
97426
  };
97363
97427
  }
97364
97428
  async function updateCachedIndexFile(fs5, filepath, cache2) {
97365
- const [stat5, rawIndexFile] = await Promise.all([
97429
+ const [stat6, rawIndexFile] = await Promise.all([
97366
97430
  fs5.lstat(filepath),
97367
97431
  fs5.read(filepath)
97368
97432
  ]);
97369
97433
  const index2 = await GitIndex.from(rawIndexFile);
97370
97434
  cache2.map.set(filepath, index2);
97371
- cache2.stats.set(filepath, stat5);
97435
+ cache2.stats.set(filepath, stat6);
97372
97436
  }
97373
97437
  async function isIndexStale(fs5, filepath, cache2) {
97374
97438
  const savedStats = cache2.stats.get(filepath);
@@ -97412,20 +97476,20 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
97412
97476
  return result;
97413
97477
  }
97414
97478
  }
97415
- function basename3(path9) {
97416
- const last = Math.max(path9.lastIndexOf("/"), path9.lastIndexOf("\\"));
97479
+ function basename3(path10) {
97480
+ const last = Math.max(path10.lastIndexOf("/"), path10.lastIndexOf("\\"));
97417
97481
  if (last > -1) {
97418
- path9 = path9.slice(last + 1);
97482
+ path10 = path10.slice(last + 1);
97419
97483
  }
97420
- return path9;
97484
+ return path10;
97421
97485
  }
97422
- function dirname6(path9) {
97423
- const last = Math.max(path9.lastIndexOf("/"), path9.lastIndexOf("\\"));
97486
+ function dirname6(path10) {
97487
+ const last = Math.max(path10.lastIndexOf("/"), path10.lastIndexOf("\\"));
97424
97488
  if (last === -1)
97425
97489
  return ".";
97426
97490
  if (last === 0)
97427
97491
  return "/";
97428
- return path9.slice(0, last);
97492
+ return path10.slice(0, last);
97429
97493
  }
97430
97494
  function flatFileListToDirectoryStructure(files) {
97431
97495
  const inodes = new Map;
@@ -97763,15 +97827,15 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
97763
97827
  * SPDX-License-Identifier: LGPL-3.0-or-later
97764
97828
  * Copyright (c) James Prevett and other ZenFS contributors.
97765
97829
  */
97766
- function normalizeString(path9, aar) {
97830
+ function normalizeString(path10, aar) {
97767
97831
  let res = "";
97768
97832
  let lastSegmentLength = 0;
97769
97833
  let lastSlash = -1;
97770
97834
  let dots = 0;
97771
97835
  let char = "\x00";
97772
- for (let i = 0;i <= path9.length; ++i) {
97773
- if (i < path9.length)
97774
- char = path9[i];
97836
+ for (let i = 0;i <= path10.length; ++i) {
97837
+ if (i < path10.length)
97838
+ char = path10[i];
97775
97839
  else if (char === "/")
97776
97840
  break;
97777
97841
  else
@@ -97805,9 +97869,9 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
97805
97869
  }
97806
97870
  } else {
97807
97871
  if (res.length > 0)
97808
- res += "/" + path9.slice(lastSlash + 1, i);
97872
+ res += "/" + path10.slice(lastSlash + 1, i);
97809
97873
  else
97810
- res = path9.slice(lastSlash + 1, i);
97874
+ res = path10.slice(lastSlash + 1, i);
97811
97875
  lastSegmentLength = i - lastSlash - 1;
97812
97876
  }
97813
97877
  lastSlash = i;
@@ -97820,20 +97884,20 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
97820
97884
  }
97821
97885
  return res;
97822
97886
  }
97823
- function normalize2(path9) {
97824
- if (!path9.length)
97887
+ function normalize2(path10) {
97888
+ if (!path10.length)
97825
97889
  return ".";
97826
- const isAbsolute2 = path9[0] === "/";
97827
- const trailingSeparator = path9.at(-1) === "/";
97828
- path9 = normalizeString(path9, !isAbsolute2);
97829
- if (!path9.length) {
97890
+ const isAbsolute2 = path10[0] === "/";
97891
+ const trailingSeparator = path10.at(-1) === "/";
97892
+ path10 = normalizeString(path10, !isAbsolute2);
97893
+ if (!path10.length) {
97830
97894
  if (isAbsolute2)
97831
97895
  return "/";
97832
97896
  return trailingSeparator ? "./" : ".";
97833
97897
  }
97834
97898
  if (trailingSeparator)
97835
- path9 += "/";
97836
- return isAbsolute2 ? `/${path9}` : path9;
97899
+ path10 += "/";
97900
+ return isAbsolute2 ? `/${path10}` : path10;
97837
97901
  }
97838
97902
  function join9(...args) {
97839
97903
  if (args.length === 0)
@@ -97941,8 +98005,8 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
97941
98005
  var getPath = (section, subsection, name) => {
97942
98006
  return [lower(section), subsection, lower(name)].filter((a) => a != null).join(".");
97943
98007
  };
97944
- var normalizePath = (path9) => {
97945
- const pathSegments = path9.split(".");
98008
+ var normalizePath = (path10) => {
98009
+ const pathSegments = path10.split(".");
97946
98010
  const section = pathSegments.shift();
97947
98011
  const name = pathSegments.pop();
97948
98012
  const subsection = pathSegments.length ? pathSegments.join(".") : undefined;
@@ -97981,23 +98045,23 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
97981
98045
  [name, value] = extractedVariable;
97982
98046
  }
97983
98047
  }
97984
- const path9 = getPath(section, subsection, name);
97985
- return { line, isSection, section, subsection, name, value, path: path9 };
98048
+ const path10 = getPath(section, subsection, name);
98049
+ return { line, isSection, section, subsection, name, value, path: path10 };
97986
98050
  }) : [];
97987
98051
  }
97988
98052
  static from(text4) {
97989
98053
  return new GitConfig(text4);
97990
98054
  }
97991
- async get(path9, getall = false) {
97992
- const normalizedPath = normalizePath(path9).path;
98055
+ async get(path10, getall = false) {
98056
+ const normalizedPath = normalizePath(path10).path;
97993
98057
  const allValues = this.parsedConfig.filter((config) => config.path === normalizedPath).map(({ section, name, value }) => {
97994
98058
  const fn2 = schema[section] && schema[section][name];
97995
98059
  return fn2 ? fn2(value) : value;
97996
98060
  });
97997
98061
  return getall ? allValues : allValues.pop();
97998
98062
  }
97999
- async getall(path9) {
98000
- return this.get(path9, true);
98063
+ async getall(path10) {
98064
+ return this.get(path10, true);
98001
98065
  }
98002
98066
  async getSubsections(section) {
98003
98067
  return this.parsedConfig.filter((config) => config.isSection && config.section === section).map((config) => config.subsection);
@@ -98005,10 +98069,10 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
98005
98069
  async deleteSection(section, subsection) {
98006
98070
  this.parsedConfig = this.parsedConfig.filter((config) => !(config.section === section && config.subsection === subsection));
98007
98071
  }
98008
- async append(path9, value) {
98009
- return this.set(path9, value, true);
98072
+ async append(path10, value) {
98073
+ return this.set(path10, value, true);
98010
98074
  }
98011
- async set(path9, value, append = false) {
98075
+ async set(path10, value, append = false) {
98012
98076
  const {
98013
98077
  section,
98014
98078
  subsection,
@@ -98016,7 +98080,7 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
98016
98080
  path: normalizedPath,
98017
98081
  sectionPath,
98018
98082
  isSection
98019
- } = normalizePath(path9);
98083
+ } = normalizePath(path10);
98020
98084
  const configIndex = findLastIndex(this.parsedConfig, (config) => config.path === normalizedPath);
98021
98085
  if (value == null) {
98022
98086
  if (configIndex !== -1) {
@@ -98389,13 +98453,13 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
98389
98453
  if (mode === "40000")
98390
98454
  mode = "040000";
98391
98455
  const type = mode2type$1(mode);
98392
- const path9 = buffer.slice(space + 1, nullchar).toString("utf8");
98393
- if (path9.includes("\\") || path9.includes("/")) {
98394
- throw new UnsafeFilepathError(path9);
98456
+ const path10 = buffer.slice(space + 1, nullchar).toString("utf8");
98457
+ if (path10.includes("\\") || path10.includes("/")) {
98458
+ throw new UnsafeFilepathError(path10);
98395
98459
  }
98396
98460
  const oid = buffer.slice(nullchar + 1, nullchar + 21).toString("hex");
98397
98461
  cursor = nullchar + 21;
98398
- _entries.push({ mode, path: path9, oid, type });
98462
+ _entries.push({ mode, path: path10, oid, type });
98399
98463
  }
98400
98464
  return _entries;
98401
98465
  }
@@ -98450,10 +98514,10 @@ If you're a developer and you believe this is a bug in isomorphic-git, please fi
98450
98514
  return Buffer.concat(entries.map((entry) => {
98451
98515
  const mode = Buffer.from(entry.mode.replace(/^0/, ""));
98452
98516
  const space = Buffer.from(" ");
98453
- const path9 = Buffer.from(entry.path, "utf8");
98517
+ const path10 = Buffer.from(entry.path, "utf8");
98454
98518
  const nullchar = Buffer.from([0]);
98455
98519
  const oid = Buffer.from(entry.oid, "hex");
98456
- return Buffer.concat([mode, space, path9, nullchar, oid]);
98520
+ return Buffer.concat([mode, space, path10, nullchar, oid]);
98457
98521
  }));
98458
98522
  }
98459
98523
  entries() {
@@ -100035,21 +100099,21 @@ gpgsig`));
100035
100099
  async stat(entry) {
100036
100100
  if (entry._stat === false) {
100037
100101
  const { fs: fs5, dir } = this;
100038
- let stat5 = await fs5.lstat(`${dir}/${entry._fullpath}`);
100039
- if (!stat5) {
100102
+ let stat6 = await fs5.lstat(`${dir}/${entry._fullpath}`);
100103
+ if (!stat6) {
100040
100104
  throw new Error(`ENOENT: no such file or directory, lstat '${entry._fullpath}'`);
100041
100105
  }
100042
- let type = stat5.isDirectory() ? "tree" : "blob";
100043
- if (type === "blob" && !stat5.isFile() && !stat5.isSymbolicLink()) {
100106
+ let type = stat6.isDirectory() ? "tree" : "blob";
100107
+ if (type === "blob" && !stat6.isFile() && !stat6.isSymbolicLink()) {
100044
100108
  type = "special";
100045
100109
  }
100046
100110
  entry._type = type;
100047
- stat5 = normalizeStats(stat5);
100048
- entry._mode = stat5.mode;
100049
- if (stat5.size === -1 && entry._actualSize) {
100050
- stat5.size = entry._actualSize;
100111
+ stat6 = normalizeStats(stat6);
100112
+ entry._mode = stat6.mode;
100113
+ if (stat6.size === -1 && entry._actualSize) {
100114
+ stat6.size = entry._actualSize;
100051
100115
  }
100052
- entry._stat = stat5;
100116
+ entry._stat = stat6;
100053
100117
  }
100054
100118
  return entry._stat;
100055
100119
  }
@@ -100237,10 +100301,10 @@ gpgsig`));
100237
100301
  } else if (entries.length) {
100238
100302
  await Promise.all(entries.map((entry) => {
100239
100303
  const subpath = join9(filepath, entry);
100240
- return fs5.lstat(subpath).then((stat5) => {
100241
- if (!stat5)
100304
+ return fs5.lstat(subpath).then((stat6) => {
100305
+ if (!stat6)
100242
100306
  return;
100243
- return stat5.isDirectory() ? rmRecursive(fs5, subpath) : fs5.rm(subpath);
100307
+ return stat6.isDirectory() ? rmRecursive(fs5, subpath) : fs5.rm(subpath);
100244
100308
  });
100245
100309
  })).then(() => fs5.rmdir(filepath));
100246
100310
  } else {
@@ -100510,13 +100574,13 @@ gpgsig`));
100510
100574
  dir,
100511
100575
  gitdir: updatedGitdir,
100512
100576
  trees,
100513
- map: async function(path9, [head, workdir, index2]) {
100577
+ map: async function(path10, [head, workdir, index2]) {
100514
100578
  const staged = !await modified(workdir, index2);
100515
- const unmerged = unmergedPaths.includes(path9);
100579
+ const unmerged = unmergedPaths.includes(path10);
100516
100580
  const unmodified = !await modified(index2, head);
100517
100581
  if (staged || unmerged) {
100518
100582
  return head ? {
100519
- path: path9,
100583
+ path: path10,
100520
100584
  mode: await head.mode(),
100521
100585
  oid: await head.oid(),
100522
100586
  type: await head.type(),
@@ -100526,7 +100590,7 @@ gpgsig`));
100526
100590
  if (unmodified)
100527
100591
  return false;
100528
100592
  else
100529
- throw new IndexResetError(path9);
100593
+ throw new IndexResetError(path10);
100530
100594
  }
100531
100595
  });
100532
100596
  await GitIndexManager.acquire({ fs: fs5, gitdir: updatedGitdir, cache: cache2 }, async function(index2) {
@@ -100772,9 +100836,9 @@ gpgsig`));
100772
100836
  const fulfilledPromises = settledPromises.filter((settle) => settle.status === "fulfilled" && settle.value).map((settle) => settle.value);
100773
100837
  return fulfilledPromises;
100774
100838
  }
100775
- async function _getConfig({ fs: fs5, gitdir, path: path9 }) {
100839
+ async function _getConfig({ fs: fs5, gitdir, path: path10 }) {
100776
100840
  const config = await GitConfigManager.get({ fs: fs5, gitdir });
100777
- return config.get(path9);
100841
+ return config.get(path10);
100778
100842
  }
100779
100843
  function assignDefined(target, ...sources) {
100780
100844
  for (const source of sources) {
@@ -102064,14 +102128,14 @@ gpgsig`));
102064
102128
  gitdir,
102065
102129
  trees: [ourTree, baseTree, theirTree],
102066
102130
  map: async function(filepath, [ours, base, theirs]) {
102067
- const path9 = basename3(filepath);
102131
+ const path10 = basename3(filepath);
102068
102132
  const ourChange = await modified(ours, base);
102069
102133
  const theirChange = await modified(theirs, base);
102070
102134
  switch (`${ourChange}-${theirChange}`) {
102071
102135
  case "false-false": {
102072
102136
  return {
102073
102137
  mode: await base.mode(),
102074
- path: path9,
102138
+ path: path10,
102075
102139
  oid: await base.oid(),
102076
102140
  type: await base.type()
102077
102141
  };
@@ -102080,14 +102144,14 @@ gpgsig`));
102080
102144
  if (!theirs && await ours.type() === "tree") {
102081
102145
  return {
102082
102146
  mode: await ours.mode(),
102083
- path: path9,
102147
+ path: path10,
102084
102148
  oid: await ours.oid(),
102085
102149
  type: await ours.type()
102086
102150
  };
102087
102151
  }
102088
102152
  return theirs ? {
102089
102153
  mode: await theirs.mode(),
102090
- path: path9,
102154
+ path: path10,
102091
102155
  oid: await theirs.oid(),
102092
102156
  type: await theirs.type()
102093
102157
  } : undefined;
@@ -102096,14 +102160,14 @@ gpgsig`));
102096
102160
  if (!ours && await theirs.type() === "tree") {
102097
102161
  return {
102098
102162
  mode: await theirs.mode(),
102099
- path: path9,
102163
+ path: path10,
102100
102164
  oid: await theirs.oid(),
102101
102165
  type: await theirs.type()
102102
102166
  };
102103
102167
  }
102104
102168
  return ours ? {
102105
102169
  mode: await ours.mode(),
102106
- path: path9,
102170
+ path: path10,
102107
102171
  oid: await ours.oid(),
102108
102172
  type: await ours.type()
102109
102173
  } : undefined;
@@ -102112,7 +102176,7 @@ gpgsig`));
102112
102176
  if (ours && theirs && await ours.type() === "tree" && await theirs.type() === "tree") {
102113
102177
  return {
102114
102178
  mode: await ours.mode(),
102115
- path: path9,
102179
+ path: path10,
102116
102180
  oid: await ours.oid(),
102117
102181
  type: "tree"
102118
102182
  };
@@ -102121,7 +102185,7 @@ gpgsig`));
102121
102185
  return mergeBlobs({
102122
102186
  fs: fs5,
102123
102187
  gitdir,
102124
- path: path9,
102188
+ path: path10,
102125
102189
  ours,
102126
102190
  base,
102127
102191
  theirs,
@@ -102167,7 +102231,7 @@ gpgsig`));
102167
102231
  mode: await theirs.mode(),
102168
102232
  oid: await theirs.oid(),
102169
102233
  type: "blob",
102170
- path: path9
102234
+ path: path10
102171
102235
  };
102172
102236
  }
102173
102237
  if (base && ours && !theirs && await base.type() === "blob" && await ours.type() === "blob") {
@@ -102184,7 +102248,7 @@ gpgsig`));
102184
102248
  mode: await ours.mode(),
102185
102249
  oid: await ours.oid(),
102186
102250
  type: "blob",
102187
- path: path9
102251
+ path: path10
102188
102252
  };
102189
102253
  }
102190
102254
  if (base && !ours && !theirs && (await base.type() === "blob" || await base.type() === "tree")) {
@@ -102224,11 +102288,11 @@ gpgsig`));
102224
102288
  gitdir,
102225
102289
  trees: [TREE({ ref: results.oid })],
102226
102290
  map: async function(filepath, [entry]) {
102227
- const path9 = `${dir}/${filepath}`;
102291
+ const path10 = `${dir}/${filepath}`;
102228
102292
  if (await entry.type() === "blob") {
102229
102293
  const mode = await entry.mode();
102230
102294
  const content4 = new TextDecoder().decode(await entry.content());
102231
- await fs5.write(path9, content4, { mode });
102295
+ await fs5.write(path10, content4, { mode });
102232
102296
  }
102233
102297
  return true;
102234
102298
  }
@@ -102241,7 +102305,7 @@ gpgsig`));
102241
102305
  async function mergeBlobs({
102242
102306
  fs: fs5,
102243
102307
  gitdir,
102244
- path: path9,
102308
+ path: path10,
102245
102309
  ours,
102246
102310
  base,
102247
102311
  theirs,
@@ -102264,19 +102328,19 @@ gpgsig`));
102264
102328
  if (await ours.oid() === await theirs.oid()) {
102265
102329
  return {
102266
102330
  cleanMerge: true,
102267
- mergeResult: { mode, path: path9, oid: await ours.oid(), type }
102331
+ mergeResult: { mode, path: path10, oid: await ours.oid(), type }
102268
102332
  };
102269
102333
  }
102270
102334
  if (await ours.oid() === baseOid) {
102271
102335
  return {
102272
102336
  cleanMerge: true,
102273
- mergeResult: { mode, path: path9, oid: await theirs.oid(), type }
102337
+ mergeResult: { mode, path: path10, oid: await theirs.oid(), type }
102274
102338
  };
102275
102339
  }
102276
102340
  if (await theirs.oid() === baseOid) {
102277
102341
  return {
102278
102342
  cleanMerge: true,
102279
- mergeResult: { mode, path: path9, oid: await ours.oid(), type }
102343
+ mergeResult: { mode, path: path10, oid: await ours.oid(), type }
102280
102344
  };
102281
102345
  }
102282
102346
  const ourContent = Buffer.from(await ours.content()).toString("utf8");
@@ -102284,7 +102348,7 @@ gpgsig`));
102284
102348
  const { mergedText, cleanMerge } = await mergeDriver({
102285
102349
  branches: [baseName, ourName, theirName],
102286
102350
  contents: [baseContent, ourContent, theirContent],
102287
- path: path9
102351
+ path: path10
102288
102352
  });
102289
102353
  const oid = await _writeObject({
102290
102354
  fs: fs5,
@@ -102293,7 +102357,7 @@ gpgsig`));
102293
102357
  object: Buffer.from(mergedText, "utf8"),
102294
102358
  dryRun
102295
102359
  });
102296
- return { cleanMerge, mergeResult: { mode, path: path9, oid, type } };
102360
+ return { cleanMerge, mergeResult: { mode, path: path10, oid, type } };
102297
102361
  }
102298
102362
  var _TreeMap = {
102299
102363
  stage: STAGE,
@@ -102997,7 +103061,7 @@ gpgsig`));
102997
103061
  const remoteHelpers = new Map;
102998
103062
  remoteHelpers.set("http", GitRemoteHTTP);
102999
103063
  remoteHelpers.set("https", GitRemoteHTTP);
103000
- const parts = parseRemoteUrl({ url });
103064
+ const parts = parseRemoteUrl2({ url });
103001
103065
  if (!parts) {
103002
103066
  throw new UrlParseError(url);
103003
103067
  }
@@ -103007,7 +103071,7 @@ gpgsig`));
103007
103071
  throw new UnknownTransportError(url, parts.transport, parts.transport === "ssh" ? translateSSHtoHTTP(url) : undefined);
103008
103072
  }
103009
103073
  }
103010
- function parseRemoteUrl({ url }) {
103074
+ function parseRemoteUrl2({ url }) {
103011
103075
  if (url.startsWith("git@")) {
103012
103076
  return {
103013
103077
  transport: "ssh",
@@ -104464,43 +104528,43 @@ gpgsig`));
104464
104528
  throw err;
104465
104529
  }
104466
104530
  }
104467
- async function getConfig({ fs: fs5, dir, gitdir = join9(dir, ".git"), path: path9 }) {
104531
+ async function getConfig({ fs: fs5, dir, gitdir = join9(dir, ".git"), path: path10 }) {
104468
104532
  try {
104469
104533
  assertParameter("fs", fs5);
104470
104534
  assertParameter("gitdir", gitdir);
104471
- assertParameter("path", path9);
104535
+ assertParameter("path", path10);
104472
104536
  const fsp3 = new FileSystem(fs5);
104473
104537
  const updatedGitdir = await discoverGitdir({ fsp: fsp3, dotgit: gitdir });
104474
104538
  return await _getConfig({
104475
104539
  fs: fsp3,
104476
104540
  gitdir: updatedGitdir,
104477
- path: path9
104541
+ path: path10
104478
104542
  });
104479
104543
  } catch (err) {
104480
104544
  err.caller = "git.getConfig";
104481
104545
  throw err;
104482
104546
  }
104483
104547
  }
104484
- async function _getConfigAll({ fs: fs5, gitdir, path: path9 }) {
104548
+ async function _getConfigAll({ fs: fs5, gitdir, path: path10 }) {
104485
104549
  const config = await GitConfigManager.get({ fs: fs5, gitdir });
104486
- return config.getall(path9);
104550
+ return config.getall(path10);
104487
104551
  }
104488
104552
  async function getConfigAll({
104489
104553
  fs: fs5,
104490
104554
  dir,
104491
104555
  gitdir = join9(dir, ".git"),
104492
- path: path9
104556
+ path: path10
104493
104557
  }) {
104494
104558
  try {
104495
104559
  assertParameter("fs", fs5);
104496
104560
  assertParameter("gitdir", gitdir);
104497
- assertParameter("path", path9);
104561
+ assertParameter("path", path10);
104498
104562
  const fsp3 = new FileSystem(fs5);
104499
104563
  const updatedGitdir = await discoverGitdir({ fsp: fsp3, dotgit: gitdir });
104500
104564
  return await _getConfigAll({
104501
104565
  fs: fsp3,
104502
104566
  gitdir: updatedGitdir,
104503
- path: path9
104567
+ path: path10
104504
104568
  });
104505
104569
  } catch (err) {
104506
104570
  err.caller = "git.getConfigAll";
@@ -106529,21 +106593,21 @@ gpgsig`));
106529
106593
  fs: _fs,
106530
106594
  dir,
106531
106595
  gitdir = join9(dir, ".git"),
106532
- path: path9,
106596
+ path: path10,
106533
106597
  value,
106534
106598
  append = false
106535
106599
  }) {
106536
106600
  try {
106537
106601
  assertParameter("fs", _fs);
106538
106602
  assertParameter("gitdir", gitdir);
106539
- assertParameter("path", path9);
106603
+ assertParameter("path", path10);
106540
106604
  const fs5 = new FileSystem(_fs);
106541
106605
  const updatedGitdir = await discoverGitdir({ fsp: fs5, dotgit: gitdir });
106542
106606
  const config = await GitConfigManager.get({ fs: fs5, gitdir: updatedGitdir });
106543
106607
  if (append) {
106544
- await config.append(path9, value);
106608
+ await config.append(path10, value);
106545
106609
  } else {
106546
- await config.set(path9, value);
106610
+ await config.set(path10, value);
106547
106611
  }
106548
106612
  await GitConfigManager.save({ fs: fs5, gitdir: updatedGitdir, config });
106549
106613
  } catch (err) {
@@ -106837,9 +106901,9 @@ gpgsig`));
106837
106901
  const stashMgr = new GitStashManager({ fs: fs5, dir, gitdir });
106838
106902
  const stashRefPath = [stashMgr.refStashPath, stashMgr.refLogsStashPath];
106839
106903
  await acquireLock$1(stashRefPath, async () => {
106840
- await Promise.all(stashRefPath.map(async (path9) => {
106841
- if (await fs5.exists(path9)) {
106842
- return fs5.rm(path9);
106904
+ await Promise.all(stashRefPath.map(async (path10) => {
106905
+ if (await fs5.exists(path10)) {
106906
+ return fs5.rm(path10);
106843
106907
  }
106844
106908
  }));
106845
106909
  });
@@ -106992,13 +107056,13 @@ gpgsig`));
106992
107056
  throw err;
106993
107057
  }
106994
107058
  }
106995
- async function getOidAtPath({ fs: fs5, cache: cache2, gitdir: updatedGitdir, tree, path: path9 }) {
106996
- if (typeof path9 === "string")
106997
- path9 = path9.split("/");
106998
- const dirname7 = path9.shift();
107059
+ async function getOidAtPath({ fs: fs5, cache: cache2, gitdir: updatedGitdir, tree, path: path10 }) {
107060
+ if (typeof path10 === "string")
107061
+ path10 = path10.split("/");
107062
+ const dirname7 = path10.shift();
106999
107063
  for (const entry of tree) {
107000
107064
  if (entry.path === dirname7) {
107001
- if (path9.length === 0) {
107065
+ if (path10.length === 0) {
107002
107066
  return entry.oid;
107003
107067
  }
107004
107068
  const { type, object } = await _readObject({
@@ -107009,10 +107073,10 @@ gpgsig`));
107009
107073
  });
107010
107074
  if (type === "tree") {
107011
107075
  const tree2 = GitTree.from(object);
107012
- return getOidAtPath({ fs: fs5, cache: cache2, gitdir: updatedGitdir, tree: tree2, path: path9 });
107076
+ return getOidAtPath({ fs: fs5, cache: cache2, gitdir: updatedGitdir, tree: tree2, path: path10 });
107013
107077
  }
107014
107078
  if (type === "blob") {
107015
- throw new ObjectTypeError(entry.oid, type, "blob", path9.join("/"));
107079
+ throw new ObjectTypeError(entry.oid, type, "blob", path10.join("/"));
107016
107080
  }
107017
107081
  }
107018
107082
  }
@@ -107597,11 +107661,26 @@ gpgsig`));
107597
107661
  // ../lib/src/lib/source-provider.ts
107598
107662
  var exports_source_provider = {};
107599
107663
  __export(exports_source_provider, {
107664
+ withRepoLock: () => withRepoLock,
107665
+ snapshotWorkingTreeUnlocked: () => snapshotWorkingTreeUnlocked,
107666
+ restoreVersionWithBackup: () => restoreVersionWithBackup,
107600
107667
  providerFor: () => providerFor,
107601
- gitDirFor: () => gitDirFor
107668
+ hasPendingChanges: () => hasPendingChanges,
107669
+ gitDirFor: () => gitDirFor,
107670
+ gitAuthor: () => gitAuthor,
107671
+ RESTORE_BACKUP_MESSAGE: () => RESTORE_BACKUP_MESSAGE
107602
107672
  });
107603
107673
  import * as fs5 from "node:fs";
107604
- import path9 from "node:path";
107674
+ import path10 from "node:path";
107675
+ function withRepoLock(projectDir, fn2) {
107676
+ const key = path10.resolve(projectDir);
107677
+ const prev = repoQueues.get(key) ?? Promise.resolve();
107678
+ const run2 = prev.then(fn2, fn2);
107679
+ repoQueues.set(key, run2.catch(() => {
107680
+ return;
107681
+ }));
107682
+ return run2;
107683
+ }
107605
107684
  function gitAuthor(name) {
107606
107685
  const n = (name ?? "").trim();
107607
107686
  return { name: n || DEFAULT_AUTHOR, email: DEFAULT_EMAIL };
@@ -107610,6 +107689,10 @@ async function stageAll(dir) {
107610
107689
  const status = await import_isomorphic_git.default.statusMatrix({ fs: fs5, dir });
107611
107690
  await Promise.all(status.map(([filepath, , worktreeStatus]) => worktreeStatus === 0 ? import_isomorphic_git.default.remove({ fs: fs5, dir, filepath }) : import_isomorphic_git.default.add({ fs: fs5, dir, filepath })));
107612
107691
  }
107692
+ async function hasPendingChanges(dir) {
107693
+ const status = await import_isomorphic_git.default.statusMatrix({ fs: fs5, dir });
107694
+ return status.some(([, head, worktree, stage]) => !(head === 1 && worktree === 1 && stage === 1));
107695
+ }
107613
107696
 
107614
107697
  class LocalFolderSourceProvider {
107615
107698
  source;
@@ -107618,22 +107701,24 @@ class LocalFolderSourceProvider {
107618
107701
  this.source = source;
107619
107702
  this.capabilities = capabilitiesFor(source);
107620
107703
  }
107621
- async initVersionHistory(options) {
107704
+ initVersionHistory(options) {
107622
107705
  const dir = options.projectDir;
107623
- await import_isomorphic_git.default.init({ fs: fs5, dir, defaultBranch: DEFAULT_BRANCH });
107624
- await stageAll(dir);
107625
- await import_isomorphic_git.default.commit({
107626
- fs: fs5,
107627
- dir,
107628
- message: options.initialMessage?.trim() || "Created project",
107629
- author: gitAuthor(options.authorName)
107706
+ return withRepoLock(dir, async () => {
107707
+ await import_isomorphic_git.default.init({ fs: fs5, dir, defaultBranch: DEFAULT_BRANCH });
107708
+ await stageAll(dir);
107709
+ await import_isomorphic_git.default.commit({
107710
+ fs: fs5,
107711
+ dir,
107712
+ message: options.initialMessage?.trim() || "Created project",
107713
+ author: gitAuthor(options.authorName)
107714
+ });
107715
+ return {
107716
+ type: "local-git-folder",
107717
+ path: dir,
107718
+ hasRemote: false,
107719
+ branch: DEFAULT_BRANCH
107720
+ };
107630
107721
  });
107631
- return {
107632
- type: "local-git-folder",
107633
- path: dir,
107634
- hasRemote: false,
107635
- branch: DEFAULT_BRANCH
107636
- };
107637
107722
  }
107638
107723
  snapshot() {
107639
107724
  return Promise.reject(new Error("This project has no version history yet. Enable version history first."));
@@ -107654,42 +107739,39 @@ class LocalGitSourceProvider {
107654
107739
  this.capabilities = capabilitiesFor(source);
107655
107740
  }
107656
107741
  async initVersionHistory(options) {
107657
- await this.snapshot({
107658
- projectDir: options.projectDir,
107659
- message: options.initialMessage?.trim() || "Created project",
107660
- authorName: options.authorName
107661
- }).catch(() => {
107662
- return;
107663
- });
107742
+ try {
107743
+ await this.snapshot({
107744
+ projectDir: options.projectDir,
107745
+ message: options.initialMessage?.trim() || "Created project",
107746
+ authorName: options.authorName
107747
+ });
107748
+ } catch (e) {
107749
+ if (!isNoChangesError(e))
107750
+ throw e;
107751
+ }
107664
107752
  return this.source;
107665
107753
  }
107666
- async snapshot(options) {
107667
- const dir = options.projectDir;
107668
- await stageAll(dir);
107669
- const author = gitAuthor(options.authorName);
107670
- const id2 = await import_isomorphic_git.default.commit({
107671
- fs: fs5,
107672
- dir,
107673
- message: options.message,
107674
- author
107754
+ snapshot(options) {
107755
+ return withRepoLock(options.projectDir, () => this.snapshotUnlocked(options));
107756
+ }
107757
+ snapshotUnlocked(options) {
107758
+ return snapshotWorkingTreeUnlocked(options);
107759
+ }
107760
+ listHistory(projectDir) {
107761
+ return withRepoLock(projectDir, async () => {
107762
+ const commits = await import_isomorphic_git.default.log({ fs: fs5, dir: projectDir });
107763
+ return commits.map((c) => ({
107764
+ id: c.oid,
107765
+ message: c.commit.message.trim(),
107766
+ timestamp: c.commit.author.timestamp * 1000,
107767
+ author: c.commit.author.name
107768
+ }));
107675
107769
  });
107676
- return {
107677
- id: id2,
107678
- message: options.message,
107679
- timestamp: Date.now(),
107680
- author: author.name
107681
- };
107682
- }
107683
- async listHistory(projectDir) {
107684
- const commits = await import_isomorphic_git.default.log({ fs: fs5, dir: projectDir });
107685
- return commits.map((c) => ({
107686
- id: c.oid,
107687
- message: c.commit.message.trim(),
107688
- timestamp: c.commit.author.timestamp * 1000,
107689
- author: c.commit.author.name
107690
- }));
107691
107770
  }
107692
- async restore(options) {
107771
+ restore(options) {
107772
+ return withRepoLock(options.projectDir, () => this.restoreUnlocked(options));
107773
+ }
107774
+ async restoreUnlocked(options) {
107693
107775
  await import_isomorphic_git.default.checkout({
107694
107776
  fs: fs5,
107695
107777
  dir: options.projectDir,
@@ -107699,6 +107781,30 @@ class LocalGitSourceProvider {
107699
107781
  });
107700
107782
  }
107701
107783
  }
107784
+ async function snapshotWorkingTreeUnlocked(options) {
107785
+ const dir = options.projectDir;
107786
+ if (!await hasPendingChanges(dir)) {
107787
+ throw new Error("No changes since the last snapshot — there is nothing new to save.");
107788
+ }
107789
+ await stageAll(dir);
107790
+ const author = gitAuthor(options.authorName);
107791
+ const id2 = await import_isomorphic_git.default.commit({
107792
+ fs: fs5,
107793
+ dir,
107794
+ message: options.message,
107795
+ author
107796
+ });
107797
+ const [head] = await import_isomorphic_git.default.log({ fs: fs5, dir, depth: 1 });
107798
+ return {
107799
+ id: id2,
107800
+ message: options.message,
107801
+ timestamp: head ? head.commit.author.timestamp * 1000 : Date.now(),
107802
+ author: author.name
107803
+ };
107804
+ }
107805
+ function isNoChangesError(e) {
107806
+ return e instanceof Error && /no changes since the last snapshot/i.test(e.message);
107807
+ }
107702
107808
  function providerFor(source) {
107703
107809
  switch (source.type) {
107704
107810
  case "local-folder":
@@ -107710,18 +107816,44 @@ function providerFor(source) {
107710
107816
  }
107711
107817
  }
107712
107818
  function gitDirFor(projectDir) {
107713
- return path9.join(projectDir, ".git");
107819
+ return path10.join(projectDir, ".git");
107820
+ }
107821
+ async function restoreVersionWithBackup(options) {
107822
+ const { projectDir, id: id2, authorName } = options;
107823
+ const source = await detectProjectSource(projectDir);
107824
+ if (source.type !== "local-git-folder") {
107825
+ throw new Error("This project has no version history yet. Enable version history first.");
107826
+ }
107827
+ const provider = new LocalGitSourceProvider(source);
107828
+ return withRepoLock(projectDir, async () => {
107829
+ let backupId;
107830
+ if (await hasPendingChanges(projectDir)) {
107831
+ const backup = await provider.snapshotUnlocked({
107832
+ projectDir,
107833
+ message: RESTORE_BACKUP_MESSAGE,
107834
+ authorName
107835
+ });
107836
+ backupId = backup.id;
107837
+ }
107838
+ try {
107839
+ await provider.restoreUnlocked({ projectDir, id: id2 });
107840
+ } catch (cause) {
107841
+ throw new Error(backupId ? "The restore could not be completed, but your work is safe — it was " + `automatically saved as a backup snapshot (${backupId.slice(0, 7)}) ` + "and appears in your version history." : "The restore could not be completed. Your project files were not changed.", { cause });
107842
+ }
107843
+ return { restoredId: id2, backupId };
107844
+ });
107714
107845
  }
107715
- var import_isomorphic_git, DEFAULT_AUTHOR = "print-md", DEFAULT_EMAIL = "noreply@print-md.local", DEFAULT_BRANCH = "main";
107846
+ var import_isomorphic_git, DEFAULT_AUTHOR = "print-md", DEFAULT_EMAIL = "noreply@print-md.local", DEFAULT_BRANCH = "main", repoQueues, RESTORE_BACKUP_MESSAGE = "Automatic backup before restoring an earlier version";
107716
107847
  var init_source_provider = __esm(() => {
107717
107848
  init_project_source();
107718
107849
  import_isomorphic_git = __toESM(require_isomorphic_git(), 1);
107850
+ repoQueues = new Map;
107719
107851
  });
107720
107852
 
107721
107853
  // ../lib/src/lib/project-scaffold.ts
107722
- import { access as access2, copyFile as copyFile2, mkdir as mkdir6, readFile as readFile21, writeFile as writeFile7 } from "node:fs/promises";
107854
+ import { access as access2, copyFile as copyFile2, mkdir as mkdir6, readFile as readFile22, writeFile as writeFile7 } from "node:fs/promises";
107723
107855
  import { constants as FS } from "node:fs";
107724
- import path10 from "node:path";
107856
+ import path11 from "node:path";
107725
107857
  function slugifyProjectName(name) {
107726
107858
  return name.normalize("NFKD").replace(/[̀-ͯ]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
107727
107859
  }
@@ -107739,7 +107871,7 @@ async function scaffoldProject(options) {
107739
107871
  throw new CreateProjectErrorImpl("invalid-name", `Could not derive a valid folder name from "${name}".`);
107740
107872
  }
107741
107873
  const parentDir = options.parentDir;
107742
- if (!parentDir || !path10.isAbsolute(parentDir)) {
107874
+ if (!parentDir || !path11.isAbsolute(parentDir)) {
107743
107875
  throw new CreateProjectErrorImpl("parent-not-writable", "The save location must be an absolute path.");
107744
107876
  }
107745
107877
  try {
@@ -107747,7 +107879,7 @@ async function scaffoldProject(options) {
107747
107879
  } catch {
107748
107880
  throw new CreateProjectErrorImpl("parent-not-writable", `The chosen save location can't be written to: ${parentDir}`);
107749
107881
  }
107750
- const projectDir = path10.join(parentDir, folderName);
107882
+ const projectDir = path11.join(parentDir, folderName);
107751
107883
  let targetExists = true;
107752
107884
  try {
107753
107885
  await access2(projectDir, FS.F_OK);
@@ -107762,14 +107894,14 @@ async function scaffoldProject(options) {
107762
107894
  const tplManifest = await getAssetPath(`templates/${template}/manifest.yaml`);
107763
107895
  const tplChapter = await getAssetPath(`templates/${template}/chapter-01.md`);
107764
107896
  await mkdir6(projectDir, { recursive: true });
107765
- await mkdir6(path10.join(projectDir, "assets"), { recursive: true });
107766
- await copyFile2(tplManifest, path10.join(projectDir, "manifest.yaml"));
107767
- await copyFile2(tplChapter, path10.join(projectDir, "chapter-01.md"));
107897
+ await mkdir6(path11.join(projectDir, "assets"), { recursive: true });
107898
+ await copyFile2(tplManifest, path11.join(projectDir, "manifest.yaml"));
107899
+ await copyFile2(tplChapter, path11.join(projectDir, "chapter-01.md"));
107768
107900
  } catch (e) {
107769
107901
  throw new CreateProjectErrorImpl("scaffold-io", `Could not create the project files: ${e instanceof Error ? e.message : String(e)}`);
107770
107902
  }
107771
- const manifestPath = path10.join(projectDir, "manifest.yaml");
107772
- const openFile = path10.join(projectDir, "chapter-01.md");
107903
+ const manifestPath = path11.join(projectDir, "manifest.yaml");
107904
+ const openFile = path11.join(projectDir, "chapter-01.md");
107773
107905
  const author = (options.author ?? "").trim() || DEFAULT_AUTHOR2;
107774
107906
  const outputPdf = `${slug}.pdf`;
107775
107907
  const substitutions = {
@@ -107813,7 +107945,7 @@ async function scaffoldProject(options) {
107813
107945
  return result;
107814
107946
  }
107815
107947
  async function fillTemplateFile(filePath2, substitutions) {
107816
- let text4 = await readFile21(filePath2, "utf8");
107948
+ let text4 = await readFile22(filePath2, "utf8");
107817
107949
  for (const [token, value] of Object.entries(substitutions)) {
107818
107950
  text4 = text4.split(token).join(value);
107819
107951
  }
@@ -107832,6 +107964,117 @@ var init_project_scaffold = __esm(() => {
107832
107964
  };
107833
107965
  });
107834
107966
 
107967
+ // ../lib/src/lib/remote-auth/token-store.ts
107968
+ import { chmod, mkdir as mkdir7, readFile as readFile23, writeFile as writeFile8 } from "node:fs/promises";
107969
+ import os3 from "node:os";
107970
+ import path12 from "node:path";
107971
+ function defaultConfigDir() {
107972
+ const override = process.env.PRINT_MD_CONFIG_DIR?.trim();
107973
+ if (override)
107974
+ return override;
107975
+ if (process.platform === "win32" && process.env.APPDATA) {
107976
+ return path12.join(process.env.APPDATA, "print-md");
107977
+ }
107978
+ const xdg = process.env.XDG_CONFIG_HOME?.trim();
107979
+ return path12.join(xdg || path12.join(os3.homedir(), ".config"), "print-md");
107980
+ }
107981
+
107982
+ class FileTokenStore {
107983
+ filePath;
107984
+ queue = Promise.resolve();
107985
+ constructor(filePath2) {
107986
+ this.filePath = filePath2 ?? path12.join(defaultConfigDir(), "credentials.json");
107987
+ }
107988
+ async read() {
107989
+ try {
107990
+ const raw = await readFile23(this.filePath, "utf8");
107991
+ const parsed = JSON.parse(raw);
107992
+ if (parsed && typeof parsed === "object" && parsed.credentials)
107993
+ return parsed;
107994
+ } catch {}
107995
+ return { version: 1, credentials: {} };
107996
+ }
107997
+ async write(data) {
107998
+ await mkdir7(path12.dirname(this.filePath), { recursive: true });
107999
+ await writeFile8(this.filePath, JSON.stringify(data, null, 2), {
108000
+ encoding: "utf8",
108001
+ mode: 384
108002
+ });
108003
+ await chmod(this.filePath, 384);
108004
+ }
108005
+ enqueue(fn2) {
108006
+ const run2 = this.queue.then(fn2, fn2);
108007
+ this.queue = run2.catch(() => {
108008
+ return;
108009
+ });
108010
+ return run2;
108011
+ }
108012
+ get(host) {
108013
+ return this.enqueue(async () => {
108014
+ const data = await this.read();
108015
+ return data.credentials[normalizeHost(host)] ?? null;
108016
+ });
108017
+ }
108018
+ set(host, credential) {
108019
+ return this.enqueue(async () => {
108020
+ const data = await this.read();
108021
+ data.credentials[normalizeHost(host)] = credential;
108022
+ await this.write(data);
108023
+ });
108024
+ }
108025
+ delete(host) {
108026
+ return this.enqueue(async () => {
108027
+ const data = await this.read();
108028
+ delete data.credentials[normalizeHost(host)];
108029
+ await this.write(data);
108030
+ });
108031
+ }
108032
+ list() {
108033
+ return this.enqueue(async () => {
108034
+ const data = await this.read();
108035
+ return Object.values(data.credentials);
108036
+ });
108037
+ }
108038
+ }
108039
+ function normalizeHost(host) {
108040
+ return host.trim().toLowerCase();
108041
+ }
108042
+ var init_token_store = () => {};
108043
+ // ../lib/src/lib/remote-auth/github-repos.ts
108044
+ var init_github_repos = () => {};
108045
+
108046
+ // ../lib/src/lib/remote-auth/clone.ts
108047
+ var init_clone = __esm(() => {
108048
+ init_source_provider();
108049
+ init_token_store();
108050
+ });
108051
+
108052
+ // ../lib/src/lib/remote-auth/test-access.ts
108053
+ var init_test_access = __esm(() => {
108054
+ init_token_store();
108055
+ });
108056
+
108057
+ // ../lib/src/lib/remote-auth/generic-auth.ts
108058
+ var init_generic_auth = __esm(() => {
108059
+ init_test_access();
108060
+ });
108061
+
108062
+ // ../lib/src/lib/remote-auth/diagnose.ts
108063
+ var init_diagnose = __esm(() => {
108064
+ init_project_source();
108065
+ init_generic_auth();
108066
+ init_test_access();
108067
+ init_token_store();
108068
+ });
108069
+
108070
+ // ../lib/src/lib/remote-auth/publish.ts
108071
+ var import_diff3;
108072
+ var init_publish = __esm(() => {
108073
+ init_source_provider();
108074
+ init_token_store();
108075
+ import_diff3 = __toESM(require_diff3(), 1);
108076
+ });
108077
+
107835
108078
  // ../lib/src/api/index.ts
107836
108079
  var init_api = __esm(() => {
107837
108080
  init_build_runner();
@@ -107841,6 +108084,13 @@ var init_api = __esm(() => {
107841
108084
  init_project_source();
107842
108085
  init_project_scaffold();
107843
108086
  init_source_provider();
108087
+ init_token_store();
108088
+ init_github_repos();
108089
+ init_clone();
108090
+ init_test_access();
108091
+ init_generic_auth();
108092
+ init_diagnose();
108093
+ init_publish();
107844
108094
  });
107845
108095
 
107846
108096
  // ../lib/src/index.ts
@@ -107936,7 +108186,7 @@ __export(exports_preview, {
107936
108186
  default: () => preview_default
107937
108187
  });
107938
108188
  import { defineCommand as defineCommand2 } from "citty";
107939
- import path11 from "node:path";
108189
+ import path13 from "node:path";
107940
108190
  import fs6 from "node:fs";
107941
108191
  function resolvePort(raw) {
107942
108192
  if (raw === undefined || raw === "")
@@ -107992,7 +108242,7 @@ var init_preview = __esm(() => {
107992
108242
  "skip-post-validate": { type: "boolean", description: "Skip post-build PDF/X validation (pdfx only)" }
107993
108243
  },
107994
108244
  async run({ args }) {
107995
- const inputPath = args.input ? path11.resolve(args.input) : undefined;
108245
+ const inputPath = args.input ? path13.resolve(args.input) : undefined;
107996
108246
  if (inputPath !== undefined) {
107997
108247
  if (!fs6.existsSync(inputPath) || !fs6.statSync(inputPath).isDirectory()) {
107998
108248
  log.error(`Input directory does not exist: ${inputPath}`);
@@ -108055,7 +108305,7 @@ __export(exports_build, {
108055
108305
  default: () => build_default
108056
108306
  });
108057
108307
  import { defineCommand as defineCommand3 } from "citty";
108058
- import path12 from "node:path";
108308
+ import path14 from "node:path";
108059
108309
  function parseFormat2(raw) {
108060
108310
  if (raw === undefined || raw === "")
108061
108311
  return "pdf";
@@ -108103,7 +108353,7 @@ var init_build = __esm(() => {
108103
108353
  const { outDir, pdfFileOverride } = splitOutPath(typeof args.out === "string" ? args.out : undefined, format);
108104
108354
  try {
108105
108355
  await runBuild({
108106
- inputDir: path12.resolve(args.input ?? "."),
108356
+ inputDir: path14.resolve(args.input ?? "."),
108107
108357
  format,
108108
108358
  outDir,
108109
108359
  pdfFileOverride,
@@ -108300,7 +108550,7 @@ __export(exports_preflight, {
108300
108550
  buildPreflightPayload: () => buildPreflightPayload
108301
108551
  });
108302
108552
  import { defineCommand as defineCommand7 } from "citty";
108303
- import { mkdir as mkdir7, writeFile as writeFile8 } from "node:fs/promises";
108553
+ import { mkdir as mkdir8, writeFile as writeFile9 } from "node:fs/promises";
108304
108554
  import { basename as basename3, dirname as dirname6, extname, join as join10, resolve as resolve15 } from "node:path";
108305
108555
  function computeStatus(errors, warnings, missingTools, skippedRequired) {
108306
108556
  if (errors > 0 || skippedRequired)
@@ -108476,10 +108726,10 @@ var init_preflight = __esm(() => {
108476
108726
  const baseName = typeof args.name === "string" && args.name.trim().length > 0 ? args.name.trim() : defaultReportName(pdfPath);
108477
108727
  const jsonPath = join10(reportDir, `${baseName}.json`);
108478
108728
  const markdownPath = join10(reportDir, `${baseName}.md`);
108479
- await mkdir7(reportDir, { recursive: true });
108480
- await writeFile8(jsonPath, `${JSON.stringify(payload, null, 2)}
108729
+ await mkdir8(reportDir, { recursive: true });
108730
+ await writeFile9(jsonPath, `${JSON.stringify(payload, null, 2)}
108481
108731
  `, "utf8");
108482
- await writeFile8(markdownPath, toPreflightMarkdown(payload), "utf8");
108732
+ await writeFile9(markdownPath, toPreflightMarkdown(payload), "utf8");
108483
108733
  log.info(`Preflight status: ${payload.status}`);
108484
108734
  log.info(`JSON report: ${jsonPath}`);
108485
108735
  log.info(`Markdown report: ${markdownPath}`);
@@ -108501,7 +108751,7 @@ var SUBCOMMANDS = {
108501
108751
  audit: () => Promise.resolve().then(() => (init_audit(), exports_audit)).then((m) => m.default),
108502
108752
  preflight: () => Promise.resolve().then(() => (init_preflight(), exports_preflight)).then((m) => m.default)
108503
108753
  };
108504
- var VERSION = "0.4.1-beta.6";
108754
+ var VERSION = "0.5.0-rc.1";
108505
108755
  var main = defineCommand8({
108506
108756
  meta: {
108507
108757
  name: "print-md",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dimm-city/print-md",
3
- "version": "0.4.1-beta.6",
3
+ "version": "0.5.0-rc.1",
4
4
  "description": "Markdown-to-PDF converter for professional print layout using Paged.js and Ghostscript.",
5
5
  "author": "itlackey",
6
6
  "license": "MPL-2.0",