Пример #1
0
        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);
        }
Пример #2
0
        /// <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);
        }
Пример #3
0
    /// <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);
        }
Пример #5
0
        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}");
            }
        }
Пример #6
0
        //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);
                            }
                        }
                    }
                }
            }
        }
Пример #7
0
        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);
        }
Пример #8
0
 /// <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());
 }
Пример #9
0
        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);
        }
Пример #11
0
        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);
        }
Пример #12
0
        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);
            }
        }
Пример #13
0
        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();
                }
            }
        }
Пример #14
0
        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);
                                }
                            }
                        }
                    }
                }
            }
        }