grf-cli 1.0.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/LICENSE +21 -0
- package/README.md +503 -0
- package/README.zh-CN.md +503 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +74 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/add.d.ts +7 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +92 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/clean.d.ts +7 -0
- package/dist/commands/clean.d.ts.map +1 -0
- package/dist/commands/clean.js +171 -0
- package/dist/commands/clean.js.map +1 -0
- package/dist/commands/config.d.ts +7 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +170 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/list.d.ts +7 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +149 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/load.d.ts +8 -0
- package/dist/commands/load.d.ts.map +1 -0
- package/dist/commands/load.js +239 -0
- package/dist/commands/load.js.map +1 -0
- package/dist/commands/unload.d.ts +7 -0
- package/dist/commands/unload.d.ts.map +1 -0
- package/dist/commands/unload.js +738 -0
- package/dist/commands/unload.js.map +1 -0
- package/dist/commands/update.d.ts +7 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +471 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/use.d.ts +8 -0
- package/dist/commands/use.d.ts.map +1 -0
- package/dist/commands/use.js +224 -0
- package/dist/commands/use.js.map +1 -0
- package/dist/core/config.d.ts +55 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +179 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/filesystem.d.ts +74 -0
- package/dist/core/filesystem.d.ts.map +1 -0
- package/dist/core/filesystem.js +300 -0
- package/dist/core/filesystem.js.map +1 -0
- package/dist/core/git.d.ts +75 -0
- package/dist/core/git.d.ts.map +1 -0
- package/dist/core/git.js +169 -0
- package/dist/core/git.js.map +1 -0
- package/dist/core/loading.d.ts +85 -0
- package/dist/core/loading.d.ts.map +1 -0
- package/dist/core/loading.js +224 -0
- package/dist/core/loading.js.map +1 -0
- package/dist/core/repository.d.ts +120 -0
- package/dist/core/repository.d.ts.map +1 -0
- package/dist/core/repository.js +374 -0
- package/dist/core/repository.js.map +1 -0
- package/dist/core/sync.d.ts +72 -0
- package/dist/core/sync.d.ts.map +1 -0
- package/dist/core/sync.js +226 -0
- package/dist/core/sync.js.map +1 -0
- package/dist/types/index.d.ts +135 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +63 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Repository 模块
|
|
4
|
+
* 负责仓库的增删改查操作,整合配置、Git 和文件系统模块
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
40
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
41
|
+
};
|
|
42
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
+
exports.parseRepoUrl = parseRepoUrl;
|
|
44
|
+
exports.getRepoStoragePath = getRepoStoragePath;
|
|
45
|
+
exports.add = add;
|
|
46
|
+
exports.get = get;
|
|
47
|
+
exports.list = list;
|
|
48
|
+
exports.remove = remove;
|
|
49
|
+
exports.exists = exists;
|
|
50
|
+
exports.resolvePath = resolvePath;
|
|
51
|
+
exports.switchBranch = switchBranch;
|
|
52
|
+
const path_1 = __importDefault(require("path"));
|
|
53
|
+
const index_js_1 = require("../types/index.js");
|
|
54
|
+
const config_js_1 = require("./config.js");
|
|
55
|
+
const git = __importStar(require("./git.js"));
|
|
56
|
+
const fs = __importStar(require("./filesystem.js"));
|
|
57
|
+
/**
|
|
58
|
+
* 解析 Git URL
|
|
59
|
+
* 支持 HTTPS 和 SSH 格式
|
|
60
|
+
* @param url Git 仓库 URL
|
|
61
|
+
* @returns 解析后的 URL 信息
|
|
62
|
+
* @throws GrfError 如果 URL 格式无效
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* // HTTPS 格式
|
|
66
|
+
* parseRepoUrl('https://github.com/facebook/react.git')
|
|
67
|
+
* // -> { host: 'github.com', owner: 'facebook', repo: 'react' }
|
|
68
|
+
*
|
|
69
|
+
* // SSH 格式
|
|
70
|
+
* parseRepoUrl('git@github.com:facebook/react.git')
|
|
71
|
+
* // -> { host: 'github.com', owner: 'facebook', repo: 'react' }
|
|
72
|
+
*/
|
|
73
|
+
function parseRepoUrl(url) {
|
|
74
|
+
// 去除首尾空白
|
|
75
|
+
url = url.trim();
|
|
76
|
+
// HTTPS 格式: https://github.com/user/repo.git
|
|
77
|
+
const httpsRegex = /^https?:\/\/([^/]+)\/([^/]+)\/([^/]+?)(?:\.git)?$/;
|
|
78
|
+
const httpsMatch = url.match(httpsRegex);
|
|
79
|
+
if (httpsMatch) {
|
|
80
|
+
return {
|
|
81
|
+
host: httpsMatch[1],
|
|
82
|
+
owner: httpsMatch[2],
|
|
83
|
+
repo: httpsMatch[3].replace(/\.git$/, ""),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
// SSH 格式: git@github.com:user/repo.git
|
|
87
|
+
const sshRegex = /^git@([^:]+):([^/]+)\/([^/]+?)(?:\.git)?$/;
|
|
88
|
+
const sshMatch = url.match(sshRegex);
|
|
89
|
+
if (sshMatch) {
|
|
90
|
+
return {
|
|
91
|
+
host: sshMatch[1],
|
|
92
|
+
owner: sshMatch[2],
|
|
93
|
+
repo: sshMatch[3].replace(/\.git$/, ""),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
throw new index_js_1.GrfError(index_js_1.ErrorCode.REPO_INVALID_URL, `无效的 Git URL: ${url}。支持的格式: https://github.com/user/repo.git 或 git@github.com:user/repo.git`);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* 根据 URL 生成本地存储路径
|
|
100
|
+
* @param url Git 仓库 URL
|
|
101
|
+
* @returns 本地存储路径
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* getRepoStoragePath('https://github.com/facebook/react.git')
|
|
105
|
+
* // -> ~/.gitreference/repos/github.com/facebook/react
|
|
106
|
+
*/
|
|
107
|
+
function getRepoStoragePath(url) {
|
|
108
|
+
const { host, owner, repo } = parseRepoUrl(url);
|
|
109
|
+
return path_1.default.join((0, config_js_1.getReposRoot)(), host, owner, repo);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* 根据解析后的 URL 信息生成仓库名称
|
|
113
|
+
* @param parsed 解析后的 URL 信息
|
|
114
|
+
* @returns 仓库名称(格式: host/owner/repo)
|
|
115
|
+
*/
|
|
116
|
+
function getRepoName(parsed) {
|
|
117
|
+
return `${parsed.host}/${parsed.owner}/${parsed.repo}`;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* 添加仓库
|
|
121
|
+
* @param url Git 仓库 URL
|
|
122
|
+
* @param options 添加选项
|
|
123
|
+
* @returns 仓库信息
|
|
124
|
+
*/
|
|
125
|
+
async function add(url, options) {
|
|
126
|
+
// 解析 URL
|
|
127
|
+
const parsed = parseRepoUrl(url);
|
|
128
|
+
const repoPath = getRepoStoragePath(url);
|
|
129
|
+
const repoName = options?.name ?? getRepoName(parsed);
|
|
130
|
+
// 检查仓库是否已存在
|
|
131
|
+
if (await exists(repoName)) {
|
|
132
|
+
throw new index_js_1.GrfError(index_js_1.ErrorCode.REPO_ALREADY_EXISTS, `仓库已存在: ${repoName}`);
|
|
133
|
+
}
|
|
134
|
+
// 确保配置目录存在
|
|
135
|
+
await (0, config_js_1.ensureConfigDir)();
|
|
136
|
+
// 确保父目录存在
|
|
137
|
+
await fs.ensureDir(path_1.default.dirname(repoPath));
|
|
138
|
+
// 克隆仓库
|
|
139
|
+
await git.clone(url, repoPath, {
|
|
140
|
+
branch: options?.branch,
|
|
141
|
+
shallow: options?.shallow,
|
|
142
|
+
depth: options?.depth,
|
|
143
|
+
});
|
|
144
|
+
// 获取 commit ID 和分支信息
|
|
145
|
+
const commitId = await git.getCurrentCommit(repoPath);
|
|
146
|
+
const branch = await git.getBranch(repoPath);
|
|
147
|
+
// 创建元信息
|
|
148
|
+
const now = new Date().toISOString();
|
|
149
|
+
const meta = {
|
|
150
|
+
url,
|
|
151
|
+
name: repoName,
|
|
152
|
+
addedAt: now,
|
|
153
|
+
updatedAt: now,
|
|
154
|
+
commitId,
|
|
155
|
+
branch,
|
|
156
|
+
};
|
|
157
|
+
// 保存元信息
|
|
158
|
+
await (0, config_js_1.writeRepoMeta)(repoPath, meta);
|
|
159
|
+
// 更新全局配置
|
|
160
|
+
const config = await (0, config_js_1.readGlobalConfig)();
|
|
161
|
+
config.repos[repoName] = {
|
|
162
|
+
url,
|
|
163
|
+
path: repoPath,
|
|
164
|
+
addedAt: now,
|
|
165
|
+
};
|
|
166
|
+
await (0, config_js_1.writeGlobalConfig)(config);
|
|
167
|
+
return {
|
|
168
|
+
name: repoName,
|
|
169
|
+
url,
|
|
170
|
+
path: repoPath,
|
|
171
|
+
commitId,
|
|
172
|
+
branch,
|
|
173
|
+
addedAt: now,
|
|
174
|
+
updatedAt: now,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* 检查仓库名称是否匹配
|
|
179
|
+
* 支持以下匹配方式:
|
|
180
|
+
* - 完整名称:github.com/owner/repo
|
|
181
|
+
* - owner/repo 格式:owner/repo
|
|
182
|
+
* - 仅 repo 名称:repo
|
|
183
|
+
*
|
|
184
|
+
* @param repoName 仓库完整名称(如 github.com/owner/repo)
|
|
185
|
+
* @param searchName 搜索名称
|
|
186
|
+
* @returns 是否匹配
|
|
187
|
+
*/
|
|
188
|
+
function matchRepoName(repoName, searchName) {
|
|
189
|
+
// 标准化:将反斜杠转换为正斜杠
|
|
190
|
+
const normalizedRepoName = repoName.replace(/\\/g, "/");
|
|
191
|
+
const normalizedSearchName = searchName.replace(/\\/g, "/");
|
|
192
|
+
// 完整名称匹配
|
|
193
|
+
if (normalizedRepoName === normalizedSearchName) {
|
|
194
|
+
return true;
|
|
195
|
+
}
|
|
196
|
+
// 分割仓库名称为各个部分
|
|
197
|
+
const repoParts = normalizedRepoName.split("/");
|
|
198
|
+
const searchParts = normalizedSearchName.split("/");
|
|
199
|
+
// 如果搜索名称有多个部分,从末尾开始匹配
|
|
200
|
+
if (searchParts.length > 1) {
|
|
201
|
+
// 检查是否匹配末尾的 N 个部分
|
|
202
|
+
if (repoParts.length >= searchParts.length) {
|
|
203
|
+
const repoSuffix = repoParts.slice(-searchParts.length).join("/");
|
|
204
|
+
return repoSuffix === normalizedSearchName;
|
|
205
|
+
}
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
// 单个名称:只匹配最后一个部分(repo 名称)
|
|
209
|
+
const repoBaseName = repoParts[repoParts.length - 1];
|
|
210
|
+
return repoBaseName === normalizedSearchName;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* 根据名称获取仓库信息
|
|
214
|
+
* @param name 仓库名称(完整路径或简短名称)
|
|
215
|
+
* @returns 仓库信息,不存在返回 null
|
|
216
|
+
*/
|
|
217
|
+
async function get(name) {
|
|
218
|
+
const config = await (0, config_js_1.readGlobalConfig)();
|
|
219
|
+
// 首先尝试完整名称匹配
|
|
220
|
+
if (config.repos[name]) {
|
|
221
|
+
const entry = config.repos[name];
|
|
222
|
+
const meta = await (0, config_js_1.readRepoMeta)(entry.path);
|
|
223
|
+
if (!meta) {
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
return {
|
|
227
|
+
name,
|
|
228
|
+
url: entry.url,
|
|
229
|
+
path: entry.path,
|
|
230
|
+
commitId: meta.commitId,
|
|
231
|
+
branch: meta.branch,
|
|
232
|
+
addedAt: meta.addedAt,
|
|
233
|
+
updatedAt: meta.updatedAt,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
// 尝试简短名称匹配(支持 repo 或 owner/repo 格式)
|
|
237
|
+
for (const [repoName, entry] of Object.entries(config.repos)) {
|
|
238
|
+
if (matchRepoName(repoName, name)) {
|
|
239
|
+
const meta = await (0, config_js_1.readRepoMeta)(entry.path);
|
|
240
|
+
if (!meta) {
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
return {
|
|
244
|
+
name: repoName,
|
|
245
|
+
url: entry.url,
|
|
246
|
+
path: entry.path,
|
|
247
|
+
commitId: meta.commitId,
|
|
248
|
+
branch: meta.branch,
|
|
249
|
+
addedAt: meta.addedAt,
|
|
250
|
+
updatedAt: meta.updatedAt,
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* 列出所有仓库
|
|
258
|
+
* @returns 仓库信息数组
|
|
259
|
+
*/
|
|
260
|
+
async function list() {
|
|
261
|
+
const config = await (0, config_js_1.readGlobalConfig)();
|
|
262
|
+
const repos = [];
|
|
263
|
+
for (const [name, entry] of Object.entries(config.repos)) {
|
|
264
|
+
const meta = await (0, config_js_1.readRepoMeta)(entry.path);
|
|
265
|
+
if (meta) {
|
|
266
|
+
repos.push({
|
|
267
|
+
name,
|
|
268
|
+
url: entry.url,
|
|
269
|
+
path: entry.path,
|
|
270
|
+
commitId: meta.commitId,
|
|
271
|
+
branch: meta.branch,
|
|
272
|
+
addedAt: meta.addedAt,
|
|
273
|
+
updatedAt: meta.updatedAt,
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return repos;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* 删除仓库
|
|
281
|
+
* @param name 仓库名称
|
|
282
|
+
* @throws GrfError 如果仓库不存在
|
|
283
|
+
*/
|
|
284
|
+
async function remove(name) {
|
|
285
|
+
const repoInfo = await get(name);
|
|
286
|
+
if (!repoInfo) {
|
|
287
|
+
throw new index_js_1.GrfError(index_js_1.ErrorCode.REPO_NOT_FOUND, `仓库不存在: ${name}`);
|
|
288
|
+
}
|
|
289
|
+
// 删除仓库目录
|
|
290
|
+
await fs.removeDir(repoInfo.path);
|
|
291
|
+
// 更新全局配置
|
|
292
|
+
const config = await (0, config_js_1.readGlobalConfig)();
|
|
293
|
+
delete config.repos[repoInfo.name];
|
|
294
|
+
await (0, config_js_1.writeGlobalConfig)(config);
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* 检查仓库是否存在
|
|
298
|
+
* @param name 仓库名称
|
|
299
|
+
* @returns 是否存在
|
|
300
|
+
*/
|
|
301
|
+
async function exists(name) {
|
|
302
|
+
const config = await (0, config_js_1.readGlobalConfig)();
|
|
303
|
+
// 首先尝试完整名称匹配
|
|
304
|
+
if (config.repos[name]) {
|
|
305
|
+
const entry = config.repos[name];
|
|
306
|
+
// 检查目录和元信息是否都存在
|
|
307
|
+
const dirExists = await fs.exists(entry.path);
|
|
308
|
+
const meta = await (0, config_js_1.readRepoMeta)(entry.path);
|
|
309
|
+
return dirExists && meta !== null;
|
|
310
|
+
}
|
|
311
|
+
// 尝试简短名称匹配(使用统一的匹配函数)
|
|
312
|
+
for (const [repoName, entry] of Object.entries(config.repos)) {
|
|
313
|
+
if (matchRepoName(repoName, name)) {
|
|
314
|
+
const dirExists = await fs.exists(entry.path);
|
|
315
|
+
const meta = await (0, config_js_1.readRepoMeta)(entry.path);
|
|
316
|
+
return dirExists && meta !== null;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
return false;
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* 将仓库名称解析为本地路径
|
|
323
|
+
* @param name 仓库名称(完整名称或简短名称)
|
|
324
|
+
* @returns 本地路径
|
|
325
|
+
* @throws GrfError 如果仓库不存在
|
|
326
|
+
*/
|
|
327
|
+
async function resolvePath(name) {
|
|
328
|
+
const repoInfo = await get(name);
|
|
329
|
+
if (!repoInfo) {
|
|
330
|
+
throw new index_js_1.GrfError(index_js_1.ErrorCode.REPO_NOT_FOUND, `仓库不存在: ${name}`);
|
|
331
|
+
}
|
|
332
|
+
return repoInfo.path;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* 切换仓库分支
|
|
336
|
+
* @param name 仓库名称
|
|
337
|
+
* @param branch 目标分支
|
|
338
|
+
* @returns 更新后的仓库信息
|
|
339
|
+
* @throws GrfError 如果仓库不存在或切换失败
|
|
340
|
+
*/
|
|
341
|
+
async function switchBranch(name, branch) {
|
|
342
|
+
// 获取仓库信息
|
|
343
|
+
const repoInfo = await get(name);
|
|
344
|
+
if (!repoInfo) {
|
|
345
|
+
throw new index_js_1.GrfError(index_js_1.ErrorCode.REPO_NOT_FOUND, `仓库不存在: ${name}`);
|
|
346
|
+
}
|
|
347
|
+
// 调用 git.checkout() 切换分支
|
|
348
|
+
await git.checkout(repoInfo.path, branch);
|
|
349
|
+
// 获取新的 commit ID
|
|
350
|
+
const commitId = await git.getCurrentCommit(repoInfo.path);
|
|
351
|
+
const currentBranch = await git.getBranch(repoInfo.path);
|
|
352
|
+
// 更新 meta.json 中的 branch 字段
|
|
353
|
+
const now = new Date().toISOString();
|
|
354
|
+
const meta = {
|
|
355
|
+
url: repoInfo.url,
|
|
356
|
+
name: repoInfo.name,
|
|
357
|
+
addedAt: repoInfo.addedAt,
|
|
358
|
+
updatedAt: now,
|
|
359
|
+
commitId,
|
|
360
|
+
branch: currentBranch,
|
|
361
|
+
};
|
|
362
|
+
await (0, config_js_1.writeRepoMeta)(repoInfo.path, meta);
|
|
363
|
+
// 返回更新后的仓库信息
|
|
364
|
+
return {
|
|
365
|
+
name: repoInfo.name,
|
|
366
|
+
url: repoInfo.url,
|
|
367
|
+
path: repoInfo.path,
|
|
368
|
+
commitId,
|
|
369
|
+
branch: currentBranch,
|
|
370
|
+
addedAt: repoInfo.addedAt,
|
|
371
|
+
updatedAt: now,
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
//# sourceMappingURL=repository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repository.js","sourceRoot":"","sources":["../../src/core/repository.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 同步模块
|
|
3
|
+
* 负责工作目录与全局缓存之间的同步操作
|
|
4
|
+
*/
|
|
5
|
+
import type { LoadingEntry } from "../types/index.js";
|
|
6
|
+
/**
|
|
7
|
+
* 同步状态
|
|
8
|
+
*/
|
|
9
|
+
export interface SyncStatus {
|
|
10
|
+
/** 条目 ID */
|
|
11
|
+
entryId: string;
|
|
12
|
+
/** 仓库名称 */
|
|
13
|
+
repoName: string;
|
|
14
|
+
/** 目标路径 */
|
|
15
|
+
targetPath: string;
|
|
16
|
+
/** loading.json 中记录的 commitId */
|
|
17
|
+
loadedCommitId: string;
|
|
18
|
+
/** 缓存仓库当前的 commitId */
|
|
19
|
+
cacheCommitId: string;
|
|
20
|
+
/** 是否需要同步 */
|
|
21
|
+
needsSync: boolean;
|
|
22
|
+
/** 缓存仓库是否存在 */
|
|
23
|
+
cacheExists: boolean;
|
|
24
|
+
/** 目标目录是否存在 */
|
|
25
|
+
targetExists: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 同步结果
|
|
29
|
+
*/
|
|
30
|
+
export interface SyncResult {
|
|
31
|
+
/** 条目 ID */
|
|
32
|
+
entryId: string;
|
|
33
|
+
/** 仓库名称 */
|
|
34
|
+
repoName: string;
|
|
35
|
+
/** 是否成功 */
|
|
36
|
+
success: boolean;
|
|
37
|
+
/** 结果消息 */
|
|
38
|
+
message: string;
|
|
39
|
+
/** 旧的 commitId */
|
|
40
|
+
oldCommitId?: string;
|
|
41
|
+
/** 新的 commitId */
|
|
42
|
+
newCommitId?: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* 获取单个加载条目的同步状态
|
|
46
|
+
* @param entry 加载条目
|
|
47
|
+
* @param projectRoot 项目根目录
|
|
48
|
+
* @returns 同步状态
|
|
49
|
+
*/
|
|
50
|
+
export declare function getSyncStatus(entry: LoadingEntry, projectRoot?: string): Promise<SyncStatus>;
|
|
51
|
+
/**
|
|
52
|
+
* 获取所有已加载条目的同步状态
|
|
53
|
+
* @param projectRoot 项目根目录
|
|
54
|
+
* @returns 同步状态列表
|
|
55
|
+
*/
|
|
56
|
+
export declare function getAllSyncStatus(projectRoot?: string): Promise<SyncStatus[]>;
|
|
57
|
+
/**
|
|
58
|
+
* 同步单个条目到工作目录
|
|
59
|
+
* @param entry 加载条目
|
|
60
|
+
* @param force 是否强制同步(忽略本地修改)
|
|
61
|
+
* @param projectRoot 项目根目录
|
|
62
|
+
* @returns 同步结果
|
|
63
|
+
*/
|
|
64
|
+
export declare function syncEntry(entry: LoadingEntry, force?: boolean, projectRoot?: string): Promise<SyncResult>;
|
|
65
|
+
/**
|
|
66
|
+
* 同步所有需要更新的条目
|
|
67
|
+
* @param force 是否强制同步
|
|
68
|
+
* @param projectRoot 项目根目录
|
|
69
|
+
* @returns 同步结果列表
|
|
70
|
+
*/
|
|
71
|
+
export declare function syncAll(force?: boolean, projectRoot?: string): Promise<SyncResult[]>;
|
|
72
|
+
//# sourceMappingURL=sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/core/sync.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAItD;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,YAAY;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,iCAAiC;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,uBAAuB;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,eAAe;IACf,WAAW,EAAE,OAAO,CAAC;IACrB,eAAe;IACf,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,YAAY;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,kBAAkB;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAID;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,YAAY,EACnB,WAAW,GAAE,MAAsB,GAClC,OAAO,CAAC,UAAU,CAAC,CA4CrB;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,WAAW,GAAE,MAAsB,GAClC,OAAO,CAAC,UAAU,EAAE,CAAC,CAUvB;AAID;;;;;;GAMG;AACH,wBAAsB,SAAS,CAC7B,KAAK,EAAE,YAAY,EACnB,KAAK,GAAE,OAAe,EACtB,WAAW,GAAE,MAAsB,GAClC,OAAO,CAAC,UAAU,CAAC,CA2ErB;AAED;;;;;GAKG;AACH,wBAAsB,OAAO,CAC3B,KAAK,GAAE,OAAe,EACtB,WAAW,GAAE,MAAsB,GAClC,OAAO,CAAC,UAAU,EAAE,CAAC,CAsCvB"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* 同步模块
|
|
4
|
+
* 负责工作目录与全局缓存之间的同步操作
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.getSyncStatus = getSyncStatus;
|
|
41
|
+
exports.getAllSyncStatus = getAllSyncStatus;
|
|
42
|
+
exports.syncEntry = syncEntry;
|
|
43
|
+
exports.syncAll = syncAll;
|
|
44
|
+
const path = __importStar(require("path"));
|
|
45
|
+
const loading = __importStar(require("./loading.js"));
|
|
46
|
+
const repository = __importStar(require("./repository.js"));
|
|
47
|
+
const filesystem = __importStar(require("./filesystem.js"));
|
|
48
|
+
const git = __importStar(require("./git.js"));
|
|
49
|
+
// ============ 状态检测 ============
|
|
50
|
+
/**
|
|
51
|
+
* 获取单个加载条目的同步状态
|
|
52
|
+
* @param entry 加载条目
|
|
53
|
+
* @param projectRoot 项目根目录
|
|
54
|
+
* @returns 同步状态
|
|
55
|
+
*/
|
|
56
|
+
async function getSyncStatus(entry, projectRoot = process.cwd()) {
|
|
57
|
+
const status = {
|
|
58
|
+
entryId: entry.id,
|
|
59
|
+
repoName: entry.repoName,
|
|
60
|
+
targetPath: entry.targetPath,
|
|
61
|
+
loadedCommitId: entry.commitId,
|
|
62
|
+
cacheCommitId: "",
|
|
63
|
+
needsSync: false,
|
|
64
|
+
cacheExists: false,
|
|
65
|
+
targetExists: false,
|
|
66
|
+
};
|
|
67
|
+
// 检查目标目录是否存在
|
|
68
|
+
const targetAbsPath = path.join(projectRoot, entry.targetPath);
|
|
69
|
+
status.targetExists = await filesystem.exists(targetAbsPath);
|
|
70
|
+
// 获取缓存仓库信息
|
|
71
|
+
try {
|
|
72
|
+
const repoInfo = await repository.get(entry.repoName);
|
|
73
|
+
if (repoInfo) {
|
|
74
|
+
status.cacheExists = true;
|
|
75
|
+
// 获取缓存仓库当前的 commitId
|
|
76
|
+
status.cacheCommitId = await git.getCurrentCommit(repoInfo.path);
|
|
77
|
+
// 判断是否需要同步
|
|
78
|
+
// 需要同步的情况:
|
|
79
|
+
// 1. 目标目录不存在
|
|
80
|
+
// 2. commitId 不一致
|
|
81
|
+
if (!status.targetExists) {
|
|
82
|
+
status.needsSync = true;
|
|
83
|
+
}
|
|
84
|
+
else if (status.loadedCommitId !== status.cacheCommitId) {
|
|
85
|
+
status.needsSync = true;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
status.cacheExists = false;
|
|
90
|
+
status.needsSync = false; // 缓存不存在,无法同步
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// 获取仓库信息失败,标记缓存不存在
|
|
95
|
+
status.cacheExists = false;
|
|
96
|
+
status.needsSync = false;
|
|
97
|
+
}
|
|
98
|
+
return status;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* 获取所有已加载条目的同步状态
|
|
102
|
+
* @param projectRoot 项目根目录
|
|
103
|
+
* @returns 同步状态列表
|
|
104
|
+
*/
|
|
105
|
+
async function getAllSyncStatus(projectRoot = process.cwd()) {
|
|
106
|
+
const entries = await loading.getEntries(projectRoot);
|
|
107
|
+
const statusList = [];
|
|
108
|
+
for (const entry of entries) {
|
|
109
|
+
const status = await getSyncStatus(entry, projectRoot);
|
|
110
|
+
statusList.push(status);
|
|
111
|
+
}
|
|
112
|
+
return statusList;
|
|
113
|
+
}
|
|
114
|
+
// ============ 同步操作 ============
|
|
115
|
+
/**
|
|
116
|
+
* 同步单个条目到工作目录
|
|
117
|
+
* @param entry 加载条目
|
|
118
|
+
* @param force 是否强制同步(忽略本地修改)
|
|
119
|
+
* @param projectRoot 项目根目录
|
|
120
|
+
* @returns 同步结果
|
|
121
|
+
*/
|
|
122
|
+
async function syncEntry(entry, force = false, projectRoot = process.cwd()) {
|
|
123
|
+
const result = {
|
|
124
|
+
entryId: entry.id,
|
|
125
|
+
repoName: entry.repoName,
|
|
126
|
+
success: false,
|
|
127
|
+
message: "",
|
|
128
|
+
oldCommitId: entry.commitId,
|
|
129
|
+
};
|
|
130
|
+
try {
|
|
131
|
+
// 获取缓存仓库信息
|
|
132
|
+
const repoInfo = await repository.get(entry.repoName);
|
|
133
|
+
if (!repoInfo) {
|
|
134
|
+
result.message = `缓存仓库不存在: ${entry.repoName}`;
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
// 获取缓存仓库当前的 commitId
|
|
138
|
+
const cacheCommitId = await git.getCurrentCommit(repoInfo.path);
|
|
139
|
+
result.newCommitId = cacheCommitId;
|
|
140
|
+
// 检查是否需要同步
|
|
141
|
+
const targetAbsPath = path.join(projectRoot, entry.targetPath);
|
|
142
|
+
const targetExists = await filesystem.exists(targetAbsPath);
|
|
143
|
+
if (targetExists && entry.commitId === cacheCommitId && !force) {
|
|
144
|
+
result.success = true;
|
|
145
|
+
result.message = "已是最新版本,无需同步";
|
|
146
|
+
return result;
|
|
147
|
+
}
|
|
148
|
+
// 确定源路径(考虑 subdir)
|
|
149
|
+
let sourcePath = repoInfo.path;
|
|
150
|
+
if (entry.subdir) {
|
|
151
|
+
sourcePath = path.join(repoInfo.path, entry.subdir);
|
|
152
|
+
// 检查子目录是否存在
|
|
153
|
+
if (!(await filesystem.exists(sourcePath))) {
|
|
154
|
+
result.message = `子目录不存在: ${entry.subdir}`;
|
|
155
|
+
return result;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// 删除旧目录(如果存在)
|
|
159
|
+
if (targetExists) {
|
|
160
|
+
await filesystem.removeDir(targetAbsPath);
|
|
161
|
+
}
|
|
162
|
+
// 确保目标父目录存在
|
|
163
|
+
const targetParentDir = path.dirname(targetAbsPath);
|
|
164
|
+
await filesystem.ensureDir(targetParentDir);
|
|
165
|
+
// 复制新内容(排除 .git 目录)
|
|
166
|
+
await filesystem.copyDir(sourcePath, targetAbsPath, {
|
|
167
|
+
exclude: [".git", ".gitreference-meta.json"],
|
|
168
|
+
overwrite: true,
|
|
169
|
+
});
|
|
170
|
+
// 更新 loading.json 中的 commitId 和 updatedAt
|
|
171
|
+
await loading.updateEntry(entry.id, {
|
|
172
|
+
commitId: cacheCommitId,
|
|
173
|
+
}, projectRoot);
|
|
174
|
+
result.success = true;
|
|
175
|
+
result.message = `同步成功: ${entry.commitId.substring(0, 7)} → ${cacheCommitId.substring(0, 7)}`;
|
|
176
|
+
return result;
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
const err = error;
|
|
180
|
+
result.message = `同步失败: ${err.message}`;
|
|
181
|
+
return result;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* 同步所有需要更新的条目
|
|
186
|
+
* @param force 是否强制同步
|
|
187
|
+
* @param projectRoot 项目根目录
|
|
188
|
+
* @returns 同步结果列表
|
|
189
|
+
*/
|
|
190
|
+
async function syncAll(force = false, projectRoot = process.cwd()) {
|
|
191
|
+
const entries = await loading.getEntries(projectRoot);
|
|
192
|
+
const results = [];
|
|
193
|
+
for (const entry of entries) {
|
|
194
|
+
// 获取同步状态
|
|
195
|
+
const status = await getSyncStatus(entry, projectRoot);
|
|
196
|
+
// 只同步需要同步的条目,或者强制同步所有
|
|
197
|
+
if (status.needsSync || force) {
|
|
198
|
+
if (!status.cacheExists) {
|
|
199
|
+
// 缓存不存在,跳过
|
|
200
|
+
results.push({
|
|
201
|
+
entryId: entry.id,
|
|
202
|
+
repoName: entry.repoName,
|
|
203
|
+
success: false,
|
|
204
|
+
message: `缓存仓库不存在: ${entry.repoName}`,
|
|
205
|
+
oldCommitId: entry.commitId,
|
|
206
|
+
});
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
const result = await syncEntry(entry, force, projectRoot);
|
|
210
|
+
results.push(result);
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
// 不需要同步
|
|
214
|
+
results.push({
|
|
215
|
+
entryId: entry.id,
|
|
216
|
+
repoName: entry.repoName,
|
|
217
|
+
success: true,
|
|
218
|
+
message: "已是最新版本",
|
|
219
|
+
oldCommitId: entry.commitId,
|
|
220
|
+
newCommitId: entry.commitId,
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return results;
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=sync.js.map
|