public IEnumerable <GitCommitRef> ListCommitsForRepository() { VssConnection connection = this.Context.Connection; GitHttpClient gitClient = connection.GetClient <GitHttpClient>(); // Find a sample project to use for listing comments Guid projectId = ClientSampleHelpers.FindAnyProject(this.Context).Id; // Get first repo in the project Guid repoId = gitClient.GetRepositoriesAsync(projectId).Result[0].Id; // Get no more than 10 commits GitQueryCommitsCriteria criteria = new GitQueryCommitsCriteria() { Top = 10 }; List <GitCommitRef> commits = gitClient.GetCommitsAsync(repoId, criteria).Result; foreach (GitCommitRef commit in commits) { Console.WriteLine("{0} by {1} ({2})", commit.CommitId, commit.Committer.Email, commit.Comment); } return(commits); }
/// <summary> /// Gets commits for the repository and branch /// </summary> /// <param name="repositoryName"></param> /// <param name="branchName"></param> /// <param name="skip"></param> /// <param name="top"></param> /// <returns></returns> public IEnumerable <GitCommitRef> GetCommits( string repositoryName, string branchName, int?skip = null, int?top = null) { Logger.Trace("Entering"); var repositoryId = GetRepositoryId(repositoryName); var info = $"{nameof(repositoryName)}: {repositoryName}"; var searchCriteria = new GitQueryCommitsCriteria { ItemVersion = new GitVersionDescriptor { VersionType = GitVersionType.Branch, Version = branchName } }; var result = WaitAndRetryPolicyAsync.ExecuteAndCaptureAsync( _ => _client.Value.GetCommitsAsync(_vsTsTool.ProjectName, repositoryId, searchCriteria, skip, top), MakeContext(info)).Result; HandlePolicyResult(result, info); var output = result.Result; Logger.Trace("Exiting"); return(output); }
/// <summary> /// Gets a value indicating whether a branch with name <paramref name="branch"/> (like 'master', 'dev') contains the commit with specified <paramref name="commitId"/>. /// Just like the <code>git branch --contains</code> it doesn't take possible reversions into account. /// </summary> public static Boolean BranchContains(this GitHttpClient git, String project, String repositoryId, String branch, String commitId) { var commitToFind = git.TryGetCommit(project: project, repositoryId: repositoryId, commitId: commitId); if (commitToFind == null) { return(false); } var committedDate = commitToFind.Committer.Date; // TODO: It will usually be the same as the author's, but I have failed to check what date TFS actually uses in date queries. var criteria = new GitQueryCommitsCriteria { ItemVersion = new GitVersionDescriptor { Version = branch, VersionType = GitVersionType.Branch }, FromDate = DateToString(committedDate.AddSeconds(-1)), // Zero length interval seems to work, but just in case ToDate = DateToString(committedDate.AddSeconds(1)), }; var commitIds = git .GetAllCommits( project: project, repositoryId: repositoryId, searchCriteria: criteria) .Select(c => c.CommitId) .ToHashSet(StringComparer.InvariantCultureIgnoreCase); return(commitIds.Contains(commitId)); }
public override async Task <Tuple <string, List <Change> >[]> GetChangesetsAsync(ReleaseData data, string apiVersion = "5.1") { var baseurl = $"{Url}/{data.TfsProject}/_apis/git/repositories/{data.TfsProject}"; var itemUrl = $"{baseurl}/items?path=/&versionType=Branch&versionOptions=None&versionDescriptor.version={data.TfsBranch}"; var itemResponse = await Client.GetAsync <ItemsObject>(itemUrl, apiVersion); var treeUrl = $"{baseurl}/trees/{itemResponse.objectId}"; var treeResponse = await Client.GetAsync <Wrapper <ItemsObject> >(treeUrl, apiVersion); var query = new GitQueryCommitsCriteria { compareVersion = GitVersionFromCommit(data.ChangesetFrom), itemVersion = GitVersionFromCommit(data.ChangesetTo) }; var changesUrl = $"{baseurl}/commitsbatch"; var categoryChangesTasks = treeResponse.treeEntries.Where(x => x.gitObjectType == "tree").Select(async category => { var currentQuery = query.CloneJson(); currentQuery.itemPath = category.relativePath; var wrapper = await Client.PostAsync <Wrapper <ChangeAzure> >(changesUrl, currentQuery, apiVersion); var mappedData = wrapper.value.Select(x => new Change(x)).ToList(); return(new Tuple <string, List <Change> >(category.relativePath, mappedData)); }); var categoryChangesResponse = await Task.WhenAll(categoryChangesTasks); return(categoryChangesResponse); }
public static void CreatePullRequests(GitHttpClient client) { var criteria = new GitQueryCommitsCriteria { }; var commits = client.GetCommitsAsync(Config.PrepopulatedRepositoryProject, Config.PrepopulatedGitRepository, criteria, 0, 10000).Result; Console.WriteLine($"Retreived {commits.Count} commits"); var someCommits = commits.Skip(1).Take(1000); var branchNumber = 0; var branches = client.UpdateRefsAsync(someCommits.Select(c => new GitRefUpdate { Name = $"refs/heads/branch{branchNumber++}", RepositoryId = Config.PrepopulatedGitRepositoryGuid, OldObjectId = "0000000000000000000000000000000000000000", NewObjectId = c.CommitId }), Config.PrepopulatedGitRepositoryGuid).Result; Console.WriteLine($"Created {branches.Count} branches"); var firstBranch = branches.First(); var otherBranches = branches.Skip(1); foreach (var branch in otherBranches) { var pullRequest = client.CreatePullRequestAsync(new GitPullRequest { SourceRefName = branch.Name, TargetRefName = firstBranch.Name, Title = $"Merge {branch.Name} to {firstBranch.Name}" }, Config.PrepopulatedGitRepositoryGuid).Result; Console.WriteLine($"Created pullrequest {pullRequest.Title}"); } }
//Only Get Commit Count Stats public TFSWork(string url, string pat, bool commitOnly = true) { // Initialize connection to azure devops personalaccesstoken = pat; var networkCredential = new VssBasicCredential(string.Empty, pat); VssConnection connection = new VssConnection(new Uri(url), networkCredential); // Initialize ProjectHttpClient and GitHttpClient var projclient = connection.GetClient <ProjectHttpClient>(); GitHttpClient gitClient = connection.GetClient <GitHttpClient>(); // Get list of projects credentials have access to var projcollection = projclient.GetProjects().Result; foreach (var proj in projcollection) { // Get list of repos for a project List <GitRepository> repos = gitClient.GetRepositoriesAsync(proj.Id.ToString()).Result; // Set commits query criteria GitQueryCommitsCriteria criteria = new GitQueryCommitsCriteria() { // Add criterias in here, some examples: ToDate, FromDate, Top, FromCommitId }; foreach (GitRepository repo in repos) { // Get list of commits for a repo List <GitCommitRef> commits = gitClient.GetCommitsAsync(repo.Id, criteria).Result.OrderBy(x => x.Committer.Date).ToList(); for (int i = 0; i < commits.Count; i++) { // ASSUMPTION: i=0 is first commit and no code/files in this commit // TODO: update to handle all cases if (i != 0) { // Collect commit count var objc = userCommitStats.FirstOrDefault(x => x.email == commits[i].Committer.Email && x.projectName == proj.Name && x.repoName == repo.Name); if (objc != null) { objc.commitCount = objc.commitCount + 1; objc.lastCommitDate = objc.lastCommitDate > commits[i].Committer.Date ? objc.lastCommitDate : commits[i].Committer.Date; } else { UserCommitStat user = new UserCommitStat(); user.projectName = proj.Name; user.repoName = repo.Name; user.email = commits[i].Committer.Email; user.name = commits[i].Committer.Name; user.commitCount = user.commitCount + 1; user.lastCommitDate = user.lastCommitDate > commits[i].Committer.Date ? user.lastCommitDate : commits[i].Committer.Date; userCommitStats.Add(user); } } } } } }
public async Task <List <GitCommitRef> > GetLatestCommits(string projectName, string repositoryName, int commits) { GitRepository repo = await GetRepository(projectName, repositoryName); if (repo == null) { throw new ModuleRepositoryNotFoundException(); } GitQueryCommitsCriteria criteria = new GitQueryCommitsCriteria { Top = commits }; List <GitCommitRef> refs = await Git.GetCommitsAsync(repositoryId : repo.Id, searchCriteria : criteria); return(refs); }
/// <summary>Retrieve all(up to <see cref="Int32.MaxValue"/>) git (unless <paramref name="top"/> is set) commits for a project</summary> public static List <GitCommitRef> GetAllCommits( this GitHttpClient git, String project, String repositoryId, GitQueryCommitsCriteria searchCriteria, Int32?skip = null, Int32?top = (Int32.MaxValue - 1)) // Current API somehow fails (silently!) on Int32.MaxValue; { return(git .GetCommitsAsync( project: project, repositoryId: repositoryId, searchCriteria: searchCriteria, skip: skip, top: top) .GetAwaiter() .GetResult()); }
private async Task <IList <ComponentActivityInfo> > GetGitActivityAsync(ApplicationTask task, TfsTeamProjectCollection tfs, TeamProjectInfo teamProject, int numberOfActivities, IList <string> userExclusions, IList <string> commentExclusions) { var activities = new List <ComponentActivityInfo>(); var client = tfs.GetClient <GitHttpClient>(); var top = numberOfActivities; // Find all repos. var repos = await client.GetRepositoriesAsync(project : teamProject.Name); var criteria = new GitQueryCommitsCriteria { Top = top, IncludeLinks = false }; foreach (var repo in repos) { var skip = 0; while (activities.Count < numberOfActivities && !task.IsCanceled) { var commits = await client.GetCommitsAsync(repo.Id, criteria, skip : skip, top : top); foreach (var commit in commits) { if ((string.IsNullOrEmpty(commit.Comment) || !commentExclusions.Any(x => commit.Comment.IndexOf(x, StringComparison.OrdinalIgnoreCase) >= 0)) && !userExclusions.Any(x => commit.Author.Name.IndexOf(x, StringComparison.OrdinalIgnoreCase) >= 0 || commit.Committer.Name.IndexOf(x, StringComparison.OrdinalIgnoreCase) >= 0)) { var commentSuffix = string.IsNullOrEmpty(commit.Comment) ? null : ": " + commit.Comment.Trim(); var time = commit.Author.Date; var user = commit.Author.Name; var description = string.Format(CultureInfo.CurrentCulture, "Commit {0}{1}", commit.CommitId.Substring(0, 7), commentSuffix); activities.Add(new ComponentActivityInfo("Git", time, user, description)); } } if (commits.Count < top) { // There are no more pages. break; } else { skip += top; } } } return(activities); }
public async Task <List <GitCommitRef> > GetCommitsAsync(Guid repositoryId, string branchName, DateTime fromDate, DateTime toDate, int top = 100, int?skip = null) { GitQueryCommitsCriteria searchCriteria = new GitQueryCommitsCriteria { FromDate = fromDate.ToUniversalTime().ToString("o"), ToDate = toDate.ToUniversalTime().ToString("o"), ItemVersion = new GitVersionDescriptor { Version = branchName, VersionType = GitVersionType.Branch }, }; List <GitCommitRef> commitRefs = await RetryHelper.SleepAndRetry(this.retryAfter, this.logger, async() => { return(await this.GetCommitsAsync(repositoryId, searchCriteria, skip, top)); }); return(commitRefs); }
private object GetFirstReleaseBranchByCommit(Guid repoId, GitCommitRef lastCommit, List <GitRef> releaseBranches) { foreach (var releaseBranch in releaseBranches) { var newBranchVersionDescriptor = new GitVersionDescriptor() { VersionType = GitVersionType.Branch, Version = AzureGitHelper.WithoutRefsAndHeadsPrefix(releaseBranch.Name) }; var criteria = new GitQueryCommitsCriteria() { Ids = new List <string>() { lastCommit.CommitId }, Top = 1, ItemVersion = newBranchVersionDescriptor }; if (gitClient.GetCommitsAsync(repoId, criteria, top: 1).Result.Any()) { return(releaseBranch); } } return(null); }
static void Main(string[] args) { IServiceProvider services = ServiceProviderBuilder.GetServiceProvider(args); IOptions <APIKeys> options = services.GetRequiredService <IOptions <APIKeys> >(); asciiArtClass asciiArt = new asciiArtClass(); Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine("\n\n"); foreach (string line in asciiArt.azureArtArr) { Console.WriteLine(line); } //use the httpclient VssCredentials creds = new VssBasicCredential(string.Empty, options.Value.PAT); // Connect to Azure DevOps Services Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("\nConnecting..."); VssConnection connection = new VssConnection(new Uri(c_collectionUri + options.Value.OrgName), creds); ProjectHttpClient projClient = connection.GetClientAsync <ProjectHttpClient>().Result; IPagedList <TeamProjectReference> projects = projClient.GetProjects().Result; // Get a GitHttpClient to talk to the Git endpoints using (GitHttpClient gitClient = connection.GetClient <GitHttpClient>()) { foreach (TeamProjectReference p in projects) { Console.WriteLine("\n\nProject --- " + p.Name); List <GitRepository> repoList = gitClient.GetRepositoriesAsync(p.Name).Result; GitRepository masterRepo = repoList.Where(x => x.Name == "master" || x.Name == p.Name).FirstOrDefault(); Console.WriteLine("Repo Name --- " + masterRepo.Name); //set a filter to only return commits within the last 7 days GitQueryCommitsCriteria searches = new GitQueryCommitsCriteria(); searches.FromDate = DateTime.Now.AddDays(-7).ToShortDateString(); List <GitCommitRef> commits = gitClient.GetCommitsBatchAsync(searches, masterRepo.Id).Result; foreach (GitCommitRef cmt in commits) { Console.WriteLine("\n\nProject --- " + p.Name); Console.WriteLine("Repo Name --- " + masterRepo.Name); Console.WriteLine("\nCommit ID - #{0}\nBy - {1}\nEmail - {2}\nOn - {3}", cmt.CommitId, cmt.Author.Name, cmt.Author.Email, cmt.Author.Date.ToLongDateString(), cmt.Comment); GitCommitChanges changes = gitClient.GetChangesAsync(p.Name, cmt.CommitId, p.Name).Result; Console.WriteLine("Files:"); foreach (GitChange change in changes.Changes) { Console.WriteLine("{0}: {1}", change.ChangeType, change.Item.Path); } } } } Console.ForegroundColor = ConsoleColor.Blue; Console.WriteLine("\n\n"); foreach (string line in asciiArt.tieFArtArr) { Console.WriteLine(line); } }
static public void Git_GetCommitLinkedWorkItemFromTags(string tfsCollectionUrl, string personalAccessToken) { VssBasicCredential credentials = new VssBasicCredential(string.Empty, personalAccessToken); VssConnection connection = new VssConnection(new Uri(tfsCollectionUrl), credentials); WorkItemTrackingHttpClient workItemTrackingHttpClient = connection.GetClient <WorkItemTrackingHttpClient>(); string projectName = "tfvctest01"; string commitDiffRepo = "repo01"; string pullRequestDiffRepo = "repo02"; GitHttpClient gitHttpClient = connection.GetClient <GitHttpClient>(); ApiResourceLocation location = new ApiResourceLocation(); List <GitRepository> repoList = gitHttpClient.GetRepositoriesAsync(projectName).Result; foreach (GitRepository repo in repoList) { if (repo.Name == commitDiffRepo) { //场景1:在MASTER分支上使用两个TAG之间的COMMIT LIST获取相关工作项 // // https://stackoverflow.com/questions/5863426/get-commit-list-between-tags-in-git // 参考以上链接,先用 git logs --online TAG1...TAG2 命令获取到2个TAG之间的所有COMMIT ID,然后再用以下方式获取相关的WORK ITEM // 找不到一个可以用的REST API可以做到以上命令做的事情 // string baseline20181106 = "refs/tags/BASELINE-20181106-3"; string baseline000 = "refs/tags/BASELINE-000"; string baseline001 = "refs/tags/BASELINE-001"; string baseline002 = "refs/tags/BASELINE-002"; List <GitRef> tagRefs = gitHttpClient.GetTagRefsAsync(repo.Id).Result; GitAnnotatedTag annotedTagBaseline20181106 = gitHttpClient.GetAnnotatedTagAsync( projectName, repo.Id, (tagRefs.Find(x => x.Name == baseline20181106)).ObjectId ).Result; GitAnnotatedTag annotedTagBaseline000 = gitHttpClient.GetAnnotatedTagAsync( projectName, repo.Id, (tagRefs.Find(x => x.Name == baseline000)).ObjectId ).Result; GitAnnotatedTag annotedTagBaseline001 = gitHttpClient.GetAnnotatedTagAsync( projectName, repo.Id, (tagRefs.Find(x => x.Name == baseline001)).ObjectId ).Result; GitAnnotatedTag annotedTagBaseline002 = gitHttpClient.GetAnnotatedTagAsync( projectName, repo.Id, (tagRefs.Find(x => x.Name == baseline002)).ObjectId ).Result; // //Diff获取的结果是两个commit之间的差异文件列表,不是我们要的,我们需要的是2个commit之间的commit列表 // /* * GitBaseVersionDescriptor baseVersion = new GitBaseVersionDescriptor(); * baseVersion.Version = annotedTagBaseline000.TaggedObject.ObjectId; * baseVersion.VersionType = GitVersionType.Commit; * GitTargetVersionDescriptor targetVersion = new GitTargetVersionDescriptor(); * targetVersion.Version = annotedTagBaseline001.TaggedObject.ObjectId; * targetVersion.VersionType = GitVersionType.Commit; * GitCommitDiffs commitDiffsResult = gitHttpClient.GetCommitDiffsAsync(repo.Id, false, null, null, baseVersion, targetVersion).Result; */ GitCommit fromCommit = gitHttpClient.GetCommitAsync(annotedTagBaseline20181106.TaggedObject.ObjectId, repo.Id).Result; GitCommit toCommit = gitHttpClient.GetCommitAsync(annotedTagBaseline000.TaggedObject.ObjectId, repo.Id).Result; GitQueryCommitsCriteria criteria = new GitQueryCommitsCriteria() { IncludeLinks = true, IncludeWorkItems = true }; List <GitCommitRef> commits = gitHttpClient.GetCommitsAsync(repo.Id, criteria).Result; foreach (GitCommitRef commitRef in commits) { Console.WriteLine("Commit Id: " + commitRef.CommitId + "\t By: " + commitRef.Author.Name + " @ " + commitRef.Author.Date); foreach (ResourceRef workItemRef in commitRef.WorkItems) { WorkItem workItem = workItemTrackingHttpClient.GetWorkItemAsync(int.Parse(workItemRef.Id)).Result; Console.WriteLine("\t WorkItem Id: " + workItem.Id + "\t " + workItem.Fields["System.Title"]); } } Console.ReadLine(); } else if (repo.Name == pullRequestDiffRepo) { //场景2:通过两个TAG之间的PULL REQUEST获取相关的工作项 //string prBaseline001 = "refs/tags/PR-BASELINE-001"; string prBaseline001 = "refs/tags/PR-BASELINE-002"; List <GitRef> tagRefs = gitHttpClient.GetTagRefsAsync(repo.Id).Result; GitAnnotatedTag annotedTagPrBaseline001 = gitHttpClient.GetAnnotatedTagAsync( projectName, repo.Id, (tagRefs.Find(x => x.Name == prBaseline001)).ObjectId ).Result; Console.WriteLine("Tag: " + prBaseline001 + "\t -> Commit ID: " + annotedTagPrBaseline001.TaggedObject.ObjectId); GitPullRequestQuery prQuery = new GitPullRequestQuery() { QueryInputs = new List <GitPullRequestQueryInput>() }; GitPullRequestQueryInput prQueryInput = new GitPullRequestQueryInput() { Items = new List <string>() }; prQueryInput.Type = GitPullRequestQueryType.LastMergeCommit; prQueryInput.Items.Add(annotedTagPrBaseline001.TaggedObject.ObjectId); prQuery.QueryInputs.Add(prQueryInput); //GitPullRequestQueryType prQueryType = new GitPullRequestQueryType(); GitPullRequestQuery prQueryResult = gitHttpClient.GetPullRequestQueryAsync(prQuery, repo.Id).Result; IDictionary <string, List <GitPullRequest> > findPRDirectory = prQueryResult.Results[0]; GitPullRequest findPR = findPRDirectory[annotedTagPrBaseline001.TaggedObject.ObjectId].First <GitPullRequest>(); GitPullRequest prDetails = gitHttpClient.GetPullRequestAsync( repo.Id, findPR.PullRequestId, null, null, null, true, //includeCommit true, //includeWorkItemRefs null ).Result; Console.WriteLine("\t Linked PR " + prDetails.PullRequestId + ": " + prDetails.Title); Console.WriteLine("\t --> Related WorkItems "); foreach (ResourceRef workItemRef in prDetails.WorkItemRefs) { WorkItem workItem = workItemTrackingHttpClient.GetWorkItemAsync(int.Parse(workItemRef.Id)).Result; Console.WriteLine("\t\t WorkItem Id: " + workItem.Id + "\t " + workItem.Fields["System.Title"]); } Console.WriteLine("\t --> Related Commits "); foreach (GitCommitRef commitRef in prDetails.Commits) { Console.WriteLine("\t\t Commit Id: " + commitRef.CommitId + "\t By " + commitRef.Committer.Name + " @ " + commitRef.Committer.Date); } Console.WriteLine("\t --> Related Reviewers "); foreach (IdentityRefWithVote reviewerRef in prDetails.Reviewers) { Console.WriteLine("\t\t Reviewer: " + reviewerRef.DisplayName + "\t Vote Value: " + reviewerRef.Vote); } Console.ReadLine(); } } }
public TFSWork(string url, string pat) { // Initialize connection to azure devops personalaccesstoken = pat; var networkCredential = new VssBasicCredential(string.Empty, pat); VssConnection connection = new VssConnection(new Uri(url), networkCredential); // Initialize ProjectHttpClient and GitHttpClient var projclient = connection.GetClient <ProjectHttpClient>(); GitHttpClient gitClient = connection.GetClient <GitHttpClient>(); // Get list of projects credentials have access to var projcollection = projclient.GetProjects().Result; foreach (var proj in projcollection) { // Get list of repos for a project List <GitRepository> repos = gitClient.GetRepositoriesAsync(proj.Id.ToString()).Result; // Set commits query criteria GitQueryCommitsCriteria criteria = new GitQueryCommitsCriteria() { // Add criterias in here, some examples: ToDate, FromDate, Top, FromCommitId }; foreach (GitRepository repo in repos) { // Get list of commits for a repo List <GitCommitRef> commits = gitClient.GetCommitsAsync(repo.Id, criteria).Result.OrderBy(x => x.Committer.Date).ToList(); for (int i = 0; i < commits.Count; i++) { // ASSUMPTION: i=0 is first commit and no code/files in this commit // TODO: update to handle all cases if (i != 0) { // Collect commit count var objc = userStats.FirstOrDefault(x => x.email == commits[i].Committer.Email && x.projectName == proj.Name && x.repoName == repo.Name); if (objc != null) { objc.commitCount = objc.commitCount + 1; objc.lastCommitDate = objc.lastCommitDate > commits[i].Committer.Date ? objc.lastCommitDate : commits[i].Committer.Date; } else { UserStat user = new UserStat(); user.projectName = proj.Name; user.repoName = repo.Name; user.email = commits[i].Committer.Email; user.name = commits[i].Committer.Name; user.commitCount = user.commitCount + 1; user.lastCommitDate = user.lastCommitDate > commits[i].Committer.Date ? user.lastCommitDate : commits[i].Committer.Date; userStats.Add(user); } // Get list of changes for a commit GitCommitChanges changes = gitClient.GetChangesAsync(commits[i].CommitId, repo.Id).Result; foreach (var change in changes.Changes) { // Only will collect stats pertaining to *.cs files if (change.Item.Path.EndsWith(".cs")) { // Collect file stats var obj = userStats.FirstOrDefault(x => x.email == commits[i].Committer.Email && x.projectName == proj.Name && x.repoName == repo.Name); if (obj != null) { if (change.ChangeType == VersionControlChangeType.Add) { obj.filesAdded = obj.filesAdded + 1; } else if (change.ChangeType == VersionControlChangeType.Delete) { obj.filesDeleted = obj.filesDeleted + 1; } else if (change.ChangeType == VersionControlChangeType.Edit) { obj.filesModified = obj.filesModified + 1; } } else { UserStat user = new UserStat(); user.projectName = proj.Name; user.repoName = repo.Name; user.email = commits[i].Committer.Email; user.name = commits[i].Committer.Name; if (change.ChangeType == VersionControlChangeType.Add) { user.filesAdded = user.filesAdded + 1; } else if (change.ChangeType == VersionControlChangeType.Delete) { user.filesDeleted = user.filesDeleted + 1; } else if (change.ChangeType == VersionControlChangeType.Edit) { user.filesModified = user.filesModified + 1; } userStats.Add(user); } // Collect code stats ChurnFileStats(url, proj.Name, repo.Id.ToString(), repo.Name, change, pat, commits[i].CommitId, commits[i - 1].CommitId, commits[i].Committer.Email, commits[i].Committer.Name); } } } } } } }