Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix importing git commit links #936

Merged
merged 7 commits into from
Dec 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.TeamFoundation.Core.WebApi;
using Microsoft.TeamFoundation.SourceControl.WebApi;
using Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models;
using Microsoft.VisualStudio.Services.WebApi.Patch.Json;
using Migration.WIContract;
Expand All @@ -13,6 +14,7 @@ public interface IWitClientWrapper
WorkItem GetWorkItem(int wiId);
WorkItem UpdateWorkItem(JsonPatchDocument patchDocument, int workItemId);
TeamProject GetProject(string projectId);
GitRepository GetRepository(string project, string repository);
List<WorkItemRelationType> GetRelationTypes();
AttachmentReference CreateAttachment(WiAttachment attachment);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,21 @@ public static JsonPatchOperation CreateJsonFieldPatchOp(Operation op, string key
};
}

public static JsonPatchOperation CreateJsonArtifactLinkPatchOp(Operation op, string project, string repository, string commitId)
public static JsonPatchOperation CreateJsonArtifactLinkPatchOp(Operation op, string projectId, string repositoryId, string commitId)
{
if (string.IsNullOrEmpty(commitId))
{
throw new ArgumentException(nameof(commitId));
}

if (string.IsNullOrEmpty(project))
if (string.IsNullOrEmpty(projectId))
{
throw new ArgumentException(nameof(project));
throw new ArgumentException(nameof(projectId));
}

if (string.IsNullOrEmpty(repository))
if (string.IsNullOrEmpty(repositoryId))
{
throw new ArgumentException(nameof(repository));
throw new ArgumentException(nameof(repositoryId));
}

return new JsonPatchOperation()
Expand All @@ -57,7 +57,7 @@ public static JsonPatchOperation CreateJsonArtifactLinkPatchOp(Operation op, str
Value = new PatchOperationValue
{
Rel = "ArtifactLink",
Url = $"vstfs:///Git/Commit/{project}/{repository}/{commitId}",
Url = $"vstfs:///Git/Commit/{projectId}%2F{repositoryId}%2F{commitId}",
Attributes = new Attributes
{
Name = "Fixed in Commit"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -682,9 +682,12 @@ public void SaveWorkItemArtifacts(WiRevision rev, WorkItem wi, Settings settings
return;
}

Guid projectId = _witClientWrapper.GetProject(settings.Project).Id;
Guid repositoryId = _witClientWrapper.GetRepository(settings.Project, rev.Commit.Repository).Id;

var patchDocument = new JsonPatchDocument
{
JsonPatchDocUtils.CreateJsonArtifactLinkPatchOp(Operation.Add, settings.Project, rev.Commit.Repository, rev.Commit.Id),
JsonPatchDocUtils.CreateJsonArtifactLinkPatchOp(Operation.Add, projectId.ToString(), repositoryId.ToString(), rev.Commit.Id),
JsonPatchDocUtils.CreateJsonFieldPatchOp(Operation.Add, WiFieldReference.ChangedDate, rev.Time),
JsonPatchDocUtils.CreateJsonFieldPatchOp(Operation.Add, WiFieldReference.ChangedBy, rev.Author)
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.TeamFoundation.Core.WebApi;
using Microsoft.TeamFoundation.SourceControl.WebApi;
using Microsoft.TeamFoundation.WorkItemTracking.WebApi;
using Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models;
using Microsoft.VisualStudio.Services.Common;
Expand All @@ -8,6 +9,7 @@
using Migration.Common.Log;
using Migration.WIContract;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Threading;
Expand All @@ -17,10 +19,15 @@ namespace WorkItemImport
{
public class WitClientWrapper : IWitClientWrapper
{
// Cache fields
private ConcurrentDictionary<string, TeamProject> _projectCache = new ConcurrentDictionary<string, TeamProject>();
private ConcurrentDictionary<string, GitRepository> _repositoryCache = new ConcurrentDictionary<string, GitRepository>();

private WorkItemTrackingHttpClient WitClient { get; }
private ProjectHttpClient ProjectClient { get; }
private VssConnection Connection { get; }
private TeamProjectReference TeamProject { get; }
private GitHttpClient GitClient { get; }

public WitClientWrapper(string collectionUri, string project, string personalAccessToken)
{
Expand All @@ -29,6 +36,7 @@ public WitClientWrapper(string collectionUri, string project, string personalAcc
WitClient = Connection.GetClient<WorkItemTrackingHttpClient>();
ProjectClient = Connection.GetClient<ProjectHttpClient>();
TeamProject = ProjectClient.GetProject(project).Result;
GitClient = Connection.GetClient<GitHttpClient>();
}

public WorkItem CreateWorkItem(string wiType, DateTime? createdDate = null, string createdBy = "")
Expand Down Expand Up @@ -101,7 +109,32 @@ public WorkItem UpdateWorkItem(JsonPatchDocument patchDocument, int workItemId)

public TeamProject GetProject(string projectId)
{
return ProjectClient.GetProject(projectId).Result;
// Check cache first
if (_projectCache.TryGetValue(projectId, out var cachedProject))
{
return cachedProject;
}

// If not in cache, fetch and store in cache
var project = ProjectClient.GetProject(projectId).Result;
_projectCache[projectId] = project;
return project;
}

public GitRepository GetRepository(string project, string repository)
{
string cacheKey = $"{project}-{repository}";

// Check cache first
if (_repositoryCache.TryGetValue(cacheKey, out var cachedRepository))
{
return cachedRepository;
}

// If not in cache, fetch and store in cache
var repo = GitClient.GetRepositoryAsync(project, repository).Result;
_repositoryCache[cacheKey] = repo;
return repo;
}

public List<WorkItemRelationType> GetRelationTypes()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,18 @@ public void When_calling_create_json_field_patch_op_Then_a_correct_op_is_returne
[Test]
public void When_calling_create_json_artifact_link_field_patch_op_Then_a_correct_op_is_returned()
{
string project = "project";
string repository = "repository";
string commitId = "commitId";
JsonPatchOperation jsonPatchOp = JsonPatchDocUtils.CreateJsonArtifactLinkPatchOp(Operation.Add, project, repository, commitId);
string projectId = Guid.NewGuid().ToString();
string repositoryId = Guid.NewGuid().ToString();
string commitId = Guid.NewGuid().ToString();
JsonPatchOperation jsonPatchOp = JsonPatchDocUtils.CreateJsonArtifactLinkPatchOp(Operation.Add, projectId, repositoryId, commitId);
PatchOperationValue artifactLink = jsonPatchOp.Value as PatchOperationValue;

Assert.Multiple(() =>
{
Assert.AreEqual(Operation.Add, jsonPatchOp.Operation);
Assert.AreEqual("/relations/-", jsonPatchOp.Path);
Assert.AreEqual("ArtifactLink", artifactLink.Rel);
Assert.AreEqual($"vstfs:///Git/Commit/{project}/{repository}/{commitId}", artifactLink.Url);
Assert.AreEqual($"vstfs:///Git/Commit/{projectId}%2F{repositoryId}%2F{commitId}", artifactLink.Url);
});
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using AutoFixture;
using AutoFixture.AutoNSubstitute;
using Microsoft.TeamFoundation.Core.WebApi;
using Microsoft.TeamFoundation.SourceControl.WebApi;
using Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models;
using Microsoft.VisualStudio.Services.WebApi;
using Microsoft.VisualStudio.Services.WebApi.Patch;
Expand All @@ -23,6 +24,8 @@ public class WitClientUtilsTests
private class MockedWitClientWrapper : IWitClientWrapper
{
private int _wiIdCounter = 1;
public Guid projectId = Guid.NewGuid();
public Guid repositoryId = Guid.NewGuid();
public Dictionary<int, WorkItem> _wiCache = new Dictionary<int, WorkItem>();

public MockedWitClientWrapper()
Expand Down Expand Up @@ -118,12 +121,21 @@ public TeamProject GetProject(string projectId)
}
else
{
tp.Id = Guid.NewGuid();
tp.Id = this.projectId;
tp.Name = projectId;
}
return tp;
}

public GitRepository GetRepository(string project, string repository)
{
GitRepository gr = new GitRepository();
gr.Id = repositoryId;
gr.Name = repository;

return gr;
}

public List<WorkItemRelationType> GetRelationTypes()
{
WorkItemRelationType hierarchyForward = new WorkItemRelationType
Expand Down Expand Up @@ -1105,7 +1117,8 @@ public void When_calling_save_workitem_artifacts_with_populated_workitem_Then_wo
Assert.Multiple(() =>
{
Assert.That(updatedWI.Relations.First().Rel, Is.EqualTo("ArtifactLink"));
Assert.That(updatedWI.Relations.First().Url, Is.EqualTo("vstfs:///Git/Commit/project/repository/1234567890"));
Assert.That(updatedWI.Relations.First().Url, Is.EqualTo($"vstfs:///Git/Commit/" +
$"{witClientWrapper.projectId}%2F{witClientWrapper.repositoryId}%2F{revision.Commit.Id}"));
});
}

Expand Down
Loading