@ -1,8 +1,10 @@
using System ;
using System.Collections.Generic ;
using System.Linq ;
using System.Net.Http ;
using System.Threading.Tasks ;
using Microsoft.Extensions.Logging ;
using Microsoft.Extensions.Options ;
using Volo.Abp.Domain.Services ;
using Volo.Docs.Documents ;
using Volo.Docs.GitHub.Projects ;
@ -23,20 +25,25 @@ namespace Volo.Docs.GitHub.Documents
private readonly IGithubRepositoryManager _ githubRepositoryManager ;
private readonly IGithubPatchAnalyzer _ githubPatchAnalyzer ;
public GithubDocumentSource ( IGithubRepositoryManager githubRepositoryManager , IGithubPatchAnalyzer githubPatchAnalyzer )
private readonly IDocumentRepository _d ocumentRepository ;
private readonly DocsGithubLanguageOptions _d ocsGithubLanguageOptions ;
public GithubDocumentSource (
IGithubRepositoryManager githubRepositoryManager ,
IGithubPatchAnalyzer githubPatchAnalyzer ,
IDocumentRepository documentRepository ,
IOptions < DocsGithubLanguageOptions > docsGithubLanguageOptions )
{
_ githubRepositoryManager = githubRepositoryManager ;
_ githubPatchAnalyzer = githubPatchAnalyzer ;
_d ocumentRepository = documentRepository ;
_d ocsGithubLanguageOptions = docsGithubLanguageOptions . Value ;
}
public virtual async Task < Document > GetDocumentAsync ( Project project , string documentName , string languageCode , string version , DateTime ? lastKnownSignificantUpdateTime = null )
{
var token = project . GetGitHubAccessTokenOrNull ( ) ;
var rootUrl = project . GetGitHubUrl ( version ) ;
var userAgent = project . GetGithubUserAgentOrNull ( ) ;
var rawRootUrl = CalculateRawRootUrlWithLanguageCode ( rootUrl , languageCode ) ;
var rawDocumentUrl = rawRootUrl + documentName ;
var isNavigationDocument = documentName = = project . NavigationDocumentName ;
var isParameterDocument = documentName = = project . ParametersDocumentName ;
var editLink = rootUrl . ReplaceFirst ( "/tree/" , "/blob/" ) . EnsureEndsWith ( '/' ) + languageCode + "/" + documentName ;
@ -49,12 +56,12 @@ namespace Volo.Docs.GitHub.Documents
fileName = documentName . Substring ( documentName . LastIndexOf ( '/' ) + 1 ) ;
}
var content = await DownloadWebContentAsStringAsync ( rawDocumentUrl , token , userAgent ) ;
var content = await DownloadWebContentAsStringAsync ( project , documentName , languageCode , version ) ;
var commits = await GetGitHubCommitsOrNull ( project , documentName , languageCode , version ) ;
var documentCreationTime = GetFirstCommitDate ( commits ) ;
var lastUpdateTime = GetLastCommitDate ( commits ) ;
var lastSignificantUpdateTime = await GetLastKnownSignificantUpdateTime ( project , documentName , languageCode , version , lastKnownSignificantUpdateTime , isNavigationDocument , isParameterDocument , commits , documentCreationTime ) ;
var lastSignificantUpdateTime = await GetLastKnownSignificantUpdateTime ( project , documentName , languageCode , version , lastKnownSignificantUpdateTime , isNavigationDocument , isParameterDocument , commits ) ;
var document = new Document
(
@ -100,18 +107,24 @@ namespace Volo.Docs.GitHub.Documents
DateTime ? lastKnownSignificantUpdateTime ,
bool isNavigationDocument ,
bool isParameterDocument ,
IReadOnlyList < GitHubCommit > commits ,
DateTime documentCreationTime )
IReadOnlyList < GitHubCommit > commits )
{
return ! isNavigationDocument & & ! isParameterDocument & & version = = project . LatestVersionBranchName
? await GetLastSignificantUpdateTime (
commits ,
project ,
project . GetGitHubInnerUrl ( languageCode , documentName ) ,
lastKnownSignificantUpdateTime ,
documentCreationTime
) ? ? lastKnownSignificantUpdateTime
: null ;
try
{
return ! isNavigationDocument & & ! isParameterDocument & & version = = project . LatestVersionBranchName
? await GetLastSignificantUpdateTime (
commits ,
project ,
project . GetGitHubInnerUrl ( languageCode , documentName ) ,
lastKnownSignificantUpdateTime
) ? ? lastKnownSignificantUpdateTime
: null ;
}
catch
{
Logger . LogWarning ( "Could not retrieved the last update time from Github." ) ;
return null ;
}
}
private static List < DocumentAuthor > GetAuthors ( IReadOnlyList < GitHubCommit > commits )
@ -206,8 +219,7 @@ namespace Volo.Docs.GitHub.Documents
IReadOnlyList < GitHubCommit > commits ,
Project project ,
string fileName ,
DateTime ? lastKnownSignificantUpdateTime ,
DateTime documentCreationTime )
DateTime ? lastKnownSignificantUpdateTime )
{
if ( commits = = null | | ! commits . Any ( ) )
{
@ -317,17 +329,28 @@ namespace Volo.Docs.GitHub.Documents
var token = project . GetGitHubAccessTokenOrNull ( ) ;
var rootUrl = project . GetGitHubUrl ( version ) ;
var userAgent = project . GetGithubUserAgentOrNull ( ) ;
var url = CalculateRawRootUrl ( rootUrl ) + DocsDomainConsts . LanguageConfigFileName ;
var configAsJson = await DownloadWebContentAsStringAsync ( url , token , userAgent ) ;
try
{
var configAsJson = await _ githubRepositoryManager . GetFileRawStringContentAsync ( url , token , userAgent ) ;
if ( ! DocsJsonSerializerHelper . TryDeserialize < LanguageConfig > ( configAsJson , out var languageConfig ) )
{
throw new UserFriendlyException ( $"Cannot validate language config file '{DocsDomainConsts.LanguageConfigFileName}' for the project {project.Name} - v{version}." ) ;
}
if ( ! DocsJsonSerializerHelper . TryDeserialize < LanguageConfig > ( configAsJson , out var languageConfig ) )
return languageConfig ;
}
catch
{
throw new UserFriendlyException ( $"Cannot validate language config file '{DocsDomainConsts.LanguageConfigFileName}' for the project {project.Name} - v{version}." ) ;
Logger . LogWarning ( "Could not retrieved language list from Github. Using the default language from DocsGithubLanguageOptions." ) ;
return new LanguageConfig
{
Languages = new List < LanguageConfigElement > { _d ocsGithubLanguageOptions . DefaultLanguage }
} ;
}
return languageConfig ;
}
private async Task < IReadOnlyList < GitHubCommit > > GetFileCommitsAsync ( Project project , string version , string filename )
@ -372,19 +395,38 @@ namespace Volo.Docs.GitHub.Documents
}
}
private async Task < string > DownloadWebContentAsStringAsync ( string rawUrl , string token , string userAgent )
private async Task < string > DownloadWebContentAsStringAsync ( Project project , string documentName , string languageCode , string version )
{
var token = project . GetGitHubAccessTokenOrNull ( ) ;
var rootUrl = project . GetGitHubUrl ( version ) ;
var userAgent = project . GetGithubUserAgentOrNull ( ) ;
var rawRootUrl = CalculateRawRootUrlWithLanguageCode ( rootUrl , languageCode ) ;
var rawDocumentUrl = rawRootUrl + documentName ;
try
{
Logger . LogInformation ( "Downloading content from Github (DownloadWebContentAsStringAsync): " + rawUrl ) ;
Logger . LogInformation ( "Downloading content from Github (DownloadWebContentAsStringAsync): " +
rawDocumentUrl ) ;
return await _ githubRepositoryManager . GetFileRawStringContentAsync ( rawUrl , token , userAgent ) ;
return await _ githubRepositoryManager . GetFileRawStringContentAsync ( rawDocumentUrl , token , userAgent ) ;
}
catch ( HttpRequestException ex )
{
Logger . LogWarning ( $"Could not retrieve the document ({rawDocumentUrl}) from Github. Trying to get it from database..." ) ;
var document = await _d ocumentRepository . FindAsync ( project . Id , documentName , languageCode , version ) ;
if ( document = = null )
{
throw new DocumentNotFoundException ( rawDocumentUrl ) ;
}
return document . Content ;
}
catch ( Exception ex )
{
//TODO: Only handle when document is really not available
Logger . LogWarning ( $"{ex.Message}: {rawUrl}" , ex ) ;
throw new DocumentNotFoundException ( rawUrl ) ;
Logger . LogWarning ( $"{ex.Message}: {rawDocument Url}" , ex ) ;
throw new DocumentNotFoundException ( rawDocument Url ) ;
}
}