diff --git a/CustomDictionary.xml b/CustomDictionary.xml
index 36a6b436..a9c1edd1 100644
--- a/CustomDictionary.xml
+++ b/CustomDictionary.xml
@@ -19,6 +19,8 @@
Prerelease
Commitish
Mergeable
+ Symlink
+ Submodule
diff --git a/Octokit.Tests.Integration/Clients/RepositoryContentsClientTests.cs b/Octokit.Tests.Integration/Clients/RepositoryContentsClientTests.cs
new file mode 100644
index 00000000..d96e9c51
--- /dev/null
+++ b/Octokit.Tests.Integration/Clients/RepositoryContentsClientTests.cs
@@ -0,0 +1,21 @@
+using System.Threading.Tasks;
+
+namespace Octokit.Tests.Integration.Clients
+{
+ public class RepositoryContentsClientTests
+ {
+ public class TheGetRootMethod
+ {
+ [IntegrationTest]
+ public async Task GetsRootContents()
+ {
+ var github = new GitHubClient(new ProductHeaderValue("OctokitTests"))
+ {
+ Credentials = Helper.Credentials
+ };
+
+ var contents = await github.Repository.Contents.GetForPath("octokit", "octokit.net", "Octokit.Reactive/ObservableGitHubClient.cs");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj
index 864c56da..3a77029c 100644
--- a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj
+++ b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj
@@ -9,18 +9,18 @@
{01687D54-1D87-4562-A721-C57F1C94052C}
Library
Properties
- Octokit.Tests.Integration
- Octokit.Tests.Integration
+ Octokit.Tests
+ Octokit.Tests
v4.5
512
- 89e72d09
+ f1b9719f
true
full
false
- bin\Debug\
- DEBUG;TRACE
+ bin\Debug\Net45\
+ TRACE;DEBUG;NET_45
prompt
4
4014, 1998
@@ -29,14 +29,19 @@
pdbonly
true
bin\Release\Net45\
- TRACE
+ TRACE;NET_45
prompt
4
4014, 1998
+
+ False
+ ..\packages\NSubstitute.1.8.0.0\lib\net45\NSubstitute.dll
+
+
False
@@ -50,9 +55,8 @@
False
..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll
+
-
-
..\packages\xunit.abstractions.2.0.0-beta5-build2785\lib\net35\xunit.abstractions.dll
@@ -62,81 +66,146 @@
..\packages\xunit.core.2.0.0-beta5-build2785\lib\portable-net45+aspnetcore50+win+wpa81+wp80+monotouch+monoandroid\xunit.core.dll
-
- False
- ..\packages\xunit.core.2.0.0-beta5-build2785\build\portable-net45+win+wpa81+wp80+monotouch+monoandroid\xunit.execution.dll
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+ Code
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
-
+
+
{674b69b8-0780-4d54-ae2b-c15821fa51cb}
Octokit.Reactive
-
- {149448d4-c2f2-4df9-86bd-03e3272f093b}
- Octokit.Tests
-
{08dd4305-7787-4823-a53f-4d0f725a07f3}
Octokit
+
+
+
+
+
+
+
+
-
- Designer
-
+
+
-
-
-
diff --git a/Octokit/Clients/IRepositoryContentsClient.cs b/Octokit/Clients/IRepositoryContentsClient.cs
index 98020220..d2e55616 100644
--- a/Octokit/Clients/IRepositoryContentsClient.cs
+++ b/Octokit/Clients/IRepositoryContentsClient.cs
@@ -1,9 +1,14 @@
+using System.Collections.Generic;
using System.Threading.Tasks;
namespace Octokit
{
public interface IRepositoryContentsClient
{
+ Task> GetRoot(string owner, string name);
+
+ Task> GetForPath(string owner, string name, string path);
+
///
/// Gets the preferred README for the specified repository.
///
diff --git a/Octokit/Clients/RepositoryContentsClient.cs b/Octokit/Clients/RepositoryContentsClient.cs
index f2666823..8fb4ebfb 100644
--- a/Octokit/Clients/RepositoryContentsClient.cs
+++ b/Octokit/Clients/RepositoryContentsClient.cs
@@ -1,3 +1,6 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
using System.Threading.Tasks;
namespace Octokit
@@ -8,6 +11,47 @@ namespace Octokit
{
}
+ public Task> GetRoot(string owner, string name)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(name, "name");
+
+ return ApiConnection.GetAll(ApiUrls.RepositoryContent(owner, name));
+ }
+
+ public async Task> GetForPath(string owner, string name, string path)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(name, "name");
+ Ensure.ArgumentNotNullOrEmptyString(path, "path");
+
+ // First, find content in parent directory.
+ var content = await FindContent(owner, name, path);
+
+ if (content == null)
+ {
+ // We've asked for a file/folder that don't exist.
+ return new List();
+ }
+
+ var url = ApiUrls.RepositoryContent(owner, name, path);
+
+ // Check which type the content is before fetching/deserializing it.
+ switch (content.Type)
+ {
+ case ContentType.Dir:
+ return await ApiConnection.GetAll(url);
+ case ContentType.File:
+ return new List { await ApiConnection.Get(url) };
+ case ContentType.Symlink:
+ return new List { await ApiConnection.Get(url) };
+ case ContentType.Submodule:
+ return new List { await ApiConnection.Get(url) };
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
///
/// Gets the preferred README for the specified repository.
///
@@ -46,5 +90,22 @@ namespace Octokit
return ApiConnection.GetHtml(ApiUrls.RepositoryReadme(owner, name), null);
}
+
+ private async Task FindContent(string owner, string name, string path)
+ {
+ var pathParts = path.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
+
+ var fileOrDirectoryName = pathParts.Last();
+
+ var parentPath = string.Join("/", pathParts.TakeWhile(x => x != fileOrDirectoryName));
+
+ var parentContentsUri = !string.IsNullOrEmpty(parentPath)
+ ? ApiUrls.RepositoryContent(owner, name, parentPath)
+ : ApiUrls.RepositoryContent(owner, name);
+
+ var parentContents = await ApiConnection.GetAll(parentContentsUri);
+
+ return parentContents.FirstOrDefault(x => x.Name == fileOrDirectoryName);
+ }
}
}
\ No newline at end of file
diff --git a/Octokit/Helpers/ApiUrls.cs b/Octokit/Helpers/ApiUrls.cs
index b46868c8..68f91d92 100644
--- a/Octokit/Helpers/ApiUrls.cs
+++ b/Octokit/Helpers/ApiUrls.cs
@@ -1356,5 +1356,28 @@ namespace Octokit
{
return "repos/{0}/{1}/readme".FormatUri(owner, name);
}
+
+ ///
+ /// Creates the relative for getting the contents of the specified repository's root
+ ///
+ /// The owner of the repository
+ /// The name of the repository
+ /// The for getting the contents of the specified repository's root
+ public static Uri RepositoryContent(string owner, string name)
+ {
+ return "repos/{0}/{1}/contents".FormatUri(owner, name);
+ }
+
+ ///
+ /// Creates the relative for getting the contents of the specified repository and path
+ ///
+ /// The owner of the repository
+ /// The name of the repository
+ /// The path of the contents to get
+ /// The for getting the contents of the specified repository and path
+ public static Uri RepositoryContent(string owner, string name, string path)
+ {
+ return "repos/{0}/{1}/contents/{2}".FormatUri(owner, name, path);
+ }
}
}
diff --git a/Octokit/Models/Response/DirectoryContent.cs b/Octokit/Models/Response/DirectoryContent.cs
new file mode 100644
index 00000000..d4d3234d
--- /dev/null
+++ b/Octokit/Models/Response/DirectoryContent.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Octokit
+{
+ public class DirectoryContent
+ {
+ public string Name { get; set; }
+
+ public string Path { get; set; }
+
+ public string Sha { get; set; }
+
+ public int? Size { get; set; }
+
+ [SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods", Justification = "Matches the property name used by the API")]
+ public ContentType Type { get; set; }
+
+ public Uri Url { get; set; }
+
+ public Uri GitUrl { get; set; }
+
+ public Uri HtmlUrl { get; set; }
+ }
+
+ public class FileContent : DirectoryContent
+ {
+ public string Encoding { get; set; }
+
+ public string Content { get; set; }
+ }
+
+ public class SymlinkContent : DirectoryContent
+ {
+ public string Target { get; set; }
+ }
+
+ public class SubmoduleContent : DirectoryContent
+ {
+ public Uri SubmoduleGitUrl { get; set; }
+ }
+
+ public enum ContentType
+ {
+ File,
+ [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Dir", Justification = "Matches the value returned by the API")]
+ Dir,
+ Symlink,
+ Submodule
+ }
+}
\ No newline at end of file
diff --git a/Octokit/Octokit-Mono.csproj b/Octokit/Octokit-Mono.csproj
index 7d0b18aa..ef65e7c6 100644
--- a/Octokit/Octokit-Mono.csproj
+++ b/Octokit/Octokit-Mono.csproj
@@ -349,6 +349,7 @@
+
diff --git a/Octokit/Octokit-MonoAndroid.csproj b/Octokit/Octokit-MonoAndroid.csproj
index 1108ca6f..7ddac418 100644
--- a/Octokit/Octokit-MonoAndroid.csproj
+++ b/Octokit/Octokit-MonoAndroid.csproj
@@ -359,6 +359,7 @@
+
\ No newline at end of file
diff --git a/Octokit/Octokit-Monotouch.csproj b/Octokit/Octokit-Monotouch.csproj
index 6bc98b0e..198629be 100644
--- a/Octokit/Octokit-Monotouch.csproj
+++ b/Octokit/Octokit-Monotouch.csproj
@@ -354,6 +354,7 @@
+
diff --git a/Octokit/Octokit-Portable.csproj b/Octokit/Octokit-Portable.csproj
index 9d0d4007..88b7c614 100644
--- a/Octokit/Octokit-Portable.csproj
+++ b/Octokit/Octokit-Portable.csproj
@@ -347,6 +347,7 @@
+
diff --git a/Octokit/Octokit-netcore45.csproj b/Octokit/Octokit-netcore45.csproj
index de4f7b6d..cc773fa0 100644
--- a/Octokit/Octokit-netcore45.csproj
+++ b/Octokit/Octokit-netcore45.csproj
@@ -351,6 +351,7 @@
+
diff --git a/Octokit/Octokit.csproj b/Octokit/Octokit.csproj
index bcd4a823..2fd26a4c 100644
--- a/Octokit/Octokit.csproj
+++ b/Octokit/Octokit.csproj
@@ -95,6 +95,7 @@
+