zen-gitsync 2.11.36 → 2.11.38

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.
@@ -651,5 +651,49 @@ export function registerFsRoutes({
651
651
  res.status(500).json({ success: false, error: error.message });
652
652
  }
653
653
  });
654
+
655
+ // ── 编辑器:在系统文件管理器中打开 / 选中 ───────────────────
656
+ // 行为:
657
+ // - 目录:直接用系统文件管理器打开
658
+ // - 文件:Windows / macOS 上在文件管理器中选中该文件;Linux 无标准接口,退化为打开所在目录
659
+ app.post('/api/editor/reveal', express.json(), async (req, res) => {
660
+ try {
661
+ const targetPath = req.body?.path;
662
+ if (!targetPath) return res.status(400).json({ success: false, error: '缺少 path 参数' });
663
+
664
+ const cwd = getCurrentProjectPath() || process.cwd();
665
+ const resolved = path.resolve(targetPath);
666
+ if (!resolved.startsWith(path.resolve(cwd))) {
667
+ return res.status(403).json({ success: false, error: '禁止访问工作目录以外的内容' });
668
+ }
669
+
670
+ try {
671
+ await fs.access(resolved);
672
+ } catch {
673
+ return res.status(404).json({ success: false, error: '目标不存在' });
674
+ }
675
+
676
+ const stat = await fs.stat(resolved);
677
+ const isDirectory = stat.isDirectory();
678
+
679
+ const platform = process.platform;
680
+ if (isDirectory) {
681
+ await open(resolved, { wait: false });
682
+ } else if (platform === 'win32') {
683
+ // Windows: explorer.exe /select,"<path>"
684
+ spawn('explorer.exe', [`/select,"${resolved}"`], { detached: true, stdio: 'ignore' }).unref();
685
+ } else if (platform === 'darwin') {
686
+ // macOS: open -R "<path>" 在 Finder 中选中
687
+ spawn('open', ['-R', resolved], { detached: true, stdio: 'ignore' }).unref();
688
+ } else {
689
+ // Linux / 其它: 没有统一标准,打开所在目录
690
+ await open(path.dirname(resolved), { wait: false });
691
+ }
692
+
693
+ res.json({ success: true });
694
+ } catch (error) {
695
+ res.status(500).json({ success: false, error: error.message });
696
+ }
697
+ });
654
698
  }
655
699
 
@@ -112,6 +112,19 @@ export function registerGitDiffRoutes({
112
112
  }
113
113
 
114
114
  try {
115
+ // 二进制/产物文件:直接告知前端 isBinary,不读取内容
116
+ if (skipExtensions.test(String(filePath))) {
117
+ const isImage = /\.(png|jpg|jpeg|gif|webp|bmp|ico|svg)$/i.test(String(filePath))
118
+ return res.json({
119
+ success: true,
120
+ isBinary: true,
121
+ isImage,
122
+ content: isImage
123
+ ? '⚠️ 该文件是图片,建议在预览中查看。'
124
+ : '⚠️ 检测到二进制/编译产物文件,不支持以文本形式显示完整内容。'
125
+ });
126
+ }
127
+
115
128
  // 读取文件内容
116
129
  const content = await fs.readFile(filePath, 'utf8');
117
130
  res.json({ success: true, content });
@@ -113,6 +113,46 @@ export function registerGitOpsRoutes({
113
113
  }
114
114
  });
115
115
 
116
+ // 批量添加文件到暂存区(一次 git add 命令,避免 index.lock 竞争)
117
+ app.post('/api/add-files', async (req, res) => {
118
+ try {
119
+ const { filePaths } = req.body || {};
120
+
121
+ if (!Array.isArray(filePaths) || filePaths.length === 0) {
122
+ return res.status(400).json({
123
+ success: false,
124
+ error: '缺少文件路径参数',
125
+ successCount: 0,
126
+ failedCount: 0
127
+ });
128
+ }
129
+
130
+ // 过滤掉空路径与重复路径
131
+ const uniquePaths = [...new Set(filePaths.filter(p => typeof p === 'string' && p.length > 0))];
132
+ if (uniquePaths.length === 0) {
133
+ return res.status(400).json({
134
+ success: false,
135
+ error: '没有有效的文件路径',
136
+ successCount: 0,
137
+ failedCount: 0
138
+ });
139
+ }
140
+
141
+ // 用一个 git add 命令暂存所有文件(按路径转义双引号防注入)
142
+ const escaped = uniquePaths.map(p => `"${String(p).replace(/"/g, '\\"')}"`).join(' ');
143
+ await execGitCommand(`git add ${escaped}`);
144
+
145
+ res.json({
146
+ success: true,
147
+ successCount: uniquePaths.length,
148
+ failedCount: 0,
149
+ filePaths: uniquePaths
150
+ });
151
+ } catch (error) {
152
+ res.status(500).json({ success: false, error: error.message, successCount: 0, failedCount: 0 });
153
+ }
154
+ });
155
+
116
156
  // 从暂存区移除单个文件
117
157
  app.post('/api/unstage-file', async (req, res) => {
118
158
  try {