Hoehlenhund
Hoehlenhund

Reputation: 1

ADOS .NET: Exchange SOAP Methode to REST equivalent

I'm currently exchanging SOAP Code to REST (6.0) Code of an ADOS OnPremise Application.

private void SetIntegratedStatusForBranch(ChangesetModel changeset, Branch changesetBranch, List<Branch> allBranches)
{
    VersionControlServer sourceControl = (VersionControlServer)_tfs.GetService(typeof(VersionControlServer));
    ItemIdentifier[] everyBranch = allBranches.Select(b => new ItemIdentifier(GetMainBranchOfTfsPath(b).TfsPath)).ToArray();
 
    var merges = sourceControl.TrackMerges(
            new int[] { changeset.Id },
            new ItemIdentifier(changesetBranch.TfsPath),
            everyBranch,
            null);

    Branch mainBranch = GetMainBranch(changesetBranch);

    IntegrationModel integrationModel = new IntegrationModel();

    if (changesetBranch.TfsPath.Contains("dev-main") && !merges.Any(m => m.TargetItem.Item == mainBranch.TfsPath))
    {
        integrationModel.IntegrationState = IntegratedState.NotIntegrated;
        integrationModel.IntegrationDate = DateTime.MinValue;
        integrationModel.IntegrationChangesetId = -1;
        changeset.AddIntegratedBranch(mainBranch, integrationModel);
    }
    if (mainBranch.TfsPath == changesetBranch.TfsPath)
    {
        integrationModel.IntegrationState = IntegratedState.Integrated;
        integrationModel.IntegrationDate = changeset.CreationDate;
        integrationModel.IntegrationChangesetId = changeset.Id;
        changeset.AddIntegratedBranch(mainBranch, integrationModel);
    }
    else if (changesetBranch.TfsPath.Contains("dlv"))
    {
        integrationModel.IntegrationState = IntegratedState.Integrated;
        integrationModel.IntegrationDate = changeset.CreationDate;
        integrationModel.IntegrationChangesetId = changeset.Id;
        changeset.AddIntegratedBranch(changesetBranch, integrationModel);
    }

    foreach (var merge in merges)
    {
        IntegrationModel integration = new IntegrationModel
        {
            IntegrationState = IntegratedState.Integrated,

            IntegrationDate = merge.TargetChangeset.CreationDate,
            IntegrationChangesetId = merge.TargetChangeset.ChangesetId
        };
        Branch branch = allBranches.FirstOrDefault(x => (!merge.TargetItem.Item.Contains("dlv") && merge.TargetItem.Item.Contains(x.TfsPath)) || x.TfsPath == merge.TargetItem.Item);

        changeset.AddIntegratedBranch(branch, integration);

    }
}

I just can't find a solution to refactor the code above. Has anyone any ideas how I could solve my issue?

In the Background we're using VS2022 and the pipeline is set, if a commit runs without errors through the pipeline it will be automatically merged (with same exceptions but those are not relevant).

I've already tried to get the merges with trying out following .NET Rest approaches:

with using snippets from: https://github.com/microsoft/azure-devops-dotnet-samples/tree/main.

I'm mainly using:

VssConnection _connection;
_connection = new VssConnection(new Uri("https://" + Settings.Default.TfsServerUri), new VssClientCredentials());

GitHttpClient gitClient = _connection.GetClient<GitHttpClient>();
etc...

I was expecting to create a workaround which basically exchanges mainly this part of the code:

    var merges = sourceControl.TrackMerges(
            new int[] { changeset.Id },
            new ItemIdentifier(changesetBranch.TfsPath),
            everyBranch,
            null);

Upvotes: 0

Views: 84

Answers (2)

Hoehlenhund
Hoehlenhund

Reputation: 1

So, Miao Tian was on the right Track. There are two approaches:

I. Use the REST API:

  1. Create a PAT
  2. Get all changesets from the Project
  3. Check if your changesetID is used in the merge of the changeset from the project (basically iterate through all changesets of the project)

to 2:

        string apiUrl = $"https://{Settings.Default.TfsServerUri}/_apis/tfvc/changesets/{responseChangesetId}/changes?api-version=6.0";
        HttpResponseMessage response = HttpHelper.Client.GetAsync(apiUrl).GetAwaiter().GetResult();

        if (!response.IsSuccessStatusCode)
        {
            return (false, $"Failed to retrieve changeset changes: {response.StatusCode}", "");
        }

        string responseBody = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
        var changesResponse = JsonConvert.DeserializeObject<ChangesetChangesResponse>(responseBody);

        foreach (var changesResponseItem in changesResponse.Value)
        { 
if ((changesResponseItem.ChangeType.Contains("merge") || 
changesResponseItem.ChangeType.Contains("rollback")) && ...

to 1:

     DateTime updatedToDateTime = toDateTime.AddDays(7);

     string baseApiUrl = $"https://{Settings.Default.TfsServerUri}/{Settings.Default.ProjectName}/_apis/tfvc/changesets";
        TfvcChangesetSearchCriteria searchCriteria = new TfvcChangesetSearchCriteria()
        {
            FromDate = fromDate.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"),
            ToDate = updatedToDateTime.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"),
            ItemPath = "$/ProjectName"
        };

        string apiUrl = $"{baseApiUrl}?api-version=6.0";
        apiUrl += $"&fromDate={searchCriteria.FromDate}&toDate={searchCriteria.ToDate}&itemPath={searchCriteria.ItemPath}";

        int skip = 0;
        const int top = 100;

        while (true)
        {
            string pagedUrl = $"{apiUrl}&$top={top}&$skip={skip}";
            HttpResponseMessage response = HttpHelper.Client.GetAsync(pagedUrl).GetAwaiter().GetResult();
            if (!response.IsSuccessStatusCode)
            {
                Console.WriteLine($"Failed to retrieve changesets: {response.StatusCode}");
                break;
            }

            string responseBody = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
            var changesetResponse = JsonConvert.DeserializeObject<ChangesetResponse>(responseBody);

etc. You need to iterate through all pages (pagination) because ADOS only gives 100 entries at the time.

II. Use .NET

The second approach would be using .NET. Basically the same approach but without the need of the PAT. I had though the issue that .NET performance was worse and the checking for the merges took longer. More information on this: https://github.com/microsoft/azure-devops-dotnet-samples/blob/main/ClientLibrary/Samples/Tfvc/ChangesetChangesSample.cs

P.S. It is better to use a synchronous method. I had the issue that values where looked after couple of times unnecessarily.

Upvotes: 0

Miao Tian-MSFT
Miao Tian-MSFT

Reputation: 5642

I checked the document of Microsoft.TeamFoundation.SourceControl.WebApi but seems no direct one-to-one mapping for the TrackMerges method.

This is TfvcMergeSource. You can explore the available methods to achieve similar functionality.

Upvotes: 0

Related Questions