Skip to content

Commit 4aa2bd1

Browse files
committed
Implement implicit host detection.
1 parent 8f819ee commit 4aa2bd1

22 files changed

+342
-72
lines changed

src/Common/GetSourceLinkUrlGitTask.cs

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ public abstract class GetSourceLinkUrlGitTask : Task
2525
/// </summary>
2626
public ITaskItem[] Hosts { get; set; }
2727

28+
public string ImplicitHost { get; set; }
29+
2830
[Output]
2931
public string SourceLinkUrl { get; set; }
3032

@@ -126,35 +128,52 @@ private IEnumerable<UrlMapping> GetUrlMappings()
126128
bool isValidContentUri(Uri uri)
127129
=> uri.Query == "" && uri.UserInfo == "";
128130

129-
if (Hosts == null)
130-
{
131-
yield break;
132-
}
131+
bool tryParseAuthority(string value, out Uri uri)
132+
=> Uri.TryCreate("unknown://" + value, UriKind.Absolute, out uri) && IsAuthorityUri(uri);
133133

134-
foreach (var item in Hosts)
135-
{
136-
string authority = item.ItemSpec;
134+
Uri getDefaultUri(string authority)
135+
=> GetDefaultContentUri(new Uri("https://" + authority, UriKind.Absolute));
137136

138-
if (!Uri.TryCreate("unknown://" + authority, UriKind.Absolute, out var authorityUri) || !IsAuthorityUri(authorityUri))
137+
if (Hosts != null)
138+
{
139+
foreach (var item in Hosts)
139140
{
140-
Log.LogError(CommonResources.ValuePassedToTaskParameterNotValidDomainName, nameof(Hosts), item.ItemSpec);
141-
continue;
141+
string authority = item.ItemSpec;
142+
143+
if (!tryParseAuthority(authority, out var authorityUri))
144+
{
145+
Log.LogError(CommonResources.ValuePassedToTaskParameterNotValidDomainName, nameof(Hosts), item.ItemSpec);
146+
continue;
147+
}
148+
149+
Uri contentUri;
150+
string contentUrl = item.GetMetadata(ContentUrlMetadataName);
151+
bool hasDefaultContentUri = string.IsNullOrEmpty(contentUrl);
152+
if (hasDefaultContentUri)
153+
{
154+
contentUri = getDefaultUri(authority);
155+
}
156+
else if (!Uri.TryCreate(contentUrl, UriKind.Absolute, out contentUri) || !isValidContentUri(contentUri))
157+
{
158+
Log.LogError(CommonResources.ValuePassedToTaskParameterNotValidHostUri, nameof(Hosts), contentUrl);
159+
continue;
160+
}
161+
162+
yield return new UrlMapping(authorityUri, contentUri, hasDefaultContentUri);
142163
}
164+
}
143165

144-
Uri contentUri;
145-
string contentUrl = item.GetMetadata(ContentUrlMetadataName);
146-
bool hasDefaultContentUri = string.IsNullOrEmpty(contentUrl);
147-
if (hasDefaultContentUri)
166+
// Add implicit host last, so that matching prefers explicitly listed hosts over the implicit one.
167+
if (!string.IsNullOrEmpty(ImplicitHost))
168+
{
169+
if (tryParseAuthority(ImplicitHost, out var authorityUri))
148170
{
149-
contentUri = GetDefaultContentUri(new Uri("https://" + authority, UriKind.Absolute));
171+
yield return new UrlMapping(authorityUri, getDefaultUri(ImplicitHost), hasDefaultContentUri: true);
150172
}
151-
else if (!Uri.TryCreate(contentUrl, UriKind.Absolute, out contentUri) || !isValidContentUri(contentUri))
173+
else
152174
{
153-
Log.LogError(CommonResources.ValuePassedToTaskParameterNotValidHostUri, nameof(Hosts), contentUrl);
154-
continue;
175+
Log.LogError(CommonResources.ValuePassedToTaskParameterNotValidDomainName, nameof(ImplicitHost), ImplicitHost);
155176
}
156-
157-
yield return new UrlMapping(authorityUri, contentUri, hasDefaultContentUri);
158177
}
159178
}
160179

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
2+
3+
using System;
4+
using Microsoft.Build.Framework;
5+
using Microsoft.Build.Utilities;
6+
7+
namespace Microsoft.SourceLink.Common
8+
{
9+
public sealed class GetImplicitRepositoryHost : Task
10+
{
11+
public string ProviderTargets { get; set; }
12+
13+
public string RepositoryUrl { get; set; }
14+
15+
[Output]
16+
public string ImplicitHost { get; set; }
17+
18+
public override bool Execute()
19+
{
20+
ExecuteImpl();
21+
return !Log.HasLoggedErrors;
22+
}
23+
24+
private void ExecuteImpl()
25+
{
26+
var targets = (ProviderTargets ?? "").Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
27+
if (targets.Length == 0)
28+
{
29+
Log.LogError(Resources.NoSourceLinkPackagesReferenced);
30+
return;
31+
}
32+
33+
if (targets.Length > 1)
34+
{
35+
// multiple providers, do not define an implicit host
36+
return;
37+
}
38+
39+
if (!Uri.TryCreate(RepositoryUrl, UriKind.Absolute, out var uri))
40+
{
41+
// TODO: report error?
42+
// unable to define an implicit host
43+
return;
44+
}
45+
46+
ImplicitHost = uri.Authority;
47+
}
48+
}
49+
}

