精确计算TFS中新增以及更改的代码行数
<configuration> <configSections> <section name="LOCTargets" type="ConsoleApplication2.TFSConfigSection, TFSChangeLOC" /> </configSections> <appSettings> <add key="OutputFilePath" value="C:\Users\xingy\Desktop\LOCdemo.html"/> </appSettings> <LOCTargets> <add LocalPath="C:\SPA_5150\Apps\IntelligentRewards\dev\source" StartChangeSetId="373171" EndChangeSetId="373173"/> <add LocalPath="C:\SPA_5150\Apps\Framework\source" StartChangeSetId="373165" EndChangeSetId="373170"/> </LOCTargets> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> </startup> </configuration>
class Program { static int addNumber = 0; static int delNumber = 0; static int editNumber = 0; static int otherNumber = 0; static int renameNumber = 0; static Dictionary<int, int> changeSetDic = new Dictionary<int, int>(); static List<string> changedFiles = new List<string>(); static void Main(string[] args) { Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); TFSConfigSection section = config.Sections["LOCTargets"] as TFSConfigSection; foreach (Target locTarget in section.Instances) { TFS(locTarget.LocalPath,locTarget.StartChangeSetId,locTarget.EndChangeSetId); } ScanFiles(); OutputHtmlFile(changeSetDic); Console.WriteLine("Press Any Key to Exit ... ..."); Console.Read(); } private static void TFS(string localPath,string startId,string endId) { Uri tfsUri = new Uri("http://rnotfsat:8080/tfs"); string tfsPath = null; try { TfsConfigurationServer configurationServer = TfsConfigurationServerFactory.GetConfigurationServer(tfsUri); // Get the catalog of team project collections ReadOnlyCollection<CatalogNode> collectionNodes = configurationServer.CatalogNode.QueryChildren( new[] {CatalogResourceTypes.ProjectCollection}, false, CatalogQueryOptions.None); // List the team project collections foreach (CatalogNode collectionNode in collectionNodes) { // Use the InstanceId property to get the team project collection Guid collectionId = new Guid(collectionNode.Resource.Properties["InstanceId"]); TfsTeamProjectCollection teamProjectCollection = configurationServer.GetTeamProjectCollection(collectionId); if (!teamProjectCollection.Name.Equals(@"rnotfsat\rnotfsat")) continue; var vcs = teamProjectCollection.GetService<VersionControlServer>(); var workSpace = vcs.GetWorkspace(localPath); tfsPath = workSpace.GetServerItemForLocalItem(localPath); var changesetList = vcs.QueryHistory( tfsPath, VersionSpec.Latest, 0, RecursionType.Full, null, VersionSpec.ParseSingleSpec(startId, null), VersionSpec.ParseSingleSpec(endId, null), Int32.MaxValue, true, false).Cast<Changeset>(); foreach (var cs in changesetList) { changeSetDic.Add(cs.ChangesetId, 0); var changeList = cs.Changes; foreach (var change in changeList) { if (change.Item != null) { var localFile = workSpace.GetLocalItemForServerItem(change.Item.ServerItem); if (change.ChangeType.HasFlag(ChangeType.Edit)) { if (!changedFiles.Contains(localFile)) { changedFiles.Add(localFile); } editNumber++; } else if (change.ChangeType.HasFlag(ChangeType.Add)) { if (File.Exists(localFile)) { changeSetDic[cs.ChangesetId] += File.ReadLines(localFile).Count(); addNumber++; } } else if (change.ChangeType.HasFlag(ChangeType.Rename) || change.ChangeType.HasFlag(ChangeType.SourceRename)) { renameNumber++; } else if (change.ChangeType.HasFlag(ChangeType.Delete)) { delNumber++; } else { otherNumber++; } } } } } } catch (ChangesetNotFoundException) { Console.WriteLine("!! Please check the change set id inside your config file !!"); } catch (Exception e) { Console.WriteLine(e); } } private static void ScanFiles() { Console.WriteLine("In total {0} files will be scanned !", changedFiles.Count); Console.WriteLine(); Console.WriteLine(); int left = changedFiles.Count; foreach (var csFile in changedFiles) { GetContent(changeSetDic, csFile); Console.WriteLine(csFile + " is scanned and analyzed !"); left--; Console.WriteLine("{0} files left.", left); } } private static void GetContent(Dictionary<int, int>csDic, string filePath) { Process proc = new Process(); proc.StartInfo.FileName = "tfpt"; proc.StartInfo.UseShellExecute = false; proc.StartInfo.RedirectStandardOutput = true; proc.StartInfo.Arguments = " annotate \"" + filePath + "\" /noprompt"; proc.Start(); StringBuilder sb = new StringBuilder(); while (!proc.HasExited) { sb.Append(proc.StandardOutput.ReadToEnd()); } string allResult = sb.ToString(); String[] lines = allResult.Split(new [] {Environment.NewLine},Int32.MaxValue,StringSplitOptions.RemoveEmptyEntries); foreach (var line in lines) { var csIdInStr = line.Split(default(string[]), StringSplitOptions.RemoveEmptyEntries); int csId = Convert.ToInt32(csIdInStr[0]); if (csDic.ContainsKey(csId)) { csDic[csId]++; } } } private static void OutputHtmlFile(Dictionary<int, int> csDic) { string htmlSource = File.ReadAllText("HTMLTemplate.html"); int totalCount = 0; StringBuilder sb = new StringBuilder(); foreach (KeyValuePair<int, int> kv in csDic) { sb.Append("<tr><td>").Append(kv.Key).Append("</td><td>").Append(kv.Value).Append("</td></tr>"); totalCount += kv.Value; } htmlSource = Regex.Replace(htmlSource, "yukunContent", sb.ToString()); htmlSource = Regex.Replace(htmlSource, "yukunTotal", totalCount.ToString()); htmlSource = Regex.Replace(htmlSource, "AddNumber", addNumber.ToString()); htmlSource = Regex.Replace(htmlSource, "EditNumber", editNumber.ToString()); htmlSource = Regex.Replace(htmlSource, "DeleteNumber", delNumber.ToString()); htmlSource = Regex.Replace(htmlSource, "OtherNumber", otherNumber.ToString()); htmlSource = Regex.Replace(htmlSource, "RenameNumber", renameNumber.ToString()); File.WriteAllText(ConfigurationManager.AppSettings["OutputFilePath"], htmlSource); } }