@dafish/gogo-meta 1.1.0 → 1.1.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.
package/dist/cli.js CHANGED
@@ -6,6 +6,7 @@ import { dirname, join, basename } from 'path';
6
6
  import { mkdir, appendFile, access, writeFile, readFile, unlink, symlink } from 'fs/promises';
7
7
  import { z } from 'zod';
8
8
  import pc from 'picocolors';
9
+ import { homedir } from 'os';
9
10
 
10
11
  var __defProp = Object.defineProperty;
11
12
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -635,6 +636,81 @@ function registerRunCommand(program) {
635
636
 
636
637
  // src/commands/git/clone.ts
637
638
  init_executor();
639
+
640
+ // src/core/ssh.ts
641
+ init_executor();
642
+ function extractSshHost(url) {
643
+ if (url.startsWith("https://") || url.startsWith("http://") || url.startsWith("file://")) {
644
+ return null;
645
+ }
646
+ const sshMatch = url.match(/^ssh:\/\/[^@]+@([^/:]+)/);
647
+ if (sshMatch) {
648
+ return sshMatch[1] ?? null;
649
+ }
650
+ const gitMatch = url.match(/^[^@]+@([^:]+):/);
651
+ if (gitMatch) {
652
+ return gitMatch[1] ?? null;
653
+ }
654
+ return null;
655
+ }
656
+ function extractUniqueSshHosts(urls) {
657
+ const hosts = /* @__PURE__ */ new Set();
658
+ for (const url of urls) {
659
+ const host = extractSshHost(url);
660
+ if (host) {
661
+ hosts.add(host);
662
+ }
663
+ }
664
+ return Array.from(hosts);
665
+ }
666
+ async function isHostKnown(host) {
667
+ const knownHostsPath = join(homedir(), ".ssh", "known_hosts");
668
+ try {
669
+ const content = await readFile(knownHostsPath, "utf-8");
670
+ const hostPatterns = [
671
+ new RegExp(`^${escapeRegex(host)}[,\\s]`, "m"),
672
+ new RegExp(`^\\[${escapeRegex(host)}\\]:\\d+[,\\s]`, "m")
673
+ ];
674
+ return hostPatterns.some((pattern) => pattern.test(content));
675
+ } catch {
676
+ return false;
677
+ }
678
+ }
679
+ function escapeRegex(str) {
680
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
681
+ }
682
+ function addHostKey(host) {
683
+ const knownHostsPath = join(homedir(), ".ssh", "known_hosts");
684
+ const result = executeSync(`ssh-keyscan -H "${host}" >> "${knownHostsPath}" 2>/dev/null`, {
685
+ cwd: process.cwd()
686
+ });
687
+ return result.exitCode === 0;
688
+ }
689
+ async function ensureSshHostsKnown(urls) {
690
+ const hosts = extractUniqueSshHosts(urls);
691
+ const added = [];
692
+ const failed = [];
693
+ if (hosts.length === 0) {
694
+ return { added, failed };
695
+ }
696
+ for (const host of hosts) {
697
+ const known = await isHostKnown(host);
698
+ if (!known) {
699
+ info(`Adding SSH host key for ${host}...`);
700
+ const success2 = addHostKey(host);
701
+ if (success2) {
702
+ success(`Added host key for ${host}`);
703
+ added.push(host);
704
+ } else {
705
+ error(`Failed to add host key for ${host}`);
706
+ failed.push(host);
707
+ }
708
+ }
709
+ }
710
+ return { added, failed };
711
+ }
712
+
713
+ // src/commands/git/clone.ts
638
714
  function extractRepoName(url) {
639
715
  const match = url.match(/\/([^/]+?)(\.git)?$/);
640
716
  return match?.[1] ?? "repo";
@@ -646,6 +722,7 @@ async function cloneCommand(url, options = {}) {
646
722
  if (await fileExists(targetDir)) {
647
723
  throw new Error(`Directory "${repoName}" already exists`);
648
724
  }
725
+ await ensureSshHostsKnown([url]);
649
726
  info(`Cloning meta repository: ${url}`);
650
727
  const cloneResult = await execute(`git clone "${url}" "${repoName}"`, { cwd });
651
728
  if (cloneResult.exitCode !== 0) {
@@ -666,6 +743,13 @@ async function cloneCommand(url, options = {}) {
666
743
  info("No child repositories defined in .gogo");
667
744
  return;
668
745
  }
746
+ const urls = projects.map(([, url2]) => url2);
747
+ const { failed: failedHosts } = await ensureSshHostsKnown(urls);
748
+ if (failedHosts.length > 0) {
749
+ warning(
750
+ `Could not verify SSH host keys for: ${failedHosts.join(", ")}. Clone may fail.`
751
+ );
752
+ }
669
753
  info(`Cloning ${projects.length} child repositories...`);
670
754
  let successCount = 0;
671
755
  let failCount = 0;
@@ -725,6 +809,13 @@ async function updateCommand(options = {}) {
725
809
  success("All repositories are already cloned");
726
810
  return;
727
811
  }
812
+ const urls = missing.map(([, url]) => url);
813
+ const { failed: failedHosts } = await ensureSshHostsKnown(urls);
814
+ if (failedHosts.length > 0) {
815
+ warning(
816
+ `Could not verify SSH host keys for: ${failedHosts.join(", ")}. Clone may fail.`
817
+ );
818
+ }
728
819
  info(`Cloning ${missing.length} missing repositories...`);
729
820
  let successCount = 0;
730
821
  let failCount = 0;