src/SourceLink.Common/Resources.resx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@
133133
<value>{0} is empty: '{1}'</value>
134134
</data>
135135
<data name="ErrorWritingToSourceLinkFile" xml:space="preserve">
136-
<value>Error writing to source link file '{0}': {1}"</value>
136+
<value>Error writing to source link file '{0}': {1}</value>
137+
</data>
138+
<data name="NoSourceLinkPackagesReferenced" xml:space="preserve">
139+
<value>Unable to generate SourceLink -- the project doesn't reference any SourceLink packages.</value>
137140
</data>
138141
</root>

src/SourceLink.Common/build/Microsoft.SourceLink.Common.targets

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
</PropertyGroup>
1111

1212
<UsingTask TaskName="Microsoft.SourceLink.Common.GenerateSourceLinkFile" AssemblyFile="$(_MicrosoftSourceLinkCommonAssemblyFile)"/>
13-
13+
<UsingTask TaskName="Microsoft.SourceLink.Common.GetImplicitRepositoryHost" AssemblyFile="$(_MicrosoftSourceLinkCommonAssemblyFile)"/>
14+
1415
<PropertyGroup Condition="'$(EnableSourceLink)' == 'true' and '$(DebugType)' != 'none'">
1516
<SourceLink>$(IntermediateOutputPath)$(MSBuildProjectName).sourcelink.json</SourceLink>
1617
</PropertyGroup>
@@ -33,29 +34,41 @@
3334
BeforeTargets="CoreCompile"
3435
Condition="'$(EmbedUntrackedSources)' == 'true' and '$(EmbedAllSources)' != 'true' and '$(DebugType)' != 'none' and '$(EnableSourceControlManagerQueries)' == 'true'" />
3536

36-
<!--
37-
If defined populates SourceRoot items and other source control information.
38-
-->
39-
<Target Name="_InitializeSourceControlInformationOpt"
40-
DependsOnTargets="InitializeSourceControlInformation"
41-
Condition="'$(SourceControlInformationFeatureSupported)' == 'true'" />
42-
4337
<!--
4438
If defined populates MappedPath metadata of SourceRoot items.
4539
-->
4640
<Target Name="_InitializeSourceRootMappedPathsOpt"
4741
DependsOnTargets="InitializeSourceRootMappedPaths"
4842
Condition="'$(SourceRootMappedPathsFeatureSupported)' == 'true'"/>
4943

