@co0ontty/wand 4.6.1-beta.gbf688fe → 4.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  {
2
- "commit": "bf688fe221770d5f427105c5f1d69651a01990ab",
3
- "builtAt": "2026-07-16T03:15:36.168Z",
4
- "version": "4.6.1-beta.gbf688fe",
5
- "channel": "beta"
2
+ "commit": "c86da1ca2559537e44e57d7a085250bae857a3cc",
3
+ "builtAt": "2026-07-16T00:54:24.041Z",
4
+ "version": "4.6.1",
5
+ "channel": "stable"
6
6
  }
@@ -81,58 +81,6 @@ async function resolvePushRemoteAsync(cwd) {
81
81
  catch { /* use origin */ }
82
82
  return "origin";
83
83
  }
84
- function githubSshPushUrl(remoteUrl) {
85
- try {
86
- const parsed = new URL(remoteUrl);
87
- if (parsed.protocol !== "https:" || parsed.hostname.toLowerCase() !== "github.com")
88
- return undefined;
89
- const path = decodeURIComponent(parsed.pathname).replace(/^\/+|\/+$/g, "");
90
- const parts = path.split("/");
91
- if (parts.length !== 2 || parts.some((part) => !part))
92
- return undefined;
93
- return `git@github.com:${parts[0]}/${parts[1]}`;
94
- }
95
- catch {
96
- return undefined;
97
- }
98
- }
99
- function isHttpsCredentialError(error) {
100
- return /could not read (?:User|Pass)name|authentication failed|terminal prompts disabled|credential[^\n]*(?:failed|missing)|http basic: access denied/i
101
- .test(getGitErrorMessage(error));
102
- }
103
- async function resolveRemotePushUrl(cwd, remote) {
104
- try {
105
- return await runGitAsync(["remote", "get-url", "--push", remote], cwd);
106
- }
107
- catch {
108
- return remote;
109
- }
110
- }
111
- /**
112
- * Push explicit refs through one transport seam. A Wand service deliberately disables interactive
113
- * credential prompts, so a GitHub HTTPS remote that has no non-interactive credential would
114
- * otherwise fail even when the same machine is already configured for GitHub SSH.
115
- */
116
- async function pushRemoteRefs(cwd, remote, options = [], refs = []) {
117
- try {
118
- await runGitAsync(["push", ...options, remote, ...refs], cwd, GIT_PUSH_TIMEOUT_MS);
119
- return;
120
- }
121
- catch (error) {
122
- if (!isHttpsCredentialError(error))
123
- throw error;
124
- const configuredUrl = await resolveRemotePushUrl(cwd, remote);
125
- const sshUrl = githubSshPushUrl(configuredUrl);
126
- if (!sshUrl)
127
- throw error;
128
- try {
129
- await runGitAsync(["push", ...options, sshUrl, ...refs], cwd, GIT_PUSH_TIMEOUT_MS);
130
- }
131
- catch (sshError) {
132
- throw new Error(`${getGitErrorMessage(error)}\nGitHub SSH 回退也失败:${getGitErrorMessage(sshError)}`, { cause: sshError });
133
- }
134
- }
135
- }
136
84
  function unquotePath(raw) {
137
85
  if (raw.startsWith("\"") && raw.endsWith("\"")) {
138
86
  return raw.slice(1, -1).replace(/\\"/g, "\"").replace(/\\\\/g, "\\");
@@ -803,21 +751,21 @@ async function doPush(opts) {
803
751
  try {
804
752
  if (pushCommits) {
805
753
  if (hasUpstream) {
806
- await pushRemoteRefs(cwd, pushRemote, [recurseFlag]);
754
+ await runGitAsync(["push", recurseFlag], cwd, GIT_PUSH_TIMEOUT_MS);
807
755
  }
808
756
  else {
809
- await pushRemoteRefs(cwd, pushRemote, ["-u", recurseFlag], ["HEAD"]);
757
+ await runGitAsync(["push", "-u", recurseFlag, pushRemote, "HEAD"], cwd, GIT_PUSH_TIMEOUT_MS);
810
758
  }
811
759
  pushedCommits = true;
812
760
  }
813
761
  if (pushTags) {
814
762
  if (Array.isArray(pushTags)) {
815
763
  for (const name of pushTags) {
816
- await pushRemoteRefs(cwd, pushRemote, [], [`refs/tags/${name}`]);
764
+ await runGitAsync(["push", pushRemote, `refs/tags/${name}`], cwd, GIT_PUSH_TIMEOUT_MS);
817
765
  }
818
766
  }
819
767
  else {
820
- await pushRemoteRefs(cwd, pushRemote, ["--tags"]);
768
+ await runGitAsync(["push", pushRemote, "--tags"], cwd, GIT_PUSH_TIMEOUT_MS);
821
769
  }
822
770
  pushedTags = true;
823
771
  }
@@ -1064,7 +1012,7 @@ async function pushSubmodules(parentCwd, subInfos, opts) {
1064
1012
  continue;
1065
1013
  }
1066
1014
  try {
1067
- await pushRemoteRefs(subCwd, info.remote, [], [`HEAD:refs/heads/${info.branch}`]);
1015
+ await runGitAsync(["push", info.remote, `HEAD:refs/heads/${info.branch}`], subCwd, GIT_PUSH_TIMEOUT_MS);
1068
1016
  }
1069
1017
  catch (error) {
1070
1018
  errors.push(`submodule ${info.path} 推送失败:${getGitErrorMessage(error)}`);
@@ -1072,7 +1020,7 @@ async function pushSubmodules(parentCwd, subInfos, opts) {
1072
1020
  }
1073
1021
  if (opts.pushTags && opts.tagName) {
1074
1022
  try {
1075
- await pushRemoteRefs(subCwd, info.remote, [], [`refs/tags/${opts.tagName}`]);
1023
+ await runGitAsync(["push", info.remote, `refs/tags/${opts.tagName}`], subCwd, GIT_PUSH_TIMEOUT_MS);
1076
1024
  }
1077
1025
  catch (error) {
1078
1026
  errors.push(`submodule ${info.path} 推送 tag 失败:${getGitErrorMessage(error)}`);
@@ -1364,13 +1312,6 @@ export async function runQuickCommit(opts) {
1364
1312
  if (!tagName && autoTag) {
1365
1313
  tagName = await generateTagAfterCommit(cwd, language, message, ai);
1366
1314
  }
1367
- let submodulePushInfos = submoduleOutcome.commits;
1368
- if (submodule) {
1369
- // The selected scope is the declared submodule set, not merely the submodules dirtied by this
1370
- // request. A clean submodule can still have an unpushed HEAD or a pre-existing pointer change.
1371
- const collected = await collectSubmodulesForPush(cwd);
1372
- submodulePushInfos = collected.infos;
1373
- }
1374
1315
  if (tagName) {
1375
1316
  try {
1376
1317
  await runGitAsync(["tag", tagName], cwd);
@@ -1378,10 +1319,9 @@ export async function runQuickCommit(opts) {
1378
1319
  catch (error) {
1379
1320
  throw new QuickCommitError(`git tag 失败:${getGitErrorMessage(error)}`, "GIT_TAG_FAILED");
1380
1321
  }
1381
- // 纳入 submodule 时给全部声明的 submodule 当前 HEAD 打同名 tag。这样纯指针变化或
1382
- // 已提前提交但尚未推送的 submodule 也不会漏掉发布 tag。
1383
- if (submodule && submodulePushInfos.length > 0) {
1384
- await tagSubmodules(cwd, submodulePushInfos, tagName);
1322
+ // 纳入 submodule 时给刚提交的 submodule 打同名 tag(非致命,失败不阻断父仓库流程)。
1323
+ if (submodule && submoduleOutcome.commits.length > 0) {
1324
+ await tagSubmodules(cwd, submoduleOutcome.commits, tagName);
1385
1325
  }
1386
1326
  }
1387
1327
  let pushed = false;
@@ -1390,10 +1330,10 @@ export async function runQuickCommit(opts) {
1390
1330
  // 纳入 submodule:先把各 submodule 的 HEAD(+ 同名 tag)分别推到各自远端分支,
1391
1331
  // 解决 detached HEAD 无法被父仓库 on-demand 递归推送的问题;父仓库随后用
1392
1332
  // recurse=no 单独推(submodule 已就绪)。否则父仓库用 recurse=check 做安全校验。
1393
- const includeSub = !!submodule && submodulePushInfos.length > 0;
1333
+ const includeSub = !!submodule && submoduleOutcome.commits.length > 0;
1394
1334
  let subPushErrors = [];
1395
1335
  if (includeSub) {
1396
- const subPush = await pushSubmodules(cwd, submodulePushInfos, { pushTags: !!tagName, tagName });
1336
+ const subPush = await pushSubmodules(cwd, submoduleOutcome.commits, { pushTags: !!tagName, tagName });
1397
1337
  subPushErrors = subPush.errors;
1398
1338
  }
1399
1339
  if (subPushErrors.length > 0) {