Skip to content
Open
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
7 changes: 6 additions & 1 deletion NGitLab.Mock/Clients/RepositoryClient.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
Expand Down Expand Up @@ -85,6 +85,11 @@ public void GetArchive(Action<Stream> parser)
throw new NotImplementedException();
}

public void GetArchive(Action<Stream> parser, FileArchiveQuery fileArchiveQuery)
{
throw new NotImplementedException();
}

public IEnumerable<Commit> GetCommits(string refName, int maxResults = 0)
{
using (Context.BeginOperationScope())
Expand Down
114 changes: 114 additions & 0 deletions NGitLab.Tests/Impl/UtilsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,118 @@ public void AddParameter_ConsidersEnumMemberAttribute(EventAction value, string

Assert.That(url, Is.EqualTo($"{basePath}?event_action={expectedQueryParamValue}"));
}

[TestCase]
public void AppendSegmentToUrl_ValueIsNullIncludeSegmentSeparatorFalse_ReturnsUrlWithoutAnyChange()
{
// Arrange
const string basePath = "https://gitlab.org/api/v4/stuff";
var url = basePath;
var expected = basePath;

// Act
var actual = NGitLab.Impl.Utils.AppendSegmentToUrl<string>(url, value: null, includeSegmentSeparator: false);

// Assert
Assert.That(expected, Is.EqualTo(actual));
}

[TestCase]
public void AppendSegmentToUrl_ValueIsNullIncludeSegmentSeparatorTrue_ReturnsUrlWithoutAnyChange()
{
// Arrange
const string basePath = "https://gitlab.org/api/v4/stuff";
var url = basePath;
var expected = basePath;

// Act
var actual = NGitLab.Impl.Utils.AppendSegmentToUrl<string>(url, value: null, includeSegmentSeparator: true);

// Assert
Assert.That(expected, Is.EqualTo(actual));
}

[TestCase]
public void AppendSegmentToUrl_UrlAlreadyContainsQueryString_ThrowsInvalidOperationException()
{
// Arrange
const string basePath = "https://gitlab.org/api/v4/stuff";
var url = basePath;

url = NGitLab.Impl.Utils.AddParameter(url, "param1", "one");

// Act and Assert
Assert.That(() => NGitLab.Impl.Utils.AppendSegmentToUrl(url, "segment"), Throws.InvalidOperationException);
}

[TestCase("https://gitlab.org/api/v4/stuff/", "/segment")]
[TestCase("https://gitlab.org/api/v4/stuff/", "segment")]
[TestCase("https://gitlab.org/api/v4/stuff", "/segment")]
[TestCase("https://gitlab.org/api/v4/stuff", "segment")]
public void AppendSegmentToUrl_IncludeSegmentSeparatorIsTrue_SegmentAppendedWithSeparator(string basePath, string segment)
{
// Arrange
var url = basePath;
var expected = "https://gitlab.org/api/v4/stuff/segment";

// Act
var actual = NGitLab.Impl.Utils.AppendSegmentToUrl(url, value: segment, includeSegmentSeparator: true);

// Assert
Assert.That(expected, Is.EqualTo(actual));
}

[TestCase("https://gitlab.org/api/v4/stuff/", "/segment")]
[TestCase("https://gitlab.org/api/v4/stuff/", "segment")]
[TestCase("https://gitlab.org/api/v4/stuff", "/segment")]
[TestCase("https://gitlab.org/api/v4/stuff", "segment")]
public void AppendSegmentToUrl_IncludeSegmentSeparatorIsFalse_SegmentAppendedWithoutSeparator(string basePath, string segment)
{
// Arrange
var url = basePath;
var expected = "https://gitlab.org/api/v4/stuffsegment";

// Act
var actual = NGitLab.Impl.Utils.AppendSegmentToUrl(url, value: segment, includeSegmentSeparator: false);

// Assert
Assert.That(expected, Is.EqualTo(actual));
}

[TestCase("https://gitlab.org/api/v4/stuff.bz2", FileArchiveFormat.Bz2)]
[TestCase("https://gitlab.org/api/v4/stuff.gz", FileArchiveFormat.Gz)]
[TestCase("https://gitlab.org/api/v4/stuff.tar", FileArchiveFormat.Tar)]
[TestCase("https://gitlab.org/api/v4/stuff.tar.bz2", FileArchiveFormat.TarBz2)]
[TestCase("https://gitlab.org/api/v4/stuff.tar.gz", FileArchiveFormat.TarGz)]
[TestCase("https://gitlab.org/api/v4/stuff.tb2", FileArchiveFormat.Tb2)]
[TestCase("https://gitlab.org/api/v4/stuff.tbz", FileArchiveFormat.Tbz)]
[TestCase("https://gitlab.org/api/v4/stuff.tbz2", FileArchiveFormat.Tbz2)]
[TestCase("https://gitlab.org/api/v4/stuff.zip", FileArchiveFormat.Zip)]
public void AppendSegmentToUrl_ValueIsEnumWithEnumMemberAttribute_EnumMemberValueAppended(string expected, FileArchiveFormat fileArchiveFormat)
{
// Arrange
const string basePath = "https://gitlab.org/api/v4/stuff";
var url = basePath;

// Act
var actual = NGitLab.Impl.Utils.AppendSegmentToUrl(url, value: fileArchiveFormat, includeSegmentSeparator: false);

// Assert
Assert.That(expected, Is.EqualTo(actual));
}

[TestCase("https://gitlab.org/api/v4/stuff/Group", BadgeKind.Group)]
[TestCase("https://gitlab.org/api/v4/stuff/Project", BadgeKind.Project)]
public void AppendSegmentToUrl_ValueIsEnumWithoutEnumMemberAttribute_EnumToStringValueAppended(string expected, BadgeKind badgeKind)
{
// Arrange
const string basePath = "https://gitlab.org/api/v4/stuff";
var url = basePath;

// Act
var actual = NGitLab.Impl.Utils.AppendSegmentToUrl(url, value: badgeKind, includeSegmentSeparator: true);

// Assert
Assert.That(expected, Is.EqualTo(actual));
}
}
156 changes: 156 additions & 0 deletions NGitLab.Tests/RepositoryClient/RepositoryClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -353,4 +353,160 @@ public async Task GetCommitRefs(CommitRefType type)
Assert.That(commitRefs, Is.Not.Empty);
}
}