44+
<!--
45+
Initializes values available to all targets in SourceLinkUrlInitializerTargets.
46+
-->
47+
<Target Name="_BeforeSourceLinkUrlInitializerTargets"
48+
DependsOnTargets="InitializeSourceControlInformation;_InitializeSourceRootMappedPathsOpt"
49+
BeforeTargets="$(SourceLinkUrlInitializerTargets)">
50+
51+
<!--
52+
If there is a single SourceLink provider use the Repository URL to infer the repository host.
53+
If the project references multiple SourceLink providers the user needs to specify hosts explicitly (ImplicitHost will be empty)
54+
as we do not know which providers should be used to produce SourceLink URL for the repository.
55+
56+
Reports an error if there is no SourceLinkUrlInitializerTargets is empty (no SourceLink provider is referenced).
57+
-->
58+
<Microsoft.SourceLink.Common.GetImplicitRepositoryHost ProviderTargets="$(SourceLinkUrlInitializerTargets)" RepositoryUrl="$(PrivateRepositoryUrl)" >
59+
<Output TaskParameter="ImplicitHost" PropertyName="SourceLinkImplicitRepositoryHost"/>
60+
</Microsoft.SourceLink.Common.GetImplicitRepositoryHost>
61+
</Target>
62+
5063
<!--
5164
Each source control provider package adds its SourceLinkUrl initialization target to SourceLinkUrlInitializerTargets.
5265
This target shall initialize SourceLinkUrl of all items that don't have it initialized yet and belong to the source control provider.
5366
-->
54-
<Target Name="_GenerateSourceLinkFile"
55-
DependsOnTargets="_InitializeSourceControlInformationOpt;_InitializeSourceRootMappedPathsOpt;$(SourceLinkUrlInitializerTargets)"
67+
<Target Name="GenerateSourceLinkFile"
68+
DependsOnTargets="$(SourceLinkUrlInitializerTargets)"
5669
BeforeTargets="CoreCompile"
5770
Outputs="$(SourceLink)"
58-
Condition="'$(SourceLink)' != ''">
71+
Condition="'$(SourceLink)' != '' and '$(SourceControlInformationFeatureSupported)' == 'true'">
5972

6073
<Microsoft.SourceLink.Common.GenerateSourceLinkFile SourceRoots="@(SourceRoot)" OutputFile="$(SourceLink)" />
6174

src/SourceLink.Common/xlf/Resources.cs.xlf

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@
2828
<note />
2929
</trans-unit>
3030
<trans-unit id="ErrorWritingToSourceLinkFile">
31-
<source>Error writing to source link file '{0}': {1}"</source>
32-
<target state="translated">Chyba při zápisu do souboru zdrojového odkazu {0}: {1}"</target>
31+
<source>Error writing to source link file '{0}': {1}</source>
32+
<target state="needs-review-translation">Chyba při zápisu do souboru zdrojového odkazu {0}: {1}"</target>
33+
<note />
34+
</trans-unit>
35+
<trans-unit id="NoSourceLinkPackagesReferenced">
36+
<source>Unable to generate SourceLink -- the project doesn't reference any SourceLink packages.</source>
37+
<target state="new">Unable to generate SourceLink -- the project doesn't reference any SourceLink packages.</target>
3338
<note />
3439
</trans-unit>
3540
</body>

src/SourceLink.Common/xlf/Resources.de.xlf

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@
2828
<note />
2929
</trans-unit>
3030
<trans-unit id="ErrorWritingToSourceLinkFile">
31-
<source>Error writing to source link file '{0}': {1}"</source>
32-
<target state="translated">Fehler beim Schreiben in Quelllinkdatei "{0}": "{1}"</target>
31+
<source>Error writing to source link file '{0}': {1}</source>
32+
<target state="needs-review-translation">Fehler beim Schreiben in Quelllinkdatei "{0}": "{1}"</target>
33+
<note />
34+
</trans-unit>
35+
<trans-unit id="NoSourceLinkPackagesReferenced">
36+
<source>Unable to generate SourceLink -- the project doesn't reference any SourceLink packages.</source>
37+
<target state="new">Unable to generate SourceLink -- the project doesn't reference any SourceLink packages.</target>
3338
<note />
3439
</trans-unit>
3540
</body>

src/SourceLink.Common/xlf/Resources.es.xlf

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@
2828
<note />
2929
</trans-unit>
3030
<trans-unit id="ErrorWritingToSourceLinkFile">
31-
<source>Error writing to source link file '{0}': {1}"</source>
32-
<target state="translated">Error al escribir en el archivo del vínculo de origen: '{0}': {1}"</target>
31+
<source>Error writing to source link file '{0}': {1}</source>
32+
<target state="needs-review-translation">Error al escribir en el archivo del vínculo de origen: '{0}': {1}"</target>
33+
<note />
34+
</trans-unit>
35+
<trans-unit id="NoSourceLinkPackagesReferenced">
36+
<source>Unable to generate SourceLink -- the project doesn't reference any SourceLink packages.</source>
37+
<target state="new">Unable to generate SourceLink -- the project doesn't reference any SourceLink packages.</target>
3338
<note />
3439
</trans-unit>
3540
</body>

