@applitools/eyes-browser 1.6.23 → 1.6.24

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 (3) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/dist/index.js +1209 -167
  3. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -18936,6 +18936,71 @@ var require_formatter = __commonJS({
18936
18936
  }
18937
18937
  });
18938
18938
 
18939
+ // ../logger/dist/log-buffer.js
18940
+ var require_log_buffer = __commonJS({
18941
+ "../logger/dist/log-buffer.js"(exports) {
18942
+ "use strict";
18943
+ init_global();
18944
+ init_process();
18945
+ init_setImmediate();
18946
+ init_buffer();
18947
+ init_setInterval();
18948
+ Object.defineProperty(exports, "__esModule", { value: true });
18949
+ exports.__resetLogBufferForTests = exports.isLogBufferActive = exports.disableLogBuffer = exports.onLogBufferFull = exports.consumeLogBuffer = exports.appendToLogBuffer = void 0;
18950
+ var LOG_BUFFER_MAX_ENTRIES = 5e4;
18951
+ var LOG_BUFFER_MAX_CHARS = 8e6;
18952
+ var logBuffer = [];
18953
+ var logBufferChars = 0;
18954
+ var onFull;
18955
+ var ANSI_REGEX = /\x1b\[[0-9;]*m/g;
18956
+ function appendToLogBuffer(line) {
18957
+ if (!logBuffer)
18958
+ return;
18959
+ logBuffer.push(line);
18960
+ logBufferChars += line.length;
18961
+ if (logBuffer.length > LOG_BUFFER_MAX_ENTRIES || logBufferChars > LOG_BUFFER_MAX_CHARS) {
18962
+ if (onFull)
18963
+ onFull();
18964
+ else {
18965
+ const dropped = logBuffer.shift();
18966
+ if (dropped)
18967
+ logBufferChars -= dropped.length;
18968
+ }
18969
+ }
18970
+ }
18971
+ exports.appendToLogBuffer = appendToLogBuffer;
18972
+ function consumeLogBuffer() {
18973
+ if (!logBuffer)
18974
+ return "";
18975
+ const text = logBuffer.length ? logBuffer.join("\n") + "\n" : "";
18976
+ logBuffer = [];
18977
+ logBufferChars = 0;
18978
+ return text.replace(ANSI_REGEX, "");
18979
+ }
18980
+ exports.consumeLogBuffer = consumeLogBuffer;
18981
+ function onLogBufferFull(cb) {
18982
+ onFull = cb;
18983
+ }
18984
+ exports.onLogBufferFull = onLogBufferFull;
18985
+ function disableLogBuffer() {
18986
+ logBuffer = void 0;
18987
+ logBufferChars = 0;
18988
+ onFull = void 0;
18989
+ }
18990
+ exports.disableLogBuffer = disableLogBuffer;
18991
+ function isLogBufferActive() {
18992
+ return logBuffer !== void 0;
18993
+ }
18994
+ exports.isLogBufferActive = isLogBufferActive;
18995
+ function __resetLogBufferForTests() {
18996
+ logBuffer = [];
18997
+ logBufferChars = 0;
18998
+ onFull = void 0;
18999
+ }
19000
+ exports.__resetLogBufferForTests = __resetLogBufferForTests;
19001
+ }
19002
+ });
19003
+
18939
19004
  // ../logger/dist/handler-console.js
18940
19005
  var require_handler_console = __commonJS({
18941
19006
  "../logger/dist/handler-console.js"(exports) {
@@ -19515,50 +19580,58 @@ var require_printer = __commonJS({
19515
19580
  Object.defineProperty(exports, "__esModule", { value: true });
19516
19581
  exports.makePrinter = void 0;
19517
19582
  var log_level_1 = require_log_level();
19583
+ var log_buffer_1 = require_log_buffer();
19518
19584
  function makePrinter({ handler, level = log_level_1.LogLevel.silent, format, masks, maskLog }) {
19519
19585
  var _a;
19520
19586
  const formatter = (_a = format === null || format === void 0 ? void 0 : format.formatter) !== null && _a !== void 0 ? _a : (chunks, options) => ({ chunks, options, isRaw: true });
19521
19587
  return { debug, log, info: log, warn, error, fatal, verbose: log };
19588
+ function emit(threshold, levelName, messages) {
19589
+ const gated = level < threshold;
19590
+ if (gated && !(0, log_buffer_1.isLogBufferActive)())
19591
+ return void 0;
19592
+ const line = formatter(messages, { ...format, level: levelName, masks, maskLog });
19593
+ if ((0, log_buffer_1.isLogBufferActive)() && typeof line === "string")
19594
+ (0, log_buffer_1.appendToLogBuffer)(line);
19595
+ return gated ? void 0 : line;
19596
+ }
19522
19597
  function debug(...messages) {
19523
- if (level < log_level_1.LogLevel.debug)
19524
- return;
19525
- const options = { ...format, level: "debug", masks, maskLog };
19526
- handler.log(formatter(messages, options));
19598
+ const line = emit(log_level_1.LogLevel.debug, "debug", messages);
19599
+ if (line !== void 0)
19600
+ handler.log(line);
19527
19601
  }
19528
19602
  function log(...messages) {
19529
- if (level < log_level_1.LogLevel.info)
19530
- return;
19531
- const options = { ...format, level: "info", masks, maskLog };
19532
- handler.log(formatter(messages, options));
19603
+ const line = emit(log_level_1.LogLevel.info, "info", messages);
19604
+ if (line !== void 0)
19605
+ handler.log(line);
19533
19606
  }
19534
19607
  function warn(...messages) {
19535
- if (level < log_level_1.LogLevel.warn)
19608
+ const line = emit(log_level_1.LogLevel.warn, "warn", messages);
19609
+ if (line === void 0)
19536
19610
  return;
19537
- const options = { ...format, level: "warn", masks, maskLog };
19538
19611
  if (handler.warn)
19539
- handler.warn(formatter(messages, options));
19612
+ handler.warn(line);
19540
19613
  else
19541
- handler.log(formatter(messages, options));
19614
+ handler.log(line);
19542
19615
  }
19543
19616
  function error(...messages) {
19544
- if (level < log_level_1.LogLevel.error)
19617
+ const line = emit(log_level_1.LogLevel.error, "error", messages);
19618
+ if (line === void 0)
19545
19619
  return;
19546
- const options = { ...format, level: "error", masks, maskLog };
19547
19620
  if (handler.error)
19548
- handler.error(formatter(messages, options));
19621
+ handler.error(line);
19549
19622
  else
19550
- handler.log(formatter(messages, options));
19623
+ handler.log(line);
19551
19624
  }
19552
19625
  function fatal(...messages) {
19553
- if (level < log_level_1.LogLevel.fatal)
19626
+ const line = emit(log_level_1.LogLevel.fatal, "fatal", messages);
19627
+ if (line === void 0)
19554
19628
  return;
19555
- const options = { ...format, level: "fatal", masks, maskLog };
19556
19629
  if (handler.fatal)
19557
- handler.fatal(formatter(messages, options));
19630
+ handler.fatal(line);
19558
19631
  else if (handler.error)
19559
- handler.error(formatter(messages, options));
19632
+ handler.error(line);
19560
19633
  else
19561
- handler.log(formatter(messages, options));
19634
+ handler.log(line);
19562
19635
  }
19563
19636
  }
19564
19637
  exports.makePrinter = makePrinter;
@@ -19834,6 +19907,7 @@ var require_browser6 = __commonJS({
19834
19907
  };
19835
19908
  Object.defineProperty(exports, "__esModule", { value: true });
19836
19909
  __exportStar(require_formatter(), exports);
19910
+ __exportStar(require_log_buffer(), exports);
19837
19911
  __exportStar(require_handler_console(), exports);
19838
19912
  __exportStar(require_handler_debug(), exports);
19839
19913
  __exportStar(require_logger(), exports);
@@ -74571,6 +74645,108 @@ var require_delete_test = __commonJS({
74571
74645
  }
74572
74646
  });
74573
74647
 
74648
+ // ../core-base/dist/server/sdk-log-upload.js
74649
+ var require_sdk_log_upload = __commonJS({
74650
+ "../core-base/dist/server/sdk-log-upload.js"(exports) {
74651
+ "use strict";
74652
+ init_global();
74653
+ init_process();
74654
+ init_setImmediate();
74655
+ init_buffer();
74656
+ init_setInterval();
74657
+ Object.defineProperty(exports, "__esModule", { value: true });
74658
+ exports.makeSdkLogUpload = void 0;
74659
+ var req_1 = (init_dist(), __toCommonJS(dist_exports));
74660
+ function makeSdkLogUpload({ url, proxy, httpVersion }) {
74661
+ let created = false;
74662
+ let stopped = false;
74663
+ let chain = Promise.resolve();
74664
+ async function append(text) {
74665
+ if (stopped || !text)
74666
+ return;
74667
+ try {
74668
+ if (!created) {
74669
+ const res2 = await (0, req_1.req)(url, {
74670
+ method: "PUT",
74671
+ headers: { "x-ms-blob-type": "AppendBlob", "Content-Length": "0" },
74672
+ proxy,
74673
+ httpVersion
74674
+ });
74675
+ if (!res2.ok && res2.status !== 409)
74676
+ throw new Error(`create blob failed (${res2.status})`);
74677
+ created = true;
74678
+ }
74679
+ const res = await (0, req_1.req)(withQuery(url, "comp=appendblock"), { method: "PUT", body: text, proxy, httpVersion });
74680
+ if (!res.ok)
74681
+ throw new Error(`appendblock failed (${res.status})`);
74682
+ } catch {
74683
+ stopped = true;
74684
+ }
74685
+ }
74686
+ return (text) => chain = chain.then(() => append(text));
74687
+ }
74688
+ exports.makeSdkLogUpload = makeSdkLogUpload;
74689
+ var withQuery = (url, q) => url + (url.includes("?") ? "&" : "?") + q;
74690
+ }
74691
+ });
74692
+
74693
+ // ../core-base/dist/sdk-log-streaming.js
74694
+ var require_sdk_log_streaming = __commonJS({
74695
+ "../core-base/dist/sdk-log-streaming.js"(exports) {
74696
+ "use strict";
74697
+ init_global();
74698
+ init_process();
74699
+ init_setImmediate();
74700
+ init_buffer();
74701
+ init_setInterval();
74702
+ Object.defineProperty(exports, "__esModule", { value: true });
74703
+ exports.decideSdkLogStreaming = void 0;
74704
+ var logger_1 = require_browser6();
74705
+ var sdk_log_upload_1 = require_sdk_log_upload();
74706
+ var SDK_LOG_RUN_ID = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
74707
+ var SDK_LOG_PLACEHOLDER = "__sdk_logs_batch_id__";
74708
+ var sdkLogDecided = false;
74709
+ var sdkLogDrain;
74710
+ function decideSdkLogStreaming(account) {
74711
+ var _a, _b;
74712
+ if (!sdkLogDecided) {
74713
+ sdkLogDecided = true;
74714
+ const disabled = !!process.env.APPLITOOLS_DISABLE_BACKEND_LOGS;
74715
+ if (!account.collectSdkLogs || !account.sdkLogsUploadUrl || disabled) {
74716
+ (0, logger_1.disableLogBuffer)();
74717
+ } else {
74718
+ const url = account.sdkLogsUploadUrl.split(SDK_LOG_PLACEHOLDER).join(encodeURIComponent(SDK_LOG_RUN_ID));
74719
+ const upload = (0, sdk_log_upload_1.makeSdkLogUpload)({
74720
+ url,
74721
+ proxy: account.eyesServer.proxy,
74722
+ httpVersion: account.eyesServer.httpVersion
74723
+ });
74724
+ sdkLogDrain = () => {
74725
+ const text = (0, logger_1.consumeLogBuffer)();
74726
+ if (text)
74727
+ void upload(text);
74728
+ };
74729
+ (0, logger_1.onLogBufferFull)(sdkLogDrain);
74730
+ const timer = setIntervalBrowser(() => sdkLogDrain === null || sdkLogDrain === void 0 ? void 0 : sdkLogDrain(), 5e3);
74731
+ (_b = (_a = timer).unref) === null || _b === void 0 ? void 0 : _b.call(_a);
74732
+ installSdkLogShutdownHooks();
74733
+ }
74734
+ }
74735
+ }
74736
+ exports.decideSdkLogStreaming = decideSdkLogStreaming;
74737
+ var shutdownHooksInstalled = false;
74738
+ function installSdkLogShutdownHooks() {
74739
+ if (shutdownHooksInstalled)
74740
+ return;
74741
+ shutdownHooksInstalled = true;
74742
+ const shutdown = () => sdkLogDrain === null || sdkLogDrain === void 0 ? void 0 : sdkLogDrain();
74743
+ process.on("beforeExit", shutdown);
74744
+ process.on("SIGINT", shutdown);
74745
+ process.on("SIGTERM", shutdown);
74746
+ }
74747
+ }
74748
+ });
74749
+
74574
74750
  // ../core-base/dist/get-account-info.js
74575
74751
  var require_get_account_info = __commonJS({
74576
74752
  "../core-base/dist/get-account-info.js"(exports) {
@@ -74614,6 +74790,7 @@ var require_get_account_info = __commonJS({
74614
74790
  };
74615
74791
  Object.defineProperty(exports, "__esModule", { value: true });
74616
74792
  exports.makeGetAccountInfo = void 0;
74793
+ var sdk_log_streaming_1 = require_sdk_log_streaming();
74617
74794
  var utils2 = __importStar(require_browser3());
74618
74795
  function makeGetAccountInfo({ requests, agentId: defaultAgentId, logger: mainLogger }) {
74619
74796
  return async function getAccountInfo({ settings, logger = mainLogger }) {
@@ -74622,11 +74799,13 @@ var require_get_account_info = __commonJS({
74622
74799
  settings.agentId = `${defaultAgentId} ${settings.agentId ? `[${settings.agentId}]` : ""}`.trim();
74623
74800
  logger.log('Command "getAccountInfo" is called with settings', settings);
74624
74801
  const account = await requests.getAccountInfo({ settings, logger });
74625
- return {
74802
+ const result = {
74626
74803
  ...account,
74627
74804
  eyesServer: { ...account.eyesServer, agentId: settings.agentId },
74628
74805
  ufgServer: { ...account.ufgServer, agentId: settings.agentId }
74629
74806
  };
74807
+ (0, sdk_log_streaming_1.decideSdkLogStreaming)(result);
74808
+ return result;
74630
74809
  };
74631
74810
  }
74632
74811
  exports.makeGetAccountInfo = makeGetAccountInfo;
@@ -75052,6 +75231,7 @@ var require_dist2 = __commonJS({
75052
75231
  __exportStar(require_core(), exports);
75053
75232
  __exportStar(require_eyes(), exports);
75054
75233
  __exportStar(require_requests(), exports);
75234
+ __exportStar(require_sdk_log_upload(), exports);
75055
75235
  __exportStar(require_core_error(), exports);
75056
75236
  __exportStar(require_missingApiKeyError(), exports);
75057
75237
  __exportStar(require_test_error(), exports);
@@ -82746,7 +82926,7 @@ ${l2}`}`, { bundledCss: u2, unfetchedResources: a2 };
82746
82926
  return m3 && (k2.shadowRoot = m3), k2;
82747
82927
  }
82748
82928
  }(t3);
82749
- f2(l2.doCaptureDoc), d2(l2.waitForImages), await Promise.all(m2), f2(l2.waitForImages), T2.version = "1.4.0", T2.scriptVersion = "11.8.2";
82929
+ f2(l2.doCaptureDoc), d2(l2.waitForImages), await Promise.all(m2), f2(l2.waitForImages), T2.version = "1.4.0", T2.scriptVersion = "11.8.3";
82750
82930
  const N2 = p2.length ? `${p2.join("\n")}
82751
82931
  ` : "", P2 = h2.size ? `${Array.from(h2).join("\n")}
82752
82932
  ` : "", A2 = JSON.stringify({ separator: w2, cssStartToken: y2, cssEndToken: y2, iframeStartToken: `"${g2}`, iframeEndToken: `${g2}"` });
@@ -89732,7 +89912,7 @@ var require_captureDomPollForIE = __commonJS({
89732
89912
  case 24:
89733
89913
  return L2 = e4.sent, A2(E2.prefetchCss), j2 = U0({ parseCss: D0, CSSImportRule, getCssFromCache: L2, absolutizeUrl: j0, unfetchedToken: _2 }), k2 = z0({ getCssFromCache: L2, absolutizeUrl: j0 }), C2 = V0({ extractCssFromNode: k2, getBundledCssFromCssText: j2, unfetchedToken: _2 }), S2(E2.doCaptureDoc), M2 = H2(i3), A2(E2.doCaptureDoc), S2(E2.waitForImages), e4.next = 35, Promise.all(O2);
89734
89914
  case 35:
89735
- return A2(E2.waitForImages), M2.version = "1.4.0", M2.scriptVersion = "11.8.2", N2 = T2.length ? T2.join("\n") + "\n" : "", U2 = x2.size ? Array.from(x2).join("\n") + "\n" : "", D2 = JSON.stringify({ separator: P2, cssStartToken: _2, cssEndToken: _2, iframeStartToken: '"' + R2, iframeEndToken: R2 + '"' }), A2(E2.total), B2 = JSON.stringify(M2), z2 = D2 + "\n" + U2 + P2 + "\n" + N2 + P2 + "\n" + ("string" == typeof B2 ? B2 : H0(M2)) + F2(), console.log("[captureFrame]", JSON.stringify(E2)), e4.abrupt("return", z2);
89915
+ return A2(E2.waitForImages), M2.version = "1.4.0", M2.scriptVersion = "11.8.3", N2 = T2.length ? T2.join("\n") + "\n" : "", U2 = x2.size ? Array.from(x2).join("\n") + "\n" : "", D2 = JSON.stringify({ separator: P2, cssStartToken: _2, cssEndToken: _2, iframeStartToken: '"' + R2, iframeEndToken: R2 + '"' }), A2(E2.total), B2 = JSON.stringify(M2), z2 = D2 + "\n" + U2 + P2 + "\n" + N2 + P2 + "\n" + ("string" == typeof B2 ? B2 : H0(M2)) + F2(), console.log("[captureFrame]", JSON.stringify(E2)), e4.abrupt("return", z2);
89736
89916
  case 46:
89737
89917
  case "end":
89738
89918
  return e4.stop();
@@ -104738,7 +104918,7 @@ creating temp style for access.`), r2 = Qh(e3);
104738
104918
  function M2(e3) {
104739
104919
  return r3.defaultView && r3.defaultView.frameElement && r3.defaultView.frameElement.getAttribute(e3);
104740
104920
  }
104741
- }(n3).then((e3) => (m2.log("processPage end"), e3.scriptVersion = "4.17.4", e3));
104921
+ }(n3).then((e3) => (m2.log("processPage end"), e3.scriptVersion = "4.17.5", e3));
104742
104922
  }, n2[S], "domSnapshotResult");
104743
104923
  return function(e3) {
104744
104924
  try {
@@ -129507,6 +129687,292 @@ var require_get_eyes_results = __commonJS({
129507
129687
  }
129508
129688
  });
129509
129689
 
129690
+ // ../../node_modules/shell-quote/quote.js
129691
+ var require_quote = __commonJS({
129692
+ "../../node_modules/shell-quote/quote.js"(exports, module) {
129693
+ "use strict";
129694
+ init_global();
129695
+ init_process();
129696
+ init_setImmediate();
129697
+ init_buffer();
129698
+ init_setInterval();
129699
+ var OPS = [
129700
+ "||",
129701
+ "&&",
129702
+ ";;",
129703
+ "|&",
129704
+ "<(",
129705
+ "<<<",
129706
+ ">>",
129707
+ ">&",
129708
+ "<&",
129709
+ "&",
129710
+ ";",
129711
+ "(",
129712
+ ")",
129713
+ "|",
129714
+ "<",
129715
+ ">"
129716
+ ];
129717
+ var LINE_TERMINATORS = /[\n\r\u2028\u2029]/;
129718
+ var GLOB_SHELL_SPECIAL = /[\s#!"$&'():;<=>@\\^`|]/g;
129719
+ module.exports = function quote(xs) {
129720
+ return xs.map(function(s) {
129721
+ if (s === "") {
129722
+ return "''";
129723
+ }
129724
+ if (s && typeof s === "object") {
129725
+ if (s.op === "glob") {
129726
+ if (typeof s.pattern !== "string") {
129727
+ throw new TypeError("glob token requires a string `pattern`");
129728
+ }
129729
+ if (LINE_TERMINATORS.test(s.pattern)) {
129730
+ throw new TypeError("glob `pattern` must not contain line terminators");
129731
+ }
129732
+ return s.pattern.replace(GLOB_SHELL_SPECIAL, "\\$&");
129733
+ }
129734
+ if (typeof s.op === "string") {
129735
+ if (OPS.indexOf(s.op) < 0) {
129736
+ throw new TypeError("invalid `op` value: " + JSON.stringify(s.op));
129737
+ }
129738
+ return s.op.replace(/[\s\S]/g, "\\$&");
129739
+ }
129740
+ if (typeof s.comment === "string") {
129741
+ if (LINE_TERMINATORS.test(s.comment)) {
129742
+ throw new TypeError("`comment` must not contain line terminators");
129743
+ }
129744
+ return "#" + s.comment;
129745
+ }
129746
+ throw new TypeError("unrecognized object token shape");
129747
+ }
129748
+ if (/["\s\\]/.test(s) && !/'/.test(s)) {
129749
+ return "'" + s.replace(/(['])/g, "\\$1") + "'";
129750
+ }
129751
+ if (/["'\s]/.test(s)) {
129752
+ return '"' + s.replace(/(["\\$`!])/g, "\\$1") + '"';
129753
+ }
129754
+ return String(s).replace(/([A-Za-z]:)?([#!"$&'()*,:;<=>?@[\\\]^`{|}])/g, "$1\\$2");
129755
+ }).join(" ");
129756
+ };
129757
+ }
129758
+ });
129759
+
129760
+ // ../../node_modules/shell-quote/parse.js
129761
+ var require_parse2 = __commonJS({
129762
+ "../../node_modules/shell-quote/parse.js"(exports, module) {
129763
+ "use strict";
129764
+ init_global();
129765
+ init_process();
129766
+ init_setImmediate();
129767
+ init_buffer();
129768
+ init_setInterval();
129769
+ var CONTROL = "(?:" + [
129770
+ "\\|\\|",
129771
+ "\\&\\&",
129772
+ ";;",
129773
+ "\\|\\&",
129774
+ "\\<\\(",
129775
+ "\\<\\<\\<",
129776
+ ">>",
129777
+ ">\\&",
129778
+ "<\\&",
129779
+ "[&;()|<>]"
129780
+ ].join("|") + ")";
129781
+ var controlRE = new RegExp("^" + CONTROL + "$");
129782
+ var META = "|&;()<> \\t";
129783
+ var SINGLE_QUOTE = '"((\\\\"|[^"])*?)"';
129784
+ var DOUBLE_QUOTE = "'((\\\\'|[^'])*?)'";
129785
+ var hash = /^#$/;
129786
+ var SQ = "'";
129787
+ var DQ = '"';
129788
+ var DS = "$";
129789
+ var TOKEN = "";
129790
+ var mult = 4294967296;
129791
+ for (i = 0; i < 4; i++) {
129792
+ TOKEN += (mult * Math.random()).toString(16);
129793
+ }
129794
+ var i;
129795
+ var startsWithToken = new RegExp("^" + TOKEN);
129796
+ function matchAll(s, r) {
129797
+ var origIndex = r.lastIndex;
129798
+ var matches = [];
129799
+ var matchObj;
129800
+ while (matchObj = r.exec(s)) {
129801
+ matches.push(matchObj);
129802
+ if (r.lastIndex === matchObj.index) {
129803
+ r.lastIndex += 1;
129804
+ }
129805
+ }
129806
+ r.lastIndex = origIndex;
129807
+ return matches;
129808
+ }
129809
+ function getVar(env, pre, key) {
129810
+ var r = typeof env === "function" ? env(key) : env[key];
129811
+ if (typeof r === "undefined" && key != "") {
129812
+ r = "";
129813
+ } else if (typeof r === "undefined") {
129814
+ r = "$";
129815
+ }
129816
+ if (typeof r === "object") {
129817
+ return pre + TOKEN + JSON.stringify(r) + TOKEN;
129818
+ }
129819
+ return pre + r;
129820
+ }
129821
+ function parseInternal(string, env, opts) {
129822
+ if (!opts) {
129823
+ opts = {};
129824
+ }
129825
+ var BS = opts.escape || "\\";
129826
+ var BAREWORD = "(\\" + BS + `['"` + META + `]|[^\\s'"` + META + "])+";
129827
+ var chunker = new RegExp([
129828
+ "(" + CONTROL + ")",
129829
+ // control chars
129830
+ "(" + BAREWORD + "|" + SINGLE_QUOTE + "|" + DOUBLE_QUOTE + ")+"
129831
+ ].join("|"), "g");
129832
+ var matches = matchAll(string, chunker);
129833
+ if (matches.length === 0) {
129834
+ return [];
129835
+ }
129836
+ if (!env) {
129837
+ env = {};
129838
+ }
129839
+ var commented = false;
129840
+ return matches.map(function(match) {
129841
+ var s = match[0];
129842
+ if (!s || commented) {
129843
+ return void 0;
129844
+ }
129845
+ if (controlRE.test(s)) {
129846
+ return { op: s };
129847
+ }
129848
+ var quote = false;
129849
+ var esc = false;
129850
+ var out = "";
129851
+ var isGlob = false;
129852
+ var i2;
129853
+ function parseEnvVar() {
129854
+ i2 += 1;
129855
+ var varend;
129856
+ var varname;
129857
+ var char = s.charAt(i2);
129858
+ if (char === "{") {
129859
+ i2 += 1;
129860
+ if (s.charAt(i2) === "}") {
129861
+ throw new Error("Bad substitution: " + s.slice(i2 - 2, i2 + 1));
129862
+ }
129863
+ varend = s.indexOf("}", i2);
129864
+ if (varend < 0) {
129865
+ throw new Error("Bad substitution: " + s.slice(i2));
129866
+ }
129867
+ varname = s.slice(i2, varend);
129868
+ i2 = varend;
129869
+ } else if (/[*@#?$!_-]/.test(char)) {
129870
+ varname = char;
129871
+ i2 += 1;
129872
+ } else {
129873
+ var slicedFromI = s.slice(i2);
129874
+ varend = slicedFromI.match(/[^\w\d_]/);
129875
+ if (!varend) {
129876
+ varname = slicedFromI;
129877
+ i2 = s.length;
129878
+ } else {
129879
+ varname = slicedFromI.slice(0, varend.index);
129880
+ i2 += varend.index - 1;
129881
+ }
129882
+ }
129883
+ return getVar(env, "", varname);
129884
+ }
129885
+ for (i2 = 0; i2 < s.length; i2++) {
129886
+ var c = s.charAt(i2);
129887
+ isGlob = isGlob || !quote && (c === "*" || c === "?");
129888
+ if (esc) {
129889
+ out += c;
129890
+ esc = false;
129891
+ } else if (quote) {
129892
+ if (c === quote) {
129893
+ quote = false;
129894
+ } else if (quote == SQ) {
129895
+ out += c;
129896
+ } else {
129897
+ if (c === BS) {
129898
+ i2 += 1;
129899
+ c = s.charAt(i2);
129900
+ if (c === DQ || c === BS || c === DS) {
129901
+ out += c;
129902
+ } else {
129903
+ out += BS + c;
129904
+ }
129905
+ } else if (c === DS) {
129906
+ out += parseEnvVar();
129907
+ } else {
129908
+ out += c;
129909
+ }
129910
+ }
129911
+ } else if (c === DQ || c === SQ) {
129912
+ quote = c;
129913
+ } else if (controlRE.test(c)) {
129914
+ return { op: s };
129915
+ } else if (hash.test(c)) {
129916
+ commented = true;
129917
+ var commentObj = { comment: string.slice(match.index + i2 + 1) };
129918
+ if (out.length) {
129919
+ return [out, commentObj];
129920
+ }
129921
+ return [commentObj];
129922
+ } else if (c === BS) {
129923
+ esc = true;
129924
+ } else if (c === DS) {
129925
+ out += parseEnvVar();
129926
+ } else {
129927
+ out += c;
129928
+ }
129929
+ }
129930
+ if (isGlob) {
129931
+ return { op: "glob", pattern: out };
129932
+ }
129933
+ return out;
129934
+ }).reduce(function(prev, arg) {
129935
+ return typeof arg === "undefined" ? prev : prev.concat(arg);
129936
+ }, []);
129937
+ }
129938
+ module.exports = function parse(s, env, opts) {
129939
+ var mapped = parseInternal(s, env, opts);
129940
+ if (typeof env !== "function") {
129941
+ return mapped;
129942
+ }
129943
+ return mapped.reduce(function(acc, s2) {
129944
+ if (typeof s2 === "object") {
129945
+ return acc.concat(s2);
129946
+ }
129947
+ var xs = s2.split(RegExp("(" + TOKEN + ".*?" + TOKEN + ")", "g"));
129948
+ if (xs.length === 1) {
129949
+ return acc.concat(xs[0]);
129950
+ }
129951
+ return acc.concat(xs.filter(Boolean).map(function(x) {
129952
+ if (startsWithToken.test(x)) {
129953
+ return JSON.parse(x.split(TOKEN)[1]);
129954
+ }
129955
+ return x;
129956
+ }));
129957
+ }, []);
129958
+ };
129959
+ }
129960
+ });
129961
+
129962
+ // ../../node_modules/shell-quote/index.js
129963
+ var require_shell_quote = __commonJS({
129964
+ "../../node_modules/shell-quote/index.js"(exports) {
129965
+ "use strict";
129966
+ init_global();
129967
+ init_process();
129968
+ init_setImmediate();
129969
+ init_buffer();
129970
+ init_setInterval();
129971
+ exports.quote = require_quote();
129972
+ exports.parse = require_parse2();
129973
+ }
129974
+ });
129975
+
129510
129976
  // ../core/dist/utils/extract-git-info.js
129511
129977
  var require_extract_git_info = __commonJS({
129512
129978
  "../core/dist/utils/extract-git-info.js"(exports) {
@@ -129552,10 +130018,11 @@ var require_extract_git_info = __commonJS({
129552
130018
  return mod && mod.__esModule ? mod : { "default": mod };
129553
130019
  };
129554
130020
  Object.defineProperty(exports, "__esModule", { value: true });
129555
- exports.extractBranchLookupFallbackList = exports.isISODate = exports.extractBranchingTimestamp = exports.extractBuildIdFromCI = exports.extractCIBranchName = exports.extractGitRepo = exports.extractGitBranch = exports.extractLatestCommitInfo = exports.getPrimaryRemoteName = exports.cacheKey = void 0;
130021
+ exports.extractBranchLookupFallbackList = exports.getBranchAncestryByLocalBranches = exports.getBranchAncestryByCommits = exports.isISODate = exports.extractBranchingTimestamp = exports.extractBuildIdFromCI = exports.extractCIBranchName = exports.extractGitRepo = exports.extractGitBranch = exports.extractLatestCommitInfo = exports.extractDefaultBranch = exports.checkGitEnvironment = exports.resolveBranchToLocalRef = exports.getPrimaryRemoteName = exports.cacheKey = void 0;
129556
130022
  var utils2 = __importStar(require_browser3());
129557
130023
  var fs_1 = __importDefault((init_fs(), __toCommonJS(fs_exports)));
129558
130024
  var path_1 = __importDefault(require_path_browserify());
130025
+ var shell_quote_1 = require_shell_quote();
129559
130026
  var logger_1 = require_browser6();
129560
130027
  var isDebugMode = () => process.env.RUNNER_DEBUG === "1";
129561
130028
  exports.cacheKey = "default";
@@ -129575,14 +130042,229 @@ var require_extract_git_info = __commonJS({
129575
130042
  cwd: (_a = args[0].execOptions) === null || _a === void 0 ? void 0 : _a.cwd
129576
130043
  };
129577
130044
  });
129578
- exports.extractLatestCommitInfo = utils2.general.cachify(async function({ execOptions, logger = (0, logger_1.makeLogger)() }) {
129579
- let result;
130045
+ async function resolveBranchToLocalRef({ branchName, remoteName, execOptions, logger = (0, logger_1.makeLogger)() }) {
130046
+ const [local, tracking] = await Promise.all([
130047
+ executeWithLog((0, shell_quote_1.quote)(["git", "rev-parse", "--verify", "--quiet", `refs/heads/${branchName}`]), {
130048
+ execOptions,
130049
+ logger
130050
+ }),
130051
+ executeWithLog((0, shell_quote_1.quote)(["git", "rev-parse", "--verify", "--quiet", `refs/remotes/${remoteName}/${branchName}`]), {
130052
+ execOptions,
130053
+ logger
130054
+ })
130055
+ ]);
130056
+ if (local.code === 0 && local.stdout.trim()) {
130057
+ return branchName;
130058
+ }
130059
+ if (tracking.code === 0 && tracking.stdout.trim()) {
130060
+ const create = await executeWithLog((0, shell_quote_1.quote)(["git", "branch", branchName, `${remoteName}/${branchName}`]), {
130061
+ execOptions,
130062
+ logger
130063
+ });
130064
+ if (create.code === 0) {
130065
+ logger.log(`resolveBranchToLocalRef: created local ref refs/heads/${branchName} from ${remoteName}/${branchName}`);
130066
+ return branchName;
130067
+ }
130068
+ const recheck = await executeWithLog((0, shell_quote_1.quote)(["git", "rev-parse", "--verify", "--quiet", `refs/heads/${branchName}`]), {
130069
+ execOptions,
130070
+ logger
130071
+ });
130072
+ if (recheck.code === 0 && recheck.stdout.trim())
130073
+ return branchName;
130074
+ }
130075
+ const env = await (0, exports.checkGitEnvironment)({ execOptions, logger });
130076
+ if (env.remoteAccessible) {
130077
+ const lsR = await executeWithLog((0, shell_quote_1.quote)(["git", "ls-remote", "--heads", remoteName, branchName]), {
130078
+ execOptions,
130079
+ logger
130080
+ });
130081
+ if (lsR.code === 0 && lsR.stdout.trim()) {
130082
+ const fetched = await executeWithLog((0, shell_quote_1.quote)(["git", "fetch", remoteName, `${branchName}:${branchName}`, "--filter=tree:0"]), { execOptions, logger });
130083
+ if (fetched.code === 0) {
130084
+ logger.log(`resolveBranchToLocalRef: fetched ${branchName} from ${remoteName} into refs/heads/${branchName}`);
130085
+ return branchName;
130086
+ }
130087
+ }
130088
+ }
130089
+ return void 0;
130090
+ }
130091
+ exports.resolveBranchToLocalRef = resolveBranchToLocalRef;
130092
+ exports.checkGitEnvironment = utils2.general.cachify(async function({ execOptions, logger = (0, logger_1.makeLogger)() }) {
130093
+ var _a, _b, _c, _d, _e, _f;
130094
+ let gitInstalled = false;
130095
+ let insideRepo = false;
130096
+ let remoteAccessible = false;
130097
+ let remoteName;
130098
+ const reasons = [];
130099
+ const finalize = (extraReason) => {
130100
+ if (extraReason)
130101
+ reasons.push(extraReason);
130102
+ const result = {
130103
+ gitInstalled,
130104
+ insideRepo,
130105
+ remoteAccessible,
130106
+ ok: gitInstalled && insideRepo,
130107
+ reason: reasons.length ? reasons.join("; ") : "ok",
130108
+ remoteName
130109
+ };
130110
+ try {
130111
+ logGitEnvironmentBanner(logger, result);
130112
+ } catch {
130113
+ }
130114
+ return result;
130115
+ };
129580
130116
  try {
129581
- const githubPullRequestLastCommitSha = await extractGithubPullRequestLastCommitSha();
129582
- result = await executeWithLog(`git log ${githubPullRequestLastCommitSha !== null && githubPullRequestLastCommitSha !== void 0 ? githubPullRequestLastCommitSha : ""} -1 --format="%aI %H"`, {
130117
+ try {
130118
+ const versionResult = await executeWithLog("git --version", { execOptions, logger });
130119
+ if (versionResult.code !== 0) {
130120
+ return finalize(`git binary: ${((_a = versionResult.stderr) === null || _a === void 0 ? void 0 : _a.trim()) || `exit ${versionResult.code} (command not found?)`}`);
130121
+ }
130122
+ gitInstalled = true;
130123
+ const repoResult = await executeWithLog("git rev-parse --is-inside-work-tree", { execOptions, logger });
130124
+ if (repoResult.code !== 0 || repoResult.stdout.trim() !== "true") {
130125
+ return finalize(`repo: ${((_b = repoResult.stderr) === null || _b === void 0 ? void 0 : _b.trim()) || "not inside a git work tree"}`);
130126
+ }
130127
+ insideRepo = true;
130128
+ const remotesResult = await executeWithLog("git remote", { execOptions, logger });
130129
+ const remotesText = remotesResult.stdout.trim();
130130
+ if (remotesResult.code !== 0 || !remotesText) {
130131
+ return finalize(`remote: ${((_c = remotesResult.stderr) === null || _c === void 0 ? void 0 : _c.trim()) || "no remote configured"}`);
130132
+ }
130133
+ const remotes = remotesText.split(/\s+/).filter(Boolean);
130134
+ remoteName = remotes.includes("origin") ? "origin" : remotes[0];
130135
+ const probe = await executeWithLog((0, shell_quote_1.quote)(["git", "ls-remote", remoteName, "HEAD"]), { execOptions, logger });
130136
+ if (probe.code !== 0) {
130137
+ return finalize(`remote: ${((_d = probe.stderr) === null || _d === void 0 ? void 0 : _d.trim()) || `ls-remote exit ${probe.code}`}`);
130138
+ }
130139
+ remoteAccessible = true;
130140
+ return finalize();
130141
+ } catch (err) {
130142
+ return finalize(`probe threw: ${(_e = err === null || err === void 0 ? void 0 : err.message) !== null && _e !== void 0 ? _e : err}`);
130143
+ }
130144
+ } catch (catastrophic) {
130145
+ return {
130146
+ gitInstalled: false,
130147
+ insideRepo: false,
130148
+ remoteAccessible: false,
130149
+ ok: false,
130150
+ reason: `checkGitEnvironment catastrophic failure: ${(_f = catastrophic === null || catastrophic === void 0 ? void 0 : catastrophic.message) !== null && _f !== void 0 ? _f : catastrophic}`,
130151
+ remoteName: void 0
130152
+ };
130153
+ }
130154
+ }, (args) => {
130155
+ var _a, _b;
130156
+ return { cwd: (_b = (_a = args[0]) === null || _a === void 0 ? void 0 : _a.execOptions) === null || _b === void 0 ? void 0 : _b.cwd };
130157
+ });
130158
+ function logGitEnvironmentBanner(logger, r) {
130159
+ const sep = "============================================================";
130160
+ const allGood = r.gitInstalled && r.insideRepo && r.remoteAccessible;
130161
+ logger.log(sep);
130162
+ if (allGood) {
130163
+ logger.log("APPLITOOLS GIT ENVIRONMENT CHECK \u2713 all ok");
130164
+ } else if (!r.gitInstalled) {
130165
+ logger.log("APPLITOOLS GIT ENVIRONMENT CHECK \u2717 GIT NOT INSTALLED");
130166
+ } else if (!r.insideRepo) {
130167
+ logger.log("APPLITOOLS GIT ENVIRONMENT CHECK \u2717 NOT IN A GIT REPOSITORY");
130168
+ } else if (!r.remoteAccessible) {
130169
+ logger.log("APPLITOOLS GIT ENVIRONMENT CHECK \u2717 REMOTE NOT ACCESSIBLE");
130170
+ }
130171
+ logger.log(` git binary: ${r.gitInstalled ? "\u2713 installed" : "\u2717 NOT FOUND"}`);
130172
+ if (r.gitInstalled) {
130173
+ logger.log(` repo: ${r.insideRepo ? "\u2713 inside work tree" : "\u2717 NOT INSIDE A WORK TREE"}`);
130174
+ }
130175
+ if (r.gitInstalled && r.insideRepo) {
130176
+ const remoteLine = r.remoteAccessible ? `\u2713 accessible (${r.remoteName})` : r.remoteName ? `\u2717 NOT ACCESSIBLE (${r.remoteName})` : "\u2717 NONE CONFIGURED";
130177
+ logger.log(` remote: ${remoteLine}`);
130178
+ }
130179
+ if (!allGood) {
130180
+ logger.log(` reason: ${r.reason}`);
130181
+ if (!r.gitInstalled) {
130182
+ logger.log(" \u2192 All git-based SCM features will be SKIPPED.");
130183
+ logger.log(" \u2192 Install git or add it to PATH to enable branch detection and baseline inheritance.");
130184
+ } else if (!r.insideRepo) {
130185
+ logger.log(" \u2192 All git-based SCM features will be SKIPPED.");
130186
+ logger.log(" \u2192 Run this from inside a git working tree to enable branch detection.");
130187
+ } else if (!r.remoteAccessible) {
130188
+ logger.log(" \u2192 All remote-dependent fallbacks will be SKIPPED.");
130189
+ logger.log(" \u2192 Branch lookup may be incomplete. Verify network / credentials / remote config.");
130190
+ }
130191
+ }
130192
+ logger.log(sep);
130193
+ }
130194
+ exports.extractDefaultBranch = utils2.general.cachify(async function({ execOptions, logger = (0, logger_1.makeLogger)() }) {
130195
+ var _a;
130196
+ logger = logger.extend({ tags: [`extract-default-branch-${utils2.general.shortid()}`] });
130197
+ const envOverride = (_a = process.env.APPLITOOLS_DEFAULT_BRANCH) === null || _a === void 0 ? void 0 : _a.trim();
130198
+ if (envOverride) {
130199
+ logger.log(`extractDefaultBranch: using APPLITOOLS_DEFAULT_BRANCH="${envOverride}"`);
130200
+ return envOverride;
130201
+ }
130202
+ const env = await (0, exports.checkGitEnvironment)({ execOptions, logger });
130203
+ if (!env.ok) {
130204
+ logger.log("extractDefaultBranch: git environment not ok, falling back to 'main'");
130205
+ return "main";
130206
+ }
130207
+ const remoteName = await (0, exports.getPrimaryRemoteName)({ execOptions, logger });
130208
+ try {
130209
+ const r = await executeWithLog((0, shell_quote_1.quote)(["git", "symbolic-ref", "--short", `refs/remotes/${remoteName}/HEAD`]), {
129583
130210
  execOptions,
129584
130211
  logger
129585
130212
  });
130213
+ if (!r.stderr && r.stdout.trim()) {
130214
+ const out = r.stdout.trim();
130215
+ const normalized = out.replace(new RegExp(`^${remoteName}/`), "");
130216
+ if (normalized) {
130217
+ logger.log(`extractDefaultBranch: resolved via symbolic-ref -> "${normalized}"`);
130218
+ return normalized;
130219
+ }
130220
+ }
130221
+ } catch (err) {
130222
+ if (isDebugMode())
130223
+ logger.log("extractDefaultBranch: symbolic-ref step failed, continuing", err);
130224
+ }
130225
+ try {
130226
+ const r = await executeWithLog((0, shell_quote_1.quote)(["git", "ls-remote", "--symref", remoteName, "HEAD"]), { execOptions, logger });
130227
+ if (!r.stderr && r.stdout) {
130228
+ const match = r.stdout.match(/^ref:\s+refs\/heads\/([^\s]+)\s+HEAD/m);
130229
+ if (match && match[1]) {
130230
+ logger.log(`extractDefaultBranch: resolved via ls-remote --symref -> "${match[1]}"`);
130231
+ return match[1];
130232
+ }
130233
+ }
130234
+ } catch (err) {
130235
+ if (isDebugMode())
130236
+ logger.log("extractDefaultBranch: ls-remote --symref step failed, continuing", err);
130237
+ }
130238
+ try {
130239
+ const r = await executeWithLog("git config --get init.defaultBranch", { execOptions, logger });
130240
+ if (!r.stderr && r.stdout.trim()) {
130241
+ logger.log(`extractDefaultBranch: resolved via init.defaultBranch -> "${r.stdout.trim()}"`);
130242
+ return r.stdout.trim();
130243
+ }
130244
+ } catch (err) {
130245
+ if (isDebugMode())
130246
+ logger.log("extractDefaultBranch: init.defaultBranch step failed, continuing", err);
130247
+ }
130248
+ logger.log('extractDefaultBranch: falling back to literal "main"');
130249
+ return "main";
130250
+ }, (args) => {
130251
+ var _a, _b;
130252
+ return { cwd: (_b = (_a = args[0]) === null || _a === void 0 ? void 0 : _a.execOptions) === null || _b === void 0 ? void 0 : _b.cwd };
130253
+ });
130254
+ exports.extractLatestCommitInfo = utils2.general.cachify(async function({ execOptions, logger = (0, logger_1.makeLogger)() }) {
130255
+ const env = await (0, exports.checkGitEnvironment)({ execOptions, logger });
130256
+ if (!env.ok) {
130257
+ logger.log("extractLatestCommitInfo: git environment not ok, skipping");
130258
+ return void 0;
130259
+ }
130260
+ let result;
130261
+ try {
130262
+ const githubPullRequestLastCommitSha = await extractGithubPullRequestLastCommitSha();
130263
+ const logArgs = ["git", "log"];
130264
+ if (githubPullRequestLastCommitSha)
130265
+ logArgs.push(githubPullRequestLastCommitSha);
130266
+ logArgs.push("-1", "--format=%aI %H");
130267
+ result = await executeWithLog((0, shell_quote_1.quote)(logArgs), { execOptions, logger });
129586
130268
  if (result.stderr) {
129587
130269
  logger.log(`Error during extracting commit information from git`, result.stderr);
129588
130270
  } else {
@@ -129600,7 +130282,7 @@ var require_extract_git_info = __commonJS({
129600
130282
  var _a, _b, _c;
129601
130283
  if (((_a = process.env.GITHUB_EVENT_NAME) === null || _a === void 0 ? void 0 : _a.startsWith("pull_request")) && process.env.GITHUB_EVENT_PATH) {
129602
130284
  const remoteName = await (0, exports.getPrimaryRemoteName)({ execOptions, logger });
129603
- await executeWithLog(`git fetch ${remoteName} --depth=2`, { execOptions, logger });
130285
+ await executeWithLog((0, shell_quote_1.quote)(["git", "fetch", remoteName, "--depth=2"]), { execOptions, logger });
129604
130286
  const event = await fs_1.default.promises.readFile(process.env.GITHUB_EVENT_PATH, "utf-8").then(JSON.parse);
129605
130287
  return (_c = (_b = event === null || event === void 0 ? void 0 : event.pull_request) === null || _b === void 0 ? void 0 : _b.head) === null || _c === void 0 ? void 0 : _c.sha;
129606
130288
  }
@@ -129612,6 +130294,11 @@ var require_extract_git_info = __commonJS({
129612
130294
  logger.log(`Extracted branch name from CI environment: "${ciBranch}"`);
129613
130295
  return ciBranch;
129614
130296
  }
130297
+ const env = await (0, exports.checkGitEnvironment)({ execOptions, logger });
130298
+ if (!env.ok) {
130299
+ logger.log("extractGitBranch: git environment not ok, no branch name available");
130300
+ return void 0;
130301
+ }
129615
130302
  const result = await executeWithLog("git branch --show-current", { execOptions, logger });
129616
130303
  if (result.stderr) {
129617
130304
  logger.log(`Error during extracting current branch from git`, result.stderr);
@@ -129628,10 +130315,15 @@ var require_extract_git_info = __commonJS({
129628
130315
  return { cwd: (_b = (_a = args[0]) === null || _a === void 0 ? void 0 : _a.execOptions) === null || _b === void 0 ? void 0 : _b.cwd, ignoreGitBranching: (_c = args[0]) === null || _c === void 0 ? void 0 : _c.ignoreGitBranching };
129629
130316
  });
129630
130317
  exports.extractGitRepo = utils2.general.cachify(async function({ execOptions, logger = (0, logger_1.makeLogger)() }) {
130318
+ const env = await (0, exports.checkGitEnvironment)({ execOptions, logger });
130319
+ if (!env.ok) {
130320
+ logger.log("extractGitRepo: git environment not ok, returning empty repo info");
130321
+ return {};
130322
+ }
129631
130323
  const remotes = await extractRemotes();
129632
130324
  logger.log(`Extracted remotes from git: ${remotes}`);
129633
130325
  const remote = remotes.includes("origin") ? "origin" : remotes[0];
129634
- const result = await executeWithLog(`git remote get-url ${remote}`, { execOptions, logger });
130326
+ const result = await executeWithLog((0, shell_quote_1.quote)(["git", "remote", "get-url", remote]), { execOptions, logger });
129635
130327
  if (result.stderr) {
129636
130328
  logger.log(`Error during extracting remote url from git`, result.stderr);
129637
130329
  return {};
@@ -129675,51 +130367,82 @@ var require_extract_git_info = __commonJS({
129675
130367
  }
129676
130368
  exports.extractBuildIdFromCI = extractBuildIdFromCI;
129677
130369
  exports.extractBranchingTimestamp = utils2.general.cachify(async function({ branchName, parentBranchName, execOptions, logger = (0, logger_1.makeLogger)() }) {
129678
- var _a;
129679
130370
  logger = logger.extend({ tags: [`extract-branching-timestamp-${utils2.general.shortid()}`] });
129680
- const remoteName = await (0, exports.getPrimaryRemoteName)({ execOptions, logger });
129681
- const shallowCheckResult = await executeWithLog("git rev-parse --is-shallow-repository", {
129682
- execOptions,
129683
- logger
129684
- });
129685
- const isShallow = shallowCheckResult.stdout.trim() === "true";
129686
- if (isShallow) {
129687
- logger.log("extractBranchingTimestamp - Repository is a shallow clone, attempting to unshallow");
129688
- await executeFetchStrategy(isShallow, execOptions, logger);
129689
- }
129690
- const command = `HASH=$(git merge-base ${branchName} ${parentBranchName}) && git show -q --format=%aI $HASH`;
129691
- let result = await executeWithLog(command, { execOptions, logger });
129692
- if (result.stderr) {
129693
- const commandWithRemoteRefs = `HASH=$(git merge-base ${remoteName}/${branchName} ${remoteName}/${parentBranchName}) && git show -q --format=%aI $HASH`;
129694
- result = await executeWithLog(commandWithRemoteRefs, { execOptions, logger });
129695
- }
129696
- if (result.stderr) {
129697
- const remoteBranches = await getAllRemoteBranches({ execOptions, logger });
129698
- for (let i = 0; i < 2; i++) {
129699
- if (result.stderr) {
129700
- const [, missingBranch] = (_a = result.stderr.match(/Not a valid object name ([^\s]+)/)) !== null && _a !== void 0 ? _a : [];
129701
- if (missingBranch) {
129702
- const normalizedBranchName = missingBranch.replace(new RegExp(`^${remoteName}/`), "");
129703
- if (!remoteBranches.has(normalizedBranchName)) {
129704
- logger.log(`Branch ${missingBranch} not found on remote, skipping fetch`);
129705
- return void 0;
129706
- }
129707
- logger.log(`Fetching missing branch ${missingBranch} from remote`);
129708
- const command2 = `HASH=$(git merge-base ${branchName} ${parentBranchName}) && git show -q --format=%aI $HASH`;
129709
- result = await executeWithLog(`git fetch ${remoteName} ${normalizedBranchName}:${normalizedBranchName} --filter=tree:0 && ${command2}`, {
129710
- execOptions,
129711
- logger
129712
- });
129713
- }
130371
+ try {
130372
+ const env = await (0, exports.checkGitEnvironment)({ execOptions, logger });
130373
+ if (!env.ok) {
130374
+ logger.log("extractBranchingTimestamp: git environment not ok, skipping");
130375
+ return void 0;
130376
+ }
130377
+ const remoteName = await (0, exports.getPrimaryRemoteName)({ execOptions, logger });
130378
+ const shallowCheckResult = await executeWithLog("git rev-parse --is-shallow-repository", {
130379
+ execOptions,
130380
+ logger
130381
+ });
130382
+ const isShallow = shallowCheckResult.stdout.trim() === "true";
130383
+ if (isShallow) {
130384
+ logger.log("extractBranchingTimestamp - Repository is a shallow clone, attempting to unshallow");
130385
+ await executeFetchStrategy(isShallow, execOptions, logger);
130386
+ }
130387
+ async function getMergeBase(ref1, ref2) {
130388
+ const { stdout, stderr } = await executeWithLog((0, shell_quote_1.quote)(["git", "merge-base", ref1, ref2]), { execOptions, logger });
130389
+ if (stderr) {
130390
+ if (isDebugMode())
130391
+ logger.log(`getMergeBase failed for ${ref1} and ${ref2}: ${stderr}`);
130392
+ return null;
129714
130393
  }
130394
+ return stdout.trim();
129715
130395
  }
129716
- }
129717
- const timestamp = result.stdout.replace(/\s/g, "");
129718
- if (isISODate(timestamp)) {
129719
- logger.log("git branching timestamp successfully extracted", timestamp);
129720
- return timestamp;
129721
- } else {
129722
- logger.log(`Error during extracting merge timestamp: git branching timestamp is an invalid ISO date string: ${timestamp}. stderr: ${result.stderr}, stdout: ${result.stdout}`);
130396
+ async function getTimestampForHash(hash) {
130397
+ if (!hash)
130398
+ return void 0;
130399
+ const { stdout, stderr } = await executeWithLog((0, shell_quote_1.quote)(["git", "show", "-s", "--format=%aI", hash]), {
130400
+ execOptions,
130401
+ logger
130402
+ });
130403
+ const timestamp2 = stdout.trim();
130404
+ if (stderr || !isISODate(timestamp2)) {
130405
+ logger.log(`Error extracting timestamp for hash ${hash}: stderr: ${stderr}, stdout: ${stdout}`);
130406
+ return void 0;
130407
+ }
130408
+ return timestamp2;
130409
+ }
130410
+ let mergeBaseHash = null;
130411
+ mergeBaseHash = await getMergeBase(`${remoteName}/${branchName}`, `${remoteName}/${parentBranchName}`);
130412
+ if (!mergeBaseHash) {
130413
+ mergeBaseHash = await getMergeBase(branchName, parentBranchName);
130414
+ }
130415
+ if (!mergeBaseHash) {
130416
+ const remoteBranches = await getAllRemoteBranches({ execOptions, logger });
130417
+ if (!remoteBranches.has(parentBranchName)) {
130418
+ logger.log(`Parent branch ${parentBranchName} not found on remote, cannot determine branching point.`);
130419
+ return void 0;
130420
+ }
130421
+ const branchesToFetch = [parentBranchName];
130422
+ if (branchName !== parentBranchName && remoteBranches.has(branchName)) {
130423
+ branchesToFetch.push(branchName);
130424
+ }
130425
+ logger.log(`Fetching missing branches [${branchesToFetch.join(", ")}] from remote and retrying merge-base`);
130426
+ for (const branch of branchesToFetch) {
130427
+ await executeWithLog((0, shell_quote_1.quote)(["git", "fetch", remoteName, `${branch}:${branch}`, "--filter=tree:0"]), {
130428
+ execOptions,
130429
+ logger
130430
+ });
130431
+ }
130432
+ mergeBaseHash = await getMergeBase(branchName, parentBranchName);
130433
+ }
130434
+ if (!mergeBaseHash) {
130435
+ logger.log(`Could not find a merge-base for ${branchName} and ${parentBranchName}.`);
130436
+ return void 0;
130437
+ }
130438
+ const timestamp = await getTimestampForHash(mergeBaseHash);
130439
+ if (timestamp) {
130440
+ logger.log(`git branching timestamp for parent '${parentBranchName}' successfully extracted: ${timestamp}`);
130441
+ return timestamp;
130442
+ }
130443
+ } catch (err) {
130444
+ logger.log("extractBranchingTimestamp: unexpected error, returning undefined", err);
130445
+ return void 0;
129723
130446
  }
129724
130447
  }, (args) => {
129725
130448
  var _a;
@@ -129744,6 +130467,47 @@ var require_extract_git_info = __commonJS({
129744
130467
  return /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\+\d{2}:\d{2})?/.test(str);
129745
130468
  }
129746
130469
  exports.isISODate = isISODate;
130470
+ var GIT_PREDICATE_MAX_ATTEMPTS = 3;
130471
+ function classifyGitPredicate(result) {
130472
+ const code = result.code;
130473
+ const hasStderr = Boolean(result.stderr && result.stderr.trim());
130474
+ if (code === 0 && !hasStderr)
130475
+ return true;
130476
+ if (code === 1 && !hasStderr)
130477
+ return false;
130478
+ return "error";
130479
+ }
130480
+ async function runGitPredicateWithRetry(command, { execOptions, logger }) {
130481
+ let outcome = "error";
130482
+ for (let attempt = 0; attempt < GIT_PREDICATE_MAX_ATTEMPTS; attempt++) {
130483
+ const result = await executeWithLog(command, { execOptions, logger });
130484
+ outcome = classifyGitPredicate(result);
130485
+ if (outcome !== "error")
130486
+ return outcome;
130487
+ if (attempt < GIT_PREDICATE_MAX_ATTEMPTS - 1) {
130488
+ await gitRetryBackoff(attempt, command, logger);
130489
+ }
130490
+ }
130491
+ return outcome;
130492
+ }
130493
+ async function gitRetryBackoff(attempt, command, logger) {
130494
+ const backoff = 50 * 2 ** attempt + Math.floor(Math.random() * 10);
130495
+ if (isDebugMode()) {
130496
+ logger.log(`git transient error (attempt ${attempt + 1}), retrying in ${backoff}ms: ${command}`);
130497
+ }
130498
+ await new Promise((resolve) => setTimeout(resolve, backoff));
130499
+ }
130500
+ async function runGitContainsWithRetry(command, { execOptions, logger }) {
130501
+ for (let attempt = 0; attempt < GIT_PREDICATE_MAX_ATTEMPTS; attempt++) {
130502
+ const result = await executeWithLog(command, { execOptions, logger });
130503
+ if (!(result.stderr && result.stderr.trim()))
130504
+ return result.stdout;
130505
+ if (attempt < GIT_PREDICATE_MAX_ATTEMPTS - 1) {
130506
+ await gitRetryBackoff(attempt, command, logger);
130507
+ }
130508
+ }
130509
+ return "";
130510
+ }
129747
130511
  async function parallelWithLimit(items, concurrency, fn) {
129748
130512
  const results = [];
129749
130513
  for (let i = 0; i < items.length; i += concurrency) {
@@ -129753,6 +130517,262 @@ var require_extract_git_info = __commonJS({
129753
130517
  }
129754
130518
  return results;
129755
130519
  }
130520
+ async function getBranchAncestryByCommits({ gitBranchName, defaultBranch, execOptions, logger = (0, logger_1.makeLogger)() }) {
130521
+ logger = logger.extend({ tags: [`get-branch-ancestry-by-commits-${utils2.general.shortid()}`] });
130522
+ if (isDebugMode()) {
130523
+ logger.log(`[byCommits] Start: gitBranchName=${gitBranchName}, defaultBranch=${defaultBranch}`);
130524
+ }
130525
+ const env = await (0, exports.checkGitEnvironment)({ execOptions, logger });
130526
+ if (!env.ok) {
130527
+ logger.log("[byCommits] git environment not ok, returning []");
130528
+ return [];
130529
+ }
130530
+ try {
130531
+ let mergeBaseResult = await executeWithLog((0, shell_quote_1.quote)(["git", "merge-base", gitBranchName, defaultBranch]), {
130532
+ execOptions,
130533
+ logger
130534
+ });
130535
+ if (mergeBaseResult.stderr || !mergeBaseResult.stdout.trim()) {
130536
+ const remoteName2 = await (0, exports.getPrimaryRemoteName)({ execOptions, logger });
130537
+ const resolved = await resolveBranchToLocalRef({ branchName: defaultBranch, remoteName: remoteName2, execOptions, logger });
130538
+ if (resolved) {
130539
+ mergeBaseResult = await executeWithLog((0, shell_quote_1.quote)(["git", "merge-base", gitBranchName, defaultBranch]), {
130540
+ execOptions,
130541
+ logger
130542
+ });
130543
+ }
130544
+ if (mergeBaseResult.stderr || !mergeBaseResult.stdout.trim()) {
130545
+ logger.log(`[byCommits] \u2717 merge-base ${gitBranchName} ${defaultBranch} failed (stderr="${mergeBaseResult.stderr}"), returning []`);
130546
+ return [];
130547
+ }
130548
+ }
130549
+ const mergeBase = mergeBaseResult.stdout.trim();
130550
+ if (isDebugMode())
130551
+ logger.log(`[byCommits] Merge-base resolved: ${mergeBase}`);
130552
+ const logResult = await executeWithLog((0, shell_quote_1.quote)(["git", "log", "--format=%H", `${mergeBase}..${gitBranchName}`]), {
130553
+ execOptions,
130554
+ logger
130555
+ });
130556
+ if (logResult.stderr) {
130557
+ logger.log(`[byCommits] \u2717 git log ${mergeBase}..${gitBranchName} failed (stderr="${logResult.stderr}"), returning []`);
130558
+ return [];
130559
+ }
130560
+ const commits = logResult.stdout.trim().split("\n").filter(Boolean);
130561
+ if (isDebugMode())
130562
+ logger.log(`[byCommits] Walking ${commits.length} commit(s) in window ${mergeBase}..${gitBranchName}`);
130563
+ const candidates = /* @__PURE__ */ new Set([defaultBranch, gitBranchName]);
130564
+ const containResults = await parallelWithLimit(commits, 10, async (hash) => {
130565
+ const r = await runGitContainsWithRetry((0, shell_quote_1.quote)(["git", "branch", "-a", "--contains", hash, "--format=%(refname:short)"]), { execOptions, logger });
130566
+ return r.split("\n").map((line) => line.trim()).filter((b) => b && b !== "HEAD");
130567
+ });
130568
+ if (isDebugMode()) {
130569
+ logger.log(`[byCommits] Branches containing commits in ${mergeBase}..${gitBranchName}:`, containResults);
130570
+ }
130571
+ for (const list of containResults)
130572
+ for (const b of list)
130573
+ candidates.add(b);
130574
+ const atMergeBase = await runGitContainsWithRetry((0, shell_quote_1.quote)(["git", "branch", "-a", "--contains", mergeBase, "--format=%(refname:short)"]), { execOptions, logger });
130575
+ for (const b of atMergeBase.split("\n").map((l) => l.trim()).filter((b2) => b2 && b2 !== "HEAD")) {
130576
+ candidates.add(b);
130577
+ }
130578
+ if (isDebugMode()) {
130579
+ logger.log(`[byCommits] Unioned candidates before descendant filter (${candidates.size}): ${Array.from(candidates).join(", ")}`);
130580
+ }
130581
+ const remoteName = await (0, exports.getPrimaryRemoteName)({ execOptions, logger });
130582
+ let droppedSelf = 0;
130583
+ let droppedDescendants = 0;
130584
+ let droppedCousins = 0;
130585
+ const finalCandidates = await parallelWithLimit(Array.from(candidates), 10, async (branch) => {
130586
+ const normalizedBranch = branch.replace(new RegExp(`^${remoteName}/`), "");
130587
+ if (normalizedBranch === gitBranchName) {
130588
+ droppedSelf++;
130589
+ return null;
130590
+ }
130591
+ if (normalizedBranch === defaultBranch) {
130592
+ if (isDebugMode())
130593
+ logger.log(`[byCommits] KEEP base (default branch): ${normalizedBranch}`);
130594
+ return normalizedBranch;
130595
+ }
130596
+ const isDescendant = await runGitPredicateWithRetry((0, shell_quote_1.quote)(["git", "merge-base", "--is-ancestor", gitBranchName, branch]), { execOptions, logger });
130597
+ if (isDescendant === true) {
130598
+ droppedDescendants++;
130599
+ if (isDebugMode())
130600
+ logger.log(`[byCommits] DROP descendant: ${normalizedBranch}`);
130601
+ return null;
130602
+ }
130603
+ const mbAllResult = await runGitContainsWithRetry((0, shell_quote_1.quote)(["git", "merge-base", "--all", gitBranchName, branch]), {
130604
+ execOptions,
130605
+ logger
130606
+ });
130607
+ const mbCs = mbAllResult.split("\n").map((line) => line.trim()).filter(Boolean);
130608
+ if (mbCs.length === 0) {
130609
+ if (isDebugMode())
130610
+ logger.log(`[byCommits] KEEP (no merge-base resolved, conservative): ${normalizedBranch}`);
130611
+ return normalizedBranch;
130612
+ }
130613
+ let anyStrictlyAboveFloor = false;
130614
+ for (const mbC of mbCs) {
130615
+ if (mbC === mergeBase)
130616
+ continue;
130617
+ const floorIsAncestorOfMbC = await runGitPredicateWithRetry((0, shell_quote_1.quote)(["git", "merge-base", "--is-ancestor", mergeBase, mbC]), { execOptions, logger });
130618
+ if (floorIsAncestorOfMbC === true || floorIsAncestorOfMbC === "error") {
130619
+ anyStrictlyAboveFloor = true;
130620
+ break;
130621
+ }
130622
+ }
130623
+ if (!anyStrictlyAboveFloor) {
130624
+ droppedCousins++;
130625
+ if (isDebugMode())
130626
+ logger.log(`[byCommits] DROP cousin (shares only the floor): ${normalizedBranch}`);
130627
+ return null;
130628
+ }
130629
+ if (isDebugMode())
130630
+ logger.log(`[byCommits] KEEP lineage point: ${normalizedBranch}`);
130631
+ return normalizedBranch;
130632
+ });
130633
+ const finalCleanBranches = finalCandidates.filter((b) => b !== null);
130634
+ const result = Array.from(new Set(finalCleanBranches)).sort();
130635
+ if (isDebugMode()) {
130636
+ logger.log(`[byCommits] Done. dropped(self=${droppedSelf}, descendants=${droppedDescendants}, cousins=${droppedCousins}) \u2192 ${result.length} lineage point(s): ${result.join(", ")}`);
130637
+ }
130638
+ return result;
130639
+ } catch (err) {
130640
+ logger.log("[byCommits] \u2717 ERROR", err);
130641
+ return [];
130642
+ }
130643
+ }
130644
+ exports.getBranchAncestryByCommits = getBranchAncestryByCommits;
130645
+ async function getBranchAncestryByLocalBranches({ gitBranchName, defaultBranch, execOptions, logger = (0, logger_1.makeLogger)() }) {
130646
+ logger = logger.extend({ tags: [`get-branch-ancestry-by-local-branches-${utils2.general.shortid()}`] });
130647
+ if (isDebugMode()) {
130648
+ logger.log(`[byLocalBranches] Start: gitBranchName=${gitBranchName}, defaultBranch=${defaultBranch}`);
130649
+ }
130650
+ const env = await (0, exports.checkGitEnvironment)({ execOptions, logger });
130651
+ if (!env.ok) {
130652
+ logger.log("[byLocalBranches] git environment not ok, returning []");
130653
+ return [];
130654
+ }
130655
+ let droppedNoMb = 0;
130656
+ let droppedRule1 = 0;
130657
+ let droppedRule2 = 0;
130658
+ let pinned = 0;
130659
+ try {
130660
+ let mergeBaseResult = await executeWithLog((0, shell_quote_1.quote)(["git", "merge-base", gitBranchName, defaultBranch]), {
130661
+ execOptions,
130662
+ logger
130663
+ });
130664
+ if (mergeBaseResult.stderr || !mergeBaseResult.stdout.trim()) {
130665
+ const remoteName2 = await (0, exports.getPrimaryRemoteName)({ execOptions, logger });
130666
+ const resolved = await resolveBranchToLocalRef({ branchName: defaultBranch, remoteName: remoteName2, execOptions, logger });
130667
+ if (resolved) {
130668
+ mergeBaseResult = await executeWithLog((0, shell_quote_1.quote)(["git", "merge-base", gitBranchName, defaultBranch]), {
130669
+ execOptions,
130670
+ logger
130671
+ });
130672
+ }
130673
+ if (mergeBaseResult.stderr || !mergeBaseResult.stdout.trim()) {
130674
+ logger.log(`[byLocalBranches] \u2717 merge-base ${gitBranchName} ${defaultBranch} failed (stderr="${mergeBaseResult.stderr}"), returning []`);
130675
+ return [];
130676
+ }
130677
+ }
130678
+ const mergeBase = mergeBaseResult.stdout.trim();
130679
+ if (isDebugMode())
130680
+ logger.log(`[byLocalBranches] Primary merge-base: ${mergeBase}`);
130681
+ const remoteName = await (0, exports.getPrimaryRemoteName)({ execOptions, logger });
130682
+ const refsResult = await executeWithLog((0, shell_quote_1.quote)(["git", "for-each-ref", "--format=%(refname:short)", "refs/heads/", `refs/remotes/${remoteName}/`]), { execOptions, logger });
130683
+ if (refsResult.stderr) {
130684
+ logger.log(`[byLocalBranches] \u2717 for-each-ref failed (stderr="${refsResult.stderr}"), returning []`);
130685
+ return [];
130686
+ }
130687
+ const candidateBranches = /* @__PURE__ */ new Map();
130688
+ candidateBranches.set(defaultBranch, defaultBranch);
130689
+ candidateBranches.set(gitBranchName, gitBranchName);
130690
+ for (const raw of refsResult.stdout.split("\n")) {
130691
+ const trimmed = raw.trim();
130692
+ if (!trimmed)
130693
+ continue;
130694
+ const normalized = trimmed.replace(new RegExp(`^${remoteName}/`), "");
130695
+ if (!normalized || normalized === "HEAD")
130696
+ continue;
130697
+ if (!candidateBranches.has(normalized)) {
130698
+ candidateBranches.set(normalized, trimmed);
130699
+ }
130700
+ }
130701
+ if (isDebugMode()) {
130702
+ logger.log(`[byLocalBranches] Enumerated ${candidateBranches.size} candidate(s): ${Array.from(candidateBranches.keys()).join(", ")}`);
130703
+ }
130704
+ const results = await parallelWithLimit(Array.from(candidateBranches.entries()), 10, async ([branch, refToUse]) => {
130705
+ if (branch === defaultBranch || branch === gitBranchName) {
130706
+ pinned++;
130707
+ if (isDebugMode())
130708
+ logger.log(`[byLocalBranches] KEEP pinned: ${branch}`);
130709
+ return branch;
130710
+ }
130711
+ const branchMbR = await runGitContainsWithRetry((0, shell_quote_1.quote)(["git", "merge-base", "--all", refToUse, gitBranchName]), {
130712
+ execOptions,
130713
+ logger
130714
+ });
130715
+ const branchMbs = branchMbR.split("\n").map((line) => line.trim()).filter(Boolean);
130716
+ if (branchMbs.length === 0) {
130717
+ droppedNoMb++;
130718
+ if (isDebugMode()) {
130719
+ logger.log(`[byLocalBranches] DROP no-merge-base: ${branch}`);
130720
+ }
130721
+ return null;
130722
+ }
130723
+ let anyStrictlyAboveFloor = false;
130724
+ for (const branchMb2 of branchMbs) {
130725
+ if (branchMb2 === mergeBase)
130726
+ continue;
130727
+ const r1 = await runGitPredicateWithRetry((0, shell_quote_1.quote)(["git", "merge-base", "--is-ancestor", mergeBase, branchMb2]), {
130728
+ execOptions,
130729
+ logger
130730
+ });
130731
+ if (r1 === true || r1 === "error") {
130732
+ anyStrictlyAboveFloor = true;
130733
+ break;
130734
+ }
130735
+ }
130736
+ if (!anyStrictlyAboveFloor) {
130737
+ droppedRule1++;
130738
+ if (isDebugMode()) {
130739
+ logger.log(`[byLocalBranches] DROP Rule 1 (cousin \u2014 shares only the floor ${mergeBase}): ${branch} \u2014 bases=${branchMbs.join(",")}`);
130740
+ }
130741
+ return null;
130742
+ }
130743
+ const branchMb = branchMbs[0];
130744
+ const r2 = await runGitPredicateWithRetry((0, shell_quote_1.quote)(["git", "merge-base", "--is-ancestor", gitBranchName, refToUse]), {
130745
+ execOptions,
130746
+ logger
130747
+ });
130748
+ if (r2 === true) {
130749
+ droppedRule2++;
130750
+ if (isDebugMode()) {
130751
+ logger.log(`[byLocalBranches] DROP Rule 2 (descendant): ${branch} \u2014 ${gitBranchName} is its ancestor`);
130752
+ }
130753
+ return null;
130754
+ }
130755
+ if (r2 === "error") {
130756
+ droppedRule2++;
130757
+ if (isDebugMode())
130758
+ logger.log(`[byLocalBranches] DROP Rule 2 (transient error): ${branch}`);
130759
+ return null;
130760
+ }
130761
+ if (isDebugMode())
130762
+ logger.log(`[byLocalBranches] KEEP ancestor: ${branch} (mb=${branchMb})`);
130763
+ return branch;
130764
+ });
130765
+ const result = Array.from(new Set(results.filter((b) => b !== null))).sort();
130766
+ if (isDebugMode()) {
130767
+ logger.log(`[byLocalBranches] Done. pinned=${pinned}, dropped(no-mb=${droppedNoMb}, rule1=${droppedRule1}, rule2=${droppedRule2}) \u2192 ${result.length} ancestor(s): ${result.join(", ")}`);
130768
+ }
130769
+ return result;
130770
+ } catch (err) {
130771
+ logger.log("[byLocalBranches] \u2717 ERROR", err);
130772
+ return [];
130773
+ }
130774
+ }
130775
+ exports.getBranchAncestryByLocalBranches = getBranchAncestryByLocalBranches;
129756
130776
  var getAllRemoteBranches = utils2.general.cachify(
129757
130777
  async function({ execOptions, logger }) {
129758
130778
  var _a;
@@ -129760,10 +130780,15 @@ var require_extract_git_info = __commonJS({
129760
130780
  logger.log("[getAllRemoteBranches] Starting git ls-remote to fetch all remote branches...");
129761
130781
  logger.log("[getAllRemoteBranches] execOptions.cwd:", (execOptions === null || execOptions === void 0 ? void 0 : execOptions.cwd) || "undefined");
129762
130782
  }
130783
+ const env = await (0, exports.checkGitEnvironment)({ execOptions, logger });
130784
+ if (!env.remoteAccessible) {
130785
+ logger.log("[getAllRemoteBranches] Skipping ls-remote (remote not accessible), returning empty set");
130786
+ return /* @__PURE__ */ new Set();
130787
+ }
129763
130788
  try {
129764
130789
  const remoteName = await (0, exports.getPrimaryRemoteName)({ execOptions, logger });
129765
130790
  const startTime = Date.now();
129766
- const result = await executeWithLog(`git ls-remote --heads ${remoteName}`, {
130791
+ const result = await executeWithLog((0, shell_quote_1.quote)(["git", "ls-remote", "--heads", remoteName]), {
129767
130792
  execOptions,
129768
130793
  logger
129769
130794
  });
@@ -129812,7 +130837,7 @@ var require_extract_git_info = __commonJS({
129812
130837
  return /* @__PURE__ */ new Set();
129813
130838
  }
129814
130839
  },
129815
- // Custom cache key generator - only cache by cwd, not by logger instance
130840
+ // Cache by cwd only, not by logger instance.
129816
130841
  (args) => {
129817
130842
  var _a;
129818
130843
  return { cwd: (_a = args[0].execOptions) === null || _a === void 0 ? void 0 : _a.cwd };
@@ -129820,17 +130845,22 @@ var require_extract_git_info = __commonJS({
129820
130845
  5 * 60 * 1e3
129821
130846
  );
129822
130847
  async function executeFetchStrategy(isShallow, execOptions, logger) {
130848
+ const env = await (0, exports.checkGitEnvironment)({ execOptions, logger });
130849
+ if (!env.remoteAccessible) {
130850
+ logger.log("executeFetchStrategy: skipping fetch (remote not accessible)");
130851
+ return;
130852
+ }
129823
130853
  const remoteName = await (0, exports.getPrimaryRemoteName)({ execOptions, logger });
129824
130854
  if (isShallow) {
129825
130855
  logger.log(`Shallow repository detected, unshallowing to enable topology discovery...`);
129826
- await executeWithLog(`git fetch ${remoteName} --unshallow --filter=blob:none`, {
130856
+ await executeWithLog((0, shell_quote_1.quote)(["git", "fetch", remoteName, "--unshallow", "--filter=blob:none"]), {
129827
130857
  execOptions,
129828
130858
  logger
129829
130859
  });
129830
130860
  logger.log(`Repository unshallowed successfully`);
129831
130861
  } else {
129832
130862
  logger.log(`Non-shallow clone detected, fetching all remote branches for topology discovery...`);
129833
- await executeWithLog(`git fetch ${remoteName} --filter=tree:0`, {
130863
+ await executeWithLog((0, shell_quote_1.quote)(["git", "fetch", remoteName, "--filter=tree:0"]), {
129834
130864
  execOptions,
129835
130865
  logger
129836
130866
  });
@@ -129838,9 +130868,14 @@ var require_extract_git_info = __commonJS({
129838
130868
  }
129839
130869
  }
129840
130870
  async function ensureRemoteBranchesAvailable(branchName, isShallow, execOptions, logger) {
130871
+ const env = await (0, exports.checkGitEnvironment)({ execOptions, logger });
130872
+ if (!env.remoteAccessible) {
130873
+ logger.log("ensureRemoteBranchesAvailable: skipping (remote not accessible)");
130874
+ return;
130875
+ }
129841
130876
  try {
129842
130877
  const remoteName = await (0, exports.getPrimaryRemoteName)({ execOptions, logger });
129843
- const symbolicResult = await executeWithLog(`git rev-parse --abbrev-ref ${branchName}@{upstream} `, {
130878
+ const symbolicResult = await executeWithLog((0, shell_quote_1.quote)(["git", "rev-parse", "--abbrev-ref", `${branchName}@{upstream}`]), {
129844
130879
  execOptions,
129845
130880
  logger
129846
130881
  });
@@ -129849,12 +130884,14 @@ var require_extract_git_info = __commonJS({
129849
130884
  return;
129850
130885
  }
129851
130886
  logger.log(`Detected remote branch scenario, fetching ancestor branches...`);
129852
- await executeWithLog(`git config remote.${remoteName}.fetch "+refs/heads/*:refs/remotes/${remoteName}/*"`, {
129853
- execOptions,
129854
- logger
129855
- });
130887
+ await executeWithLog((0, shell_quote_1.quote)(["git", "config", `remote.${remoteName}.fetch`, `+refs/heads/*:refs/remotes/${remoteName}/*`]), { execOptions, logger });
129856
130888
  await executeFetchStrategy(isShallow, execOptions, logger);
129857
130889
  logger.log(`Remote branches fetched successfully for complete ancestor check`);
130890
+ try {
130891
+ await executeWithLog((0, shell_quote_1.quote)(["git", "remote", "set-head", remoteName, "-a"]), { execOptions, logger });
130892
+ } catch (err) {
130893
+ logger.log("ensureRemoteBranchesAvailable: remote set-head -a failed (continuing)", err);
130894
+ }
129858
130895
  } catch (err) {
129859
130896
  logger.log("Note: Could not determine if branch is remote, continuing with topology discovery", err);
129860
130897
  }
@@ -129862,46 +130899,60 @@ var require_extract_git_info = __commonJS({
129862
130899
  exports.extractBranchLookupFallbackList = utils2.general.cachify(async function({ gitBranchName, execOptions, logger = (0, logger_1.makeLogger)(), enableShallowClone = true }) {
129863
130900
  const functionStartTime = Date.now();
129864
130901
  logger = logger.extend({ tags: [`extract-branch-fallback-list-${utils2.general.shortid()}`] });
129865
- logger.log(`[PERF] extractBranchLookupFallbackList started for branch: ${gitBranchName}`);
130902
+ if (isDebugMode())
130903
+ logger.log(`[PERF] extractBranchLookupFallbackList started for branch: ${gitBranchName}`);
130904
+ const env = await (0, exports.checkGitEnvironment)({ execOptions, logger });
130905
+ if (!env.ok) {
130906
+ logger.log("extractBranchLookupFallbackList: git environment not ok, skipping");
130907
+ return void 0;
130908
+ }
129866
130909
  try {
129867
130910
  const shallowCheckStartTime = Date.now();
129868
130911
  const shallowCheckResult = await executeWithLog("git rev-parse --is-shallow-repository", {
129869
130912
  execOptions,
129870
130913
  logger
129871
130914
  });
129872
- logger.log(`[PERF] Shallow check took ${Date.now() - shallowCheckStartTime}ms`);
130915
+ if (isDebugMode())
130916
+ logger.log(`[PERF] Shallow check took ${Date.now() - shallowCheckStartTime}ms`);
129873
130917
  const isShallow = shallowCheckResult.stdout.trim() === "true";
129874
130918
  if (!enableShallowClone && isShallow) {
129875
- logger.log("Shallow clone detected and APPLITOOLS_SKIP_BRANCH_LOOKUP_IN_SHALLOW_CLONE is enabled, skipping branch lookup");
130919
+ logger.log("Shallow clone detected and enableShallowClone=false, skipping branch lookup");
129876
130920
  return void 0;
129877
130921
  }
129878
130922
  const ensureRemoteStartTime = Date.now();
129879
130923
  await ensureRemoteBranchesAvailable(gitBranchName, isShallow, execOptions, logger);
129880
- logger.log(`[PERF] ensureRemoteBranchesAvailable took ${Date.now() - ensureRemoteStartTime}ms`);
129881
- const topologyStartTime = Date.now();
129882
- logger.log(`Discovering ancestor branches using git topology for ${gitBranchName}...`);
130924
+ if (isDebugMode())
130925
+ logger.log(`[PERF] ensureRemoteBranchesAvailable took ${Date.now() - ensureRemoteStartTime}ms`);
129883
130926
  const remoteName = await (0, exports.getPrimaryRemoteName)({ execOptions, logger });
129884
- const logResult = await executeWithLog(`git log --first-parent --simplify-by-decoration --format="%D" ${gitBranchName}`, { execOptions, logger });
129885
- const foundBranches = /* @__PURE__ */ new Set();
129886
- if (!logResult.stderr && logResult.stdout.trim()) {
129887
- const rawLines = logResult.stdout.split("\n");
129888
- for (const line of rawLines) {
129889
- const refs = line.split(",").map((r) => r.trim());
129890
- for (const ref of refs) {
129891
- if (ref.includes("tag:"))
129892
- continue;
129893
- const cleanRef = ref.replace("HEAD -> ", "").replace(new RegExp(`^${remoteName}/`), "");
129894
- if (cleanRef && cleanRef !== gitBranchName && cleanRef !== "HEAD")
129895
- foundBranches.add(cleanRef);
129896
- }
129897
- }
130927
+ const defaultBranch = await (0, exports.extractDefaultBranch)({ execOptions, logger });
130928
+ logger.log(`Default branch detected: ${defaultBranch}`);
130929
+ const resolvedDefaultBranch = await resolveBranchToLocalRef({
130930
+ branchName: defaultBranch,
130931
+ remoteName,
130932
+ execOptions,
130933
+ logger
130934
+ });
130935
+ if (!resolvedDefaultBranch) {
130936
+ logger.log(`extractBranchLookupFallbackList: default branch "${defaultBranch}" not resolvable locally or on remote, skipping ancestry`);
130937
+ return void 0;
129898
130938
  }
129899
- let allBranches = Array.from(foundBranches);
129900
- logger.log(`[PERF] Topology discovery took ${Date.now() - topologyStartTime}ms`);
130939
+ const ancestryStrategy = (process.env.APPLITOOLS_BRANCH_ANCESTRY_STRATEGY || "commits").trim().toLowerCase();
130940
+ const ancestryDriver = ancestryStrategy === "local" ? getBranchAncestryByLocalBranches : getBranchAncestryByCommits;
130941
+ const ancestryStartTime = Date.now();
130942
+ logger.log(`Discovering ancestor branches via "${ancestryStrategy}" strategy for ${gitBranchName} (default=${defaultBranch})...`);
130943
+ const ancestry = await ancestryDriver({ gitBranchName, defaultBranch, execOptions, logger });
130944
+ if (isDebugMode())
130945
+ logger.log(`[PERF] Ancestry discovery took ${Date.now() - ancestryStartTime}ms`);
129901
130946
  if (isDebugMode()) {
129902
- logger.log(`Topology discovered ${allBranches.length} potential ancestor branches: ${allBranches.join(", ")}`);
130947
+ logger.log(`Ancestry discovery found ${ancestry.length} candidate branches: ${ancestry.join(", ")}`);
129903
130948
  } else {
129904
- logger.log(`Topology discovered ${allBranches.length} potential ancestor branches`);
130949
+ logger.log(`Ancestry discovery found ${ancestry.length} candidate branches`);
130950
+ }
130951
+ let allBranches = ancestry.filter((b) => b !== gitBranchName);
130952
+ if (isDebugMode()) {
130953
+ logger.log(`Ancestry discovered ${allBranches.length} potential ancestor branches: ${allBranches.join(", ")}`);
130954
+ } else {
130955
+ logger.log(`Ancestry discovered ${allBranches.length} potential ancestor branches`);
129905
130956
  }
129906
130957
  const remoteBranchesStartTime = Date.now();
129907
130958
  if (isDebugMode()) {
@@ -129951,48 +131002,41 @@ var require_extract_git_info = __commonJS({
129951
131002
  logger.log("[Remote Filtering] Continuing with all discovered branches");
129952
131003
  }
129953
131004
  }
129954
- logger.log(`[Remote Filtering] [PERF] Remote branch filtering took ${Date.now() - remoteBranchesStartTime}ms`);
129955
131005
  if (isDebugMode()) {
131006
+ logger.log(`[Remote Filtering] [PERF] Remote branch filtering took ${Date.now() - remoteBranchesStartTime}ms`);
129956
131007
  logger.log("[Remote Filtering] ========================================");
129957
131008
  }
129958
- const filteringStartTime = Date.now();
129959
- logger.log(`Filtering out sibling branches to keep only true ancestors...`);
129960
- const ANCESTOR_CHECK_CONCURRENCY = 10;
129961
- const ancestorChecks = await parallelWithLimit(allBranches, ANCESTOR_CHECK_CONCURRENCY, async (candidateBranch) => {
129962
- try {
129963
- const isAncestorResult = await executeWithLog(`git merge-base --is-ancestor ${candidateBranch} ${gitBranchName}`, {
129964
- execOptions,
129965
- logger
129966
- });
129967
- if (isAncestorResult.code === 0) {
129968
- logger.log(`\u2713 ${candidateBranch} is a true ancestor`);
129969
- return { branch: candidateBranch, isAncestor: true };
129970
- } else if (isAncestorResult.code === 1) {
129971
- logger.log(`\u2717 ${candidateBranch} is a sibling, not an ancestor`);
129972
- return { branch: candidateBranch, isAncestor: false };
129973
- } else {
129974
- logger.log(`\u26A0 Could not determine if ${candidateBranch} is an ancestor (exit code: ${isAncestorResult.code}), including it to be safe`);
129975
- return { branch: candidateBranch, isAncestor: true };
129976
- }
129977
- } catch (err) {
129978
- logger.log(`Error checking if ${candidateBranch} is a true ancestor:`, err);
129979
- return { branch: candidateBranch, isAncestor: true };
129980
- }
129981
- });
129982
- const trueAncestors = ancestorChecks.filter((result) => result.isAncestor).map((result) => result.branch);
129983
- logger.log(`[PERF] Sibling filtering took ${Date.now() - filteringStartTime}ms`);
129984
- logger.log(`Filtered to ${trueAncestors.length} true ancestors: ${trueAncestors.join(", ")}`);
129985
131009
  const timestampStartTime = Date.now();
129986
- const branchesWithTimestamps = await Promise.all(trueAncestors.map(async (ancestorBranch) => {
129987
- const timestamp = await (0, exports.extractBranchingTimestamp)({
131010
+ const branchesWithTimestamps = await Promise.all(allBranches.map(async (ancestorBranch) => {
131011
+ let timestamp = await (0, exports.extractBranchingTimestamp)({
129988
131012
  branchName: gitBranchName,
129989
131013
  parentBranchName: ancestorBranch,
129990
131014
  execOptions,
129991
131015
  logger
129992
131016
  });
131017
+ if (!timestamp) {
131018
+ timestamp = await (0, exports.extractBranchingTimestamp)({
131019
+ branchName: gitBranchName,
131020
+ parentBranchName: ancestorBranch,
131021
+ execOptions,
131022
+ logger
131023
+ });
131024
+ }
131025
+ if (!timestamp) {
131026
+ const tip = await executeWithLog((0, shell_quote_1.quote)(["git", "show", "-s", "--format=%aI", ancestorBranch]), {
131027
+ execOptions,
131028
+ logger
131029
+ });
131030
+ const tipTimestamp = tip.stdout.trim();
131031
+ if (!tip.stderr && isISODate(tipTimestamp)) {
131032
+ logger.log(`No branching timestamp for confirmed ancestor '${ancestorBranch}', using tip commit date ${tipTimestamp}`);
131033
+ timestamp = tipTimestamp;
131034
+ }
131035
+ }
129993
131036
  return timestamp ? { branchName: ancestorBranch, latestViableTimestamp: timestamp } : null;
129994
131037
  }));
129995
- logger.log(`[PERF] Timestamp extraction took ${Date.now() - timestampStartTime}ms`);
131038
+ if (isDebugMode())
131039
+ logger.log(`[PERF] Timestamp extraction took ${Date.now() - timestampStartTime}ms`);
129996
131040
  const validBranches = branchesWithTimestamps.filter((item) => item !== null).sort((a, b) => {
129997
131041
  const timeDiff = new Date(b.latestViableTimestamp).getTime() - new Date(a.latestViableTimestamp).getTime();
129998
131042
  if (timeDiff === 0) {
@@ -130008,35 +131052,22 @@ var require_extract_git_info = __commonJS({
130008
131052
  if (firstCommitResult.stdout.trim()) {
130009
131053
  const firstCommitHash = firstCommitResult.stdout.trim().split("\n")[0];
130010
131054
  logger.log(`Found root commit: ${firstCommitHash}`);
130011
- let branchesContainingRootResult = await executeWithLog(`git branch -r --contains ${firstCommitHash}`, {
130012
- execOptions,
130013
- logger
130014
- });
131055
+ let branchesContainingRootResult = await executeWithLog((0, shell_quote_1.quote)(["git", "branch", "-r", "--contains", firstCommitHash]), { execOptions, logger });
130015
131056
  if (!branchesContainingRootResult.stdout.trim()) {
130016
131057
  logger.log("No remote branches contain root commit, trying local branches");
130017
- branchesContainingRootResult = await executeWithLog(`git branch --contains ${firstCommitHash}`, {
130018
- execOptions,
130019
- logger
130020
- });
131058
+ branchesContainingRootResult = await executeWithLog((0, shell_quote_1.quote)(["git", "branch", "--contains", firstCommitHash]), { execOptions, logger });
130021
131059
  }
130022
131060
  if (branchesContainingRootResult.stdout.trim()) {
130023
131061
  const branchesContainingRoot = branchesContainingRootResult.stdout.split("\n").map((line) => line.trim()).filter((line) => line && !line.includes("->") && !line.includes("HEAD")).map((line) => line.replace(new RegExp(`^${remoteName}/`), "").replace(/^\* /, ""));
130024
- const commonRootNames = ["main", "master", "develop", "trunk"];
130025
131062
  let rootBranch = null;
130026
- for (const commonName of commonRootNames) {
130027
- if (branchesContainingRoot.includes(commonName)) {
130028
- rootBranch = commonName;
130029
- logger.log(`Found root branch using common name: ${rootBranch}`);
130030
- break;
130031
- }
131063
+ if (branchesContainingRoot.includes(defaultBranch)) {
131064
+ rootBranch = defaultBranch;
131065
+ logger.log(`Found root branch via detected defaultBranch: ${rootBranch}`);
130032
131066
  }
130033
131067
  if (!rootBranch && branchesContainingRoot.length > 0) {
130034
131068
  const branchTimestamps = await Promise.all(branchesContainingRoot.slice(0, 10).map(async (branch) => {
130035
131069
  try {
130036
- const branchTimestampResult = await executeWithLog(`git log -1 --format=%aI ${branch}`, {
130037
- execOptions,
130038
- logger
130039
- });
131070
+ const branchTimestampResult = await executeWithLog((0, shell_quote_1.quote)(["git", "log", "-1", "--format=%aI", branch]), { execOptions, logger });
130040
131071
  return {
130041
131072
  branch,
130042
131073
  timestamp: branchTimestampResult.stdout.trim()
@@ -130055,12 +131086,19 @@ var require_extract_git_info = __commonJS({
130055
131086
  const alreadyIncluded = validBranches.some((b) => b.branchName === rootBranch);
130056
131087
  if (!alreadyIncluded) {
130057
131088
  try {
130058
- const isAncestorResult = await executeWithLog(`git merge-base --is-ancestor ${rootBranch} ${gitBranchName}`, {
130059
- execOptions,
130060
- logger
130061
- });
130062
- if (isAncestorResult.code === 0) {
130063
- logger.log(`Root branch ${rootBranch} is a true ancestor, adding it as final fallback`);
131089
+ const isAncestorResult = await executeWithLog((0, shell_quote_1.quote)(["git", "merge-base", "--is-ancestor", rootBranch, gitBranchName]), { execOptions, logger });
131090
+ let accepted = isAncestorResult.code === 0;
131091
+ if (!accepted && rootBranch === defaultBranch) {
131092
+ const sharedHistory = await executeWithLog((0, shell_quote_1.quote)(["git", "merge-base", rootBranch, gitBranchName]), { execOptions, logger });
131093
+ if (!sharedHistory.stderr && sharedHistory.stdout.trim()) {
131094
+ accepted = true;
131095
+ logger.log(`Root branch ${rootBranch} is the advanced base, adding it as final fallback`);
131096
+ }
131097
+ }
131098
+ if (accepted) {
131099
+ if (isAncestorResult.code === 0) {
131100
+ logger.log(`Root branch ${rootBranch} is a true ancestor, adding it as final fallback`);
131101
+ }
130064
131102
  const rootTimestamp = await (0, exports.extractBranchingTimestamp)({
130065
131103
  branchName: gitBranchName,
130066
131104
  parentBranchName: rootBranch,
@@ -130089,7 +131127,9 @@ var require_extract_git_info = __commonJS({
130089
131127
  } catch (err) {
130090
131128
  logger.log("Failed to detect and add root branch, continuing without it", err);
130091
131129
  }
130092
- logger.log(`[PERF] extractBranchLookupFallbackList completed in ${Date.now() - functionStartTime}ms total`);
131130
+ if (isDebugMode()) {
131131
+ logger.log(`[PERF] extractBranchLookupFallbackList completed in ${Date.now() - functionStartTime}ms total`);
131132
+ }
130093
131133
  logger.log("Successfully extracted branch lookup fallback list", JSON.stringify(validBranches));
130094
131134
  return validBranches.length > 0 ? validBranches : void 0;
130095
131135
  } catch (err) {
@@ -130954,7 +131994,7 @@ var require_package3 = __commonJS({
130954
131994
  "../core/package.json"(exports, module) {
130955
131995
  module.exports = {
130956
131996
  name: "@applitools/core",
130957
- version: "4.65.2",
131997
+ version: "4.66.0",
130958
131998
  homepage: "https://applitools.com",
130959
131999
  bugs: {
130960
132000
  url: "https://github.com/applitools/eyes.sdk.javascript1/issues"
@@ -131032,6 +132072,7 @@ var require_package3 = __commonJS({
131032
132072
  chalk: "4.1.2",
131033
132073
  "node-fetch": "2.6.7",
131034
132074
  semver: "7.6.2",
132075
+ "shell-quote": "^1.8.4",
131035
132076
  throat: "6.0.2"
131036
132077
  },
131037
132078
  devDependencies: {
@@ -131048,6 +132089,7 @@ var require_package3 = __commonJS({
131048
132089
  "@types/node": "^12.20.55",
131049
132090
  "@types/selenium-webdriver": "^4.1.2",
131050
132091
  "@types/semver": "^7.5.8",
132092
+ "@types/shell-quote": "^1",
131051
132093
  chai: "^4.2.0",
131052
132094
  chromedriver: "^131.0.5",
131053
132095
  crypto: "^1.0.1",
@@ -132506,7 +133548,7 @@ var require_package4 = __commonJS({
132506
133548
  "../eyes/package.json"(exports, module) {
132507
133549
  module.exports = {
132508
133550
  name: "@applitools/eyes",
132509
- version: "1.43.4",
133551
+ version: "1.43.5",
132510
133552
  keywords: [
132511
133553
  "applitools",
132512
133554
  "eyes",
@@ -134122,7 +135164,7 @@ var require_package5 = __commonJS({
134122
135164
  "package.json"(exports, module) {
134123
135165
  module.exports = {
134124
135166
  name: "@applitools/eyes-browser",
134125
- version: "1.6.23",
135167
+ version: "1.6.24",
134126
135168
  type: "module",
134127
135169
  keywords: [
134128
135170
  "applitools",