Skip to content

Commit

Permalink
Merge pull request #5 from cdonke/feat/azuredevops-maven
Browse files Browse the repository at this point in the history
Adding Azure DevOps Maven Support
  • Loading branch information
Redth committed Jun 3, 2021
2 parents b5e3d7a + 4be6c12 commit e6d7b15
Show file tree
Hide file tree
Showing 4 changed files with 226 additions and 81 deletions.
105 changes: 105 additions & 0 deletions MavenNet/AzureDevOpsRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
using MavenNet.Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Linq;

namespace MavenNet
{
public class AzureDevOpsRepository: MavenRepository
{
private readonly HttpClient _http;
private readonly string _apiVersion= "api-version=6.0-preview.1";
private readonly string _protocolType = "protocolType=maven";
private readonly string _includeAllVersions = "includeAllVersions=true";
private readonly Uri _pkgsUri;

public AzureDevOpsRepository(string url)
{
_http = new HttpClient();
BaseUri = new Uri(url);
}
public AzureDevOpsRepository(string organization, string feed, string personalAccessToken)
: this($"https://feeds.dev.azure.com/{organization}/_apis/packaging/Feeds/{feed}")
{
_pkgsUri = new Uri($"https://{organization}.pkgs.visualstudio.com/_apis/packaging/Feeds/{feed}");
if (!string.IsNullOrWhiteSpace(personalAccessToken))
{
_http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
Convert.ToBase64String(
Encoding.ASCII.GetBytes(
string.Format("{0}:{1}", "", personalAccessToken?? string.Empty))));
}
}

public Uri BaseUri { get; private set; }

protected override char PathSeparator => '/';

protected override string CombinePaths(params string[] parts)
=> throw new NotImplementedException();

protected override async Task<IEnumerable<Artifact>> GetArtifactsAsync(string groupId)
{
var artifacts = new List<Artifact>();

var uriBuilder = new UriBuilder(BaseUri);
uriBuilder.Path += "/packages";
uriBuilder.Query += $"{_apiVersion}&{_protocolType}&{_includeAllVersions}&packageNameQuery={groupId}";

var result = await _http.GetStringAsync(uriBuilder.Uri);
var packages = JsonConvert.DeserializeObject<Models.DevOps.Packages>(result);

foreach (var package in packages.value)
{
if (!package.groupId.Equals(groupId, StringComparison.OrdinalIgnoreCase))
continue;

artifacts.Add(new Artifact(
package.artifactId,
package.groupId,
package.versions.Select(q => q.version).ToArray()
)
);
}

return artifacts;
}

public override Task<Stream> OpenArtifactPomFile(string groupId, string artifactId, string version)
{
var path = $"/maven/{groupId}/{artifactId}/{version}/{artifactId}-{version}.pom/content";
return OpenFileAsync(path);
}

public override Task<Stream> OpenArtifactLibraryFile(string groupId, string artifactId, string version, string packaging = "jar")
{
var path = $"/maven/{groupId}/{artifactId}/{version}/{artifactId}-{version}.{packaging}/content";
return OpenFileAsync(path);
}
public override Task<Stream> OpenArtifactSourcesFile(string groupId, string artifactId, string version, string sourcesPostfix = "sources", string sourcesExtension = "jar")
{
var path = $"/maven/{groupId}/{artifactId}/{version}/{artifactId}-{version}-{sourcesPostfix}.{sourcesExtension}/content";
return OpenFileAsync(path);
}

protected override Task<IEnumerable<string>> GetGroupIdsAsync()
{
throw new NotImplementedException();
}

protected override Task<Stream> OpenFileAsync(string path)
{
var uriBuilder = new UriBuilder(_pkgsUri);
uriBuilder.Path += path;

return _http.GetStreamAsync(uriBuilder.Uri);
}
}
}
4 changes: 4 additions & 0 deletions MavenNet/MavenNet.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
<Authors>Redth</Authors>
<Owners>Redth</Owners>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|netstandard2.0|AnyCPU'">
<NoWarn>1701;1702;1591</NoWarn>
</PropertyGroup>

<ItemGroup>
<Compile Remove="Properties\AssemblyInfo.cs" />
Expand Down
168 changes: 87 additions & 81 deletions MavenNet/MavenRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,64 +7,70 @@