src/SourceLink.Common/xlf/Resources.fr.xlf

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@
2828
<note />
2929
</trans-unit>
3030
<trans-unit id="ErrorWritingToSourceLinkFile">
31-
<source>Error writing to source link file '{0}': {1}"</source>
32-
<target state="translated">Erreur d'écriture dans le fichier de lien source '{0}' : {1}"</target>
31+
<source>Error writing to source link file '{0}': {1}</source>
32+
<target state="needs-review-translation">Erreur d'écriture dans le fichier de lien source '{0}' : {1}"</target>
33+
<note />
34+
</trans-unit>
35+
<trans-unit id="NoSourceLinkPackagesReferenced">
36+
<source>Unable to generate SourceLink -- the project doesn't reference any SourceLink packages.</source>
37+
<target state="new">Unable to generate SourceLink -- the project doesn't reference any SourceLink packages.</target>
3338
<note />
3439
</trans-unit>
3540
</body>

src/SourceLink.Common/xlf/Resources.it.xlf

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@
2828
<note />
2929
</trans-unit>
3030
<trans-unit id="ErrorWritingToSourceLinkFile">
31-
<source>Error writing to source link file '{0}': {1}"</source>
32-
<target state="translated">Si è verificato un errore durante la scrittura nel file del collegamento all'origine '{0}': {1}"</target>
31+
<source>Error writing to source link file '{0}': {1}</source>
32+
<target state="needs-review-translation">Si è verificato un errore durante la scrittura nel file del collegamento all'origine '{0}': {1}"</target>
33+
<note />
34+
</trans-unit>
35+
<trans-unit id="NoSourceLinkPackagesReferenced">
36+
<source>Unable to generate SourceLink -- the project doesn't reference any SourceLink packages.</source>
37+
<target state="new">Unable to generate SourceLink -- the project doesn't reference any SourceLink packages.</target>
3338
<note />
3439
</trans-unit>
3540
</body>

src/SourceLink.Common/xlf/Resources.ja.xlf

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@
2828
<note />
2929
</trans-unit>
3030
<trans-unit id="ErrorWritingToSourceLinkFile">
31-
<source>Error writing to source link file '{0}': {1}"</source>
32-
<target state="translated">ソース リンク ファイル '{0}' への書き込みでエラーが発生しました: {1}"</target>
31+
<source>Error writing to source link file '{0}': {1}</source>
32+
<target state="needs-review-translation">ソース リンク ファイル '{0}' への書き込みでエラーが発生しました: {1}"</target>
33+
<note />
34+
</trans-unit>
35+
<trans-unit id="NoSourceLinkPackagesReferenced">
36+
<source>Unable to generate SourceLink -- the project doesn't reference any SourceLink packages.</source>
37+
<target state="new">Unable to generate SourceLink -- the project doesn't reference any SourceLink packages.</target>
3338
<note />
3439
</trans-unit>
3540
</body>

src/SourceLink.Common/xlf/Resources.ko.xlf

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@
2828
<note />
2929
</trans-unit>
3030
<trans-unit id="ErrorWritingToSourceLinkFile">
31-
<source>Error writing to source link file '{0}': {1}"</source>
32-
<target state="translated">소스 링크 파일 '{0}'에 작성하는 중 오류가 발생했습니다. {1}"</target>
31+
<source>Error writing to source link file '{0}': {1}</source>
32+
<target state="needs-review-translation">소스 링크 파일 '{0}'에 작성하는 중 오류가 발생했습니다. {1}"</target>
33+
<note />
34+
</trans-unit>
35+
<trans-unit id="NoSourceLinkPackagesReferenced">
36+
<source>Unable to generate SourceLink -- the project doesn't reference any SourceLink packages.</source>
37+
<target state="new">Unable to generate SourceLink -- the project doesn't reference any SourceLink packages.</target>
3338
<note />
3439
</trans-unit>
3540
</body>

