目录

  • 前言
  • 需求拆分
  • 解决方案
  • 实操


前言

最近工作有一个需求,简单来说是在 Unity 里面动态获取 SVN diff 的数据,并且针对这些 diff 文件做对应操作

需求拆分

我们首先拆分下需求

  1. Unity里面获取 SVNdiff 文件
  2. 针对生成的 diff 文件做解析,找到对应的文件
  3. 对这些文件做对应操作

下面是伪代码

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 指令就好了

但是我们需要知道以下知识:

  1. 如何利用C#代码,在程序里面开启一个进程
  2. 了解 SVN 的一些指令,例如 svn diff
  3. 知道如何在 cmd 生成对应文件

下面来告诉大家上面三个知识

  1. 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(); //关闭进程
  1. svn diff
    直接在 cmd 中输入 svn diff 就好了
  2. 知道如何在 cmd 生成对应文件
    需要在后面加一个

> log.txt

svn diff > log.txt

unity 拿到运行时的host_svn


unity 拿到运行时的host_unity_02


4. 其实我们可以写一个更高级的,不需要先利用 cd 命令进入对应文件夹,我们可以直接在初始路径进行操作

unity 拿到运行时的host_unity 拿到运行时的host_03

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
}