svn更新 git更新 打开文件夹 同步文件夹
using Microsoft.Win32;
using System;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
namespace winFormTest
{using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Windows.Forms;
namespace winFormTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
/// <summary> svn更新 </summary>
private void btn1_Click(object sender, EventArgs e)
{
GitSvnPath.StartSvnProc("update", @"G:\aoe2020", false);
}
/// <summary> git更新 </summary>
private void btn2_Click(object sender, EventArgs e)
{
GitSvnPath.StartGitProc("pull", @"C: \Users\Administrator\Desktop\TT0\svn");//pull拉取,commit提交,puch向远程推送
}
/// <summary> 打开文件夹 </summary>
private void btn3_Click(object sender, EventArgs e)
{
GitSvnPath.OpenExplorer(@"C:\Users\Administrator\Desktop\TT0\svn");
}
/// <summary> 同步文件夹 </summary>
private void btn4_Click(object sender, EventArgs e)
{
ClientSyncHelper.AddIgnore(".git", ".gitattributes", "README.md");
ClientSyncHelper.StartSyncFolderContext(@"C:\Users\Administrator\Desktop\TT0\svn", @"C:\Users\Administrator\Desktop\TT0\git", "a目录", true);//svn的内容同步到git
MessageBox.Show("成功"); //AssetDatabase.Refresh();
}
}
public static class GitSvnPath
{
/// <summary>
/// 开始运行SVN
/// </summary>
/// <param name="cmd">指令</param>
/// <param name="path">路径</param>
/// <param name="closeOnEnd">指令之后是否关闭</param>
public static void StartSvnProc(string cmd, string path, bool closeOnEnd = false)
{
var tortoiseProcPath = GetTortoiseProcSvnPath();
if (string.IsNullOrEmpty(tortoiseProcPath))
{
MessageBox.Show("TortoiseProc未找到");
return;
}
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = tortoiseProcPath;
startInfo.Arguments = $"/command:{cmd} /path:\"{path}\" /closeonend:{(closeOnEnd ? 2 : 0)}";
Process svnUpProcess = new Process();
svnUpProcess.StartInfo = startInfo;
svnUpProcess.Start();
}
//去 注册表 拿 svn安装目录
private static string GetTortoiseProcSvnPath()
{
try
{
RegistryKey key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default);
var path = key.OpenSubKey("SOFTWARE").OpenSubKey("TortoiseSVN").GetValue("ProcPath").ToString();
return path;
}
catch (Exception)
{
string[] vols = { "C", "D", "E", "F", "G", "H" };
string[] dirs = {
@"Program Files",
@"Program Files (x86)",
};
foreach (var vol in vols)
foreach (var dir in dirs)
{
string file = $"{vol}:\\{dir}\\TortoiseSVN\\bin\\TortoiseProc.exe";
if (File.Exists(file))
return file;
}
return null;
}
}
public static void StartGitProc(string cmd, string path)
{
string gitProcPath = GetTortoiseGitProcPath();
if (string.IsNullOrEmpty(gitProcPath))
{
MessageBox.Show("TortoiseGitProc未找到");
return;
}
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = gitProcPath;
startInfo.Arguments = $"/command:{cmd} /path:\"{path}\"/closeonend:2";
Process svnUpProcess = new Process();
svnUpProcess.StartInfo = startInfo;
svnUpProcess.Start();
svnUpProcess.WaitForExit();
if (svnUpProcess.ExitCode > 0)
MessageBox.Show("提示", $"svn update exit with code:{svnUpProcess.ExitCode}");
}
public static string GetTortoiseGitProcPath()
{
try
{
RegistryKey key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default);
var path = key.OpenSubKey("SOFTWARE").OpenSubKey("TortoiseGit").GetValue("ProcPath").ToString();
return path;
}
catch (Exception)
{
return null;
}
}
public static void OpenExplorer(string path)
{
if (!Directory.Exists(path)) return;
path = path.Replace("/", "\\");
Process p = new Process();
p.StartInfo = new ProcessStartInfo()
{
FileName = "explorer.exe",
Arguments = path,
};
p.Start();
}
}
public static class ClientSyncHelper
{
private static List<string> copyFileList = new List<string>();
private static List<string> delFileList = new List<string>();
private static List<string> addFolderList = new List<string>();
private static List<string> delFolderList = new List<string>();
private static Dictionary<string, string> srcMd5 = new Dictionary<string, string>();
private static Dictionary<string, string> targetMd5 = new Dictionary<string, string>();
private static List<string> ignoreList = new List<string>();
static public void AddIgnore(params string[] strs)
{
foreach (var str in strs)
if (!ignoreList.Contains(str))
ignoreList.Add(str);
}
private static bool IsIgnore(string path, bool isSyncMeta)
{
if (isSyncMeta == false && path.EndsWith(".meta"))
return true;
foreach (string s in ignoreList)
{
if (path.Contains(s))
return true;
}
return false;
}
//增加忽略文件夹,要增加meta文件忽略逻辑
/// <summary>
/// 开始同步
/// </summary>
/// <param name="SrcClient">源</param>
/// <param name="TargetClient">目标 使目标和源一样</param>
/// <param name="subPath">子目录</param>
/// <param name="isSyncMeta">是否忽略meta文件</param>
public static void StartSyncFolderContext(string SrcClient, string TargetClient, string subPath, bool isSyncMeta = true)
{
copyFileList.Clear();
delFileList.Clear();
addFolderList.Clear();
delFolderList.Clear();
srcMd5.Clear();
targetMd5.Clear();
//将相对路径,转成绝对路径,否则是有相对路径可能在下面的运算中出错.
SrcClient = Path.GetFullPath(SrcClient).Replace("\\", "/");
TargetClient = Path.GetFullPath(TargetClient).Replace("\\", "/");
CollectFoldersRule(SrcClient, TargetClient, subPath, isSyncMeta);
CollectSyncContext(SrcClient, TargetClient, subPath, isSyncMeta);
// 为了减少一些gc,所以全部文件md5信息收集完毕之后,才在这外面进行
foreach (string key in srcMd5.Keys)
{
if (targetMd5.ContainsKey(key) == false)
{
copyFileList.Add(key);
continue;
}
if (srcMd5[key] != targetMd5[key])
{
copyFileList.Add(key);
continue;
}
}
foreach (string key in targetMd5.Keys)
{
if (srcMd5.ContainsKey(key) == false)
{
delFileList.Add(key);
}
}
// 删除文件
foreach (string delFile in delFileList)
{
File.Delete($"{TargetClient}/{delFile}");
}
// 复制文件
foreach (string copyFile in copyFileList)
{
var targetFilePath = $"{TargetClient}/{copyFile}";
var targetPath = Path.GetDirectoryName(targetFilePath);
if (!Directory.Exists(targetPath))
Directory.CreateDirectory(targetPath);
if (File.Exists(targetFilePath))
File.Delete(targetFilePath);
File.Copy($"{SrcClient}/{copyFile}", targetFilePath);
}
// 最后RefreshAsset,清理对应数据
copyFileList.Clear();
delFileList.Clear();
addFolderList.Clear();
delFolderList.Clear();
srcMd5.Clear();
targetMd5.Clear();
ignoreList.Clear();
}
private static void CollectSyncContext(string SrcClient, string TargetClient, string subPath, bool isSyncMeta)
{
string srcPath = $"{SrcClient}/{subPath}";
string targetPath = $"{TargetClient}/{subPath}";
if (IsIgnore(srcPath, isSyncMeta) || IsIgnore(targetPath, isSyncMeta))
return;
bool isSrcExist = Directory.Exists(srcPath);
bool isTargetExist = Directory.Exists(targetPath);
if (isSrcExist == false && isTargetExist == false)
return;
// 递归遍历子文件夹
foreach (string dir in Directory.GetDirectories(srcPath))
{
string subFolder = dir.Replace("\\", "/").Substring(SrcClient.Length + 1);
CollectSyncContext(SrcClient, TargetClient, subFolder, isSyncMeta);
}
// 遍历当前文件夹下的所有文件
List<string> srcFiles = new List<string>();
if (Directory.Exists(srcPath))
srcFiles.AddRange(Directory.GetFiles(srcPath));
List<string> targetFiles = new List<string>();
if (Directory.Exists(targetPath))
targetFiles.AddRange(Directory.GetFiles(targetPath));
//FileStream fileStream;
string filePath;
foreach (string file in srcFiles)
{
filePath = file.Replace("\\", "/");
if (IsIgnore(file, isSyncMeta))
continue;
using (FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read))
{
srcMd5.Add(file.Replace("\\", "/").Substring(SrcClient.Length + 1), CalcMD5(fileStream));
fileStream.Close();
}
}
foreach (string file in targetFiles)
{
filePath = file.Replace("\\", "/");
if (IsIgnore(file, isSyncMeta))
continue;
using (FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read))
{
targetMd5.Add(file.Replace("\\", "/").Substring(TargetClient.Length + 1), CalcMD5(fileStream));
fileStream.Close();
}
}
}
static StringBuilder sb = new StringBuilder();
public static string CalcMD5(FileStream fs)
{
MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider();
byte[] hashvalue = provider.ComputeHash(fs);
sb.Clear();
for (int i = 0; i < hashvalue.Length; ++i)
{
sb.Append(hashvalue[i].ToString("x2"));
}
return sb.ToString();
}
/// <summary>
/// 先提取出需要增加和删除的文件夹
/// </summary>
public static void CollectFoldersRule(string SrcClient, string TargetClient, string subPath, bool isSyncMeta = true)
{
string srcPath = subPath == "" ? SrcClient : $"{SrcClient}/{subPath}";
string targetPath = subPath == "" ? TargetClient : $"{TargetClient}/{subPath}";
List<string> srcDireList = new List<string>();
List<string> targetDireList = new List<string>();
GetFoldersByRecursion(srcPath, ref srcDireList);
GetFoldersByRecursion(targetPath, ref targetDireList);
foreach (var dir in srcDireList)
{
if (IsIgnore(dir, isSyncMeta))
continue;
string subFolder = dir.Replace("\\", "/").Substring(srcPath.Length + 1);
bool isTargetExist = Directory.Exists($"{targetPath}/{subFolder}");
if (isTargetExist == false)
{
addFolderList.Add(dir);
}
}
foreach (var dir in targetDireList)
{
if (IsIgnore(dir, isSyncMeta))
continue;
string subFolder = dir.Replace("\\", "/").Substring(targetPath.Length + 1);
bool isSrcExist = Directory.Exists($"{srcPath}/{subFolder}");
if (!isSrcExist)
{
delFolderList.Add(dir);
}
}
// 删除文件夹
foreach (string delPath in delFolderList)
{
string path = delPath.Replace("\\", "/");
FileHelper.DeleteDirectory(path, true);
}
// 复制文件夹
foreach (string addPath in addFolderList)
{
string subFolder = addPath.Replace("\\", "/").Substring(srcPath.Length + 1);
FileHelper.CopyDirectory(addPath, $"{targetPath}/{subFolder}");
}
}
/// <summary>
/// 递归获取文件夹目录
/// </summary>
public static void GetFoldersByRecursion(string sourcePath, ref List<string> folderList)
{
if (Directory.Exists(sourcePath))//判断源文件夹是否存在
{
string[] tmp = Directory.GetDirectories(sourcePath);//获取源文件夹中的目录,存入字符串
//循环遍历
for (int i = 0; i < tmp.Length; i++)
{
string path = tmp[i].Replace("\\", "/");
folderList.Add(path);
if ((Directory.GetDirectories(path)).Length == 0)
{
continue;
}
//递归开始.......
GetFoldersByRecursion(path, ref folderList);
}
}
}
}
public class FileHelper
{
static FileHelper()
{
}
public static void CopyDirectory(string direcSource, string direcTarget)
{
if (!Directory.Exists(direcTarget))
Directory.CreateDirectory(direcTarget);
DirectoryInfo direcInfo = new DirectoryInfo(direcSource);
FileInfo[] files = direcInfo.GetFiles();
foreach (FileInfo file in files)
{
var tar = Path.Combine(direcTarget, file.Name);
if (File.Exists(tar))
File.Delete(tar);
file.CopyTo(tar);
}
DirectoryInfo[] direcInfoArr = direcInfo.GetDirectories();
foreach (DirectoryInfo dir in direcInfoArr)
CopyDirectory(Path.Combine(direcSource, dir.Name), Path.Combine(direcTarget, dir.Name));
}
public static void DeleteDirectory(string path, bool delete_myself = false)
{
DirectoryInfo dir = new DirectoryInfo(path);
if (dir.Exists)
{
foreach (DirectoryInfo child in dir.GetDirectories())
{
try
{
DeleteDirectory(child.FullName, true);
}
catch (Exception e)
{
MessageBox.Show(string.Format("Delete Directory Failed: path->{0}, error->{1}", child.FullName, e.Message));
}
}
foreach (FileInfo child in dir.GetFiles())
{
try
{
child.Delete();
}
catch (Exception e)
{
MessageBox.Show(string.Format("Delete File Failed: path->{0}, error->{1}", child.FullName, e.Message));
}
}
if (delete_myself)
{
dir.Delete(true);
}
}
}
public static string[] FindFileBySuffix(string search_path, string suffix)
{
List<string> result = new List<string>();
foreach (string dir in Directory.GetDirectories(search_path))
{
FindFileBySuffix(dir, suffix, ref result);
}
foreach (string file in Directory.GetFiles(search_path))
{
if (file.EndsWith(suffix, StringComparison.OrdinalIgnoreCase))
{
string str = file.Replace("\\", "/");
result.Add(str);
}
}
return result.ToArray();
}
public static void FindFileBySuffix(string search_path, string suffix, ref List<string> result)
{
foreach (string dir in Directory.GetDirectories(search_path))
{
FindFileBySuffix(dir, suffix, ref result);
}
foreach (string file in Directory.GetFiles(search_path))
{
if (file.EndsWith(suffix, StringComparison.OrdinalIgnoreCase))
{
string str = file.Replace("\\", "/");
result.Add(str);
}
}
}
public static void DeleteEmptyDirectory(string path)
{
DirectoryInfo dir_info = new DirectoryInfo(path);
foreach (var dir in dir_info.GetDirectories())
{
if (dir.GetFileSystemInfos().Length == 0)
{
dir.Delete();
}
else
{
DeleteEmptyDirectory(dir.FullName);
}
}
}
public static bool ExistInParentFolder(string startDir, string dirName)
{
DirectoryInfo info = new DirectoryInfo(startDir);
while (info != null)
{
if (Directory.Exists(Path.Combine(info.FullName, dirName)))
return true;
info = info.Parent;
}
return false;
}
}
}