解决 TFS 中的 .resx 合并问题
这是“解决 .resx 合并问题”的另一种方案
简介
本文扩展了 原始文章,介绍了如何在 TFS 实现中解决 .resx 文件的合并问题。但可以轻松调整以适用于 ant diff 合并应用程序。
使用代码
在 Visual Studio 中执行以下操作:工具 -> 选项 -> 源代码管理 -> Visual Studio Team Foundation Server -> 配置用户工具
点击“添加”并填写
扩展名:.resx
操作:比较
命令:C:\SortRESX.exe
参数:compare %1 %2 %6 %7 %5
点击“确定”,然后再次点击“添加”并填写
扩展名:.resx
操作:合并
命令:C:\SortRESX.exe
参数:merge %1 %2 %3 %4 %6 %7 %8
代码
该程序在启动 TFS 合并实用程序之前,使用原始文章中的排序功能。
class Program
{
private const string DiffMergeLocation =
@"C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\diffmerge.exe";
static void Main(string[] args)
{
//Are we mergeing or comparing
if (String.Equals(args[0], "merge", StringComparison.CurrentCultureIgnoreCase))
{
HandleMerge(args);
}
else if (String.Equals(args[0], "compare", StringComparison.CurrentCultureIgnoreCase))
{
HandleCompare(args);
}
else
{
throw new NotSupportedException("Unknown mode, use either merge or compare");
}
}
private static void HandleCompare(string[] args)
{
var theirsSource = args[1];
var theirs = Path.GetTempFileName();
var yoursSource = args[2];
var yours = Path.GetTempFileName();
try
{
//Sort input files
var doc = XDocument.Load(theirsSource);
var sortedDoc = SortDataByName(doc);
sortedDoc.Save(theirs);
doc = XDocument.Load(yoursSource);
sortedDoc = SortDataByName(doc);
sortedDoc.Save(yours);
var theirLabel = args[3];
var yoursLabel = args[4];
//var options = args.Length >= 6 ? "\"" + args[5] + "\"" : "";
//Launch diffmerge and wait for exit
var start = new ProcessStartInfo
{
Arguments = string.Format("\"{0}\" \"{1}\" \"{2}\"
\"{3}\" /ignorespace", theirs, yours, theirLabel, yoursLabel),
FileName = DiffMergeLocation,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
};
// Run the external process & wait for it to finish
using (var proc = Process.Start(start))
{
proc.WaitForExit();
}
}
finally
{
//Clean up temp files
File.Delete(theirs);
File.Delete(yours);
}
}
private static void HandleMerge(string[] args)
{
var theirsSource = args[1];
var theirs = Path.GetTempFileName();
var yoursSource = args[2];
var yours = Path.GetTempFileName();
var baseFileSource = args[3];
var baseFile = Path.GetTempFileName();
var merged = args[4];
var theirLabel = args[5];
var yoursLabel = args[6];
try
{
//Sort input files
var doc = XDocument.Load(theirsSource);
var sortedDoc = SortDataByName(doc);
sortedDoc.Save(theirs);
doc = XDocument.Load(yoursSource);
sortedDoc = SortDataByName(doc);
sortedDoc.Save(yours);
doc = XDocument.Load(baseFileSource);
sortedDoc = SortDataByName(doc);
sortedDoc.Save(baseFile);
//Launch diffmerge and wait for exit
var start = new ProcessStartInfo
{
Arguments = string.Format("/merge \"{0}\" \"{1}\" \"{2}\"
\"{3}\" \"{4}\" \"{5}\"", theirs, yours, baseFile, merged, theirLabel, yoursLabel),
FileName = DiffMergeLocation,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
};
// Run the external process & wait for it to finish
using (var proc = Process.Start(start))
{
proc.WaitForExit();
}
}
finally
{
//Clean up temp files
File.Delete(theirs);
File.Delete(yours);
File.Delete(baseFile);
}
}
/// <summary>
/// Use Linq to sort the elements. The comment, schema, resheader, assembly, metadata, data appear in that order,
/// with resheader, assembly, metadata and data elements sorted by name attribute.
/// </summary>
/// <param name="resx"></param>
/// <returns></returns>
private static XDocument SortDataByName(XDocument resx)
{
return new XDocument(
new XElement(resx.Root.Name,
resx.Root.Nodes().Where(comment => comment.NodeType == XmlNodeType.Comment),
resx.Root.Elements().Where(schema => schema.Name.LocalName == "schema"),
resx.Root.Elements("resheader").OrderBy(resheader => (string) resheader.Attribute("name")),
resx.Root.Elements("assembly").OrderBy(assembly => (string) assembly.Attribute("name")),
resx.Root.Elements("metadata").OrderBy(metadata => (string) metadata.Attribute("name")),
resx.Root.Elements("data").OrderBy(data => (string) data.Attribute("name"))
)
);
}
}