[Test]
[NGitLabRetry]
public async Task GetArchive_NoQuerySpecified_PathConstructedWithNoParameters()
{
// Arrange
using var context = await RepositoryClientTestsContext.CreateAsync(commitCount: 2).ConfigureAwait(false);

// Act
context.RepositoryClient.GetArchive((stream) => { });

// Assert
var requestPathAndQuery = context.Context.LastRequest.RequestUri.PathAndQuery;

Assert.Multiple(() =>
{
Assert.That(requestPathAndQuery, Is.Not.Null);
Assert.That(requestPathAndQuery.EndsWith("/archive", StringComparison.OrdinalIgnoreCase), Is.True);
});
}

[Test]
[NGitLabRetry]
public async Task GetArchive_QueryInstanceIsNull_PathConstructedWithNoParameters()
{
// Arrange
using var context = await RepositoryClientTestsContext.CreateAsync(commitCount: 2).ConfigureAwait(false);
var firstCommitId = context.Commits[0].Id.ToString();

// Act
context.RepositoryClient.GetArchive((stream) => { }, fileArchiveQuery: null);

// Assert
var requestPathAndQuery = context.Context.LastRequest.RequestUri.PathAndQuery;

Assert.Multiple(() =>
{
Assert.That(requestPathAndQuery, Is.Not.Null);
Assert.That(requestPathAndQuery.EndsWith("/archive", StringComparison.OrdinalIgnoreCase), Is.True);
});
}

[TestCase(null, "")]
[TestCase(FileArchiveFormat.Bz2, ".bz2")]
[TestCase(FileArchiveFormat.Gz, ".gz")]
[TestCase(FileArchiveFormat.Tar, ".tar")]
[TestCase(FileArchiveFormat.TarBz2, ".tar.bz2")]
[TestCase(FileArchiveFormat.TarGz, ".tar.gz")]
[TestCase(FileArchiveFormat.Tb2, ".tb2")]
[TestCase(FileArchiveFormat.Tbz2, ".tbz2")]
[TestCase(FileArchiveFormat.Zip, ".zip")]
[NGitLabRetry]
public async Task GetArchive_QuerySpecifiesFormatValue_ArchiveExtensionPassedCorrectly(
FileArchiveFormat? archiveFormat, string expectedExtension)
{
// Arrange
using var context = await RepositoryClientTestsContext.CreateAsync(commitCount: 2);
var fileArchiveQuery = new FileArchiveQuery
{
Format = archiveFormat,
};

// Act
context.RepositoryClient.GetArchive((stream) => { }, fileArchiveQuery);

// Assert
var requestPathAndQuery = context.Context.LastRequest.RequestUri.PathAndQuery;

Assert.Multiple(() =>
{
Assert.That(requestPathAndQuery, Is.Not.Null);
Assert.That(requestPathAndQuery.EndsWith($"/archive{expectedExtension}",
StringComparison.OrdinalIgnoreCase), Is.True);
});
}

