@boses/github-clone 1.1.6 → 1.3.0

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/gitClone.js CHANGED
@@ -1,2 +1,132 @@
1
- "use strict";var t=require("child_process"),r=require("process");function e(t){return t&&"object"==typeof t&&"default"in t?t:{default:t}}require("path");var i=e(r);module.exports=(r,e)=>{if(!(()=>{try{return t.execSync("git --version"),!0}catch(t){return!1}})())throw new Error("Git does not exist!");if(!(t=>!!/^(https:\/\/github\.com\/|git@github\.com:)[\s\S]+\/[\s\S]+(\.git)?$/.exec(t))(r))throw new Error(`The current URL ${r} is not in a valid GitHub clone format!`);const{dirName:o,branch:c,cwd:s=i.default.cwd(),mirrorAddress:n,silence:h}=e||{};((r,e)=>{const i=r.split(" "),o=i.shift()||"",c=t.spawnSync(o,i,e);if(c.error)throw c.error})(["git","clone",n?((t,r)=>{let e=t;if(e.startsWith("git@")){const[,t,r]=e.match(/^git@github\.com:([\s\S]+)\/([\s\S]+)\.git$/)||[];e=`https://github.com/${t}/${r}.git`}return e.endsWith(".git")||(e+=".git"),e=e.replace("github.com",r),e})(r,n):r,`${o||""}`,c?`--branch ${c}`:""].filter((t=>t)).join(" "),{cwd:s,stdio:h?"pipe":"inherit"})};
2
- //# sourceMappingURL=gitClone.js.map
1
+ //#region \0rolldown/runtime.js
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
+ key = keys[i];
11
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
+ get: ((k) => from[k]).bind(null, key),
13
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
+ });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
+ value: mod,
20
+ enumerable: true
21
+ }) : target, mod));
22
+ //#endregion
23
+ let node_process = require("node:process");
24
+ node_process = __toESM(node_process);
25
+ let node_path = require("node:path");
26
+ node_path = __toESM(node_path);
27
+ let execa = require("execa");
28
+ //#region src/core/git-client.ts
29
+ function toExecaStdio(silence) {
30
+ return silence ? "pipe" : "inherit";
31
+ }
32
+ function buildCloneArgs(params) {
33
+ const args = ["clone", params.url];
34
+ if (params.branch) args.push("--branch", params.branch);
35
+ if (params.depth !== void 0) args.push("--depth", String(params.depth));
36
+ if (params.singleBranch) args.push("--single-branch");
37
+ if (params.dirName) args.push(params.dirName);
38
+ return args;
39
+ }
40
+ function assertGitSuccess(result) {
41
+ if (result.failed || result.exitCode !== void 0 && result.exitCode !== 0) {
42
+ const stderr = result.stderr?.trim();
43
+ throw new Error(stderr || `Git 命令执行失败,退出码 ${result.exitCode ?? "未知"}`);
44
+ }
45
+ }
46
+ function gitExists() {
47
+ try {
48
+ (0, execa.execaSync)("git", ["--version"]);
49
+ return true;
50
+ } catch {
51
+ return false;
52
+ }
53
+ }
54
+ function runGitClone(params) {
55
+ assertGitSuccess((0, execa.execaSync)("git", buildCloneArgs(params), {
56
+ cwd: params.cwd,
57
+ stdio: toExecaStdio(params.silence),
58
+ reject: false
59
+ }));
60
+ }
61
+ function setRemoteOrigin(dir, url, cwd) {
62
+ const dirPath = node_path.default.join(cwd, dir);
63
+ assertGitSuccess((0, execa.execaSync)("git", [
64
+ "remote",
65
+ "set-url",
66
+ "origin",
67
+ url
68
+ ], {
69
+ cwd: dirPath,
70
+ stdio: "pipe",
71
+ reject: false
72
+ }));
73
+ }
74
+ //#endregion
75
+ //#region src/core/github-url.ts
76
+ const GITHUB_HTTPS_RE = /^https:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?(?:\/.*)?$/;
77
+ const GITHUB_SSH_RE = /^git@github\.com:([^/]+)\/([^/]+?)(?:\.git)?$/;
78
+ function parseGithubUrl(url) {
79
+ const trimmed = url.trim();
80
+ const httpsMatch = GITHUB_HTTPS_RE.exec(trimmed);
81
+ if (httpsMatch) {
82
+ const [, owner, repo] = httpsMatch;
83
+ return {
84
+ owner,
85
+ repo,
86
+ normalizedHttps: `https://github.com/${owner}/${repo}.git`
87
+ };
88
+ }
89
+ const sshMatch = GITHUB_SSH_RE.exec(trimmed);
90
+ if (sshMatch) {
91
+ const [, owner, repo] = sshMatch;
92
+ return {
93
+ owner,
94
+ repo,
95
+ normalizedHttps: `https://github.com/${owner}/${repo}.git`
96
+ };
97
+ }
98
+ throw new Error(`无效的 GitHub 仓库地址:${url}`);
99
+ }
100
+ function replaceMirrorHost(url, mirrorHost) {
101
+ const { normalizedHttps } = parseGithubUrl(url);
102
+ return normalizedHttps.replace("github.com", mirrorHost);
103
+ }
104
+ function getRepoDirName(url) {
105
+ const { repo } = parseGithubUrl(url);
106
+ return repo;
107
+ }
108
+ //#endregion
109
+ //#region src/core/clone-repo.ts
110
+ function cloneGithubRepo(url, options) {
111
+ if (!gitExists()) throw new Error("未检测到 Git,请先安装 Git,并确保其在 PATH 中可用");
112
+ const { normalizedHttps } = parseGithubUrl(url);
113
+ const mirrorHost = options?.mirrorHost;
114
+ const cloneUrl = mirrorHost ? replaceMirrorHost(url, mirrorHost) : normalizedHttps;
115
+ const { dirName, branch, cwd = node_process.default.cwd(), silence, depth, singleBranch } = options ?? {};
116
+ const requestedDir = dirName?.trim() ? dirName.trim() : void 0;
117
+ const targetDir = requestedDir ?? getRepoDirName(url);
118
+ runGitClone({
119
+ url: cloneUrl,
120
+ dirName: requestedDir,
121
+ branch,
122
+ depth,
123
+ singleBranch,
124
+ cwd,
125
+ silence
126
+ });
127
+ if (mirrorHost) setRemoteOrigin(targetDir, normalizedHttps, cwd);
128
+ }
129
+ //#endregion
130
+ module.exports = cloneGithubRepo;
131
+
132
+ //# sourceMappingURL=gitClone.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"gitClone.js","sources":["../src/gitClone.ts","../src/utils.ts"],"sourcesContent":["import { execSync, spawnSync, SpawnSyncOptionsWithBufferEncoding } from 'child_process';\nimport process from 'process';\nimport { isGithubLink, replaceMirror } from './utils';\n\n/**\n * 判断git是否存在\n */\nconst gitExist = () => {\n try {\n execSync(`git --version`);\n return true;\n } catch {\n return false;\n }\n};\n\nconst pull = (shellStr: string, option?: SpawnSyncOptionsWithBufferEncoding) => {\n const args = shellStr.split(' ');\n const name = args.shift() || '';\n const info = spawnSync(name, args, option);\n if (info.error) {\n throw info.error;\n }\n return info;\n};\ninterface Options {\n dirName: string;\n branch: string;\n mirrorAddress: string;\n cwd: string;\n silence: boolean;\n}\n\nconst clone = (url: string, options?: Partial<Options>) => {\n if (!gitExist()) {\n throw new Error(`Git does not exist!`);\n }\n if (!isGithubLink(url)) {\n throw new Error(`The current URL ${url} is not in a valid GitHub clone format!`);\n }\n const { dirName, branch, cwd = process.cwd(), mirrorAddress, silence } = options || {};\n // 如果存在镜像网站就替换一下格式\n const template = mirrorAddress ? replaceMirror(url, mirrorAddress) : url;\n const shellArr = ['git', 'clone', template, `${dirName || ''}`, branch ? `--branch ${branch}` : ''];\n const shell = shellArr.filter((f) => f).join(' ');\n pull(shell, { cwd, stdio: silence ? 'pipe' : 'inherit' });\n};\n\nexport default clone;\n","import path from 'path';\nimport { execSync } from 'child_process';\n\n/**\n * 替换git的远程推送源地址,这里暂定origin名称为固定的\n */\nexport const setGitSource = (dir: string, url: string) => {\n // 仓库所在文件地址\n const dirPath = path.join(process.cwd(), dir);\n // 先删除在执行\n const shellStr = `git remote set-url origin ${url}`;\n execSync(shellStr, { cwd: dirPath });\n};\n\n/**\n * 根据github的url返回对应的文件夹名称\n * https://github.com.cnpmjs.org/bosens-China/github-clone会返回github-clone\n *\n */\nexport const getDir = (url: string) => {\n const str = url;\n const dir = str.split('/').pop() || '';\n return dir.includes('.git') ? dir.slice(0, dir.indexOf('.git')) : dir;\n};\n\n/* 是否为支持的git clone拉取格式\n * https://github.com/bosens-China/breeze-cli\n * https://github.com/bosens-China/breeze-cli.git\n * git@github.com:bosens-China/breeze-cli.git\n */\nexport const isGithubLink = (url: string) => {\n const reg = /^(https:\\/\\/github\\.com\\/|git@github\\.com:)[\\s\\S]+\\/[\\s\\S]+(\\.git)?$/;\n return !!reg.exec(url);\n};\n\n/**\n * 将当前的网站替换成镜像网站,例如\n * https://github.com/bosens-China/github-clone会被替换成\n * https://github.com.cnpmjs.org/bosens-China/github-clone\n */\n\nexport const replaceMirror = (currentWebsite: string, replaceWebsite: string) => {\n let s = currentWebsite;\n // 这里处理一下以git@开头的情况,如果git@开头,把用户名和仓库提取出来,用https的形式拉取\n // https://github.com/bosens-China/breeze-cli.git\n // git@github.com:bosens-China/breeze-cli.git\n if (s.startsWith('git@')) {\n const [, name, warehouse] = s.match(/^git@github\\.com:([\\s\\S]+)\\/([\\s\\S]+)\\.git$/) || [];\n s = `https://github.com/${name}/${warehouse}.git`;\n }\n if (!s.endsWith('.git')) {\n s += '.git';\n }\n s = s.replace('github.com', replaceWebsite);\n return s;\n};\n"],"names":["url","options","execSync","gitExist","Error","exec","isGithubLink","dirName","branch","cwd","process","mirrorAddress","silence","shellStr","option","args","split","name","shift","info","spawnSync","error","pull","currentWebsite","replaceWebsite","s","startsWith","warehouse","match","endsWith","replace","replaceMirror","filter","f","join","stdio"],"mappings":"mLAiCc,CAACA,EAAaC,KAC1B,IA3Be,MACf,IAEE,OADAC,WAAS,kBACF,EACP,SACA,OAAO,IAsBJC,GACH,MAAM,IAAIC,MAAM,uBAElB,ICP0B,CAACJ,KACf,uEACCK,KAAKL,GDKbM,CAAaN,GAChB,MAAM,IAAII,MAAM,mBAAmBJ,4CAErC,MAAMO,QAAEA,EAAOC,OAAEA,EAAMC,IAAEA,EAAMC,UAAQD,MAAKE,cAAEA,EAAaC,QAAEA,GAAYX,GAAW,GAxBzE,EAACY,EAAkBC,KAC9B,MAAMC,EAAOF,EAASG,MAAM,KACtBC,EAAOF,EAAKG,SAAW,GACvBC,EAAOC,YAAUH,EAAMF,EAAMD,GACnC,GAAIK,EAAKE,MACP,MAAMF,EAAKE,OAwBbC,CAFiB,CAAC,MAAO,QADRX,ECDU,EAACY,EAAwBC,KACpD,IAAIC,EAAIF,EAIR,GAAIE,EAAEC,WAAW,QAAS,CACxB,OAAST,EAAMU,GAAaF,EAAEG,MAAM,gDAAkD,GACtFH,EAAI,sBAAsBR,KAAQU,QAMpC,OAJKF,EAAEI,SAAS,UACdJ,GAAK,QAEPA,EAAIA,EAAEK,QAAQ,aAAcN,GACrBC,GDZ0BM,CAAc/B,EAAKW,GAAiBX,EACzB,GAAGO,GAAW,KAAMC,EAAS,YAAYA,IAAW,IACzEwB,QAAQC,GAAMA,IAAGC,KAAK,KACjC,CAAEzB,IAAAA,EAAK0B,MAAOvB,EAAU,OAAS"}
1
+ {"version":3,"file":"gitClone.js","names":["path","process"],"sources":["../src/core/git-client.ts","../src/core/github-url.ts","../src/core/clone-repo.ts"],"sourcesContent":["import path from 'node:path';\nimport { execaSync } from 'execa';\n\nexport interface GitCloneParams {\n url: string;\n dirName?: string;\n branch?: string;\n depth?: number;\n singleBranch?: boolean;\n cwd?: string;\n silence?: boolean;\n}\n\nfunction toExecaStdio(silence?: boolean): 'pipe' | 'inherit' {\n return silence ? 'pipe' : 'inherit';\n}\n\nfunction buildCloneArgs(params: GitCloneParams): string[] {\n const args = ['clone', params.url];\n if (params.branch) {\n args.push('--branch', params.branch);\n }\n if (params.depth !== undefined) {\n args.push('--depth', String(params.depth));\n }\n if (params.singleBranch) {\n args.push('--single-branch');\n }\n if (params.dirName) {\n args.push(params.dirName);\n }\n return args;\n}\n\nfunction assertGitSuccess(result: { failed: boolean; exitCode?: number; stderr?: string }): void {\n if (result.failed || (result.exitCode !== undefined && result.exitCode !== 0)) {\n const stderr = result.stderr?.trim();\n throw new Error(stderr || `Git 命令执行失败,退出码 ${result.exitCode ?? '未知'}`);\n }\n}\n\nexport function gitExists(): boolean {\n try {\n execaSync('git', ['--version']);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function runGitClone(params: GitCloneParams): void {\n const result = execaSync('git', buildCloneArgs(params), {\n cwd: params.cwd,\n stdio: toExecaStdio(params.silence),\n reject: false,\n });\n assertGitSuccess(result);\n}\n\nexport function setRemoteOrigin(dir: string, url: string, cwd: string): void {\n const dirPath = path.join(cwd, dir);\n const result = execaSync('git', ['remote', 'set-url', 'origin', url], {\n cwd: dirPath,\n stdio: 'pipe',\n reject: false,\n });\n assertGitSuccess(result);\n}\n","const GITHUB_HTTPS_RE = /^https:\\/\\/github\\.com\\/([^/]+)\\/([^/]+?)(?:\\.git)?(?:\\/.*)?$/;\nconst GITHUB_SSH_RE = /^git@github\\.com:([^/]+)\\/([^/]+?)(?:\\.git)?$/;\n\nexport interface ParsedGithubUrl {\n owner: string;\n repo: string;\n normalizedHttps: string;\n}\n\nexport function isGithubLink(url: string): boolean {\n const trimmed = url.trim();\n return GITHUB_HTTPS_RE.test(trimmed) || GITHUB_SSH_RE.test(trimmed);\n}\n\nexport function parseGithubUrl(url: string): ParsedGithubUrl {\n const trimmed = url.trim();\n const httpsMatch = GITHUB_HTTPS_RE.exec(trimmed);\n if (httpsMatch) {\n const [, owner, repo] = httpsMatch as RegExpExecArray & [string, string, string];\n return {\n owner,\n repo,\n normalizedHttps: `https://github.com/${owner}/${repo}.git`,\n };\n }\n\n const sshMatch = GITHUB_SSH_RE.exec(trimmed);\n if (sshMatch) {\n const [, owner, repo] = sshMatch as RegExpExecArray & [string, string, string];\n return {\n owner,\n repo,\n normalizedHttps: `https://github.com/${owner}/${repo}.git`,\n };\n }\n\n throw new Error(`无效的 GitHub 仓库地址:${url}`);\n}\n\nexport function replaceMirrorHost(url: string, mirrorHost: string): string {\n const { normalizedHttps } = parseGithubUrl(url);\n return normalizedHttps.replace('github.com', mirrorHost);\n}\n\nexport function getRepoDirName(url: string): string {\n const { repo } = parseGithubUrl(url);\n return repo;\n}\n\nexport function buildMirrorProbeUrl(mirrorHost: string, repoPath: string): string {\n return `https://${mirrorHost}/${repoPath}`;\n}\n","import process from 'node:process';\nimport type { CloneOptions } from '../types';\nimport { gitExists, runGitClone, setRemoteOrigin } from './git-client';\nimport { getRepoDirName, parseGithubUrl, replaceMirrorHost } from './github-url';\n\nexport function cloneGithubRepo(url: string, options?: CloneOptions): void {\n if (!gitExists()) {\n throw new Error('未检测到 Git,请先安装 Git,并确保其在 PATH 中可用');\n }\n\n const { normalizedHttps } = parseGithubUrl(url);\n const mirrorHost = options?.mirrorHost;\n const cloneUrl = mirrorHost ? replaceMirrorHost(url, mirrorHost) : normalizedHttps;\n\n const {\n dirName,\n branch,\n cwd = process.cwd(),\n silence,\n depth,\n singleBranch,\n } = options ?? {};\n\n const requestedDir = dirName?.trim() ? dirName.trim() : undefined;\n const targetDir = requestedDir ?? getRepoDirName(url);\n\n runGitClone({\n url: cloneUrl,\n dirName: requestedDir,\n branch,\n depth,\n singleBranch,\n cwd,\n silence,\n });\n\n if (mirrorHost) {\n setRemoteOrigin(targetDir, normalizedHttps, cwd);\n }\n}\n\nexport default cloneGithubRepo;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAaA,SAAS,aAAa,SAAuC;CAC3D,OAAO,UAAU,SAAS;AAC5B;AAEA,SAAS,eAAe,QAAkC;CACxD,MAAM,OAAO,CAAC,SAAS,OAAO,GAAG;CACjC,IAAI,OAAO,QACT,KAAK,KAAK,YAAY,OAAO,MAAM;CAErC,IAAI,OAAO,UAAU,KAAA,GACnB,KAAK,KAAK,WAAW,OAAO,OAAO,KAAK,CAAC;CAE3C,IAAI,OAAO,cACT,KAAK,KAAK,iBAAiB;CAE7B,IAAI,OAAO,SACT,KAAK,KAAK,OAAO,OAAO;CAE1B,OAAO;AACT;AAEA,SAAS,iBAAiB,QAAuE;CAC/F,IAAI,OAAO,UAAW,OAAO,aAAa,KAAA,KAAa,OAAO,aAAa,GAAI;EAC7E,MAAM,SAAS,OAAO,QAAQ,KAAK;EACnC,MAAM,IAAI,MAAM,UAAU,kBAAkB,OAAO,YAAY,MAAM;CACvE;AACF;AAEA,SAAgB,YAAqB;CACnC,IAAI;EACF,CAAA,GAAA,MAAA,UAAA,CAAU,OAAO,CAAC,WAAW,CAAC;EAC9B,OAAO;CACT,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAgB,YAAY,QAA8B;CAMxD,kBAAA,GAAA,MAAA,UAAA,CALyB,OAAO,eAAe,MAAM,GAAG;EACtD,KAAK,OAAO;EACZ,OAAO,aAAa,OAAO,OAAO;EAClC,QAAQ;CACV,CACsB,CAAC;AACzB;AAEA,SAAgB,gBAAgB,KAAa,KAAa,KAAmB;CAC3E,MAAM,UAAUA,UAAAA,QAAK,KAAK,KAAK,GAAG;CAMlC,kBAAA,GAAA,MAAA,UAAA,CALyB,OAAO;EAAC;EAAU;EAAW;EAAU;CAAG,GAAG;EACpE,KAAK;EACL,OAAO;EACP,QAAQ;CACV,CACsB,CAAC;AACzB;;;ACnEA,MAAM,kBAAkB;AACxB,MAAM,gBAAgB;AAatB,SAAgB,eAAe,KAA8B;CAC3D,MAAM,UAAU,IAAI,KAAK;CACzB,MAAM,aAAa,gBAAgB,KAAK,OAAO;CAC/C,IAAI,YAAY;EACd,MAAM,GAAG,OAAO,QAAQ;EACxB,OAAO;GACL;GACA;GACA,iBAAiB,sBAAsB,MAAM,GAAG,KAAK;EACvD;CACF;CAEA,MAAM,WAAW,cAAc,KAAK,OAAO;CAC3C,IAAI,UAAU;EACZ,MAAM,GAAG,OAAO,QAAQ;EACxB,OAAO;GACL;GACA;GACA,iBAAiB,sBAAsB,MAAM,GAAG,KAAK;EACvD;CACF;CAEA,MAAM,IAAI,MAAM,mBAAmB,KAAK;AAC1C;AAEA,SAAgB,kBAAkB,KAAa,YAA4B;CACzE,MAAM,EAAE,oBAAoB,eAAe,GAAG;CAC9C,OAAO,gBAAgB,QAAQ,cAAc,UAAU;AACzD;AAEA,SAAgB,eAAe,KAAqB;CAClD,MAAM,EAAE,SAAS,eAAe,GAAG;CACnC,OAAO;AACT;;;AC1CA,SAAgB,gBAAgB,KAAa,SAA8B;CACzE,IAAI,CAAC,UAAU,GACb,MAAM,IAAI,MAAM,kCAAkC;CAGpD,MAAM,EAAE,oBAAoB,eAAe,GAAG;CAC9C,MAAM,aAAa,SAAS;CAC5B,MAAM,WAAW,aAAa,kBAAkB,KAAK,UAAU,IAAI;CAEnE,MAAM,EACJ,SACA,QACA,MAAMC,aAAAA,QAAQ,IAAI,GAClB,SACA,OACA,iBACE,WAAW,CAAC;CAEhB,MAAM,eAAe,SAAS,KAAK,IAAI,QAAQ,KAAK,IAAI,KAAA;CACxD,MAAM,YAAY,gBAAgB,eAAe,GAAG;CAEpD,YAAY;EACV,KAAK;EACL,SAAS;EACT;EACA;EACA;EACA;EACA;CACF,CAAC;CAED,IAAI,YACF,gBAAgB,WAAW,iBAAiB,GAAG;AAEnD"}
@@ -0,0 +1,3 @@
1
+ export { cloneGithubRepo as default } from './core/clone-repo';
2
+ export type { CloneOptions } from './types';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,IAAI,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC/D,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC"}
package/dist/main.js CHANGED
@@ -1,3 +1,344 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var e=require("commander"),t=require("os"),r=require("path"),o=require("fs"),i=require("./gitClone"),c=require("child_process");function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var s=n(t),a=n(r),u=n(o),l=n(i);const d=s.default.homedir(),g=a.default.join(d,".g.config"),h="github.com.cnpmjs.org",m=()=>u.default.existsSync(g)&&u.default.readFileSync(g,"utf-8")||h,p=new e.Command;p.version("1.1.6","-v, --version","输出当前版本号"),p.command("clone <url> [warehouse]").description("根据url拉取指定仓库").option("-b, --branch <value>","拉取指定分支").action(((e,t,{branch:r}={})=>{try{l.default(e,{dirName:t,branch:r,mirrorAddress:m()});const o=t||(e=>{const t=e.split("/").pop()||"";return t.includes(".git")?t.slice(0,t.indexOf(".git")):t})(m()?((e,t)=>{let r=e;if(r.startsWith("git@")){const[,e,t]=r.match(/^git@github\.com:([\s\S]+)\/([\s\S]+)\.git$/)||[];r=`https://github.com/${e}/${t}.git`}return r.endsWith(".git")||(r+=".git"),r=r.replace("github.com",t),r})(e,m()):e);((e,t)=>{const r=a.default.join(process.cwd(),e),o=`git remote set-url origin ${t}`;c.execSync(o,{cwd:r})})(o,e)}catch(e){console.error(`${e instanceof Error?e.message:e}`)}})),p.command("set [path]").description(`修改github的镜像仓库地址,<path>可选,如果省略,默认为: ${h}`).action(((e=h)=>{try{t=e,u.default.writeFileSync(g,t),console.log(`set ${e}成功`)}catch(e){console.error("set path error")}var t})),p.command("get [path]").description("读取当前的默认镜像地址").action((()=>{const e=m();console.log(`当前镜像地址为:${e}`)})),p.parse(process.argv);
3
- //# sourceMappingURL=main.js.map
2
+ //#region \0rolldown/runtime.js
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
13
+ get: ((k) => from[k]).bind(null, key),
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
20
+ value: mod,
21
+ enumerable: true
22
+ }) : target, mod));
23
+ //#endregion
24
+ let node_process = require("node:process");
25
+ node_process = __toESM(node_process);
26
+ let commander = require("commander");
27
+ let picocolors = require("picocolors");
28
+ picocolors = __toESM(picocolors);
29
+ let zod = require("zod");
30
+ let node_fs = require("node:fs");
31
+ node_fs = __toESM(node_fs);
32
+ let node_os = require("node:os");
33
+ node_os = __toESM(node_os);
34
+ let node_path = require("node:path");
35
+ node_path = __toESM(node_path);
36
+ let execa = require("execa");
37
+ //#region package.json
38
+ var version = "1.3.0";
39
+ //#endregion
40
+ //#region src/config/mirror-store.ts
41
+ const mirrorHostSchema = zod.z.string().trim().min(1, "镜像地址不能为空").regex(/^[a-zA-Z0-9](?:[-a-zA-Z0-9.]*[a-zA-Z0-9])?(?:\/[a-zA-Z0-9](?:[-a-zA-Z0-9.]*[a-zA-Z0-9])?)*$/, "镜像地址格式无效,请输入域名或域名/路径,例如 kgithub.com 或 gitclone.com/github.com");
42
+ const defaultConfigPath = node_path.default.join(node_os.default.homedir(), ".g.config");
43
+ var ConfigStore = class {
44
+ configPath;
45
+ constructor(configPath = defaultConfigPath) {
46
+ this.configPath = configPath;
47
+ }
48
+ getMirrorHost() {
49
+ if (!node_fs.default.existsSync(this.configPath)) return;
50
+ return node_fs.default.readFileSync(this.configPath, "utf-8").trim() || void 0;
51
+ }
52
+ setMirrorHost(host) {
53
+ const parsed = mirrorHostSchema.parse(host);
54
+ node_fs.default.writeFileSync(this.configPath, parsed, "utf-8");
55
+ }
56
+ unsetMirrorHost() {
57
+ if (node_fs.default.existsSync(this.configPath)) node_fs.default.unlinkSync(this.configPath);
58
+ }
59
+ getConfigPath() {
60
+ return this.configPath;
61
+ }
62
+ };
63
+ const defaultConfigStore = new ConfigStore();
64
+ //#endregion
65
+ //#region src/core/git-client.ts
66
+ function toExecaStdio(silence) {
67
+ return silence ? "pipe" : "inherit";
68
+ }
69
+ function buildCloneArgs(params) {
70
+ const args = ["clone", params.url];
71
+ if (params.branch) args.push("--branch", params.branch);
72
+ if (params.depth !== void 0) args.push("--depth", String(params.depth));
73
+ if (params.singleBranch) args.push("--single-branch");
74
+ if (params.dirName) args.push(params.dirName);
75
+ return args;
76
+ }
77
+ function assertGitSuccess(result) {
78
+ if (result.failed || result.exitCode !== void 0 && result.exitCode !== 0) {
79
+ const stderr = result.stderr?.trim();
80
+ throw new Error(stderr || `Git 命令执行失败,退出码 ${result.exitCode ?? "未知"}`);
81
+ }
82
+ }
83
+ function gitExists() {
84
+ try {
85
+ (0, execa.execaSync)("git", ["--version"]);
86
+ return true;
87
+ } catch {
88
+ return false;
89
+ }
90
+ }
91
+ function runGitClone(params) {
92
+ assertGitSuccess((0, execa.execaSync)("git", buildCloneArgs(params), {
93
+ cwd: params.cwd,
94
+ stdio: toExecaStdio(params.silence),
95
+ reject: false
96
+ }));
97
+ }
98
+ function setRemoteOrigin(dir, url, cwd) {
99
+ const dirPath = node_path.default.join(cwd, dir);
100
+ assertGitSuccess((0, execa.execaSync)("git", [
101
+ "remote",
102
+ "set-url",
103
+ "origin",
104
+ url
105
+ ], {
106
+ cwd: dirPath,
107
+ stdio: "pipe",
108
+ reject: false
109
+ }));
110
+ }
111
+ //#endregion
112
+ //#region src/core/github-url.ts
113
+ const GITHUB_HTTPS_RE = /^https:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?(?:\/.*)?$/;
114
+ const GITHUB_SSH_RE = /^git@github\.com:([^/]+)\/([^/]+?)(?:\.git)?$/;
115
+ function parseGithubUrl(url) {
116
+ const trimmed = url.trim();
117
+ const httpsMatch = GITHUB_HTTPS_RE.exec(trimmed);
118
+ if (httpsMatch) {
119
+ const [, owner, repo] = httpsMatch;
120
+ return {
121
+ owner,
122
+ repo,
123
+ normalizedHttps: `https://github.com/${owner}/${repo}.git`
124
+ };
125
+ }
126
+ const sshMatch = GITHUB_SSH_RE.exec(trimmed);
127
+ if (sshMatch) {
128
+ const [, owner, repo] = sshMatch;
129
+ return {
130
+ owner,
131
+ repo,
132
+ normalizedHttps: `https://github.com/${owner}/${repo}.git`
133
+ };
134
+ }
135
+ throw new Error(`无效的 GitHub 仓库地址:${url}`);
136
+ }
137
+ function replaceMirrorHost(url, mirrorHost) {
138
+ const { normalizedHttps } = parseGithubUrl(url);
139
+ return normalizedHttps.replace("github.com", mirrorHost);
140
+ }
141
+ function getRepoDirName(url) {
142
+ const { repo } = parseGithubUrl(url);
143
+ return repo;
144
+ }
145
+ function buildMirrorProbeUrl(mirrorHost, repoPath) {
146
+ return `https://${mirrorHost}/${repoPath}`;
147
+ }
148
+ //#endregion
149
+ //#region src/core/clone-repo.ts
150
+ function cloneGithubRepo(url, options) {
151
+ if (!gitExists()) throw new Error("未检测到 Git,请先安装 Git,并确保其在 PATH 中可用");
152
+ const { normalizedHttps } = parseGithubUrl(url);
153
+ const mirrorHost = options?.mirrorHost;
154
+ const cloneUrl = mirrorHost ? replaceMirrorHost(url, mirrorHost) : normalizedHttps;
155
+ const { dirName, branch, cwd = node_process.default.cwd(), silence, depth, singleBranch } = options ?? {};
156
+ const requestedDir = dirName?.trim() ? dirName.trim() : void 0;
157
+ const targetDir = requestedDir ?? getRepoDirName(url);
158
+ runGitClone({
159
+ url: cloneUrl,
160
+ dirName: requestedDir,
161
+ branch,
162
+ depth,
163
+ singleBranch,
164
+ cwd,
165
+ silence
166
+ });
167
+ if (mirrorHost) setRemoteOrigin(targetDir, normalizedHttps, cwd);
168
+ }
169
+ //#endregion
170
+ //#region src/cli/commands/clone-command.ts
171
+ function normalizeDirName(dir) {
172
+ const trimmed = dir?.trim();
173
+ return trimmed ? trimmed : void 0;
174
+ }
175
+ function printVerboseClonePlan(url, dirName, options, mirrorHost) {
176
+ const { normalizedHttps } = parseGithubUrl(url);
177
+ const cloneUrl = mirrorHost ? replaceMirrorHost(url, mirrorHost) : normalizedHttps;
178
+ const targetDir = normalizeDirName(dirName) ?? getRepoDirName(url);
179
+ console.log(picocolors.default.bold("克隆计划"));
180
+ console.log(picocolors.default.dim(` 模式 : ${mirrorHost ? `镜像(${mirrorHost})` : "直连 GitHub"}`));
181
+ console.log(picocolors.default.dim(` 克隆地址 : ${cloneUrl}`));
182
+ if (mirrorHost) console.log(picocolors.default.dim(` 恢复 origin: ${normalizedHttps}`));
183
+ console.log(picocolors.default.dim(` 本地目录 : ${targetDir}`));
184
+ const gitFlags = [];
185
+ if (options.branch) gitFlags.push(`--branch ${options.branch}`);
186
+ if (options.depth !== void 0) gitFlags.push(`--depth ${options.depth}`);
187
+ if (options.singleBranch) gitFlags.push("--single-branch");
188
+ if (gitFlags.length > 0) console.log(picocolors.default.dim(` Git 参数 : ${gitFlags.join(" ")}`));
189
+ else console.log(picocolors.default.dim(" Git 参数 : (无额外参数,完整克隆)"));
190
+ console.log("");
191
+ }
192
+ function runCloneCommand(url, dirName, options) {
193
+ const mirrorHost = options.mirror !== false ? defaultConfigStore.getMirrorHost() : void 0;
194
+ const requestedDir = normalizeDirName(dirName);
195
+ if (options.verbose) printVerboseClonePlan(url, requestedDir, options, mirrorHost);
196
+ else console.log(picocolors.default.dim(mirrorHost ? `→ 使用镜像 ${mirrorHost}` : "→ 直连 github.com"));
197
+ try {
198
+ cloneGithubRepo(url, {
199
+ dirName: requestedDir,
200
+ branch: options.branch,
201
+ mirrorHost,
202
+ depth: options.depth,
203
+ singleBranch: options.singleBranch
204
+ });
205
+ } catch (error) {
206
+ if (mirrorHost) console.error(picocolors.default.yellow(`提示:镜像 ${mirrorHost} 可能不可用,可执行 g mirror test 验证,或加 --no-mirror 直连`));
207
+ throw error;
208
+ }
209
+ const repoDir = requestedDir ?? getRepoDirName(url);
210
+ const branchInfo = options.branch ? `,分支 ${options.branch}` : "";
211
+ console.log(picocolors.default.green(`✓ 克隆完成:${repoDir}${branchInfo}`));
212
+ if (mirrorHost && !options.verbose) console.log(picocolors.default.dim(` 已恢复 origin 为 GitHub 官方地址`));
213
+ }
214
+ //#endregion
215
+ //#region src/constants.ts
216
+ const MIRROR_PRESETS = [
217
+ {
218
+ name: "kgithub",
219
+ host: "kgithub.com",
220
+ description: "KGitHub 镜像(域名替换)"
221
+ },
222
+ {
223
+ name: "moeyy",
224
+ host: "github.moeyy.xyz",
225
+ description: "Moeyy 镜像(域名替换)"
226
+ },
227
+ {
228
+ name: "gitclone",
229
+ host: "gitclone.com/github.com",
230
+ description: "GitClone 缓存(路径前缀)"
231
+ }
232
+ ];
233
+ /** 用于 mirror test 的探测仓库路径(GitHub 官方示例仓库,长期稳定) */
234
+ const MIRROR_PROBE_REPO = "octocat/Hello-World";
235
+ //#endregion
236
+ //#region src/cli/commands/mirror-command.ts
237
+ const PROBE_TIMEOUT_MS = 1e4;
238
+ function printMirror(host) {
239
+ if (host) {
240
+ console.log(`当前镜像:${picocolors.default.cyan(host)}`);
241
+ return;
242
+ }
243
+ console.log(picocolors.default.yellow("当前未配置镜像,克隆将直连 GitHub"));
244
+ }
245
+ function runMirrorSet(host) {
246
+ defaultConfigStore.setMirrorHost(host);
247
+ console.log(picocolors.default.green(`镜像已设置为 ${host}`));
248
+ console.log(picocolors.default.dim("提示:执行 g mirror test 验证镜像是否可用"));
249
+ }
250
+ function runMirrorUnset() {
251
+ defaultConfigStore.unsetMirrorHost();
252
+ console.log(picocolors.default.green("已清除镜像配置,克隆将直连 GitHub"));
253
+ }
254
+ function runMirrorList() {
255
+ const current = defaultConfigStore.getMirrorHost();
256
+ const isPresetCurrent = current ? MIRROR_PRESETS.some((p) => p.host === current) : false;
257
+ console.log(picocolors.default.bold("可用镜像预设:"));
258
+ for (const preset of MIRROR_PRESETS) {
259
+ const marker = current === preset.host ? picocolors.default.green(" (当前)") : "";
260
+ console.log(` ${picocolors.default.cyan(preset.name.padEnd(8))} ${preset.host} ${picocolors.default.dim(`— ${preset.description}`)}${marker}`);
261
+ }
262
+ console.log("");
263
+ if (current && !isPresetCurrent) console.log(`当前配置:${picocolors.default.cyan(current)} ${picocolors.default.dim("(自定义镜像,非内置预设)")}`);
264
+ else if (!current) {
265
+ console.log(picocolors.default.dim("当前未配置镜像,克隆将直连 GitHub"));
266
+ console.log(picocolors.default.dim("提示:使用 g mirror set <address> 或 g mirror set <预设名> 进行配置"));
267
+ }
268
+ }
269
+ function formatProbeError(error, mirrorHost) {
270
+ if (error instanceof Error) {
271
+ if (error.name === "TimeoutError") return `镜像 ${mirrorHost} 探测超时(>${PROBE_TIMEOUT_MS / 1e3}s),可能不可用`;
272
+ const code = error.cause?.code;
273
+ if (code === "ENOTFOUND" || code === "EAI_AGAIN") return `无法解析镜像地址 ${mirrorHost},请检查配置是否正确`;
274
+ if (code === "ECONNREFUSED" || code === "ECONNRESET") return `连接 ${mirrorHost} 被拒绝或重置,镜像可能不可用`;
275
+ if (error.message === "fetch failed") return `无法连接 ${mirrorHost},请检查网络或镜像是否可用`;
276
+ }
277
+ return `镜像 ${mirrorHost} 探测失败:${error instanceof Error ? error.message : String(error)}`;
278
+ }
279
+ async function runMirrorTest(host) {
280
+ const mirrorHost = host ?? defaultConfigStore.getMirrorHost();
281
+ if (!mirrorHost) throw new Error("未配置镜像,请先执行 g mirror set <address> 或指定测试地址");
282
+ const probeUrl = buildMirrorProbeUrl(mirrorHost, MIRROR_PROBE_REPO);
283
+ console.log(picocolors.default.dim(`正在探测 ${probeUrl}⋯⋯`));
284
+ let response;
285
+ try {
286
+ response = await fetch(probeUrl, {
287
+ method: "HEAD",
288
+ signal: AbortSignal.timeout(PROBE_TIMEOUT_MS)
289
+ });
290
+ } catch (error) {
291
+ throw new Error(formatProbeError(error, mirrorHost), { cause: error });
292
+ }
293
+ if (!response.ok) throw new Error(`镜像 ${mirrorHost} 返回 HTTP ${response.status},可能不可用`);
294
+ console.log(picocolors.default.green(`镜像 ${mirrorHost} 可用`));
295
+ }
296
+ function resolveMirrorHostInput(input) {
297
+ return MIRROR_PRESETS.find((item) => item.name === input || item.host === input)?.host ?? input;
298
+ }
299
+ //#endregion
300
+ //#region src/cli/index.ts
301
+ function formatCliError(error) {
302
+ if (error instanceof zod.ZodError) return error.issues.map((item) => item.message).join(";");
303
+ if (error instanceof Error) return error.message;
304
+ return String(error);
305
+ }
306
+ const program = new commander.Command();
307
+ program.name("g").description("加速国内 GitHub clone:通过镜像拉取代码,完成后自动将 origin 恢复为 GitHub 官方地址").version(version, "-v, --version", "输出版本号").addHelpText("after", `
308
+ 快速开始:
309
+ $ g mirror set kgithub # 配置镜像(首次使用)
310
+ $ g mirror test # 验证镜像可用
311
+ $ g clone https://github.com/owner/repo # 克隆仓库
312
+ `);
313
+ program.command("clone <url> [dir]").description("克隆 GitHub 仓库。若已通过 g mirror set 配置镜像,将经镜像加速下载;克隆结束后将 origin 改回 github.com,便于后续 push。").option("-b, --branch <name>", "只检出指定分支(传给 git clone --branch)。例如 -b dev 表示克隆 dev 分支的工作区").option("--depth <n>", "浅克隆:只拉取最近 n 次提交(传给 git clone --depth)。如 --depth 1 表示只要最新版本,体积更小、速度更快,但本地没有完整 Git 历史", (value) => Number.parseInt(value, 10)).option("--single-branch", "只克隆单个分支,不下载其他远程分支(传给 git clone --single-branch)。常与 -b 联用;单独使用时默认只拉远程默认分支(通常是 main)").option("--no-mirror", "忽略 ~/.g.config 中的镜像配置,强制直连 github.com 克隆").option("--verbose", "输出克隆前的详细信息:镜像/直连模式、实际克隆地址、分支与 Git 参数等(不改变 Git 本身的输出)").addHelpText("after", `
314
+ 示例:
315
+ $ g clone https://github.com/owner/repo
316
+ $ g clone https://github.com/owner/repo my-dir -b dev
317
+ $ g clone https://github.com/owner/repo -b main --single-branch --depth 1
318
+ $ g clone https://github.com/owner/repo --no-mirror --verbose
319
+ `).action(async (url, dir, options) => {
320
+ runCloneCommand(url, dir, options);
321
+ });
322
+ const mirror = program.command("mirror").description("管理 GitHub 镜像配置(保存在 ~/.g.config,如 kgithub.com 或 gitclone.com/github.com)");
323
+ mirror.command("set <address>").description("设置镜像地址,或传入预设名(kgithub / moeyy / gitclone)。执行 g mirror list 查看预设").action(async (address) => {
324
+ runMirrorSet(resolveMirrorHostInput(address));
325
+ });
326
+ mirror.command("get").description("查看 ~/.g.config 中保存的镜像;未配置时克隆将直连 GitHub").action(async () => {
327
+ printMirror(defaultConfigStore.getMirrorHost());
328
+ });
329
+ mirror.command("list").alias("ls").description("列出内置镜像预设及说明,并标注当前正在使用的镜像").action(async () => {
330
+ runMirrorList();
331
+ });
332
+ mirror.command("unset").description("删除 ~/.g.config,清除镜像配置(克隆将直连 GitHub)").action(async () => {
333
+ runMirrorUnset();
334
+ });
335
+ mirror.command("test [address]").description("探测镜像是否可达:对镜像站发起 HTTP HEAD 请求。省略 address 时测试当前配置;可传镜像地址或预设名").action(async (address) => {
336
+ await runMirrorTest(address ? resolveMirrorHostInput(address) : void 0);
337
+ });
338
+ program.parseAsync(node_process.default.argv).catch((error) => {
339
+ console.error(picocolors.default.red(`错误:${formatCliError(error)}`));
340
+ node_process.default.exit(1);
341
+ });
342
+ //#endregion
343
+
344
+ //# sourceMappingURL=main.js.map
package/dist/main.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"main.js","sources":["../src/config.ts","../src/main.ts","../src/utils.ts"],"sourcesContent":["import os from 'os';\nimport path from 'path';\nimport fs from 'fs';\n\nconst dir = os.homedir();\nconst configPath = path.join(dir, '.g.config');\n\n// 默认github镜像网站\nexport const DEFAULTPATH = 'github.com.cnpmjs.org';\n\n/**\n * 读取配置\n *\n */\nexport const getAddress = () => {\n if (!fs.existsSync(configPath)) {\n return DEFAULTPATH;\n }\n return fs.readFileSync(configPath, 'utf-8') || DEFAULTPATH;\n};\n\n/**\n * 设置配置\n *\n */\nexport const setAddress = (address: string) => {\n fs.writeFileSync(configPath, address);\n};\n","#!/usr/bin/env node\n\nimport { Command } from 'commander';\nimport { version } from '../package.json';\nimport { getAddress, setAddress, DEFAULTPATH } from './config';\nimport GitClone from './gitClone';\nimport { setGitSource, getDir, replaceMirror } from './utils';\n\nconst program = new Command();\nprogram.version(version, '-v, --version', '输出当前版本号');\n// git clone 支持多个命令,但是这里只让他支持-b也就是拉取指定分支,非必填\nprogram\n .command('clone <url> [warehouse]')\n .description('根据url拉取指定仓库')\n .option('-b, --branch <value>', '拉取指定分支')\n .action((url, dirName, { branch } = {}) => {\n try {\n // 开始拉取\n GitClone(url, { dirName, branch, mirrorAddress: getAddress() });\n // 拉取成功之后,进入拉取目录修改推送源地址\n const directory = dirName || getDir(getAddress() ? replaceMirror(url, getAddress()) : url);\n setGitSource(directory, url);\n } catch (e) {\n console.error(`${e instanceof Error ? e.message : e}`);\n }\n });\n\nprogram\n .command('set [path]')\n .description(`修改github的镜像仓库地址,<path>可选,如果省略,默认为: ${DEFAULTPATH}`)\n .action((pathUrl = DEFAULTPATH) => {\n try {\n setAddress(pathUrl);\n console.log(`set ${pathUrl}成功`);\n } catch {\n console.error(`set path error`);\n }\n });\nprogram\n .command('get [path]')\n .description(`读取当前的默认镜像地址`)\n .action(() => {\n const path = getAddress();\n console.log(`当前镜像地址为:${path}`);\n });\nprogram.parse(process.argv);\n","import path from 'path';\nimport { execSync } from 'child_process';\n\n/**\n * 替换git的远程推送源地址,这里暂定origin名称为固定的\n */\nexport const setGitSource = (dir: string, url: string) => {\n // 仓库所在文件地址\n const dirPath = path.join(process.cwd(), dir);\n // 先删除在执行\n const shellStr = `git remote set-url origin ${url}`;\n execSync(shellStr, { cwd: dirPath });\n};\n\n/**\n * 根据github的url返回对应的文件夹名称\n * https://github.com.cnpmjs.org/bosens-China/github-clone会返回github-clone\n *\n */\nexport const getDir = (url: string) => {\n const str = url;\n const dir = str.split('/').pop() || '';\n return dir.includes('.git') ? dir.slice(0, dir.indexOf('.git')) : dir;\n};\n\n/* 是否为支持的git clone拉取格式\n * https://github.com/bosens-China/breeze-cli\n * https://github.com/bosens-China/breeze-cli.git\n * git@github.com:bosens-China/breeze-cli.git\n */\nexport const isGithubLink = (url: string) => {\n const reg = /^(https:\\/\\/github\\.com\\/|git@github\\.com:)[\\s\\S]+\\/[\\s\\S]+(\\.git)?$/;\n return !!reg.exec(url);\n};\n\n/**\n * 将当前的网站替换成镜像网站,例如\n * https://github.com/bosens-China/github-clone会被替换成\n * https://github.com.cnpmjs.org/bosens-China/github-clone\n */\n\nexport const replaceMirror = (currentWebsite: string, replaceWebsite: string) => {\n let s = currentWebsite;\n // 这里处理一下以git@开头的情况,如果git@开头,把用户名和仓库提取出来,用https的形式拉取\n // https://github.com/bosens-China/breeze-cli.git\n // git@github.com:bosens-China/breeze-cli.git\n if (s.startsWith('git@')) {\n const [, name, warehouse] = s.match(/^git@github\\.com:([\\s\\S]+)\\/([\\s\\S]+)\\.git$/) || [];\n s = `https://github.com/${name}/${warehouse}.git`;\n }\n if (!s.endsWith('.git')) {\n s += '.git';\n }\n s = s.replace('github.com', replaceWebsite);\n return s;\n};\n"],"names":["dir","os","homedir","configPath","path","join","DEFAULTPATH","getAddress","fs","existsSync","readFileSync","program","Command","version","command","description","option","action","url","dirName","branch","GitClone","mirrorAddress","directory","split","pop","includes","slice","indexOf","getDir","currentWebsite","replaceWebsite","s","startsWith","name","warehouse","match","endsWith","replace","replaceMirror","dirPath","process","cwd","shellStr","execSync","setGitSource","e","console","error","Error","message","pathUrl","address","writeFileSync","log","parse","argv"],"mappings":";qPAIA,MAAMA,EAAMC,UAAGC,UACTC,EAAaC,UAAKC,KAAKL,EAAK,aAGrBM,EAAc,wBAMdC,EAAa,IACnBC,UAAGC,WAAWN,IAGZK,UAAGE,aAAaP,EAAY,UAF1BG,ECRLK,EAAU,IAAIC,UACpBD,EAAQE,gBAAiB,gBAAiB,WAE1CF,EACGG,QAAQ,2BACRC,YAAY,eACZC,OAAO,uBAAwB,UAC/BC,QAAO,CAACC,EAAKC,GAAWC,OAAAA,GAAW,MAClC,IAEEC,UAASH,EAAK,CAAEC,QAAAA,EAASC,OAAAA,EAAQE,cAAef,MAEhD,MAAMgB,EAAYJ,GCDF,CAACD,IACrB,MACMlB,EADMkB,EACIM,MAAM,KAAKC,OAAS,GACpC,OAAOzB,EAAI0B,SAAS,QAAU1B,EAAI2B,MAAM,EAAG3B,EAAI4B,QAAQ,SAAW5B,GDFjC6B,CAAOtB,ICqBb,EAACuB,EAAwBC,KACpD,IAAIC,EAAIF,EAIR,GAAIE,EAAEC,WAAW,QAAS,CACxB,OAASC,EAAMC,GAAaH,EAAEI,MAAM,gDAAkD,GACtFJ,EAAI,sBAAsBE,KAAQC,QAMpC,OAJKH,EAAEK,SAAS,UACdL,GAAK,QAEPA,EAAIA,EAAEM,QAAQ,aAAcP,GACrBC,GDlCgDO,CAAcrB,EAAKX,KAAgBW,GCdhE,EAAClB,EAAakB,KAExC,MAAMsB,EAAUpC,UAAKC,KAAKoC,QAAQC,MAAO1C,GAEnC2C,EAAW,6BAA6BzB,IAC9C0B,WAASD,EAAU,CAAED,IAAKF,KDUtBK,CAAatB,EAAWL,GACxB,MAAO4B,GACPC,QAAQC,MAAM,GAAGF,aAAaG,MAAQH,EAAEI,QAAUJ,SAIxDnC,EACGG,QAAQ,cACRC,YAAY,sCAAsCT,KAClDW,QAAO,CAACkC,EAAU7C,KACjB,IDNuB8C,ECOVD,EDNf3C,UAAG6C,cAAclD,EAAYiD,GCOzBL,QAAQO,IAAI,OAAOH,OACnB,SACAJ,QAAQC,MAAM,kBDVM,IAACI,KCa3BzC,EACGG,QAAQ,cACRC,YAAY,eACZE,QAAO,KACN,MAAMb,EAAOG,IACbwC,QAAQO,IAAI,WAAWlD,QAE3BO,EAAQ4C,MAAMd,QAAQe"}
1
+ {"version":3,"file":"main.js","names":["z","path","os","fs","path","process","pc","pc","ZodError","Command","process","pc"],"sources":["../package.json","../src/config/mirror-store.ts","../src/core/git-client.ts","../src/core/github-url.ts","../src/core/clone-repo.ts","../src/cli/commands/clone-command.ts","../src/constants.ts","../src/cli/commands/mirror-command.ts","../src/cli/index.ts"],"sourcesContent":["","import fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport { z } from 'zod';\n\nconst mirrorHostSchema = z\n .string()\n .trim()\n .min(1, '镜像地址不能为空')\n .regex(\n /^[a-zA-Z0-9](?:[-a-zA-Z0-9.]*[a-zA-Z0-9])?(?:\\/[a-zA-Z0-9](?:[-a-zA-Z0-9.]*[a-zA-Z0-9])?)*$/,\n '镜像地址格式无效,请输入域名或域名/路径,例如 kgithub.com 或 gitclone.com/github.com',\n );\n\nconst defaultConfigPath = path.join(os.homedir(), '.g.config');\n\nexport class ConfigStore {\n constructor(private readonly configPath = defaultConfigPath) {}\n\n getMirrorHost(): string | undefined {\n if (!fs.existsSync(this.configPath)) {\n return undefined;\n }\n const raw = fs.readFileSync(this.configPath, 'utf-8').trim();\n return raw || undefined;\n }\n\n setMirrorHost(host: string): void {\n const parsed = mirrorHostSchema.parse(host);\n fs.writeFileSync(this.configPath, parsed, 'utf-8');\n }\n\n unsetMirrorHost(): void {\n if (fs.existsSync(this.configPath)) {\n fs.unlinkSync(this.configPath);\n }\n }\n\n getConfigPath(): string {\n return this.configPath;\n }\n}\n\nexport const defaultConfigStore = new ConfigStore();\n","import path from 'node:path';\nimport { execaSync } from 'execa';\n\nexport interface GitCloneParams {\n url: string;\n dirName?: string;\n branch?: string;\n depth?: number;\n singleBranch?: boolean;\n cwd?: string;\n silence?: boolean;\n}\n\nfunction toExecaStdio(silence?: boolean): 'pipe' | 'inherit' {\n return silence ? 'pipe' : 'inherit';\n}\n\nfunction buildCloneArgs(params: GitCloneParams): string[] {\n const args = ['clone', params.url];\n if (params.branch) {\n args.push('--branch', params.branch);\n }\n if (params.depth !== undefined) {\n args.push('--depth', String(params.depth));\n }\n if (params.singleBranch) {\n args.push('--single-branch');\n }\n if (params.dirName) {\n args.push(params.dirName);\n }\n return args;\n}\n\nfunction assertGitSuccess(result: { failed: boolean; exitCode?: number; stderr?: string }): void {\n if (result.failed || (result.exitCode !== undefined && result.exitCode !== 0)) {\n const stderr = result.stderr?.trim();\n throw new Error(stderr || `Git 命令执行失败,退出码 ${result.exitCode ?? '未知'}`);\n }\n}\n\nexport function gitExists(): boolean {\n try {\n execaSync('git', ['--version']);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function runGitClone(params: GitCloneParams): void {\n const result = execaSync('git', buildCloneArgs(params), {\n cwd: params.cwd,\n stdio: toExecaStdio(params.silence),\n reject: false,\n });\n assertGitSuccess(result);\n}\n\nexport function setRemoteOrigin(dir: string, url: string, cwd: string): void {\n const dirPath = path.join(cwd, dir);\n const result = execaSync('git', ['remote', 'set-url', 'origin', url], {\n cwd: dirPath,\n stdio: 'pipe',\n reject: false,\n });\n assertGitSuccess(result);\n}\n","const GITHUB_HTTPS_RE = /^https:\\/\\/github\\.com\\/([^/]+)\\/([^/]+?)(?:\\.git)?(?:\\/.*)?$/;\nconst GITHUB_SSH_RE = /^git@github\\.com:([^/]+)\\/([^/]+?)(?:\\.git)?$/;\n\nexport interface ParsedGithubUrl {\n owner: string;\n repo: string;\n normalizedHttps: string;\n}\n\nexport function isGithubLink(url: string): boolean {\n const trimmed = url.trim();\n return GITHUB_HTTPS_RE.test(trimmed) || GITHUB_SSH_RE.test(trimmed);\n}\n\nexport function parseGithubUrl(url: string): ParsedGithubUrl {\n const trimmed = url.trim();\n const httpsMatch = GITHUB_HTTPS_RE.exec(trimmed);\n if (httpsMatch) {\n const [, owner, repo] = httpsMatch as RegExpExecArray & [string, string, string];\n return {\n owner,\n repo,\n normalizedHttps: `https://github.com/${owner}/${repo}.git`,\n };\n }\n\n const sshMatch = GITHUB_SSH_RE.exec(trimmed);\n if (sshMatch) {\n const [, owner, repo] = sshMatch as RegExpExecArray & [string, string, string];\n return {\n owner,\n repo,\n normalizedHttps: `https://github.com/${owner}/${repo}.git`,\n };\n }\n\n throw new Error(`无效的 GitHub 仓库地址:${url}`);\n}\n\nexport function replaceMirrorHost(url: string, mirrorHost: string): string {\n const { normalizedHttps } = parseGithubUrl(url);\n return normalizedHttps.replace('github.com', mirrorHost);\n}\n\nexport function getRepoDirName(url: string): string {\n const { repo } = parseGithubUrl(url);\n return repo;\n}\n\nexport function buildMirrorProbeUrl(mirrorHost: string, repoPath: string): string {\n return `https://${mirrorHost}/${repoPath}`;\n}\n","import process from 'node:process';\nimport type { CloneOptions } from '../types';\nimport { gitExists, runGitClone, setRemoteOrigin } from './git-client';\nimport { getRepoDirName, parseGithubUrl, replaceMirrorHost } from './github-url';\n\nexport function cloneGithubRepo(url: string, options?: CloneOptions): void {\n if (!gitExists()) {\n throw new Error('未检测到 Git,请先安装 Git,并确保其在 PATH 中可用');\n }\n\n const { normalizedHttps } = parseGithubUrl(url);\n const mirrorHost = options?.mirrorHost;\n const cloneUrl = mirrorHost ? replaceMirrorHost(url, mirrorHost) : normalizedHttps;\n\n const {\n dirName,\n branch,\n cwd = process.cwd(),\n silence,\n depth,\n singleBranch,\n } = options ?? {};\n\n const requestedDir = dirName?.trim() ? dirName.trim() : undefined;\n const targetDir = requestedDir ?? getRepoDirName(url);\n\n runGitClone({\n url: cloneUrl,\n dirName: requestedDir,\n branch,\n depth,\n singleBranch,\n cwd,\n silence,\n });\n\n if (mirrorHost) {\n setRemoteOrigin(targetDir, normalizedHttps, cwd);\n }\n}\n\nexport default cloneGithubRepo;\n","import pc from 'picocolors';\nimport { defaultConfigStore } from '../../config/mirror-store';\nimport { cloneGithubRepo } from '../../core/clone-repo';\nimport { getRepoDirName, parseGithubUrl, replaceMirrorHost } from '../../core/github-url';\n\nexport interface CloneCommandOptions {\n branch?: string;\n depth?: number;\n singleBranch?: boolean;\n /** commander 由 --no-mirror 写入 false;未传时为 true 或 undefined */\n mirror?: boolean;\n verbose?: boolean;\n}\n\nfunction normalizeDirName(dir: string | undefined): string | undefined {\n const trimmed = dir?.trim();\n return trimmed ? trimmed : undefined;\n}\n\nfunction printVerboseClonePlan(\n url: string,\n dirName: string | undefined,\n options: CloneCommandOptions,\n mirrorHost: string | undefined,\n): void {\n const { normalizedHttps } = parseGithubUrl(url);\n const cloneUrl = mirrorHost ? replaceMirrorHost(url, mirrorHost) : normalizedHttps;\n const targetDir = normalizeDirName(dirName) ?? getRepoDirName(url);\n\n console.log(pc.bold('克隆计划'));\n console.log(pc.dim(` 模式 : ${mirrorHost ? `镜像(${mirrorHost})` : '直连 GitHub'}`));\n console.log(pc.dim(` 克隆地址 : ${cloneUrl}`));\n if (mirrorHost) {\n console.log(pc.dim(` 恢复 origin: ${normalizedHttps}`));\n }\n console.log(pc.dim(` 本地目录 : ${targetDir}`));\n\n const gitFlags: string[] = [];\n if (options.branch) {\n gitFlags.push(`--branch ${options.branch}`);\n }\n if (options.depth !== undefined) {\n gitFlags.push(`--depth ${options.depth}`);\n }\n if (options.singleBranch) {\n gitFlags.push('--single-branch');\n }\n if (gitFlags.length > 0) {\n console.log(pc.dim(` Git 参数 : ${gitFlags.join(' ')}`));\n } else {\n console.log(pc.dim(' Git 参数 : (无额外参数,完整克隆)'));\n }\n console.log('');\n}\n\nexport function runCloneCommand(\n url: string,\n dirName: string | undefined,\n options: CloneCommandOptions,\n): void {\n const useMirror = options.mirror !== false;\n const mirrorHost = useMirror ? defaultConfigStore.getMirrorHost() : undefined;\n const requestedDir = normalizeDirName(dirName);\n\n if (options.verbose) {\n printVerboseClonePlan(url, requestedDir, options, mirrorHost);\n } else {\n console.log(pc.dim(mirrorHost ? `→ 使用镜像 ${mirrorHost}` : '→ 直连 github.com'));\n }\n\n try {\n cloneGithubRepo(url, {\n dirName: requestedDir,\n branch: options.branch,\n mirrorHost,\n depth: options.depth,\n singleBranch: options.singleBranch,\n });\n } catch (error) {\n if (mirrorHost) {\n console.error(\n pc.yellow(`提示:镜像 ${mirrorHost} 可能不可用,可执行 g mirror test 验证,或加 --no-mirror 直连`),\n );\n }\n throw error;\n }\n\n const repoDir = requestedDir ?? getRepoDirName(url);\n const branchInfo = options.branch ? `,分支 ${options.branch}` : '';\n console.log(pc.green(`✓ 克隆完成:${repoDir}${branchInfo}`));\n if (mirrorHost && !options.verbose) {\n console.log(pc.dim(` 已恢复 origin 为 GitHub 官方地址`));\n }\n}\n","/** 将 URL 中的 github.com 替换为镜像地址(域名或域名/路径) */\nexport interface MirrorPreset {\n name: string;\n host: string;\n description: string;\n}\n\nexport const MIRROR_PRESETS: readonly MirrorPreset[] = [\n {\n name: 'kgithub',\n host: 'kgithub.com',\n description: 'KGitHub 镜像(域名替换)',\n },\n {\n name: 'moeyy',\n host: 'github.moeyy.xyz',\n description: 'Moeyy 镜像(域名替换)',\n },\n {\n name: 'gitclone',\n host: 'gitclone.com/github.com',\n description: 'GitClone 缓存(路径前缀)',\n },\n] as const;\n\n/** 用于 mirror test 的探测仓库路径(GitHub 官方示例仓库,长期稳定) */\nexport const MIRROR_PROBE_REPO = 'octocat/Hello-World';\n","import pc from 'picocolors';\nimport { defaultConfigStore } from '../../config/mirror-store';\nimport { MIRROR_PRESETS, MIRROR_PROBE_REPO, type MirrorPreset } from '../../constants';\nimport { buildMirrorProbeUrl } from '../../core/github-url';\n\nconst PROBE_TIMEOUT_MS = 10_000;\n\nexport function printMirror(host: string | undefined): void {\n if (host) {\n console.log(`当前镜像:${pc.cyan(host)}`);\n return;\n }\n console.log(pc.yellow('当前未配置镜像,克隆将直连 GitHub'));\n}\n\nexport function runMirrorSet(host: string): void {\n defaultConfigStore.setMirrorHost(host);\n console.log(pc.green(`镜像已设置为 ${host}`));\n console.log(pc.dim('提示:执行 g mirror test 验证镜像是否可用'));\n}\n\nexport function runMirrorUnset(): void {\n defaultConfigStore.unsetMirrorHost();\n console.log(pc.green('已清除镜像配置,克隆将直连 GitHub'));\n}\n\nexport function runMirrorList(): void {\n const current = defaultConfigStore.getMirrorHost();\n const isPresetCurrent = current ? MIRROR_PRESETS.some((p) => p.host === current) : false;\n\n console.log(pc.bold('可用镜像预设:'));\n for (const preset of MIRROR_PRESETS) {\n const marker = current === preset.host ? pc.green(' (当前)') : '';\n console.log(\n ` ${pc.cyan(preset.name.padEnd(8))} ${preset.host} ${pc.dim(`— ${preset.description}`)}${marker}`,\n );\n }\n console.log('');\n if (current && !isPresetCurrent) {\n console.log(`当前配置:${pc.cyan(current)} ${pc.dim('(自定义镜像,非内置预设)')}`);\n } else if (!current) {\n console.log(pc.dim('当前未配置镜像,克隆将直连 GitHub'));\n console.log(pc.dim('提示:使用 g mirror set <address> 或 g mirror set <预设名> 进行配置'));\n }\n}\n\nfunction formatProbeError(error: unknown, mirrorHost: string): string {\n if (error instanceof Error) {\n // AbortSignal.timeout 触发的错误名为 'TimeoutError'\n if (error.name === 'TimeoutError') {\n return `镜像 ${mirrorHost} 探测超时(>${PROBE_TIMEOUT_MS / 1000}s),可能不可用`;\n }\n const cause = (error as Error & { cause?: { code?: string } }).cause;\n const code = cause?.code;\n if (code === 'ENOTFOUND' || code === 'EAI_AGAIN') {\n return `无法解析镜像地址 ${mirrorHost},请检查配置是否正确`;\n }\n if (code === 'ECONNREFUSED' || code === 'ECONNRESET') {\n return `连接 ${mirrorHost} 被拒绝或重置,镜像可能不可用`;\n }\n if (error.message === 'fetch failed') {\n return `无法连接 ${mirrorHost},请检查网络或镜像是否可用`;\n }\n }\n return `镜像 ${mirrorHost} 探测失败:${error instanceof Error ? error.message : String(error)}`;\n}\n\nexport async function runMirrorTest(host?: string): Promise<void> {\n const mirrorHost = host ?? defaultConfigStore.getMirrorHost();\n if (!mirrorHost) {\n throw new Error('未配置镜像,请先执行 g mirror set <address> 或指定测试地址');\n }\n\n const probeUrl = buildMirrorProbeUrl(mirrorHost, MIRROR_PROBE_REPO);\n console.log(pc.dim(`正在探测 ${probeUrl}⋯⋯`));\n\n let response: Response;\n try {\n response = await fetch(probeUrl, {\n method: 'HEAD',\n signal: AbortSignal.timeout(PROBE_TIMEOUT_MS),\n });\n } catch (error) {\n throw new Error(formatProbeError(error, mirrorHost), { cause: error });\n }\n if (!response.ok) {\n throw new Error(`镜像 ${mirrorHost} 返回 HTTP ${response.status},可能不可用`);\n }\n console.log(pc.green(`镜像 ${mirrorHost} 可用`));\n}\n\nexport function resolveMirrorHostInput(input: string): string {\n const preset = MIRROR_PRESETS.find((item: MirrorPreset) => item.name === input || item.host === input);\n return preset?.host ?? input;\n}\n","#!/usr/bin/env node\n\nimport process from 'node:process';\nimport { Command } from 'commander';\nimport pc from 'picocolors';\nimport { ZodError } from 'zod';\nimport { version } from '../../package.json';\nimport { defaultConfigStore } from '../config/mirror-store';\nimport { runCloneCommand, type CloneCommandOptions } from './commands/clone-command';\nimport {\n printMirror,\n resolveMirrorHostInput,\n runMirrorList,\n runMirrorSet,\n runMirrorTest,\n runMirrorUnset,\n} from './commands/mirror-command';\n\nfunction formatCliError(error: unknown): string {\n if (error instanceof ZodError) {\n return error.issues.map((item) => item.message).join(';');\n }\n if (error instanceof Error) {\n return error.message;\n }\n return String(error);\n}\n\nconst program = new Command();\n\nprogram\n .name('g')\n .description('加速国内 GitHub clone:通过镜像拉取代码,完成后自动将 origin 恢复为 GitHub 官方地址')\n .version(version, '-v, --version', '输出版本号')\n .addHelpText(\n 'after',\n `\n快速开始:\n $ g mirror set kgithub # 配置镜像(首次使用)\n $ g mirror test # 验证镜像可用\n $ g clone https://github.com/owner/repo # 克隆仓库\n`,\n );\n\nprogram\n .command('clone <url> [dir]')\n .description(\n '克隆 GitHub 仓库。若已通过 g mirror set 配置镜像,将经镜像加速下载;' +\n '克隆结束后将 origin 改回 github.com,便于后续 push。',\n )\n .option(\n '-b, --branch <name>',\n '只检出指定分支(传给 git clone --branch)。例如 -b dev 表示克隆 dev 分支的工作区',\n )\n .option(\n '--depth <n>',\n '浅克隆:只拉取最近 n 次提交(传给 git clone --depth)。' +\n '如 --depth 1 表示只要最新版本,体积更小、速度更快,但本地没有完整 Git 历史',\n (value: string) => Number.parseInt(value, 10),\n )\n .option(\n '--single-branch',\n '只克隆单个分支,不下载其他远程分支(传给 git clone --single-branch)。' +\n '常与 -b 联用;单独使用时默认只拉远程默认分支(通常是 main)',\n )\n .option(\n '--no-mirror',\n '忽略 ~/.g.config 中的镜像配置,强制直连 github.com 克隆',\n )\n .option(\n '--verbose',\n '输出克隆前的详细信息:镜像/直连模式、实际克隆地址、分支与 Git 参数等(不改变 Git 本身的输出)',\n )\n .addHelpText(\n 'after',\n `\n示例:\n $ g clone https://github.com/owner/repo\n $ g clone https://github.com/owner/repo my-dir -b dev\n $ g clone https://github.com/owner/repo -b main --single-branch --depth 1\n $ g clone https://github.com/owner/repo --no-mirror --verbose\n`,\n )\n .action(async (url: string, dir: string | undefined, options: CloneCommandOptions) => {\n runCloneCommand(url, dir, options);\n });\n\nconst mirror = program\n .command('mirror')\n .description('管理 GitHub 镜像配置(保存在 ~/.g.config,如 kgithub.com 或 gitclone.com/github.com)');\n\nmirror\n .command('set <address>')\n .description('设置镜像地址,或传入预设名(kgithub / moeyy / gitclone)。执行 g mirror list 查看预设')\n .action(async (address: string) => {\n runMirrorSet(resolveMirrorHostInput(address));\n });\n\nmirror\n .command('get')\n .description('查看 ~/.g.config 中保存的镜像;未配置时克隆将直连 GitHub')\n .action(async () => {\n printMirror(defaultConfigStore.getMirrorHost());\n });\n\nmirror\n .command('list')\n .alias('ls')\n .description('列出内置镜像预设及说明,并标注当前正在使用的镜像')\n .action(async () => {\n runMirrorList();\n });\n\nmirror\n .command('unset')\n .description('删除 ~/.g.config,清除镜像配置(克隆将直连 GitHub)')\n .action(async () => {\n runMirrorUnset();\n });\n\nmirror\n .command('test [address]')\n .description(\n '探测镜像是否可达:对镜像站发起 HTTP HEAD 请求。' +\n '省略 address 时测试当前配置;可传镜像地址或预设名',\n )\n .action(async (address?: string) => {\n await runMirrorTest(address ? resolveMirrorHostInput(address) : undefined);\n });\n\nvoid program.parseAsync(process.argv).catch((error: unknown) => {\n console.error(pc.red(`错误:${formatCliError(error)}`));\n process.exit(1);\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACKA,MAAM,mBAAmBA,IAAAA,EACtB,OAAO,CAAC,CACR,KAAK,CAAC,CACN,IAAI,GAAG,UAAU,CAAC,CAClB,MACC,+FACA,+DACF;AAEF,MAAM,oBAAoBC,UAAAA,QAAK,KAAKC,QAAAA,QAAG,QAAQ,GAAG,WAAW;AAE7D,IAAa,cAAb,MAAyB;CACM;CAA7B,YAAY,aAA8B,mBAAmB;EAAhC,KAAA,aAAA;CAAiC;CAE9D,gBAAoC;EAClC,IAAI,CAACC,QAAAA,QAAG,WAAW,KAAK,UAAU,GAChC;EAGF,OADYA,QAAAA,QAAG,aAAa,KAAK,YAAY,OAAO,CAAC,CAAC,KAC7C,KAAK,KAAA;CAChB;CAEA,cAAc,MAAoB;EAChC,MAAM,SAAS,iBAAiB,MAAM,IAAI;EAC1C,QAAA,QAAG,cAAc,KAAK,YAAY,QAAQ,OAAO;CACnD;CAEA,kBAAwB;EACtB,IAAIA,QAAAA,QAAG,WAAW,KAAK,UAAU,GAC/B,QAAA,QAAG,WAAW,KAAK,UAAU;CAEjC;CAEA,gBAAwB;EACtB,OAAO,KAAK;CACd;AACF;AAEA,MAAa,qBAAqB,IAAI,YAAY;;;AC9BlD,SAAS,aAAa,SAAuC;CAC3D,OAAO,UAAU,SAAS;AAC5B;AAEA,SAAS,eAAe,QAAkC;CACxD,MAAM,OAAO,CAAC,SAAS,OAAO,GAAG;CACjC,IAAI,OAAO,QACT,KAAK,KAAK,YAAY,OAAO,MAAM;CAErC,IAAI,OAAO,UAAU,KAAA,GACnB,KAAK,KAAK,WAAW,OAAO,OAAO,KAAK,CAAC;CAE3C,IAAI,OAAO,cACT,KAAK,KAAK,iBAAiB;CAE7B,IAAI,OAAO,SACT,KAAK,KAAK,OAAO,OAAO;CAE1B,OAAO;AACT;AAEA,SAAS,iBAAiB,QAAuE;CAC/F,IAAI,OAAO,UAAW,OAAO,aAAa,KAAA,KAAa,OAAO,aAAa,GAAI;EAC7E,MAAM,SAAS,OAAO,QAAQ,KAAK;EACnC,MAAM,IAAI,MAAM,UAAU,kBAAkB,OAAO,YAAY,MAAM;CACvE;AACF;AAEA,SAAgB,YAAqB;CACnC,IAAI;EACF,CAAA,GAAA,MAAA,UAAA,CAAU,OAAO,CAAC,WAAW,CAAC;EAC9B,OAAO;CACT,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAgB,YAAY,QAA8B;CAMxD,kBAAA,GAAA,MAAA,UAAA,CALyB,OAAO,eAAe,MAAM,GAAG;EACtD,KAAK,OAAO;EACZ,OAAO,aAAa,OAAO,OAAO;EAClC,QAAQ;CACV,CACsB,CAAC;AACzB;AAEA,SAAgB,gBAAgB,KAAa,KAAa,KAAmB;CAC3E,MAAM,UAAUC,UAAAA,QAAK,KAAK,KAAK,GAAG;CAMlC,kBAAA,GAAA,MAAA,UAAA,CALyB,OAAO;EAAC;EAAU;EAAW;EAAU;CAAG,GAAG;EACpE,KAAK;EACL,OAAO;EACP,QAAQ;CACV,CACsB,CAAC;AACzB;;;ACnEA,MAAM,kBAAkB;AACxB,MAAM,gBAAgB;AAatB,SAAgB,eAAe,KAA8B;CAC3D,MAAM,UAAU,IAAI,KAAK;CACzB,MAAM,aAAa,gBAAgB,KAAK,OAAO;CAC/C,IAAI,YAAY;EACd,MAAM,GAAG,OAAO,QAAQ;EACxB,OAAO;GACL;GACA;GACA,iBAAiB,sBAAsB,MAAM,GAAG,KAAK;EACvD;CACF;CAEA,MAAM,WAAW,cAAc,KAAK,OAAO;CAC3C,IAAI,UAAU;EACZ,MAAM,GAAG,OAAO,QAAQ;EACxB,OAAO;GACL;GACA;GACA,iBAAiB,sBAAsB,MAAM,GAAG,KAAK;EACvD;CACF;CAEA,MAAM,IAAI,MAAM,mBAAmB,KAAK;AAC1C;AAEA,SAAgB,kBAAkB,KAAa,YAA4B;CACzE,MAAM,EAAE,oBAAoB,eAAe,GAAG;CAC9C,OAAO,gBAAgB,QAAQ,cAAc,UAAU;AACzD;AAEA,SAAgB,eAAe,KAAqB;CAClD,MAAM,EAAE,SAAS,eAAe,GAAG;CACnC,OAAO;AACT;AAEA,SAAgB,oBAAoB,YAAoB,UAA0B;CAChF,OAAO,WAAW,WAAW,GAAG;AAClC;;;AC9CA,SAAgB,gBAAgB,KAAa,SAA8B;CACzE,IAAI,CAAC,UAAU,GACb,MAAM,IAAI,MAAM,kCAAkC;CAGpD,MAAM,EAAE,oBAAoB,eAAe,GAAG;CAC9C,MAAM,aAAa,SAAS;CAC5B,MAAM,WAAW,aAAa,kBAAkB,KAAK,UAAU,IAAI;CAEnE,MAAM,EACJ,SACA,QACA,MAAMC,aAAAA,QAAQ,IAAI,GAClB,SACA,OACA,iBACE,WAAW,CAAC;CAEhB,MAAM,eAAe,SAAS,KAAK,IAAI,QAAQ,KAAK,IAAI,KAAA;CACxD,MAAM,YAAY,gBAAgB,eAAe,GAAG;CAEpD,YAAY;EACV,KAAK;EACL,SAAS;EACT;EACA;EACA;EACA;EACA;CACF,CAAC;CAED,IAAI,YACF,gBAAgB,WAAW,iBAAiB,GAAG;AAEnD;;;ACzBA,SAAS,iBAAiB,KAA6C;CACrE,MAAM,UAAU,KAAK,KAAK;CAC1B,OAAO,UAAU,UAAU,KAAA;AAC7B;AAEA,SAAS,sBACP,KACA,SACA,SACA,YACM;CACN,MAAM,EAAE,oBAAoB,eAAe,GAAG;CAC9C,MAAM,WAAW,aAAa,kBAAkB,KAAK,UAAU,IAAI;CACnE,MAAM,YAAY,iBAAiB,OAAO,KAAK,eAAe,GAAG;CAEjE,QAAQ,IAAIC,WAAAA,QAAG,KAAK,MAAM,CAAC;CAC3B,QAAQ,IAAIA,WAAAA,QAAG,IAAI,eAAe,aAAa,MAAM,WAAW,KAAK,aAAa,CAAC;CACnF,QAAQ,IAAIA,WAAAA,QAAG,IAAI,aAAa,UAAU,CAAC;CAC3C,IAAI,YACF,QAAQ,IAAIA,WAAAA,QAAG,IAAI,gBAAgB,iBAAiB,CAAC;CAEvD,QAAQ,IAAIA,WAAAA,QAAG,IAAI,aAAa,WAAW,CAAC;CAE5C,MAAM,WAAqB,CAAC;CAC5B,IAAI,QAAQ,QACV,SAAS,KAAK,YAAY,QAAQ,QAAQ;CAE5C,IAAI,QAAQ,UAAU,KAAA,GACpB,SAAS,KAAK,WAAW,QAAQ,OAAO;CAE1C,IAAI,QAAQ,cACV,SAAS,KAAK,iBAAiB;CAEjC,IAAI,SAAS,SAAS,GACpB,QAAQ,IAAIA,WAAAA,QAAG,IAAI,eAAe,SAAS,KAAK,GAAG,GAAG,CAAC;MAEvD,QAAQ,IAAIA,WAAAA,QAAG,IAAI,0BAA0B,CAAC;CAEhD,QAAQ,IAAI,EAAE;AAChB;AAEA,SAAgB,gBACd,KACA,SACA,SACM;CAEN,MAAM,aADY,QAAQ,WAAW,QACN,mBAAmB,cAAc,IAAI,KAAA;CACpE,MAAM,eAAe,iBAAiB,OAAO;CAE7C,IAAI,QAAQ,SACV,sBAAsB,KAAK,cAAc,SAAS,UAAU;MAE5D,QAAQ,IAAIA,WAAAA,QAAG,IAAI,aAAa,UAAU,eAAe,iBAAiB,CAAC;CAG7E,IAAI;EACF,gBAAgB,KAAK;GACnB,SAAS;GACT,QAAQ,QAAQ;GAChB;GACA,OAAO,QAAQ;GACf,cAAc,QAAQ;EACxB,CAAC;CACH,SAAS,OAAO;EACd,IAAI,YACF,QAAQ,MACNA,WAAAA,QAAG,OAAO,SAAS,WAAW,8CAA8C,CAC9E;EAEF,MAAM;CACR;CAEA,MAAM,UAAU,gBAAgB,eAAe,GAAG;CAClD,MAAM,aAAa,QAAQ,SAAS,OAAO,QAAQ,WAAW;CAC9D,QAAQ,IAAIA,WAAAA,QAAG,MAAM,UAAU,UAAU,YAAY,CAAC;CACtD,IAAI,cAAc,CAAC,QAAQ,SACzB,QAAQ,IAAIA,WAAAA,QAAG,IAAI,4BAA4B,CAAC;AAEpD;;;ACtFA,MAAa,iBAA0C;CACrD;EACE,MAAM;EACN,MAAM;EACN,aAAa;CACf;CACA;EACE,MAAM;EACN,MAAM;EACN,aAAa;CACf;CACA;EACE,MAAM;EACN,MAAM;EACN,aAAa;CACf;AACF;;AAGA,MAAa,oBAAoB;;;ACrBjC,MAAM,mBAAmB;AAEzB,SAAgB,YAAY,MAAgC;CAC1D,IAAI,MAAM;EACR,QAAQ,IAAI,QAAQC,WAAAA,QAAG,KAAK,IAAI,GAAG;EACnC;CACF;CACA,QAAQ,IAAIA,WAAAA,QAAG,OAAO,sBAAsB,CAAC;AAC/C;AAEA,SAAgB,aAAa,MAAoB;CAC/C,mBAAmB,cAAc,IAAI;CACrC,QAAQ,IAAIA,WAAAA,QAAG,MAAM,UAAU,MAAM,CAAC;CACtC,QAAQ,IAAIA,WAAAA,QAAG,IAAI,8BAA8B,CAAC;AACpD;AAEA,SAAgB,iBAAuB;CACrC,mBAAmB,gBAAgB;CACnC,QAAQ,IAAIA,WAAAA,QAAG,MAAM,sBAAsB,CAAC;AAC9C;AAEA,SAAgB,gBAAsB;CACpC,MAAM,UAAU,mBAAmB,cAAc;CACjD,MAAM,kBAAkB,UAAU,eAAe,MAAM,MAAM,EAAE,SAAS,OAAO,IAAI;CAEnF,QAAQ,IAAIA,WAAAA,QAAG,KAAK,SAAS,CAAC;CAC9B,KAAK,MAAM,UAAU,gBAAgB;EACnC,MAAM,SAAS,YAAY,OAAO,OAAOA,WAAAA,QAAG,MAAM,OAAO,IAAI;EAC7D,QAAQ,IACN,KAAKA,WAAAA,QAAG,KAAK,OAAO,KAAK,OAAO,CAAC,CAAC,EAAE,GAAG,OAAO,KAAK,IAAIA,WAAAA,QAAG,IAAI,KAAK,OAAO,aAAa,IAAI,QAC7F;CACF;CACA,QAAQ,IAAI,EAAE;CACd,IAAI,WAAW,CAAC,iBACd,QAAQ,IAAI,QAAQA,WAAAA,QAAG,KAAK,OAAO,EAAE,GAAGA,WAAAA,QAAG,IAAI,eAAe,GAAG;MAC5D,IAAI,CAAC,SAAS;EACnB,QAAQ,IAAIA,WAAAA,QAAG,IAAI,sBAAsB,CAAC;EAC1C,QAAQ,IAAIA,WAAAA,QAAG,IAAI,wDAAwD,CAAC;CAC9E;AACF;AAEA,SAAS,iBAAiB,OAAgB,YAA4B;CACpE,IAAI,iBAAiB,OAAO;EAE1B,IAAI,MAAM,SAAS,gBACjB,OAAO,MAAM,WAAW,SAAS,mBAAmB,IAAK;EAG3D,MAAM,OADS,MAAgD,OAC3C;EACpB,IAAI,SAAS,eAAe,SAAS,aACnC,OAAO,YAAY,WAAW;EAEhC,IAAI,SAAS,kBAAkB,SAAS,cACtC,OAAO,MAAM,WAAW;EAE1B,IAAI,MAAM,YAAY,gBACpB,OAAO,QAAQ,WAAW;CAE9B;CACA,OAAO,MAAM,WAAW,QAAQ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACvF;AAEA,eAAsB,cAAc,MAA8B;CAChE,MAAM,aAAa,QAAQ,mBAAmB,cAAc;CAC5D,IAAI,CAAC,YACH,MAAM,IAAI,MAAM,2CAA2C;CAG7D,MAAM,WAAW,oBAAoB,YAAY,iBAAiB;CAClE,QAAQ,IAAIA,WAAAA,QAAG,IAAI,QAAQ,SAAS,GAAG,CAAC;CAExC,IAAI;CACJ,IAAI;EACF,WAAW,MAAM,MAAM,UAAU;GAC/B,QAAQ;GACR,QAAQ,YAAY,QAAQ,gBAAgB;EAC9C,CAAC;CACH,SAAS,OAAO;EACd,MAAM,IAAI,MAAM,iBAAiB,OAAO,UAAU,GAAG,EAAE,OAAO,MAAM,CAAC;CACvE;CACA,IAAI,CAAC,SAAS,IACZ,MAAM,IAAI,MAAM,MAAM,WAAW,WAAW,SAAS,OAAO,OAAO;CAErE,QAAQ,IAAIA,WAAAA,QAAG,MAAM,MAAM,WAAW,IAAI,CAAC;AAC7C;AAEA,SAAgB,uBAAuB,OAAuB;CAE5D,OADe,eAAe,MAAM,SAAuB,KAAK,SAAS,SAAS,KAAK,SAAS,KACpF,CAAC,EAAE,QAAQ;AACzB;;;AC5EA,SAAS,eAAe,OAAwB;CAC9C,IAAI,iBAAiBC,IAAAA,UACnB,OAAO,MAAM,OAAO,KAAK,SAAS,KAAK,OAAO,CAAC,CAAC,KAAK,GAAG;CAE1D,IAAI,iBAAiB,OACnB,OAAO,MAAM;CAEf,OAAO,OAAO,KAAK;AACrB;AAEA,MAAM,UAAU,IAAIC,UAAAA,QAAQ;AAE5B,QACG,KAAK,GAAG,CAAC,CACT,YAAY,0DAA0D,CAAC,CACvE,QAAQ,SAAS,iBAAiB,OAAO,CAAC,CAC1C,YACC,SACA;;;;;CAMF;AAEF,QACG,QAAQ,mBAAmB,CAAC,CAC5B,YACC,qFAEF,CAAC,CACA,OACC,uBACA,0DACF,CAAC,CACA,OACC,eACA,wFAEC,UAAkB,OAAO,SAAS,OAAO,EAAE,CAC9C,CAAC,CACA,OACC,mBACA,oFAEF,CAAC,CACA,OACC,eACA,0CACF,CAAC,CACA,OACC,aACA,sDACF,CAAC,CACA,YACC,SACA;;;;;;CAOF,CAAC,CACA,OAAO,OAAO,KAAa,KAAyB,YAAiC;CACpF,gBAAgB,KAAK,KAAK,OAAO;AACnC,CAAC;AAEH,MAAM,SAAS,QACZ,QAAQ,QAAQ,CAAC,CACjB,YAAY,yEAAyE;AAExF,OACG,QAAQ,eAAe,CAAC,CACxB,YAAY,iEAAiE,CAAC,CAC9E,OAAO,OAAO,YAAoB;CACjC,aAAa,uBAAuB,OAAO,CAAC;AAC9C,CAAC;AAEH,OACG,QAAQ,KAAK,CAAC,CACd,YAAY,wCAAwC,CAAC,CACrD,OAAO,YAAY;CAClB,YAAY,mBAAmB,cAAc,CAAC;AAChD,CAAC;AAEH,OACG,QAAQ,MAAM,CAAC,CACf,MAAM,IAAI,CAAC,CACX,YAAY,0BAA0B,CAAC,CACvC,OAAO,YAAY;CAClB,cAAc;AAChB,CAAC;AAEH,OACG,QAAQ,OAAO,CAAC,CAChB,YAAY,qCAAqC,CAAC,CAClD,OAAO,YAAY;CAClB,eAAe;AACjB,CAAC;AAEH,OACG,QAAQ,gBAAgB,CAAC,CACzB,YACC,4DAEF,CAAC,CACA,OAAO,OAAO,YAAqB;CAClC,MAAM,cAAc,UAAU,uBAAuB,OAAO,IAAI,KAAA,CAAS;AAC3E,CAAC;AAEE,QAAQ,WAAWC,aAAAA,QAAQ,IAAI,CAAC,CAAC,OAAO,UAAmB;CAC9D,QAAQ,MAAMC,WAAAA,QAAG,IAAI,MAAM,eAAe,KAAK,GAAG,CAAC;CACnD,aAAA,QAAQ,KAAK,CAAC;AAChB,CAAC"}
@@ -0,0 +1,17 @@
1
+ export interface CloneOptions {
2
+ /** 克隆到本地的目录名称 */
3
+ dirName?: string;
4
+ /** 指定分支 */
5
+ branch?: string;
6
+ /** 镜像地址,例如 kgithub.com 或 gitclone.com/github.com */
7
+ mirrorHost?: string;
8
+ /** 工作目录 */
9
+ cwd?: string;
10
+ /** 静默模式,不继承 Git 输出 */
11
+ silence?: boolean;
12
+ /** 浅克隆深度 */
13
+ depth?: number;
14
+ /** 仅克隆指定分支 */
15
+ singleBranch?: boolean;
16
+ }
17
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,iBAAiB;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW;IACX,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,sBAAsB;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc;IACd,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB"}