Skip to content

Commit

Permalink
Merge pull request #933 from cobypritchard/fix-importing-git-commit-l…
Browse files Browse the repository at this point in the history
…inks

Fix importing git commit links
  • Loading branch information
Alexander-Hjelm authored Dec 22, 2023
2 parents d1b74af + 816864b commit 4400138
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 13 deletions.
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 @@ -12,6 +13,8 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using WorkItemImport;

namespace Migration.Wi_Import.Tests
Expand Down Expand Up @@ -124,6 +127,25 @@ public TeamProject GetProject(string projectId)
return tp;
}

public GitRepository GetRepository(string project, string repository)
{
GitRepository gr = new GitRepository();
Guid repoGuid;

// Create a new instance of the MD5CryptoServiceProvider object.
MD5 md5Hasher = MD5.Create();

// Convert the input string to a byte array and compute the hash.
byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(project));

// Create a new Guid using the hash value.
repoGuid = new Guid(md5Hasher.ComputeHash(Encoding.Default.GetBytes(project)));
gr.Id = repoGuid;
gr.Name = repository;

return gr;
}

public List<WorkItemRelationType> GetRelationTypes()
{
WorkItemRelationType hierarchyForward = new WorkItemRelationType
Expand Down

0 comments on commit 4400138

Please sign in to comment.