src/SourceLink.Common/xlf/Resources.pl.xlf

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@
2828
<note />
2929
</trans-unit>
3030
<trans-unit id="ErrorWritingToSourceLinkFile">
31-
<source>Error writing to source link file '{0}': {1}"</source>
32-
<target state="translated">Błąd zapisywania do pliku linku do źródła „{0}”: {1}"</target>
31+
<source>Error writing to source link file '{0}': {1}</source>
32+
<target state="needs-review-translation">Błąd zapisywania do pliku linku do źródła „{0}”: {1}"</target>
33+
<note />
34+
</trans-unit>
35+
<trans-unit id="NoSourceLinkPackagesReferenced">
36+
<source>Unable to generate SourceLink -- the project doesn't reference any SourceLink packages.</source>
37+
<target state="new">Unable to generate SourceLink -- the project doesn't reference any SourceLink packages.</target>
3338
<note />
3439
</trans-unit>
3540
</body>

src/SourceLink.Common/xlf/Resources.pt-BR.xlf

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@
2828
<note />
2929
</trans-unit>
3030
<trans-unit id="ErrorWritingToSourceLinkFile">
31-
<source>Error writing to source link file '{0}': {1}"</source>
32-
<target state="translated">Erro ao gravar no arquivo do link de origem '{0}': {1}"</target>
31+
<source>Error writing to source link file '{0}': {1}</source>
32+
<target state="needs-review-translation">Erro ao gravar no arquivo do link de origem '{0}': {1}"</target>
33+
<note />
34+
</trans-unit>
35+
<trans-unit id="NoSourceLinkPackagesReferenced">
36+
<source>Unable to generate SourceLink -- the project doesn't reference any SourceLink packages.</source>
37+
<target state="new">Unable to generate SourceLink -- the project doesn't reference any SourceLink packages.</target>
3338
<note />
3439
</trans-unit>
3540
</body>

src/SourceLink.Common/xlf/Resources.ru.xlf

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@
2828
<note />
2929
</trans-unit>
3030
<trans-unit id="ErrorWritingToSourceLinkFile">
31-
<source>Error writing to source link file '{0}': {1}"</source>
32-
<target state="translated">Ошибка записи в файл ссылки на источник "{0}": "{1}"</target>
31+
<source>Error writing to source link file '{0}': {1}</source>
32+
<target state="needs-review-translation">Ошибка записи в файл ссылки на источник "{0}": "{1}"</target>
33+
<note />
34+
</trans-unit>
35+
<trans-unit id="NoSourceLinkPackagesReferenced">
36+
<source>Unable to generate SourceLink -- the project doesn't reference any SourceLink packages.</source>
37+
<target state="new">Unable to generate SourceLink -- the project doesn't reference any SourceLink packages.</target>
3338
<note />
3439
</trans-unit>
3540
</body>

src/SourceLink.Common/xlf/Resources.tr.xlf

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@
2828
<note />
2929
</trans-unit>
3030
<trans-unit id="ErrorWritingToSourceLinkFile">
31-
<source>Error writing to source link file '{0}': {1}"</source>
32-
<target state="translated">'{0}' adlı kaynak bağlantı dosyasına yazılırken hata oluştu: {1}"</target>
31+
<source>Error writing to source link file '{0}': {1}</source>
32+
<target state="needs-review-translation">'{0}' adlı kaynak bağlantı dosyasına yazılırken hata oluştu: {1}"</target>
33+
<note />
34+
</trans-unit>
35+
<trans-unit id="NoSourceLinkPackagesReferenced">
36+
<source>Unable to generate SourceLink -- the project doesn't reference any SourceLink packages.</source>
37+
<target state="new">Unable to generate SourceLink -- the project doesn't reference any SourceLink packages.</target>
3338
<note />
3439
</trans-unit>
3540
</body>

src/SourceLink.Common/xlf/Resources.zh-Hans.xlf

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@
2828
<note />
2929
</trans-unit>
3030
<trans-unit id="ErrorWritingToSourceLinkFile">
31-
<source>Error writing to source link file '{0}': {1}"</source>
32-
<target state="translated">写入源链接文件 '{0}' 时出错: {1}"</target>
31+
<source>Error writing to source link file '{0}': {1}</source>
32+
<target state="needs-review-translation">写入源链接文件 '{0}' 时出错: {1}"</target>
33+
<note />
34+
</trans-unit>
35+
<trans-unit id="NoSourceLinkPackagesReferenced">
36+
<source>Unable to generate SourceLink -- the project doesn't reference any SourceLink packages.</source>
37+
<target state="new">Unable to generate SourceLink -- the project doesn't reference any SourceLink packages.</target>
3338
<note />
3439
</trans-unit>
3540
</body>

0 commit comments

Comments
 (0)