namespace MavenNet
{
public abstract class MavenRepository : IMavenRepository
{
public static GoogleMavenRepository FromGoogle()
{
return new GoogleMavenRepository();
}
public abstract class MavenRepository : IMavenRepository
{
public static GoogleMavenRepository FromGoogle()
{
return new GoogleMavenRepository();
}

public static MavenCentralRepository FromMavenCentral()
{
return new MavenCentralRepository();
}

public static FileBasedMavenRepository FromUrl(string url)
{
return new UrlMavenRepository(url);
}
public static FileBasedMavenRepository FromUrl(string url)
{
return new UrlMavenRepository(url);
}
public static AzureDevOpsRepository FromAzureDevOps(string organization, string feed, string PAT)
{
return new AzureDevOpsRepository(organization, feed, PAT);
}

public static FileBasedMavenRepository FromDirectory(string directoryPath)
{
return new DirectoryMavenRepository(directoryPath);
}
public static FileBasedMavenRepository FromDirectory(string directoryPath)
{
return new DirectoryMavenRepository(directoryPath);
}

public IList<Group> Groups { get; private set; } = new List<Group>();
public IList<Group> Groups { get; private set; } = new List<Group>();


protected abstract char PathSeparator { get; }
protected abstract char PathSeparator { get; }

protected abstract Task<Stream> OpenFileAsync(string path);
protected abstract Task<IEnumerable<string>> GetGroupIdsAsync();
protected abstract Task<IEnumerable<Artifact>> GetArtifactsAsync(string groupId);
protected abstract string CombinePaths(params string[] parts);
protected abstract Task<Stream> OpenFileAsync(string path);
protected abstract Task<IEnumerable<string>> GetGroupIdsAsync();
protected abstract Task<IEnumerable<Artifact>> GetArtifactsAsync(string groupId);
protected abstract string CombinePaths(params string[] parts);

public virtual async Task Refresh()
{
var groupIds = await GetGroupIdsAsync().ConfigureAwait(false);

await Refresh(groupIds.ToArray());
}
public virtual async Task Refresh()
{
var groupIds = await GetGroupIdsAsync().ConfigureAwait(false);

public virtual async Task Refresh (params string[] groupIds)
{
Groups.Clear();
await Refresh(groupIds.ToArray());
}

public virtual async Task Refresh(params string[] groupIds)
{
Groups.Clear();

foreach (var groupId in groupIds) {
foreach (var groupId in groupIds)
{

var g = new Group(groupId);
var g = new Group(groupId);

var artifacts = await GetArtifactsAsync(groupId).ConfigureAwait(false);
var artifacts = await GetArtifactsAsync(groupId).ConfigureAwait(false);

// Set a reference to this repository implementation
foreach (var a in artifacts) {
a.Repository = this;
g.Artifacts.Add(a);
}

Groups.Add(g);
}
}
// Set a reference to this repository implementation
foreach (var a in artifacts)
{
a.Repository = this;
g.Artifacts.Add(a);
}

Groups.Add(g);
}
}

public virtual Task Refresh(params Group[] groups)
{
Expand All @@ -81,62 +87,62 @@ public virtual Task Refresh(params Group[] groups)
return Task.CompletedTask;
}

public Task<Stream> OpenArtifactPomFile (string groupId, string artifactId, string version)
{
var path = CombinePaths(CombinePaths(groupId.Split('.')), artifactId, version, artifactId + "-" + version + ".pom");
public virtual Task<Stream> OpenArtifactPomFile(string groupId, string artifactId, string version)
{
var path = CombinePaths(CombinePaths(groupId.Split('.')), artifactId, version, artifactId + "-" + version + ".pom");

return OpenFileAsync(path);
}
return OpenFileAsync(path);
}

public Task<Stream> OpenArtifactLibraryFile(string groupId, string artifactId, string version, string packaging = "jar")
{
var path = CombinePaths(CombinePaths(groupId.Split('.')), artifactId, version, artifactId + "-" + version + "." + packaging.ToLowerInvariant().TrimStart('.'));
public virtual Task<Stream> OpenArtifactLibraryFile(string groupId, string artifactId, string version, string packaging = "jar")
{
var path = CombinePaths(CombinePaths(groupId.Split('.')), artifactId, version, artifactId + "-" + version + "." + packaging.ToLowerInvariant().TrimStart('.'));

return OpenFileAsync(path);
}
return OpenFileAsync(path);
}

public Task<Stream> OpenArtifactSourcesFile(string groupId, string artifactId, string version, string sourcesPostfix = "sources", string sourcesExtension = "jar")
public virtual Task<Stream> OpenArtifactSourcesFile(string groupId, string artifactId, string version, string sourcesPostfix = "sources", string sourcesExtension = "jar")
{
var path = CombinePaths(CombinePaths(groupId.Split('.')), artifactId, version, artifactId + "-" + version + $"-{sourcesPostfix}.{sourcesExtension.TrimStart('.')}");

return OpenFileAsync(path);
}

public Task<Stream> OpenArtifactDocsFile(string groupId, string artifactId, string version, string sourcesPostfix = "javadoc", string sourcesExtension = "jar")
{
var path = CombinePaths(CombinePaths(groupId.Split('.')), artifactId, version, artifactId + "-" + version + $"-{sourcesPostfix}.{sourcesExtension.TrimStart('.')}");
public Task<Stream> OpenMavenMetadataFile(string groupId, string artifactId)
{
var path = CombinePaths(CombinePaths(groupId.Split('.')), artifactId, "maven-metadata.xml");

return OpenFileAsync(path);
}

return OpenFileAsync(path);
}
public Task<Stream> OpenArtifactDocsFile(string groupId, string artifactId, string version, string sourcesPostfix = "javadoc", string sourcesExtension = "jar")
{
var path = CombinePaths(CombinePaths(groupId.Split('.')), artifactId, version, artifactId + "-" + version + $"-{sourcesPostfix}.{sourcesExtension.TrimStart('.')}");

public Task<Stream> OpenMavenMetadataFile(string groupId, string artifactId)
{
var path = CombinePaths(CombinePaths(groupId.Split('.')), artifactId, "maven-metadata.xml");
return OpenFileAsync(path);
}

return OpenFileAsync(path);
}
public Task<Project> GetProjectAsync(string groupId, string artifactId)
{
return GetProjectAsync(groupId, artifactId, null);
}

public Task<Project> GetProjectAsync(string groupId, string artifactId)
{
return GetProjectAsync(groupId, artifactId, null);
}
public async Task<Project> GetProjectAsync(string groupId, string artifactId, string version)
{
var group = Groups?.FirstOrDefault(g => g.Id == groupId);
if (group == null)
throw new KeyNotFoundException($"No group found for groupId: `{groupId}`");

public async Task<Project> GetProjectAsync(string groupId, string artifactId, string version)
{
var group = Groups?.FirstOrDefault(g => g.Id == groupId);
if (group == null)
throw new KeyNotFoundException($"No group found for groupId: `{groupId}`");
var artifact = group.Artifacts?.FirstOrDefault(a => a.Id == artifactId);
if (artifact == null)
throw new KeyNotFoundException($"No artifact found for artifactId: `{artifactId}`");

var artifact = group.Artifacts?.FirstOrDefault(a => a.Id == artifactId);
if (artifact == null)
throw new KeyNotFoundException($"No artifact found for artifactId: `{artifactId}`");

var hasVersion = artifact.Versions?.Any(v => v == version) ?? false;
var hasVersion = artifact.Versions?.Any(v => v == version) ?? false;

if (!hasVersion)
throw new KeyNotFoundException($"No version for artifact `{artifactId}` with version: `{version}`");
if (!hasVersion)
throw new KeyNotFoundException($"No version for artifact `{artifactId}` with version: `{version}`");

return PomParser.Parse(await artifact.OpenPomFile(version).ConfigureAwait(false));
}
}
return PomParser.Parse(await artifact.OpenPomFile(version).ConfigureAwait(false));
}
}
}
30 changes: 30 additions & 0 deletions MavenNet/Models/DevOps/Packages.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace MavenNet.Models.DevOps
{

public class Packages
{
public int count { get; set; }
public Package[] value { get; set; }
}

public class Package
{
public string name { get; set; }

public string groupId => name?.Substring(0, name.IndexOf(":"));
public string artifactId => name?.Substring(name.IndexOf(":")+1);

public string url { get; set; }
public Version[] versions { get; set; }
}

public class Version
{
public string version { get; set; }
public DateTime publishDate { get; set; }
}
}

0 comments on commit e6d7b15

Please sign in to comment.