目录
- 前言
- 需求拆分
- 解决方案
- 实操
前言
最近工作有一个需求,简单来说是在 Unity 里面动态获取 SVN diff 的数据,并且针对这些 diff 文件做对应操作
需求拆分
我们首先拆分下需求
- Unity里面获取 SVN 的 diff 文件
- 针对生成的 diff 文件做解析,找到对应的文件
- 对这些文件做对应操作
下面是伪代码
string target_folder_path = "";//SVN diff文件夹
//步骤一
string svn_diff_file_path = Tools.CreateSVNDiffFile(folder_path);
//步骤二
string[] diff_files_path = Tools.Deserialize(svn_diff_file_path);
//步骤三
foreach(string file in diff_files_path)
{
DoSomethings(file);
}
这里面最关键的是 SVN diff 文件的生成
解决方案
由于我们知道 SVN 支持 cmd 操作,所以我们可以考虑使用 cmd 来生成对应文件。
但是这里有个难点,Unity怎么打开 cmd 窗口呢?
我们可以考虑开一个进程,这个进程启动 cmd 就好了,然后输入我们需要的 SVN 指令就好了
但是我们需要知道以下知识:
- 如何利用C#代码,在程序里面开启一个进程
- 了解 SVN 的一些指令,例如 svn diff
- 知道如何在 cmd 生成对应文件
下面来告诉大家上面三个知识
- C#中开启一个进程
Process p = new Process(); //新建系统进程
//Process中的StartInfo为要传递给Process.Start()方法的属性
//设置p.StartInfo属性
p.StartInfo.FileName = "cmd.exe"; //要启动的应用程序
p.StartInfo.Arguments = ""; //启动应用程序时要使用的一组命令行参数
p.StartInfo.UseShellExecute = false; //是否使用操作系统shell启动进程(如果是从可执行文件创建进程,应设置为false)
p.StartInfo.RedirectStandardInput = true; //指示应用程序的输入是否从StandardInput流中读取的值(StandardInput)
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.CreateNoWindow = true; //不显示程序窗口
p.Start(); //启动进程
p.WaitForExit(); //等待程序执行完退出进程
p.Close(); //关闭进程
- svn diff
直接在 cmd 中输入 svn diff 就好了 - 知道如何在 cmd 生成对应文件
需要在后面加一个
> log.txt
svn diff > log.txt
4. 其实我们可以写一个更高级的,不需要先利用 cd 命令进入对应文件夹,我们可以直接在初始路径进行操作
svn diff 你的路径 > 输出log.txt文件路径
实操
现在我们知道了上述知识,我们就可以开始写代码了
SVNTools.cs
using System.Diagnostics;
using UnityEditor;
using System.Collections.Generic;
namespace SVNTool
{
/// <summary>
/// Unity SVN工具
/// </summary>
public class SVNTool
{
/// <summary>
/// cmd命令模板
/// </summary>
private static string cmdCommandModule = "svn {0} {1} > {2}";//svn 操作 输入文件夹路径 输出文件路径
//例:svn diff C:/TestInput > C:/TestInput/diff.txt
public static string DiffSelect(string folder_path)
{
string output_file_path = folder_path + "/diff.txt";
string cmdCommand = string.Format(cmdCommandModule, "diff", folder_path, output_file_path);
InvokeCmd(cmdCommand);
return output_file_path;
}
/// <summary>
/// 调用cmd
/// </summary>
/// <param name="cmdCommand">cmd命令</param>
private static void InvokeCmd(string cmdCommand)
{
Process p = new Process(); //新建系统进程
//Process中的StartInfo为要传递给Process.Start()方法的属性
//设置p.StartInfo属性
p.StartInfo.FileName = "cmd.exe"; //要启动的应用程序
p.StartInfo.Arguments = "/c " + cmdCommand + "&exit"; //启动应用程序时要使用的一组命令行参数
p.StartInfo.UseShellExecute = false; //是否使用操作系统shell启动进程(如果是从可执行文件创建进程,应设置为false)
p.StartInfo.RedirectStandardInput = true; //指示应用程序的输入是否从StandardInput流中读取的值(StandardInput)
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.CreateNoWindow = true; //不显示程序窗口
p.Start(); //启动进程
p.WaitForExit(); //等待程序执行完退出进程
p.Close(); //关闭进程
}
}
// 负责解析 diff 文件数据
public class SVNDiffDeSerializeHelper
{
private string SPLIT_SIGN = "Index: ";
public List<SVNDiffData> datas;
public SVNDiffDeSerializeHelper()
{
datas = new List<SVNDiffData>();
}
public void DeSerialize(string[] contents)
{
for (int i = 0; i < contents.Length; i++)
{
if (contents[i].StartsWith(SPLIT_SIGN))
{
string file_path = contents[i].Substring(SPLIT_SIGN.Length);
datas.Add(new SVNDiffData(file_path));
}
}
}
}
// diff 文件Data
public class SVNDiffData
{
public string file_path;//由于当前需求只需要知道文件路径,所以这里只存了文件路径,大家如果有自己的需求,可以加成员变量
public SVNDiffData(string file_path_in)
{
file_path = file_path_in;
}
}
}
具体执行函数
private void Do(string folderPath)
{
//生成diff.txt文件
string diff_file_path = SVNTool.DiffSelect(folderPath);
SVNDiffDeSerializeHelper svn_helper = new SVNDiffDeSerializeHelper();
//反序列化
svn_helper.DeSerialize(File.ReadAllLines(diff_file_path));
//获得被修改之后的.fbx文件路径
List<SVNDiffData> datas = svn_helper.datas;
foreach(SVNDiffData data in datas)
{
DoSomethings(data);
}
}
private void DoSomethings(SVNDiffData svn_diff_data)
{
//DoSomethings
}