@applitools/eyes-browser 1.6.22 → 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 +125 -0
  2. package/dist/index.js +1214 -168
  3. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -11968,7 +11968,7 @@ var require_browser_process = __commonJS({
11968
11968
  init_buffer();
11969
11969
  init_setInterval();
11970
11970
  Object.defineProperty(exports, "__esModule", { value: true });
11971
- exports.sh = exports.executeProcess = exports.executeAndControlProcess = exports.execute = void 0;
11971
+ exports.sampleProcessTreeMemory = exports.sh = exports.executeProcess = exports.executeAndControlProcess = exports.execute = void 0;
11972
11972
  var executionOutput = {
11973
11973
  stdout: "",
11974
11974
  stderr: "process execution is not supported in browser environment",
@@ -11997,6 +11997,10 @@ var require_browser_process = __commonJS({
11997
11997
  return executionOutput;
11998
11998
  }
11999
11999
  exports.sh = sh;
12000
+ async function sampleProcessTreeMemory(_rootPid, _options = {}) {
12001
+ return null;
12002
+ }
12003
+ exports.sampleProcessTreeMemory = sampleProcessTreeMemory;
12000
12004
  }
12001
12005
  });
12002
12006
 
@@ -18932,6 +18936,71 @@ var require_formatter = __commonJS({
18932
18936
  }
18933
18937
  });
18934
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
+
18935
19004
  // ../logger/dist/handler-console.js
