diff --git a/Octokit.Tests.Integration/Clients/RepositoryContentsClientTests.cs b/Octokit.Tests.Integration/Clients/RepositoryContentsClientTests.cs index 2cc8cf7013..e1d70edfa0 100644 --- a/Octokit.Tests.Integration/Clients/RepositoryContentsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/RepositoryContentsClientTests.cs @@ -469,6 +469,182 @@ await Assert.ThrowsAsync( } } + [IntegrationTest] + public async Task CrudTestWithExplicitBase64() + { + var client = Helper.GetAuthenticatedClient(); + var fixture = client.Repository.Content; + var repoName = Helper.MakeNameWithTimestamp("source-repo"); + + using (var context = await client.CreateRepositoryContext(new NewRepository(repoName) { AutoInit = true })) + { + var repository = context.Repository; + + var file = await fixture.CreateFile( + repository.Owner.Login, + repository.Name, + "somefile.txt", + new CreateFileRequest("Test commit", "U29tZSBDb250ZW50", false)); + Assert.Equal("somefile.txt", file.Content.Name); + + var contents = await fixture.GetAllContents(repository.Owner.Login, repository.Name, "somefile.txt"); + string fileSha = contents.First().Sha; + Assert.Equal("Some Content", contents.First().Content); + + var update = await fixture.UpdateFile( + repository.Owner.Login, + repository.Name, + "somefile.txt", + new UpdateFileRequest("Updating file", "TmV3IENvbnRlbnQ=", fileSha, false)); + Assert.Equal("somefile.txt", update.Content.Name); + + contents = await fixture.GetAllContents(repository.Owner.Login, repository.Name, "somefile.txt"); + Assert.Equal("New Content", contents.First().Content); + fileSha = contents.First().Sha; + + await fixture.DeleteFile( + repository.Owner.Login, + repository.Name, + "somefile.txt", + new DeleteFileRequest("Deleted file", fileSha)); + + await Assert.ThrowsAsync( + () => fixture.GetAllContents(repository.Owner.Login, repository.Name, "somefile.txt")); + } + } + + [IntegrationTest] + public async Task CrudTestWithRepositoryIdWithExplicitBase64() + { + var client = Helper.GetAuthenticatedClient(); + var fixture = client.Repository.Content; + var repoName = Helper.MakeNameWithTimestamp("source-repo"); + + using (var context = await client.CreateRepositoryContext(new NewRepository(repoName) { AutoInit = true })) + { + var repository = context.Repository; + + var file = await fixture.CreateFile( + repository.Id, + "somefile.txt", + new CreateFileRequest("Test commit", "U29tZSBDb250ZW50", false)); + Assert.Equal("somefile.txt", file.Content.Name); + + var contents = await fixture.GetAllContents(repository.Owner.Login, repository.Name, "somefile.txt"); + string fileSha = contents.First().Sha; + Assert.Equal("Some Content", contents.First().Content); + + var update = await fixture.UpdateFile( + repository.Id, + "somefile.txt", + new UpdateFileRequest("Updating file", "TmV3IENvbnRlbnQ=", fileSha, false)); + Assert.Equal("somefile.txt", update.Content.Name); + + contents = await fixture.GetAllContents(repository.Owner.Login, repository.Name, "somefile.txt"); + Assert.Equal("New Content", contents.First().Content); + fileSha = contents.First().Sha; + + await fixture.DeleteFile( + repository.Id, + "somefile.txt", + new DeleteFileRequest("Deleted file", fileSha)); + + await Assert.ThrowsAsync( + () => fixture.GetAllContents(repository.Owner.Login, repository.Name, "somefile.txt")); + } + } + + [IntegrationTest] + public async Task CrudTestWithNamedBranchWithExplicitBase64() + { + var client = Helper.GetAuthenticatedClient(); + var fixture = client.Repository.Content; + var repoName = Helper.MakeNameWithTimestamp("source-repo"); + var branchName = "other-branch"; + + using (var context = await client.CreateRepositoryContext(new NewRepository(repoName) { AutoInit = true })) + { + var repository = context.Repository; + + var master = await client.Git.Reference.Get(Helper.UserName, repository.Name, "heads/master"); + await client.Git.Reference.Create(Helper.UserName, repository.Name, new NewReference("refs/heads/" + branchName, master.Object.Sha)); + var file = await fixture.CreateFile( + repository.Owner.Login, + repository.Name, + "somefile.txt", + new CreateFileRequest("Test commit", "U29tZSBDb250ZW50", branchName, false)); + Assert.Equal("somefile.txt", file.Content.Name); + + var contents = await fixture.GetAllContentsByRef(repository.Owner.Login, repository.Name, "somefile.txt", branchName); + string fileSha = contents.First().Sha; + Assert.Equal("Some Content", contents.First().Content); + + var update = await fixture.UpdateFile( + repository.Owner.Login, + repository.Name, + "somefile.txt", + new UpdateFileRequest("Updating file", "TmV3IENvbnRlbnQ=", fileSha, branchName, false)); + Assert.Equal("somefile.txt", update.Content.Name); + + contents = await fixture.GetAllContentsByRef(repository.Owner.Login, repository.Name, "somefile.txt", branchName); + Assert.Equal("New Content", contents.First().Content); + fileSha = contents.First().Sha; + + await fixture.DeleteFile( + repository.Owner.Login, + repository.Name, + "somefile.txt", + new DeleteFileRequest("Deleted file", fileSha, branchName)); + + await Assert.ThrowsAsync( + () => fixture.GetAllContents(repository.Owner.Login, repository.Name, "somefile.txt")); + } + } + + [IntegrationTest] + public async Task CrudTestWithNamedBranchWithRepositoryIdWithExplicitBase64() + { + var client = Helper.GetAuthenticatedClient(); + var fixture = client.Repository.Content; + var repoName = Helper.MakeNameWithTimestamp("source-repo"); + var branchName = "other-branch"; + + using (var context = await client.CreateRepositoryContext(new NewRepository(repoName) { AutoInit = true })) + { + var repository = context.Repository; + + var master = await client.Git.Reference.Get(Helper.UserName, repository.Name, "heads/master"); + await client.Git.Reference.Create(Helper.UserName, repository.Name, new NewReference("refs/heads/" + branchName, master.Object.Sha)); + var file = await fixture.CreateFile( + repository.Id, + "somefile.txt", + new CreateFileRequest("Test commit", "U29tZSBDb250ZW50", branchName, false)); + Assert.Equal("somefile.txt", file.Content.Name); + + var contents = await fixture.GetAllContentsByRef(repository.Owner.Login, repository.Name, "somefile.txt", branchName); + string fileSha = contents.First().Sha; + Assert.Equal("Some Content", contents.First().Content); + + var update = await fixture.UpdateFile( + repository.Id, + "somefile.txt", + new UpdateFileRequest("Updating file", "TmV3IENvbnRlbnQ=", fileSha, branchName, false)); + Assert.Equal("somefile.txt", update.Content.Name); + + contents = await fixture.GetAllContentsByRef(repository.Owner.Login, repository.Name, "somefile.txt", branchName); + Assert.Equal("New Content", contents.First().Content); + fileSha = contents.First().Sha; + + await fixture.DeleteFile( + repository.Id, + "somefile.txt", + new DeleteFileRequest("Deleted file", fileSha, branchName)); + + await Assert.ThrowsAsync( + () => fixture.GetAllContents(repository.Owner.Login, repository.Name, "somefile.txt")); + } + } + public class TheGetArchiveMethod { [IntegrationTest(Skip = "this will probably take too long")] diff --git a/Octokit.Tests/Clients/RepositoryContentsClientTests.cs b/Octokit.Tests/Clients/RepositoryContentsClientTests.cs index f04ca7da42..58a04b4ec9 100644 --- a/Octokit.Tests/Clients/RepositoryContentsClientTests.cs +++ b/Octokit.Tests/Clients/RepositoryContentsClientTests.cs @@ -349,7 +349,7 @@ public async Task PassesRequestObject() Arg.Any(), Arg.Is(a => a.Message == "message" - && a.Content == "myfilecontents" + && a.Content == "bXlmaWxlY29udGVudHM=" && a.Branch == "mybranch")); } @@ -365,7 +365,63 @@ public async Task PassesRequestObjectWithRepositoryId() Arg.Any(), Arg.Is(a => a.Message == "message" - && a.Content == "myfilecontents" + && a.Content == "bXlmaWxlY29udGVudHM=" + && a.Branch == "mybranch")); + } + + [Fact] + public async Task RequestsCorrectUrlWithExplicitBase64() + { + var connection = Substitute.For(); + var client = new RepositoryContentsClient(connection); + + string expectedUri = "repos/org/repo/contents/path/to/file"; + await client.CreateFile("org", "repo", "path/to/file", new CreateFileRequest("message", "bXlmaWxlY29udGVudHM=", "mybranch", false)); + + connection.Received().Put(Arg.Is(u => u.ToString() == expectedUri), Arg.Any()); + } + + [Fact] + public async Task RequestsCorrectUrlWithRepositoryIdWithExplicitBase64() + { + var connection = Substitute.For(); + var client = new RepositoryContentsClient(connection); + + string expectedUri = "repositories/1/contents/path/to/file"; + await client.CreateFile(1, "path/to/file", new CreateFileRequest("message", "bXlmaWxlY29udGVudHM=", "mybranch", false)); + + connection.Received().Put(Arg.Is(u => u.ToString() == expectedUri), Arg.Any()); + } + + [Fact] + public async Task PassesRequestObjectWithExplicitBase64() + { + var connection = Substitute.For(); + var client = new RepositoryContentsClient(connection); + + await client.CreateFile("org", "repo", "path/to/file", new CreateFileRequest("message", "bXlmaWxlY29udGVudHM=", "mybranch", false)); + + connection.Received().Put( + Arg.Any(), + Arg.Is(a => + a.Message == "message" + && a.Content == "bXlmaWxlY29udGVudHM=" + && a.Branch == "mybranch")); + } + + [Fact] + public async Task PassesRequestObjectWithRepositoryIdWithExplicitBase64() + { + var connection = Substitute.For(); + var client = new RepositoryContentsClient(connection); + + await client.CreateFile(1, "path/to/file", new CreateFileRequest("message", "bXlmaWxlY29udGVudHM=", "mybranch", false)); + + connection.Received().Put( + Arg.Any(), + Arg.Is(a => + a.Message == "message" + && a.Content == "bXlmaWxlY29udGVudHM=" && a.Branch == "mybranch")); } @@ -509,7 +565,7 @@ public async Task PassesRequestObject() Arg.Any(), Arg.Is(a => a.Message == "message" - && a.Content == "myfilecontents" + && a.Content == "bXlmaWxlY29udGVudHM=" && a.Sha == "1234abc" && a.Branch == "mybranch")); } @@ -526,7 +582,65 @@ public async Task PassesRequestObjectWithRepositoriesId() Arg.Any(), Arg.Is(a => a.Message == "message" - && a.Content == "myfilecontents" + && a.Content == "bXlmaWxlY29udGVudHM=" + && a.Sha == "1234abc" + && a.Branch == "mybranch")); + } + + [Fact] + public async Task RequestsCorrectUrlWithExplicitBase64() + { + var connection = Substitute.For(); + var client = new RepositoryContentsClient(connection); + + string expectedUri = "repos/org/repo/contents/path/to/file"; + await client.UpdateFile("org", "repo", "path/to/file", new UpdateFileRequest("message", "bXlmaWxlY29udGVudHM=", "1234abc", "mybranch", false)); + + connection.Received().Put(Arg.Is(u => u.ToString() == expectedUri), Arg.Any()); + } + + [Fact] + public async Task RequestsCorrectUrlWithRepositoryIdWithExplicitBase64() + { + var connection = Substitute.For(); + var client = new RepositoryContentsClient(connection); + + string expectedUri = "repositories/1/contents/path/to/file"; + await client.UpdateFile(1, "path/to/file", new UpdateFileRequest("message", "bXlmaWxlY29udGVudHM=", "1234abc", "mybranch", false)); + + connection.Received().Put(Arg.Is(u => u.ToString() == expectedUri), Arg.Any()); + } + + [Fact] + public async Task PassesRequestObjectWithExplicitBase64() + { + var connection = Substitute.For(); + var client = new RepositoryContentsClient(connection); + + await client.UpdateFile("org", "repo", "path/to/file", new UpdateFileRequest("message", "bXlmaWxlY29udGVudHM=", "1234abc", "mybranch", false)); + + connection.Received().Put( + Arg.Any(), + Arg.Is(a => + a.Message == "message" + && a.Content == "bXlmaWxlY29udGVudHM=" + && a.Sha == "1234abc" + && a.Branch == "mybranch")); + } + + [Fact] + public async Task PassesRequestObjectWithRepositoriesIdWithExplicitBase64() + { + var connection = Substitute.For(); + var client = new RepositoryContentsClient(connection); + + await client.UpdateFile(1, "path/to/file", new UpdateFileRequest("message", "bXlmaWxlY29udGVudHM=", "1234abc", "mybranch", false)); + + connection.Received().Put( + Arg.Any(), + Arg.Is(a => + a.Message == "message" + && a.Content == "bXlmaWxlY29udGVudHM=" && a.Sha == "1234abc" && a.Branch == "mybranch")); } diff --git a/Octokit.Tests/Reactive/ObservableRepositoryContentsClientTests.cs b/Octokit.Tests/Reactive/ObservableRepositoryContentsClientTests.cs index f374f9b07f..7bdc3154a6 100644 --- a/Octokit.Tests/Reactive/ObservableRepositoryContentsClientTests.cs +++ b/Octokit.Tests/Reactive/ObservableRepositoryContentsClientTests.cs @@ -437,7 +437,7 @@ public void PassesRequestObject() Arg.Any(), Arg.Is(a => a.Message == "message" - && a.Content == "myfilecontents" + && a.Content == "bXlmaWxlY29udGVudHM=" && a.Branch == "mybranch")); } @@ -454,7 +454,66 @@ public void PassesRequestObjectWithRepositoryId() Arg.Any(), Arg.Is(a => a.Message == "message" - && a.Content == "myfilecontents" + && a.Content == "bXlmaWxlY29udGVudHM=" + && a.Branch == "mybranch")); + } + [Fact] + public void RequestsCorrectUrlWithExplicitBase64() + { + var connection = Substitute.For(); + var gitHubClient = new GitHubClient(connection); + var client = new ObservableRepositoryContentsClient(gitHubClient); + + string expectedUri = "repos/org/repo/contents/path/to/file"; + client.CreateFile("org", "repo", "path/to/file", new CreateFileRequest("message", "bXlmaWxlY29udGVudHM=", "mybranch", false)); + + gitHubClient.Connection.Received().Put(Arg.Is(u => u.ToString() == expectedUri), Arg.Any()); + } + + [Fact] + public void RequestsCorrectUrlWithRepositoryIdWithExplicitBase64() + { + var connection = Substitute.For(); + var gitHubClient = new GitHubClient(connection); + var client = new ObservableRepositoryContentsClient(gitHubClient); + + string expectedUri = "repositories/1/contents/path/to/file"; + client.CreateFile(1, "path/to/file", new CreateFileRequest("message", "bXlmaWxlY29udGVudHM=", "mybranch", false)); + + gitHubClient.Connection.Received().Put(Arg.Is(u => u.ToString() == expectedUri), Arg.Any()); + } + + [Fact] + public void PassesRequestObjectWithExplicitBase64() + { + var connection = Substitute.For(); + var gitHubClient = new GitHubClient(connection); + var client = new ObservableRepositoryContentsClient(gitHubClient); + + client.CreateFile("org", "repo", "path/to/file", new CreateFileRequest("message", "bXlmaWxlY29udGVudHM=", "mybranch", false)); + + gitHubClient.Connection.Received().Put( + Arg.Any(), + Arg.Is(a => + a.Message == "message" + && a.Content == "bXlmaWxlY29udGVudHM=" + && a.Branch == "mybranch")); + } + + [Fact] + public void PassesRequestObjectWithRepositoryIdWithExplicitBase64() + { + var connection = Substitute.For(); + var gitHubClient = new GitHubClient(connection); + var client = new ObservableRepositoryContentsClient(gitHubClient); + + client.CreateFile(1, "path/to/file", new CreateFileRequest("message", "bXlmaWxlY29udGVudHM=", "mybranch", false)); + + gitHubClient.Connection.Received().Put( + Arg.Any(), + Arg.Is(a => + a.Message == "message" + && a.Content == "bXlmaWxlY29udGVudHM=" && a.Branch == "mybranch")); } @@ -606,7 +665,7 @@ public void PassesRequestObject() Arg.Any(), Arg.Is(a => a.Message == "message" - && a.Content == "myfilecontents" + && a.Content == "bXlmaWxlY29udGVudHM=" && a.Sha == "1234abc" && a.Branch == "mybranch")); } @@ -624,7 +683,69 @@ public void PassesRequestObjectWithRepositoriesId() Arg.Any(), Arg.Is(a => a.Message == "message" - && a.Content == "myfilecontents" + && a.Content == "bXlmaWxlY29udGVudHM=" + && a.Sha == "1234abc" + && a.Branch == "mybranch")); + } + + [Fact] + public void RequestsCorrectUrlWithExplicitBase64() + { + var connection = Substitute.For(); + var gitHubClient = new GitHubClient(connection); + var client = new ObservableRepositoryContentsClient(gitHubClient); + + string expectedUri = "repos/org/repo/contents/path/to/file"; + client.UpdateFile("org", "repo", "path/to/file", new UpdateFileRequest("message", "bXlmaWxlY29udGVudHM=", "1234abc", "mybranch", false)); + + gitHubClient.Connection.Received().Put(Arg.Is(u => u.ToString() == expectedUri), Arg.Any()); + } + + [Fact] + public void RequestsCorrectUrlWithRepositoryIdWithExplicitBase64() + { + var connection = Substitute.For(); + var gitHubClient = new GitHubClient(connection); + var client = new ObservableRepositoryContentsClient(gitHubClient); + + string expectedUri = "repositories/1/contents/path/to/file"; + client.UpdateFile(1, "path/to/file", new UpdateFileRequest("message", "bXlmaWxlY29udGVudHM=", "1234abc", "mybranch", false)); + + gitHubClient.Connection.Received().Put(Arg.Is(u => u.ToString() == expectedUri), Arg.Any()); + } + + [Fact] + public void PassesRequestObjectWithExplicitBase64() + { + var connection = Substitute.For(); + var gitHubClient = new GitHubClient(connection); + var client = new ObservableRepositoryContentsClient(gitHubClient); + + client.UpdateFile("org", "repo", "path/to/file", new UpdateFileRequest("message", "bXlmaWxlY29udGVudHM=", "1234abc", "mybranch", false)); + + gitHubClient.Connection.Received().Put( + Arg.Any(), + Arg.Is(a => + a.Message == "message" + && a.Content == "bXlmaWxlY29udGVudHM=" + && a.Sha == "1234abc" + && a.Branch == "mybranch")); + } + + [Fact] + public void PassesRequestObjectWithRepositoriesIdWithExplicitBase64() + { + var connection = Substitute.For(); + var gitHubClient = new GitHubClient(connection); + var client = new ObservableRepositoryContentsClient(gitHubClient); + + client.UpdateFile(1, "path/to/file", new UpdateFileRequest("message", "bXlmaWxlY29udGVudHM=", "1234abc", "mybranch", false)); + + gitHubClient.Connection.Received().Put( + Arg.Any(), + Arg.Is(a => + a.Message == "message" + && a.Content == "bXlmaWxlY29udGVudHM=" && a.Sha == "1234abc" && a.Branch == "mybranch")); } diff --git a/Octokit/Models/Request/CreateFileRequest.cs b/Octokit/Models/Request/CreateFileRequest.cs index b54dfee3d2..06d6f5e133 100644 --- a/Octokit/Models/Request/CreateFileRequest.cs +++ b/Octokit/Models/Request/CreateFileRequest.cs @@ -107,10 +107,32 @@ public class CreateFileRequest : ContentRequest /// /// The message. /// The content. - public CreateFileRequest(string message, string content) : base(message) + public CreateFileRequest(string message, string content) : this(message, content, true) + { } + + /// + /// Initializes a new instance of the class. + /// + /// The message. + /// The content. + /// The branch the request is for. + public CreateFileRequest(string message, string content, string branch) : this(message, content, branch, true) + { } + + /// + /// Creates an instance of a . + /// + /// The message. + /// The content. + /// True to convert content to base64. + public CreateFileRequest(string message, string content, bool convertContentToBase64) : base(message) { Ensure.ArgumentNotNull(content, "content"); + if (convertContentToBase64) + { + content = content.ToBase64String(); + } Content = content; } @@ -120,16 +142,21 @@ public CreateFileRequest(string message, string content) : base(message) /// The message. /// The content. /// The branch the request is for. - public CreateFileRequest(string message, string content, string branch) : base(message, branch) + /// True to convert content to base64. + public CreateFileRequest(string message, string content, string branch, bool convertContentToBase64) : base(message, branch) { Ensure.ArgumentNotNullOrEmptyString(content, "content"); + if (convertContentToBase64) + { + content = content.ToBase64String(); + } Content = content; } + /// - /// The contents of the file to create. This is required. + /// The contents of the file to create, Base64 encoded. This is required. /// - [SerializeAsBase64] public string Content { get; private set; } internal virtual string DebuggerDisplay @@ -154,7 +181,29 @@ public class UpdateFileRequest : CreateFileRequest /// The content. /// The sha. public UpdateFileRequest(string message, string content, string sha) - : base(message, content) + : this(message, content, sha, true) + { } + + /// + /// Creates an instance of a . + /// + /// The message. + /// The content. + /// The sha. + /// The branch the request is for. + public UpdateFileRequest(string message, string content, string sha, string branch) + : this(message, content, sha, branch, true) + { } + + /// + /// Creates an instance of a . + /// + /// The message. + /// The content. + /// The sha. + /// True to convert content to base64. + public UpdateFileRequest(string message, string content, string sha, bool convertContentToBase64) + : base(message, content, convertContentToBase64) { Ensure.ArgumentNotNullOrEmptyString(sha, "sha"); @@ -168,8 +217,9 @@ public UpdateFileRequest(string message, string content, string sha) /// The content. /// The sha. /// The branch the request is for. - public UpdateFileRequest(string message, string content, string sha, string branch) - : base(message, content, branch) + /// True to convert content to base64. + public UpdateFileRequest(string message, string content, string sha, string branch, bool convertContentToBase64) + : base(message, content, branch, convertContentToBase64) { Ensure.ArgumentNotNullOrEmptyString(sha, "sha");