[Test]
[NGitLabRetry]
public async Task GetArchive_QuerySpecifiesRevision_ShaValuePassedCorrectly()
{
// Arrange
using var context = await RepositoryClientTestsContext.CreateAsync(commitCount: 2);
var firstCommitId = context.Commits[0].Id.ToString();
var fileArchiveQuery = new FileArchiveQuery
{
Ref = firstCommitId,
};

// Act
context.RepositoryClient.GetArchive((stream) => { }, fileArchiveQuery);

// Assert
var requestPathAndQuery = context.Context.LastRequest.RequestUri.PathAndQuery;

Assert.Multiple(() =>
{
Assert.That(requestPathAndQuery, Is.Not.Null);
Assert.That(requestPathAndQuery.Contains($"sha={firstCommitId}",
StringComparison.OrdinalIgnoreCase), Is.True);
});
}

[Test]
[NGitLabRetry]
public async Task GetArchive_QuerySpecifiesPath_PathValuePassedCorrectly()
{
// Arrange
using var context = await RepositoryClientTestsContext.CreateAsync(commitCount: 2);
var path = RepositoryClientTestsContext.SubfolderName;
var fileArchiveQuery = new FileArchiveQuery
{
Path = path,
};

// Act
context.RepositoryClient.GetArchive((stream) => { }, fileArchiveQuery);

// Assert
var requestPathAndQuery = context.Context.LastRequest.RequestUri.PathAndQuery;

Assert.Multiple(() =>
{
Assert.That(requestPathAndQuery, Is.Not.Null);
Assert.That(requestPathAndQuery.Contains($"path={path}", StringComparison.OrdinalIgnoreCase), Is.True);
});
}

[Test]
[NGitLabRetry]
public async Task GetArchive_QuerySpecifiesAllParameters_AllParametersPassedCorrectly()
{
// Arrange
using var context = await RepositoryClientTestsContext.CreateAsync(commitCount: 2);
var firstCommitId = context.Commits[0].Id.ToString();
var path = RepositoryClientTestsContext.SubfolderName;
var fileArchiveQuery = new FileArchiveQuery
{
Format = FileArchiveFormat.Zip,
Path = path,
Ref = firstCommitId,
};

// Act
context.RepositoryClient.GetArchive((stream) => { }, fileArchiveQuery);

// Assert
var requestPathAndQuery = context.Context.LastRequest.RequestUri.PathAndQuery;

Assert.Multiple(() =>
{
Assert.That(requestPathAndQuery, Is.Not.Null);
Assert.That(requestPathAndQuery.Contains($"/archive.zip", StringComparison.OrdinalIgnoreCase), Is.True);
Assert.That(requestPathAndQuery.Contains($"path={path}", StringComparison.OrdinalIgnoreCase), Is.True);
Assert.That(requestPathAndQuery.Contains($"sha={firstCommitId}", StringComparison.OrdinalIgnoreCase), Is.True);
});
}
}
4 changes: 3 additions & 1 deletion NGitLab/IRepositoryClient.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.IO;
using NGitLab.Models;
Expand All @@ -23,6 +23,8 @@ public interface IRepositoryClient

void GetArchive(Action<Stream> parser);

void GetArchive(Action<Stream> parser, FileArchiveQuery fileArchiveQuery);

IEnumerable<Commit> Commits { get; }

IContributorClient Contributors { get; }
Expand Down
20 changes: 17 additions & 3 deletions NGitLab/Impl/RepositoryClient.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
Expand Down Expand Up @@ -55,9 +55,23 @@ public void GetRawBlob(string sha, Action<Stream> parser)
_api.Get().Stream(_repoPath + "/raw_blobs/" + sha, parser);
}

public void GetArchive(Action<Stream> parser)
public void GetArchive(Action<Stream> parser) => GetArchive(parser, fileArchiveQuery: null);

public void GetArchive(Action<Stream> parser, FileArchiveQuery fileArchiveQuery)
{
_api.Get().Stream(_repoPath + "/archive", parser);
var url = Utils.AppendSegmentToUrl(_repoPath, "/archive");

if (fileArchiveQuery != null)
{
// If a particular archive file format is requested, it is appended to the path directly as follows:
// /project/123/repository/archive.zip
// /project/123/repository/archive.tar
url = Utils.AppendSegmentToUrl(url, fileArchiveQuery.Format, includeSegmentSeparator: false);
url = Utils.AddParameter(url, "path", fileArchiveQuery.Path);
url = Utils.AddParameter(url, "sha", fileArchiveQuery.Ref);
}

_api.Get().Stream(url, parser);
}

public IEnumerable<Commit> Commits => _api.Get().GetAll<Commit>(_repoPath + $"/commits?per_page={GetCommitsRequest.DefaultPerPage}");
Expand Down
Loading