Version control 如何查找TFS 2015版本控制期间更改频率最高的前10个文件?
我的团队使用TFS 2015作为ALM和版本控制系统,我想分析哪些文件更改最频繁 我发现TFS没有现成的功能,但TFS2015有一个REST API来查询文件的更改集,如下所示:Version control 如何查找TFS 2015版本控制期间更改频率最高的前10个文件?,version-control,tfs-2015,Version Control,Tfs 2015,我的团队使用TFS 2015作为ALM和版本控制系统,我想分析哪些文件更改最频繁 我发现TFS没有现成的功能,但TFS2015有一个REST API来查询文件的更改集,如下所示: http://{instance}/tfs/DefaultCollection/_apis/tfvc/changesets?searchCriteria.itemPath={filePath}&api-version=1.0 我的项目存储库中有数千个文件,逐个查询不是一个好主意,这个问题有没有更好的解决方案?
http://{instance}/tfs/DefaultCollection/_apis/tfvc/changesets?searchCriteria.itemPath={filePath}&api-version=1.0
我的项目存储库中有数千个文件,逐个查询不是一个好主意,这个问题有没有更好的解决方案?我认为没有现成的解决方案来解决您的问题,我尝试了两种不同的方法来解决您的问题,我最初关注的是
restapi
,但后来切换到soapapi
,看看它支持哪些功能
在下面的所有选项中,以下api应该足够了:
安装客户端API
在所有选项中,需要以下扩展方法
限制条件为:仅扫描源中的特定路径
控制,因为源代码管理中的某些系统比较旧,可能只是出于历史目的
使用Microsoft.TeamFoundation.Client;
使用Microsoft.TeamFoundation.VersionControl.Client;
使用制度;
使用System.Collections.Generic;
使用System.Linq;
Net系统;
public void getTopChangedFilesOAPAPI()
{
变量tfsUrl=”https:///tfs/";
var域=”;
var password=“”;
var userName=“”;
//只对特定系统感兴趣,因此只扫描这些系统
var directoriesToScan=新列表{
“$/projectdir/subdir/subdir/subdir/subdirA/systemnameA”,
“$/projectdir/subdir/subdir/subdir/subdir/systemnameB”,
“$/projectdir/subdir/subdir/subdir/subdirC/systemnameC”,
“$/projectdir/subdir/subdir/subdir/subdir/systemnameD”
};
var maxResultsPerPath=10;
var fromDate=DateTime.Now.AddDays(-120);
var toDate=DateTime.Now;
var fileExtensionToInclude=新列表{.cs',.js};
var extensionExclusions=新列表{.csproj“,.json“,.css”};
var fileExclusions=新列表{“AssemblyInfo.cs”、“jquery-1.12.3.min.js”、“config.js”};
var pathExclutions=新列表{
“/subdirToForceExclude1/”,
“/subdirToForceExclude2/”,
“/subdirToForceExclude3/”,
};
使用(var collection=new-tfstreamprojectcollection)(新Uri(tfsUrl),
新网络凭据(用户名:用户名,密码:密码,域:域)))
{
集合。确保重新验证();
var tfvc=collection.GetService(typeof(VersionControlServer))作为VersionControlServer;
foreach(directoriesToScan中的var rootDirectory)
{
//获取变更集
//注意:maxcount设置为maxvalue,因为下面的linq查询将对服务器的影响降至最低
var changeSets=tfvc.QueryHistory(路径:rootDirectory,版本:VersionSpec.Latest,
删除ID:0,递归:RecursionType.Full,用户:null,
versionFrom:new DateVersionSpec(fromDate),VersionOn:new DateVersionSpec(toDate),
maxCount:int.MaxValue,includeChanges:true,
includeDownloadInfo:false,slotMode:true)
如同数不清的;
//筛选变更集中包含的变更
var changes=changeSets.SelectMany(a=>a.changes)
.Where(a=>a.ChangeType!=ChangeType.Lock | | a.ChangeType!=ChangeType.Delete | | a.ChangeType!=ChangeType.Property)
.Where(e=>!e.Item.ServerItem.ContainsAny(路径排除))
.Where(e=>!e.Item.ServerItem.Substring(e.Item.ServerItem.LastIndexOf('/')+1).ContainsAny(文件排除))
.Where(e=>!e.Item.ServerItem.Substring(e.Item.ServerItem.LastIndexOf('.')).ContainsAny(extensionExclusions))
.Where(e=>e.Item.ServerItem.Substring(e.Item.ServerItem.LastIndexOf('.')).ContainsAny(fileExtensionToInclude))
.GroupBy(g=>g.Item.ServerItem)
.Select(d=>new{File=d.Key,Count=d.Count()})
.OrderByDescending(o=>o.Count)
.Take(maxResultsPerPath);
//为控制台的每个路径写入顶部项目
Console.WriteLine(rootDirectory);Console.WriteLine(“->”);
foreach(变化中的var变化)
{
WriteLine(“changecont:{0}:文件:{1}”,change.Count,change.File);
}
Console.WriteLine(Environment.NewLine);
}
}
}
选项2A:REST API (!!OP发现的问题导致在api的v.xxx-14.95.4中发现严重缺陷)选项2B是解决方法 在api的v.xxx至14.95.4中发现的缺陷:TfvcChangesetSearchCriteria类型包含一个
ItemPath
属性
它应该将搜索限制到指定的目录。这个
此属性的默认值为$/
,使用时很遗憾
GetChangesetsAsync
将始终使用tfvc
源存储库的根路径,而不考虑值集
也就是说,如果要修复缺陷,这仍然是一种合理的方法
限制对scm系统影响的一种方法是
Install-Package Microsoft.TeamFoundationServer.ExtendedClient -Version 14.89.0 or later
public static class StringExtensions
{
public static bool ContainsAny(this string source, List<string> lookFor)
{
if (!string.IsNullOrEmpty(source) && lookFor.Count > 0)
{
return lookFor.Any(source.Contains);
}
return false;
}
}
Install-Package Microsoft.TeamFoundationServer.ExtendedClient -Version 14.95.2
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Microsoft.TeamFoundation.SourceControl.WebApi;
using Microsoft.VisualStudio.Services.Client;
using Microsoft.VisualStudio.Services.Common;
using System.Text;
using System.IO;
using Newtonsoft.Json;