18936
19005
  var require_handler_console = __commonJS({
18937
19006
  "../logger/dist/handler-console.js"(exports) {
@@ -19511,50 +19580,58 @@ var require_printer = __commonJS({
19511
19580
  Object.defineProperty(exports, "__esModule", { value: true });
19512
19581
  exports.makePrinter = void 0;
19513
19582
  var log_level_1 = require_log_level();
19583
+ var log_buffer_1 = require_log_buffer();
19514
19584
  function makePrinter({ handler, level = log_level_1.LogLevel.silent, format, masks, maskLog }) {
19515
19585
  var _a;
19516
19586
  const formatter = (_a = format === null || format === void 0 ? void 0 : format.formatter) !== null && _a !== void 0 ? _a : (chunks, options) => ({ chunks, options, isRaw: true });
19517
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
+ }
19518
19597
  function debug(...messages) {
19519
- if (level < log_level_1.LogLevel.debug)
19520
- return;
19521
- const options = { ...format, level: "debug", masks, maskLog };
19522
- 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);
19523
19601
  }
19524
19602
  function log(...messages) {
19525
- if (level < log_level_1.LogLevel.info)
19526
- return;
19527
- const options = { ...format, level: "info", masks, maskLog };
19528
- 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);
19529
19606
  }
19530
19607
  function warn(...messages) {
19531
- if (level < log_level_1.LogLevel.warn)
19608
+ const line = emit(log_level_1.LogLevel.warn, "warn", messages);
19609
+ if (line === void 0)
19532
19610
  return;
19533
- const options = { ...format, level: "warn", masks, maskLog };
19534
19611
  if (handler.warn)
19535
- handler.warn(formatter(messages, options));
19612
+ handler.warn(line);
19536
19613
  else
19537
- handler.log(formatter(messages, options));
19614
+ handler.log(line);
19538
19615
  }
19539
19616
  function error(...messages) {
19540
- if (level < log_level_1.LogLevel.error)
19617
+ const line = emit(log_level_1.LogLevel.error, "error", messages);
19618
+ if (line === void 0)
19541
19619
  return;
19542
- const options = { ...format, level: "error", masks, maskLog };
19543
19620
  if (handler.error)
19544
- handler.error(formatter(messages, options));
19621
+ handler.error(line);
19545
19622
  else
19546
- handler.log(formatter(messages, options));
19623
+ handler.log(line);
19547
19624
  }
19548
19625
  function fatal(...messages) {
19549
- if (level < log_level_1.LogLevel.fatal)
19626
+ const line = emit(log_level_1.LogLevel.fatal, "fatal", messages);
19627
+ if (line === void 0)
19550
19628
  return;
19551
- const options = { ...format, level: "fatal", masks, maskLog };
19552
19629
  if (handler.fatal)
19553
- handler.fatal(formatter(messages, options));
19630
+ handler.fatal(line);
19554
19631
  else if (handler.error)
19555
- handler.error(formatter(messages, options));
19632
+ handler.error(line);
19556
19633
  else
19557
- handler.log(formatter(messages, options));
19634
+ handler.log(line);
19558
19635
  }
19559
19636
  }
19560
19637
  exports.makePrinter = makePrinter;
@@ -19830,6 +19907,7 @@ var require_browser6 = __commonJS({
19830
19907
  };
19831
19908
  Object.defineProperty(exports, "__esModule", { value: true });
19832
19909
  __exportStar(require_formatter(), exports);
19910
+ __exportStar(require_log_buffer(), exports);
19833
19911
  __exportStar(require_handler_console(), exports);
19834
19912
  __exportStar(require_handler_debug(), exports);
19835
19913
  __exportStar(require_logger(), exports);
@@ -74567,6 +74645,108 @@ var require_delete_test = __commonJS({
74567
74645
  }
74568
74646
  });
74569
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
+
74570
74750
  // ../core-base/dist/get-account-info.js
74571
74751
  var require_get_account_info = __commonJS({
74572
74752
  "../core-base/dist/get-account-info.js"(exports) {
@@ -74610,6 +74790,7 @@ var require_get_account_info = __commonJS({
74610
74790
  };
74611
74791
  Object.defineProperty(exports, "__esModule", { value: true });
74612
74792
  exports.makeGetAccountInfo = void 0;
74793
+ var sdk_log_streaming_1 = require_sdk_log_streaming();
74613
74794
  var utils2 = __importStar(require_browser3());
74614
74795
  function makeGetAccountInfo({ requests, agentId: defaultAgentId, logger: mainLogger }) {
74615
74796
  return async function getAccountInfo({ settings, logger = mainLogger }) {
@@ -74618,11 +74799,13 @@ var require_get_account_info = __commonJS({
74618
74799
  settings.agentId = `${defaultAgentId} ${settings.agentId ? `[${settings.agentId}]` : ""}`.trim();
74619
74800
  logger.log('Command "getAccountInfo" is called with settings', settings);
74620
74801
  const account = await requests.getAccountInfo({ settings, logger });
74621
- return {
74802
+ const result = {
74622
74803
  ...account,
74623
74804
  eyesServer: { ...account.eyesServer, agentId: settings.agentId },
74624
74805
  ufgServer: { ...account.ufgServer, agentId: settings.agentId }
74625
74806
  };
74807
+ (0, sdk_log_streaming_1.decideSdkLogStreaming)(result);
74808
+ return result;
74626
74809
  };
74627
74810
  }
74628
74811
  exports.makeGetAccountInfo = makeGetAccountInfo;
@@ -75048,6 +75231,7 @@ var require_dist2 = __commonJS({
75048
75231
  __exportStar(require_core(), exports);
75049
75232
  __exportStar(require_eyes(), exports);
75050
75233
  __exportStar(require_requests(), exports);
75234
+ __exportStar(require_sdk_log_upload(), exports);
75051
75235
  __exportStar(require_core_error(), exports);
75052
75236
  __exportStar(require_missingApiKeyError(), exports);
75053
75237
  __exportStar(require_test_error(), exports);
@@ -82742,7 +82926,7 @@ ${l2}`}`, { bundledCss: u2, unfetchedResources: a2 };
82742
82926
  return m3 && (k2.shadowRoot = m3), k2;
82743
82927
  }
82744
82928
  }(t3);
82745
- f2(l2.doCaptureDoc), d2(l2.waitForImages), await Promise.all(m2), f2(l2.waitForImages), T2.version = "1.4.0", T2.scriptVersion = "11.8.1";
82929
+ f2(l2.doCaptureDoc), d2(l2.waitForImages), await Promise.all(m2), f2(l2.waitForImages), T2.version = "1.4.0", T2.scriptVersion = "11.8.3";
82746
82930
  const N2 = p2.length ? `${p2.join("\n")}
82747
82931
  ` : "", P2 = h2.size ? `${Array.from(h2).join("\n")}
82748
82932
  ` : "", A2 = JSON.stringify({ separator: w2, cssStartToken: y2, cssEndToken: y2, iframeStartToken: `"${g2}`, iframeEndToken: `${g2}"` });
@@ -89728,7 +89912,7 @@ var require_captureDomPollForIE = __commonJS({
89728
89912
  case 24:
89729
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);
89730
89914
  case 35:
89731
- return A2(E2.waitForImages), M2.version = "1.4.0", M2.scriptVersion = "11.8.1", 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);
89732
89916
  case 46:
89733
89917
  case "end":
89734
89918
  return e4.stop();
@@ -104734,7 +104918,7 @@ creating temp style for access.`), r2 = Qh(e3);
104734
104918
  function M2(e3) {
104735
104919
  return r3.defaultView && r3.defaultView.frameElement && r3.defaultView.frameElement.getAttribute(e3);
104736
104920
  }
104737
- }(n3).then((e3) => (m2.log("processPage end"), e3.scriptVersion = "4.17.3", e3));
104921
+ }(n3).then((e3) => (m2.log("processPage end"), e3.scriptVersion = "4.17.5", e3));
104738
104922
  }, n2[S], "domSnapshotResult");
104739
104923
  return function(e3) {
104740
104924
  try {
@@ -129503,6 +129687,292 @@ var require_get_eyes_results = __commonJS({
129503
129687
  }
129504
129688
  });
129505
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
+
129506
129976
  // ../core/dist/utils/extract-git-info.js
129507
129977
  var require_extract_git_info = __commonJS({
129508
129978
  "../core/dist/utils/extract-git-info.js"(exports) {
@@ -129548,10 +130018,11 @@ var require_extract_git_info = __commonJS({
129548
130018
  return mod && mod.__esModule ? mod : { "default": mod };
129549
130019
  };
129550
130020
  Object.defineProperty(exports, "__esModule", { value: true });
129551
- 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;
129552
130022
  var utils2 = __importStar(require_browser3());
129553
130023
  var fs_1 = __importDefault((init_fs(), __toCommonJS(fs_exports)));
129554
130024
  var path_1 = __importDefault(require_path_browserify());
130025
+ var shell_quote_1 = require_shell_quote();
129555
130026
  var logger_1 = require_browser6();
129556
130027
  var isDebugMode = () => process.env.RUNNER_DEBUG === "1";
129557
130028
  exports.cacheKey = "default";
@@ -129571,14 +130042,229 @@ var require_extract_git_info = __commonJS({
129571
130042
  cwd: (_a = args[0].execOptions) === null || _a === void 0 ? void 0 : _a.cwd
129572
130043
  };
129573
130044
  });
129574
- exports.extractLatestCommitInfo = utils2.general.cachify(async function({ execOptions, logger = (0, logger_1.makeLogger)() }) {
129575
- 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
+ };
129576
130116
  try {
129577
- const githubPullRequestLastCommitSha = await extractGithubPullRequestLastCommitSha();
129578
- 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`]), {
129579
130210
  execOptions,
129580
130211
  logger
129581
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 });
129582
130268
  if (result.stderr) {
129583
130269
  logger.log(`Error during extracting commit information from git`, result.stderr);
129584
130270
  } else {
@@ -129596,7 +130282,7 @@ var require_extract_git_info = __commonJS({
129596
130282
  var _a, _b, _c;
129597
130283
  if (((_a = process.env.GITHUB_EVENT_NAME) === null || _a === void 0 ? void 0 : _a.startsWith("pull_request")) && process.env.GITHUB_EVENT_PATH) {
129598
130284
  const remoteName = await (0, exports.getPrimaryRemoteName)({ execOptions, logger });
129599
- await executeWithLog(`git fetch ${remoteName} --depth=2`, { execOptions, logger });
130285
+ await executeWithLog((0, shell_quote_1.quote)(["git", "fetch", remoteName, "--depth=2"]), { execOptions, logger });
129600
130286
  const event = await fs_1.default.promises.readFile(process.env.GITHUB_EVENT_PATH, "utf-8").then(JSON.parse);
129601
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;
129602
130288
  }
@@ -129608,6 +130294,11 @@ var require_extract_git_info = __commonJS({
129608
130294
  logger.log(`Extracted branch name from CI environment: "${ciBranch}"`);
129609
130295
  return ciBranch;
129610
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
+ }
129611
130302
  const result = await executeWithLog("git branch --show-current", { execOptions, logger });
129612
130303
  if (result.stderr) {
129613
130304
  logger.log(`Error during extracting current branch from git`, result.stderr);
@@ -129624,10 +130315,15 @@ var require_extract_git_info = __commonJS({
129624
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 };
129625
130316
  });
129626
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
+ }
129627
130323
  const remotes = await extractRemotes();
129628
130324
  logger.log(`Extracted remotes from git: ${remotes}`);
129629
130325
  const remote = remotes.includes("origin") ? "origin" : remotes[0];
129630
- 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 });
129631
130327
  if (result.stderr) {
129632
130328
  logger.log(`Error during extracting remote url from git`, result.stderr);
129633
130329
  return {};
@@ -129671,51 +130367,82 @@ var require_extract_git_info = __commonJS({
129671
130367
  }
129672
130368
  exports.extractBuildIdFromCI = extractBuildIdFromCI;
129673
130369
  exports.extractBranchingTimestamp = utils2.general.cachify(async function({ branchName, parentBranchName, execOptions, logger = (0, logger_1.makeLogger)() }) {
129674
- var _a;
129675
130370
  logger = logger.extend({ tags: [`extract-branching-timestamp-${utils2.general.shortid()}`] });
129676
- const remoteName = await (0, exports.getPrimaryRemoteName)({ execOptions, logger });
129677
- const shallowCheckResult = await executeWithLog("git rev-parse --is-shallow-repository", {
129678
- execOptions,
129679
- logger
129680
- });
129681
- const isShallow = shallowCheckResult.stdout.trim() === "true";
129682
- if (isShallow) {
129683
- logger.log("extractBranchingTimestamp - Repository is a shallow clone, attempting to unshallow");
129684
- await executeFetchStrategy(isShallow, execOptions, logger);
129685
- }
129686
- const command = `HASH=$(git merge-base ${branchName} ${parentBranchName}) && git show -q --format=%aI $HASH`;
129687
- let result = await executeWithLog(command, { execOptions, logger });
129688
- if (result.stderr) {
129689
- const commandWithRemoteRefs = `HASH=$(git merge-base ${remoteName}/${branchName} ${remoteName}/${parentBranchName}) && git show -q --format=%aI $HASH`;
129690
- result = await executeWithLog(commandWithRemoteRefs, { execOptions, logger });
129691
- }
129692
- if (result.stderr) {
129693
- const remoteBranches = await getAllRemoteBranches({ execOptions, logger });
129694
- for (let i = 0; i < 2; i++) {
129695
- if (result.stderr) {
129696
- const [, missingBranch] = (_a = result.stderr.match(/Not a valid object name ([^\s]+)/)) !== null && _a !== void 0 ? _a : [];
129697
- if (missingBranch) {
129698
- const normalizedBranchName = missingBranch.replace(new RegExp(`^${remoteName}/`), "");
129699
- if (!remoteBranches.has(normalizedBranchName)) {
129700
- logger.log(`Branch ${missingBranch} not found on remote, skipping fetch`);
129701
- return void 0;
129702
- }
129703
- logger.log(`Fetching missing branch ${missingBranch} from remote`);
129704
- const command2 = `HASH=$(git merge-base ${branchName} ${parentBranchName}) && git show -q --format=%aI $HASH`;
129705
- result = await executeWithLog(`git fetch ${remoteName} ${normalizedBranchName}:${normalizedBranchName} --filter=tree:0 && ${command2}`, {
129706
- execOptions,
129707
- logger
129708
- });
129709
- }
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;
129710
130393
  }
130394
+ return stdout.trim();
129711
130395
  }
129712
- }
129713
- const timestamp = result.stdout.replace(/\s/g, "");
129714
- if (isISODate(timestamp)) {
129715
- logger.log("git branching timestamp successfully extracted", timestamp);
129716
- return timestamp;
129717
- } else {
129718
- 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;
129719
130446
  }
129720
130447
  }, (args) => {
129721
130448
  var _a;
@@ -129740,6 +130467,47 @@ var require_extract_git_info = __commonJS({
129740
130467
  return /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\+\d{2}:\d{2})?/.test(str);
129741
130468
  }
129742
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
+ }
129743
130511
  async function parallelWithLimit(items, concurrency, fn) {
129744
130512
  const results = [];
129745
130513
  for (let i = 0; i < items.length; i += concurrency) {
@@ -129749,6 +130517,262 @@ var require_extract_git_info = __commonJS({
129749
130517
  }
129750
130518
  return results;
129751
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;
129752
130776
  var getAllRemoteBranches = utils2.general.cachify(
129753
130777
  async function({ execOptions, logger }) {
129754
130778
  var _a;
@@ -129756,10 +130780,15 @@ var require_extract_git_info = __commonJS({
129756
130780
  logger.log("[getAllRemoteBranches] Starting git ls-remote to fetch all remote branches...");
129757
130781
  logger.log("[getAllRemoteBranches] execOptions.cwd:", (execOptions === null || execOptions === void 0 ? void 0 : execOptions.cwd) || "undefined");
129758
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
+ }
129759
130788
  try {
129760
130789
  const remoteName = await (0, exports.getPrimaryRemoteName)({ execOptions, logger });
129761
130790
  const startTime = Date.now();
129762
- const result = await executeWithLog(`git ls-remote --heads ${remoteName}`, {
130791
+ const result = await executeWithLog((0, shell_quote_1.quote)(["git", "ls-remote", "--heads", remoteName]), {
129763
130792
  execOptions,
129764
130793
  logger
129765
130794
  });
@@ -129808,7 +130837,7 @@ var require_extract_git_info = __commonJS({
129808
130837
  return /* @__PURE__ */ new Set();
129809
130838
  }
129810
130839
  },
129811
- // Custom cache key generator - only cache by cwd, not by logger instance
130840
+ // Cache by cwd only, not by logger instance.
129812
130841
  (args) => {
129813
130842
  var _a;
129814
130843
  return { cwd: (_a = args[0].execOptions) === null || _a === void 0 ? void 0 : _a.cwd };
@@ -129816,17 +130845,22 @@ var require_extract_git_info = __commonJS({
129816
130845
  5 * 60 * 1e3
129817
130846
  );
129818
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
+ }
129819
130853
  const remoteName = await (0, exports.getPrimaryRemoteName)({ execOptions, logger });
129820
130854
  if (isShallow) {
129821
130855
  logger.log(`Shallow repository detected, unshallowing to enable topology discovery...`);
129822
- await executeWithLog(`git fetch ${remoteName} --unshallow --filter=blob:none`, {
130856
+ await executeWithLog((0, shell_quote_1.quote)(["git", "fetch", remoteName, "--unshallow", "--filter=blob:none"]), {
129823
130857
  execOptions,
129824
130858
  logger
129825
130859
  });
129826
130860
  logger.log(`Repository unshallowed successfully`);
129827
130861
  } else {
129828
130862
  logger.log(`Non-shallow clone detected, fetching all remote branches for topology discovery...`);
129829
- await executeWithLog(`git fetch ${remoteName} --filter=tree:0`, {
130863
+ await executeWithLog((0, shell_quote_1.quote)(["git", "fetch", remoteName, "--filter=tree:0"]), {
129830
130864
  execOptions,
129831
130865
  logger
129832
130866
  });
@@ -129834,9 +130868,14 @@ var require_extract_git_info = __commonJS({
129834
130868
  }
129835
130869
  }
129836
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
+ }
129837
130876
  try {
129838
130877
  const remoteName = await (0, exports.getPrimaryRemoteName)({ execOptions, logger });
129839
- 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}`]), {
129840
130879
  execOptions,
129841
130880
  logger
129842
130881
  });
@@ -129845,12 +130884,14 @@ var require_extract_git_info = __commonJS({
129845
130884
  return;
129846
130885
  }
129847
130886
  logger.log(`Detected remote branch scenario, fetching ancestor branches...`);
129848
- await executeWithLog(`git config remote.${remoteName}.fetch "+refs/heads/*:refs/remotes/${remoteName}/*"`, {
129849
- execOptions,
129850
- logger
129851
- });
130887
+ await executeWithLog((0, shell_quote_1.quote)(["git", "config", `remote.${remoteName}.fetch`, `+refs/heads/*:refs/remotes/${remoteName}/*`]), { execOptions, logger });
129852
130888
  await executeFetchStrategy(isShallow, execOptions, logger);
129853
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
+ }
129854
130895
  } catch (err) {
129855
130896
  logger.log("Note: Could not determine if branch is remote, continuing with topology discovery", err);
129856
130897
  }
@@ -129858,46 +130899,60 @@ var require_extract_git_info = __commonJS({
129858
130899
  exports.extractBranchLookupFallbackList = utils2.general.cachify(async function({ gitBranchName, execOptions, logger = (0, logger_1.makeLogger)(), enableShallowClone = true }) {
129859
130900
  const functionStartTime = Date.now();
129860
130901
  logger = logger.extend({ tags: [`extract-branch-fallback-list-${utils2.general.shortid()}`] });
129861
- 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
+ }
129862
130909
  try {
129863
130910
  const shallowCheckStartTime = Date.now();
129864
130911
  const shallowCheckResult = await executeWithLog("git rev-parse --is-shallow-repository", {
129865
130912
  execOptions,
129866
130913
  logger
129867
130914
  });
129868
- logger.log(`[PERF] Shallow check took ${Date.now() - shallowCheckStartTime}ms`);
130915
+ if (isDebugMode())
130916
+ logger.log(`[PERF] Shallow check took ${Date.now() - shallowCheckStartTime}ms`);
129869
130917
  const isShallow = shallowCheckResult.stdout.trim() === "true";
129870
130918
  if (!enableShallowClone && isShallow) {
129871
- 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");
129872
130920
  return void 0;
129873
130921
  }
129874
130922
  const ensureRemoteStartTime = Date.now();
129875
130923
  await ensureRemoteBranchesAvailable(gitBranchName, isShallow, execOptions, logger);
129876
- logger.log(`[PERF] ensureRemoteBranchesAvailable took ${Date.now() - ensureRemoteStartTime}ms`);
129877
- const topologyStartTime = Date.now();
129878
- logger.log(`Discovering ancestor branches using git topology for ${gitBranchName}...`);
130924
+ if (isDebugMode())
130925
+ logger.log(`[PERF] ensureRemoteBranchesAvailable took ${Date.now() - ensureRemoteStartTime}ms`);
129879
130926
  const remoteName = await (0, exports.getPrimaryRemoteName)({ execOptions, logger });
129880
- const logResult = await executeWithLog(`git log --first-parent --simplify-by-decoration --format="%D" ${gitBranchName}`, { execOptions, logger });
129881
- const foundBranches = /* @__PURE__ */ new Set();
129882
- if (!logResult.stderr && logResult.stdout.trim()) {
129883
- const rawLines = logResult.stdout.split("\n");
129884
- for (const line of rawLines) {
129885
- const refs = line.split(",").map((r) => r.trim());
129886
- for (const ref of refs) {
129887
- if (ref.includes("tag:"))
129888
- continue;
129889
- const cleanRef = ref.replace("HEAD -> ", "").replace(new RegExp(`^${remoteName}/`), "");
129890
- if (cleanRef && cleanRef !== gitBranchName && cleanRef !== "HEAD")
129891
- foundBranches.add(cleanRef);
129892
- }
129893
- }
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;
130938
+ }
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`);
130946
+ if (isDebugMode()) {
130947
+ logger.log(`Ancestry discovery found ${ancestry.length} candidate branches: ${ancestry.join(", ")}`);
130948
+ } else {
130949
+ logger.log(`Ancestry discovery found ${ancestry.length} candidate branches`);
129894
130950
  }
129895
- let allBranches = Array.from(foundBranches);
129896
- logger.log(`[PERF] Topology discovery took ${Date.now() - topologyStartTime}ms`);
130951
+ let allBranches = ancestry.filter((b) => b !== gitBranchName);
129897
130952
  if (isDebugMode()) {
129898
- logger.log(`Topology discovered ${allBranches.length} potential ancestor branches: ${allBranches.join(", ")}`);
130953
+ logger.log(`Ancestry discovered ${allBranches.length} potential ancestor branches: ${allBranches.join(", ")}`);
129899
130954
  } else {
129900
- logger.log(`Topology discovered ${allBranches.length} potential ancestor branches`);
130955
+ logger.log(`Ancestry discovered ${allBranches.length} potential ancestor branches`);
129901
130956
  }
129902
130957
  const remoteBranchesStartTime = Date.now();
129903
130958
  if (isDebugMode()) {
@@ -129947,48 +131002,41 @@ var require_extract_git_info = __commonJS({
129947
131002
  logger.log("[Remote Filtering] Continuing with all discovered branches");
129948
131003
  }
129949
131004
  }
129950
- logger.log(`[Remote Filtering] [PERF] Remote branch filtering took ${Date.now() - remoteBranchesStartTime}ms`);
129951
131005
  if (isDebugMode()) {
131006
+ logger.log(`[Remote Filtering] [PERF] Remote branch filtering took ${Date.now() - remoteBranchesStartTime}ms`);
129952
131007
  logger.log("[Remote Filtering] ========================================");
129953
131008
  }
129954
- const filteringStartTime = Date.now();
129955
- logger.log(`Filtering out sibling branches to keep only true ancestors...`);
129956
- const ANCESTOR_CHECK_CONCURRENCY = 10;
129957
- const ancestorChecks = await parallelWithLimit(allBranches, ANCESTOR_CHECK_CONCURRENCY, async (candidateBranch) => {
129958
- try {
129959
- const isAncestorResult = await executeWithLog(`git merge-base --is-ancestor ${candidateBranch} ${gitBranchName}`, {
129960
- execOptions,
129961
- logger
129962
- });
129963
- if (isAncestorResult.code === 0) {
129964
- logger.log(`\u2713 ${candidateBranch} is a true ancestor`);
129965
- return { branch: candidateBranch, isAncestor: true };
129966
- } else if (isAncestorResult.code === 1) {
129967
- logger.log(`\u2717 ${candidateBranch} is a sibling, not an ancestor`);
129968
- return { branch: candidateBranch, isAncestor: false };
129969
- } else {
129970
- logger.log(`\u26A0 Could not determine if ${candidateBranch} is an ancestor (exit code: ${isAncestorResult.code}), including it to be safe`);
129971
- return { branch: candidateBranch, isAncestor: true };
129972
- }
129973
- } catch (err) {
129974
- logger.log(`Error checking if ${candidateBranch} is a true ancestor:`, err);
129975
- return { branch: candidateBranch, isAncestor: true };
129976
- }
129977
- });
129978
- const trueAncestors = ancestorChecks.filter((result) => result.isAncestor).map((result) => result.branch);
129979
- logger.log(`[PERF] Sibling filtering took ${Date.now() - filteringStartTime}ms`);
129980
- logger.log(`Filtered to ${trueAncestors.length} true ancestors: ${trueAncestors.join(", ")}`);
129981
131009
  const timestampStartTime = Date.now();
129982
- const branchesWithTimestamps = await Promise.all(trueAncestors.map(async (ancestorBranch) => {
129983
- const timestamp = await (0, exports.extractBranchingTimestamp)({
131010
+ const branchesWithTimestamps = await Promise.all(allBranches.map(async (ancestorBranch) => {
131011
+ let timestamp = await (0, exports.extractBranchingTimestamp)({
129984
131012
  branchName: gitBranchName,
129985
131013
  parentBranchName: ancestorBranch,
129986
131014
  execOptions,
129987
131015
  logger
129988
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
+ }
129989
131036
  return timestamp ? { branchName: ancestorBranch, latestViableTimestamp: timestamp } : null;
129990
131037
  }));
129991
- logger.log(`[PERF] Timestamp extraction took ${Date.now() - timestampStartTime}ms`);
131038
+ if (isDebugMode())
131039
+ logger.log(`[PERF] Timestamp extraction took ${Date.now() - timestampStartTime}ms`);
129992
131040
  const validBranches = branchesWithTimestamps.filter((item) => item !== null).sort((a, b) => {
129993
131041
  const timeDiff = new Date(b.latestViableTimestamp).getTime() - new Date(a.latestViableTimestamp).getTime();
129994
131042
  if (timeDiff === 0) {
@@ -130004,35 +131052,22 @@ var require_extract_git_info = __commonJS({
130004
131052
  if (firstCommitResult.stdout.trim()) {
130005
131053
  const firstCommitHash = firstCommitResult.stdout.trim().split("\n")[0];
130006
131054
  logger.log(`Found root commit: ${firstCommitHash}`);
130007
- let branchesContainingRootResult = await executeWithLog(`git branch -r --contains ${firstCommitHash}`, {
130008
- execOptions,
130009
- logger
130010
- });
131055
+ let branchesContainingRootResult = await executeWithLog((0, shell_quote_1.quote)(["git", "branch", "-r", "--contains", firstCommitHash]), { execOptions, logger });
130011
131056
  if (!branchesContainingRootResult.stdout.trim()) {
130012
131057
  logger.log("No remote branches contain root commit, trying local branches");
130013
- branchesContainingRootResult = await executeWithLog(`git branch --contains ${firstCommitHash}`, {
130014
- execOptions,
130015
- logger
130016
- });
131058
+ branchesContainingRootResult = await executeWithLog((0, shell_quote_1.quote)(["git", "branch", "--contains", firstCommitHash]), { execOptions, logger });
130017
131059
  }
130018
131060
  if (branchesContainingRootResult.stdout.trim()) {
130019
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(/^\* /, ""));
130020
- const commonRootNames = ["main", "master", "develop", "trunk"];
130021
131062
  let rootBranch = null;
130022
- for (const commonName of commonRootNames) {
130023
- if (branchesContainingRoot.includes(commonName)) {
130024
- rootBranch = commonName;
130025
- logger.log(`Found root branch using common name: ${rootBranch}`);
130026
- break;
130027
- }
131063
+ if (branchesContainingRoot.includes(defaultBranch)) {
131064
+ rootBranch = defaultBranch;
131065
+ logger.log(`Found root branch via detected defaultBranch: ${rootBranch}`);
130028
131066
  }
130029
131067
  if (!rootBranch && branchesContainingRoot.length > 0) {
130030
131068
  const branchTimestamps = await Promise.all(branchesContainingRoot.slice(0, 10).map(async (branch) => {
130031
131069
  try {
130032
- const branchTimestampResult = await executeWithLog(`git log -1 --format=%aI ${branch}`, {
130033
- execOptions,
130034
- logger
130035
- });
131070
+ const branchTimestampResult = await executeWithLog((0, shell_quote_1.quote)(["git", "log", "-1", "--format=%aI", branch]), { execOptions, logger });
130036
131071
  return {
130037
131072
  branch,
130038
131073
  timestamp: branchTimestampResult.stdout.trim()
@@ -130051,12 +131086,19 @@ var require_extract_git_info = __commonJS({
130051
131086
  const alreadyIncluded = validBranches.some((b) => b.branchName === rootBranch);
130052
131087
  if (!alreadyIncluded) {
130053
131088
  try {
130054
- const isAncestorResult = await executeWithLog(`git merge-base --is-ancestor ${rootBranch} ${gitBranchName}`, {
130055
- execOptions,
130056
- logger
130057
- });
130058
- if (isAncestorResult.code === 0) {
130059
- 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
+ }
130060
131102
  const rootTimestamp = await (0, exports.extractBranchingTimestamp)({
130061
131103
  branchName: gitBranchName,
130062
131104
  parentBranchName: rootBranch,
@@ -130085,7 +131127,9 @@ var require_extract_git_info = __commonJS({
130085
131127
  } catch (err) {
130086
131128
  logger.log("Failed to detect and add root branch, continuing without it", err);
130087
131129
  }
130088
- 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
+ }
130089
131133
  logger.log("Successfully extracted branch lookup fallback list", JSON.stringify(validBranches));
130090
131134
  return validBranches.length > 0 ? validBranches : void 0;
130091
131135
  } catch (err) {
@@ -130950,7 +131994,7 @@ var require_package3 = __commonJS({
130950
131994
  "../core/package.json"(exports, module) {
130951
131995
  module.exports = {
130952
131996
  name: "@applitools/core",
130953
- version: "4.65.1",
131997
+ version: "4.66.0",
130954
131998
  homepage: "https://applitools.com",
130955
131999
  bugs: {
130956
132000
  url: "https://github.com/applitools/eyes.sdk.javascript1/issues"
@@ -131028,6 +132072,7 @@ var require_package3 = __commonJS({
131028
132072
  chalk: "4.1.2",
131029
132073
  "node-fetch": "2.6.7",
131030
132074
  semver: "7.6.2",
132075
+ "shell-quote": "^1.8.4",
131031
132076
  throat: "6.0.2"
131032
132077
  },
131033
132078
  devDependencies: {
@@ -131044,6 +132089,7 @@ var require_package3 = __commonJS({
131044
132089
  "@types/node": "^12.20.55",
131045
132090
  "@types/selenium-webdriver": "^4.1.2",
131046
132091
  "@types/semver": "^7.5.8",
132092
+ "@types/shell-quote": "^1",
131047
132093
  chai: "^4.2.0",
131048
132094
  chromedriver: "^131.0.5",
131049
132095
  crypto: "^1.0.1",
@@ -132502,7 +133548,7 @@ var require_package4 = __commonJS({
132502
133548
  "../eyes/package.json"(exports, module) {
132503
133549
  module.exports = {
132504
133550
  name: "@applitools/eyes",
132505
- version: "1.43.3",
133551
+ version: "1.43.5",
132506
133552
  keywords: [
132507
133553
  "applitools",
132508
133554
  "eyes",
@@ -134118,7 +135164,7 @@ var require_package5 = __commonJS({
134118
135164
  "package.json"(exports, module) {
134119
135165
  module.exports = {
134120
135166
  name: "@applitools/eyes-browser",
134121
- version: "1.6.22",
135167
+ version: "1.6.24",
134122
135168
  type: "module",
134123
135169
  keywords: [
134124
135170
  "applitools",