Skip to content

Commit

Permalink
🔧 chore(scm): 优化版本控制系统检测和提交消息处理
Browse files Browse the repository at this point in the history
- 【功能优化】改进提交消息生成后的处理流程
- 【新增功能】添加命令行SVN支持
- 【文案优化】更新中英文提示信息,使其更准确清晰
- 【SCM检测】增加目录结构和系统命令检测功能
- 【错误处理】完善写入失败时的降级策略
- 【国际化】新增多个本地化文案条目
  • Loading branch information
littleCareless committed Feb 5, 2025
1 parent d0f22e8 commit d92553e
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 47 deletions.
12 changes: 7 additions & 5 deletions i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
"scm.not.detected": "No supported version control system detected",
"no.changes": "No changes to commit",
"diff.too.long": "Changes are too long and exceed the model's maximum limit. Please reduce the number of selected files or content length.\nCurrent length: {0} characters\nMaximum limit: {1} characters",
"commit.message.generated": "Commit message has been filled in {0} commit box (generated by {1} - {2})",
"commit.message.write.failed": "Failed to write commit message: {0}",
"commit.message.copied": "Commit message has been copied to clipboard",
"commit.message.generated": "Commit message generated successfully (by {1} - {2})",
"commit.message.write.failed": "Failed to write commit message to SCM input box: {0}",
"commit.message.copied": "Commit message has been copied to clipboard. Please paste it into your version control system's commit input box",
"commit.message.copy.failed": "Failed to copy commit message: {0}",
"commit.message.manual.copy": "Commit message has been generated, please manually copy to commit box",
"commit.message.manual.copy": "Commit message has been generated, please manually copy to commit box: \n {0}",
"generate.commit.failed": "Failed to generate commit message: {0}",
"get.models.failed": "Failed to get model list",
"openai.config.required": "OpenAI API configuration is required to use this feature. Would you like to configure it now?",
Expand Down Expand Up @@ -59,6 +59,7 @@
"openai.models.error": "Failed to get OpenAI model list",
"model.not.found": "Selected model not found",
"model.list.empty": "Model list is empty",
"model.list.partial.failed": "Failed to fetch models from some providers: {0}",
"no.commit.message.generated": "No commit message generated",
"input.truncated": "Input content exceeds maximum character limit and has been truncated, this may affect the quality of generated results",
"extension.activation.failed": "Extension activation failed: {0}",
Expand Down Expand Up @@ -113,5 +114,6 @@
"codeReview.report.findings": "Detailed Findings",
"codeReview.issue.label": "Issue:",
"codeReview.suggestion.label": "Suggestion:",
"codeReview.documentation.label": "Documentation"
"codeReview.documentation.label": "Documentation",
"cli.commit.input.not.supported": "Unable to access the commit message input box instance"
}
12 changes: 7 additions & 5 deletions i18n/zh-cn.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
"scm.not.detected": "未检测到支持的版本控制系统",
"no.changes": "没有可提交的更改",
"diff.too.long": "变更内容过长,超出模型最大限制。请减少选中的文件数量或内容长度。\n当前长度: {0} 字符\n最大限制: {1} 字符",
"commit.message.generated": "已将提交信息填入 {0} 提交框 (生成自 {1} - {2})",
"commit.message.write.failed": "写入提交信息失败: {0}",
"commit.message.copied": "提交信息已复制到剪贴板",
"commit.message.generated": "提交信息生成成功 (生成自 {1} - {2})",
"commit.message.write.failed": "写入提交信息到版本控制输入框失败: {0}",
"commit.message.copied": "提交信息已复制到剪贴板,请粘贴到版本控制系统的提交输入框中",
"commit.message.copy.failed": "复制提交信息失败: {0}",
"commit.message.manual.copy": "提交信息已生成,请手动复制到提交框",
"commit.message.manual.copy": "提交信息已生成,请手动复制到提交框: \n {0}",
"generate.commit.failed": "生成提交信息失败: {0}",
"get.models.failed": "获取模型列表失败",
"openai.config.required": "需要配置 OpenAI API 信息才能使用该功能,是否现在配置?",
Expand Down Expand Up @@ -99,6 +99,7 @@
"review.results.title": "代码评审结果",
"codeReview.generation.failed": "代码评审生成失败: {0}",
"model.list.empty": "模型列表为空",
"model.list.partial.failed": "部分 AI 提供商模型列表获取失败: {0}",
"no.changes.selected": "未选择任何待评审的文件",
"please.select.valid.files": "选择的文件中包含无效项,请重新选择要评审的文件",
"no.changes.found": "未找到需要评审的变更",
Expand All @@ -113,5 +114,6 @@
"codeReview.report.findings": "详细问题",
"codeReview.issue.label": "问题:",
"codeReview.suggestion.label": "建议:",
"codeReview.documentation.label": "相关文档"
"codeReview.documentation.label": "相关文档",
"cli.commit.input.not.supported": "无法获取提交信息输入框实例"
}
29 changes: 13 additions & 16 deletions src/commands/GenerateCommitCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,36 +220,33 @@ export class GenerateCommitCommand extends BaseCommand {

// 尝试设置提交信息
if (response?.content) {
NotificationHandler.info(
locManager.format(
"commit.message.generated",
scmProvider.type.toUpperCase(),
provider,
model
)
);
try {
await scmProvider.setCommitInput(response.content);
NotificationHandler.info(
locManager.format(
"commit.message.generated",
scmProvider.type.toUpperCase(),
provider,
model
)
);
} catch (error) {
// 处理写入失败的情况
// 写入失败,尝试复制到剪贴板
if (error instanceof Error) {
NotificationHandler.error(
locManager.format("commit.message.write.failed", error.message)
);

// 尝试复制到剪贴板
try {
await vscode.env.clipboard.writeText(response.content);
NotificationHandler.error(
locManager.format("commit.message.write.failed", error.message)
);
NotificationHandler.info(
locManager.getMessage("commit.message.copied")
);
} catch (error) {
// 处理复制失败的情况
// 复制也失败了,显示消息内容
if (error instanceof Error) {
NotificationHandler.error(
locManager.format("commit.message.copy.failed", error.message)
);
// 提示手动复制
vscode.window.showInformationMessage(
locManager.getMessage("commit.message.manual.copy"),
response.content
Expand Down
57 changes: 57 additions & 0 deletions src/scm/CliSvnProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { exec } from "child_process";
import { promisify } from "util";
import { ISCMProvider } from "./SCMProvider";
import { LocalizationManager } from "../utils/LocalizationManager";

const execAsync = promisify(exec);

export class CliSvnProvider implements ISCMProvider {
type: "svn" = "svn";
private workspaceRoot: string;

constructor(workspaceRoot: string) {
this.workspaceRoot = workspaceRoot;
}

async isAvailable(): Promise<boolean> {
try {
await execAsync("svn --version");
return true;
} catch {
return false;
}
}

async getDiff(files?: string[]): Promise<string | undefined> {
try {
const filePaths = files?.join(" ") || ".";
const { stdout } = await execAsync(`svn diff ${filePaths}`, {
cwd: this.workspaceRoot,
});
return stdout;
} catch (error) {
console.error("Failed to get SVN diff:", error);
return undefined;
}
}

async commit(message: string, files?: string[]): Promise<void> {
const filePaths = files?.join(" ") || ".";
await execAsync(`svn commit -m "${message}" ${filePaths}`, {
cwd: this.workspaceRoot,
});
}

// 由于是命令行方式,这两个方法可能用不到,但需要实现接口
async setCommitInput(message: string): Promise<void> {
throw new Error(
LocalizationManager.getInstance().getMessage(
"cli.commit.input.not.supported"
)
);
}

async getCommitInput(): Promise<string> {
return "";
}
}
99 changes: 78 additions & 21 deletions src/scm/SCMProvider.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import * as vscode from "vscode";
import * as fs from "fs";
import * as path from "path";
import { exec } from "child_process";
import { GitProvider } from "./GitProvider";
import { SvnProvider } from "./SvnProvider";
import { LocalizationManager } from "../utils/LocalizationManager";
import { CliSvnProvider } from "./CliSvnProvider";

/**
* 源代码管理提供者接口
Expand Down Expand Up @@ -35,6 +39,42 @@ export class SCMFactory {
/** 当前激活的SCM提供者实例 */
private static currentProvider: ISCMProvider | undefined;

/**
* 通过项目目录检测SCM类型
* @param workspaceRoot 工作区根目录
* @returns {"git" | "svn" | undefined} SCM类型
*/
private static detectSCMFromDir(workspaceRoot: string): "git" | "svn" | undefined {
try {
const gitPath = path.join(workspaceRoot, ".git");
const svnPath = path.join(workspaceRoot, ".svn");

if (fs.existsSync(gitPath)) {
return "git";
}
if (fs.existsSync(svnPath)) {
return "svn";
}
return undefined;
} catch (error) {
console.error("Failed to detect SCM from directory:", error);
return undefined;
}
}

/**
* 检测系统是否安装了指定的SCM命令
* @param cmd 要检测的命令
* @returns {Promise<boolean>} 命令是否可用
*/
private static async checkSCMCommand(cmd: string): Promise<boolean> {
return new Promise((resolve) => {
exec(`${cmd} --version`, (error) => {
resolve(!error);
});
});
}

/**
* 检测并创建可用的SCM提供者
* @returns {Promise<ISCMProvider | undefined>} 返回可用的SCM提供者实例,如果没有可用的提供者则返回undefined
Expand All @@ -45,31 +85,48 @@ export class SCMFactory {
return this.currentProvider;
}

// 获取工作区根目录
const workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath;
if (!workspaceRoot) {
return undefined;
}

// 首先通过目录检测
const scmType = this.detectSCMFromDir(workspaceRoot);

const gitExtension = vscode.extensions.getExtension("vscode.git");
const svnExtension = vscode.extensions.getExtension(
"littleCareless.svn-scm-ai"
);
const svnExtension = vscode.extensions.getExtension("littleCareless.svn-scm-ai");

// if (!gitExtension && !svnExtension) {
// throw new Error(
// LocalizationManager.getInstance().getMessage("scm.no.provider")
// );
// }

const git = gitExtension?.exports
? new GitProvider(gitExtension.exports)
: undefined;
if (git && (await git.isAvailable())) {
this.currentProvider = git;
return git;
// 如果检测到Git
if (scmType === "git") {
const git = gitExtension?.exports
? new GitProvider(gitExtension.exports)
: undefined;
if (git && (await git.isAvailable())) {
this.currentProvider = git;
return git;
}
}

const svn = svnExtension?.exports
? new SvnProvider(svnExtension.exports)
: undefined;
if (svn && (await svn.isAvailable())) {
this.currentProvider = svn;
return svn;
// 如果检测到SVN
if (scmType === "svn") {
// 先尝试使用SVN插件
const svn = svnExtension?.exports
? new SvnProvider(svnExtension.exports)
: undefined;
if (svn && (await svn.isAvailable())) {
this.currentProvider = svn;
return svn;
}

// 如果没有插件但系统有SVN命令,使用命令行方式
if (await this.checkSCMCommand("svn")) {
const cliSvn = new CliSvnProvider(workspaceRoot);
if (await cliSvn.isAvailable()) {
this.currentProvider = cliSvn;
return cliSvn;
}
}
}

return undefined;
Expand Down

0 comments on commit d92553e

Please sign in to comment.