Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parameterize product version #8031

Merged
merged 3 commits into from
Jan 6, 2020
Merged
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
33 changes: 30 additions & 3 deletions FSharpBuild.Directory.Build.targets
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<Project>

<Import Project="Sdk.targets" Sdk="Microsoft.DotNet.Arcade.Sdk" />
<Import Project="eng\targets\Imports.targets" />
<Import Project="eng\targets\NuGet.targets" />
Expand All @@ -8,7 +9,7 @@
<Target Name="NoneSubstituteTextFiles"
Inputs="@(NoneSubstituteText)"
Outputs="@(NoneSubstituteText->'$(IntermediateOutputPath)%(Filename)%(Extension)')"
BeforeTargets="AssignTargetPaths;BeforeBuild">
BeforeTargets="AssignTargetPaths;BeforeBuild;GenerateFSharpTextResources">

<PropertyGroup>
<__TargetFilePath>@(NoneSubstituteText->'$(IntermediateOutputPath)%(Filename)%(Extension)')</__TargetFilePath>
Expand All @@ -20,16 +21,19 @@

<_CopyToOutputDirectory Condition="'%(NoneSubstituteText.CopyToOutputDirectory)' != ''">%(NoneSubstituteText.CopyToOutputDirectory)</_CopyToOutputDirectory>
<_CopyToOutputDirectory Condition="'%(NoneSubstituteText.CopyToOutputDirectory)' == ''">Never</_CopyToOutputDirectory>

<_IncludeInVsix>false</_IncludeInVsix>
<_IncludeInVsix Condition="'%(NoneSubstituteText.IncludeInVsix)' == 'true'">true</_IncludeInVsix>
</PropertyGroup>

<MakeDir Directories="$(IntermediateOutputPath)"
Condition="!Exists('$(IntermediateOutputPath)')" />
<WriteLinesToFile File="$(__TargetFilePath)" Lines="$(_ReplacementText)" Overwrite="true" WriteOnlyWhenDifferent="true" />

<!-- Make sure it will get cleaned -->
<ItemGroup >
<ItemGroup>
<None Include="$(__TargetFilePath)" CopyToOutputDirectory="$(_CopyToOutputDirectory)" />
<FileWrites Include="$(__TargetFilePath)" Condition="'$(__TargetFileName)' != 'App.config'" />
<Content Include="$(__TargetFilePath)" CopyToOutputDirectory="Always" IncludeInVsix="true" />
</ItemGroup>
</Target>

Expand Down Expand Up @@ -61,4 +65,27 @@
</ItemGroup>
</Target>

<Target Name="BeforeResGen"
Inputs="@(EmbeddedResource->'$(IntermediateOutputPath)%(Filename)%(Extension)')"
Outputs="@(EmbeddedResource->'$(IntermediateOutputPath)resources\%(Filename)%(Extension)')"
DependsOnTargets="CopyVsixResources"
Condition="'$(Configuration)' != 'Proto' and '$(Language)'=='F#' and '$(DisableCompilerRedirection)' != 'true' ">

<SubstituteText EmbeddedResources="@(EmbeddedResource)">
<Output TaskParameter="CopiedFiles" ItemName="CopiedFiles" />
</SubstituteText>

<ItemGroup>
<EmbeddedResource Remove="@(EmbeddedResource)"/>
<EmbeddedResource Include="@(CopiedFiles)"/>
</ItemGroup>

<MakeDir Directories="$(IntermediateOutputPath)" Condition="!Exists('$(IntermediateOutputPath)')" />
<MakeDir Directories="$(IntermediateOutputPath)resources\" Condition="!Exists('$(IntermediateOutputPath)resources\')" />
</Target>

<Target Name="CopyVsixResources">
<Copy SourceFiles="@(CopyVsixResources)" DestinationFolder="$(IntermediateOutputPath)\resources\Resources" />
</Target>

</Project>
6 changes: 3 additions & 3 deletions fcs/build.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,16 +66,16 @@ Target.create "Build" (fun _ ->
runDotnet __SOURCE_DIRECTORY__ "build" "../src/buildtools/buildtools.proj -v n -c Proto"
let fslexPath = __SOURCE_DIRECTORY__ + "/../artifacts/bin/fslex/Proto/netcoreapp2.1/fslex.dll"
let fsyaccPath = __SOURCE_DIRECTORY__ + "/../artifacts/bin/fsyacc/Proto/netcoreapp2.1/fsyacc.dll"
runDotnet __SOURCE_DIRECTORY__ "build" (sprintf "FSharp.Compiler.Service.sln -v n -c Release /p:FsLexPath=%s /p:FsYaccPath=%s" fslexPath fsyaccPath)
runDotnet __SOURCE_DIRECTORY__ "build" (sprintf "FSharp.Compiler.Service.sln -nodereuse:false -v n -c Release /p:DisableCompilerRedirection=true /p:FsLexPath=%s /p:FsYaccPath=%s" fslexPath fsyaccPath)
)

Target.create "Test" (fun _ ->
// This project file is used for the netcoreapp2.0 tests to work out reference sets
runDotnet __SOURCE_DIRECTORY__ "build" "../tests/projects/Sample_NETCoreSDK_FSharp_Library_netstandard2_0/Sample_NETCoreSDK_FSharp_Library_netstandard2_0.fsproj -v n /restore /p:DisableCompilerRedirection=true"
runDotnet __SOURCE_DIRECTORY__ "build" "../tests/projects/Sample_NETCoreSDK_FSharp_Library_netstandard2_0/Sample_NETCoreSDK_FSharp_Library_netstandard2_0.fsproj -nodereuse:false -v n /restore /p:DisableCompilerRedirection=true"

// Now run the tests
let logFilePath = Path.Combine(__SOURCE_DIRECTORY__, "..", "artifacts", "TestResults", "Release", "FSharp.Compiler.Service.Test.xml")
runDotnet __SOURCE_DIRECTORY__ "test" (sprintf "FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj --no-restore --no-build -v n -c Release --test-adapter-path . --logger \"nunit;LogFilePath=%s\"" logFilePath)
runDotnet __SOURCE_DIRECTORY__ "test" (sprintf "FSharp.Compiler.Service.Tests/FSharp.Compiler.Service.Tests.fsproj --no-restore --no-build -nodereuse:false -v n -c Release --test-adapter-path . --logger \"nunit;LogFilePath=%s\"" logFilePath)
)

Target.create "NuGet" (fun _ ->
Expand Down
1 change: 1 addition & 0 deletions src/fsharp/FSharp.Build/FSharp.Build.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<Compile Include="FSharpEmbedResXSource.fs" />
<Compile Include="WriteCodeFragment.fs" />
<Compile Include="CreateFSharpManifestResourceName.fs" />
<Compile Include="SubstituteText.fs" />
<None Include="Microsoft.FSharp.Targets" CopyToOutputDirectory="PreserveNewest" />
<None Include="Microsoft.Portable.FSharp.Targets" CopyToOutputDirectory="PreserveNewest" />
<None Include="Microsoft.FSharp.NetSdk.targets" CopyToOutputDirectory="PreserveNewest" />
Expand Down
1 change: 1 addition & 0 deletions src/fsharp/FSharp.Build/Microsoft.FSharp.Targets
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ this file.
<UsingTask TaskName="CreateFSharpManifestResourceName" AssemblyFile="$(FSharpBuildAssemblyFile)" />
<UsingTask TaskName="WriteCodeFragment" AssemblyFile="$(FSharpBuildAssemblyFile)" />
<UsingTask TaskName="FSharpPlatformInformation" AssemblyFile="$(FSharpBuildAssemblyFile)" />
<UsingTask TaskName="SubstituteText" AssemblyFile="$(FSharpBuildAssemblyFile)" />

<PropertyGroup>
<ImportByWildcardBeforeMicrosoftFSharpTargets Condition="'$(ImportByWildcardBeforeMicrosoftFSharpTargets)' == ''">true</ImportByWildcardBeforeMicrosoftFSharpTargets>
Expand Down
92 changes: 92 additions & 0 deletions src/fsharp/FSharp.Build/SubstituteText.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.

namespace FSharp.Build

open System
open System.Collections
open System.IO
open Microsoft.Build.Framework
open Microsoft.Build.Utilities

type SubstituteText () =

let mutable _buildEngine : IBuildEngine = null
let mutable _hostObject : ITaskHost = null

let mutable copiedFiles = new ResizeArray<ITaskItem>()
let mutable embeddedResources : ITaskItem[] = [||]

[<Required>]
member this.EmbeddedResources
with get() = embeddedResources
and set(value) = embeddedResources <- value

[<Output>]
member this.CopiedFiles
with get() = copiedFiles.ToArray()

interface ITask with
member this.BuildEngine
with get() = _buildEngine
and set(value) = _buildEngine <- value

member this.HostObject
with get() = _hostObject
and set(value) = _hostObject <- value

member this.Execute() =
copiedFiles.Clear()
if not(isNull embeddedResources) then
for item in embeddedResources do
// Update ITaskItem metadata to point to new location
let sourcePath = item.GetMetadata("FullPath")

let pattern1 = item.GetMetadata("Pattern1")
let pattern2 = item.GetMetadata("Pattern2")

// Is there any replacement to do?
if not (String.IsNullOrWhiteSpace(pattern1) && String.IsNullOrWhiteSpace(pattern2)) then
if not(String.IsNullOrWhiteSpace(sourcePath)) then
try
let getTargetPathFrom key =
let md = item.GetMetadata(key)
let path = Path.GetDirectoryName(md)
let filename = Path.GetFileName(md)
let target = Path.Combine(path, @"..\resources", filename)
target

// Copy from the location specified in Identity
let sourcePath=item.GetMetadata("Identity")

// Copy to the location specified in TargetPath unless no TargetPath is provided, then use Identity
let targetPath=
let identityPath = getTargetPathFrom "Identity"
let intermediateTargetPath = item.GetMetadata("IntermediateTargetPath")
if not (String.IsNullOrWhiteSpace(intermediateTargetPath)) then
let filename = Path.GetFileName(identityPath)
let target = Path.Combine(intermediateTargetPath, filename)
target
else
identityPath

item.ItemSpec <- targetPath

// Transform file
let mutable contents = File.ReadAllText(sourcePath)
if not (String.IsNullOrWhiteSpace(pattern1)) then
let replacement = item.GetMetadata("Replacement1")
contents <- contents.Replace(pattern1, replacement)
if not (String.IsNullOrWhiteSpace(pattern2)) then
let replacement = item.GetMetadata("Replacement2")
contents <- contents.Replace(pattern2, replacement)

let directory = Path.GetDirectoryName(targetPath)
if not(Directory.Exists(directory)) then
Directory.CreateDirectory(directory) |>ignore

File.WriteAllText(targetPath, contents)
with
| _ -> ()

copiedFiles.Add(item)
true
2 changes: 1 addition & 1 deletion vsintegration/Vsix/RegisterFsharpPackage.pkgdef
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"1"="{92EF0900-2251-11D2-B72E-0000F87572EF}"

[$RootKey$\Packages\{91a04a73-4f2c-4e7c-ad38-c1a68e7da05c}]
"ProductVersion"="10.4"
"ProductVersion"="{{FSProductVersion}}"
"ProductName"="Visual F#"
"CompanyName"="Microsoft Corp."

Expand Down
16 changes: 11 additions & 5 deletions vsintegration/Vsix/VisualFSharpFull/VisualFSharpFull.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,22 @@
<None Include="Source.extension.vsixmanifest">
<SubType>Designer</SubType>
</None>
<Content Include="..\RegisterFsharpPackage.pkgdef">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<IncludeInVSIX>true</IncludeInVSIX>
<Link>RegisterFsharpPackage.pkgdef</Link>
</Content>

<NoneSubstituteText Include="..\RegisterFsharpPackage.pkgdef" CopyToOutputDirectory="PreserveNewest">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably won't work unless we specially handle @(ContentSubstituteText), otherwise the VSSDK probably won't find the .pkgdef in the @(None) collection.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@brettfo I believe the VSSDK picks the packagedefs out of the output directory and since the NoneSubstituteText puts the transformed file there, all is good..

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@brettfo, Okay fixed it.

<TargetFileName>RegisterFsharpPackage.pkgdef</TargetFileName>
<Pattern1>{{FSProductVersion}}</Pattern1>
<Replacement1>$(FSProductVersion)</Replacement1>
<Pattern2>{{FSLanguageVersion}}</Pattern2>
<Replacement2>$(FSLanguageVersion)</Replacement2>
<IncludeInVSix>true</IncludeInVSix>
</NoneSubstituteText>

<Content Include="$(FSharpSourcesRoot)\..\License.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Link>License.txt</Link>
<IncludeInVSIX>true</IncludeInVSIX>
</Content>

<Content Include="$(NuGetPackageRoot)\Microsoft.VisualFSharp.Type.Providers.Redist\$(MicrosoftVisualFSharpTypeProvidersRedistVersion)\content\$(FSharpDataTypeProvidersVersion)\FSharp.Data.TypeProviders.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Link>FSharp.Data.TypeProviders.dll</Link>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,22 @@
<ResourceName>Menus.ctmenu</ResourceName>
<SubType>Designer</SubType>
</VSCTCompile>

<!-- Copy resx file and transform product/language version -->
<CopyVsixResources Include="Resources/**" />
<EmbeddedResource Include="VSPackage.resx">
<GenerateSource>true</GenerateSource>
<GeneratedModuleName>Microsoft.VisualStudio.FSharp.ProjectSystem.FSharpSR</GeneratedModuleName>
<MergeWithCTO>true</MergeWithCTO>
<ManifestResourceName>VSPackage</ManifestResourceName>
<SubType>Designer</SubType>
<IntermediateTargetPath>$(IntermediateOutputPath)resources\</IntermediateTargetPath>
<Pattern1>{{FSProductVersion}}</Pattern1>
<Replacement1>$(FSProductVersion)</Replacement1>
<Pattern2>{{FSLanguageVersion}}</Pattern2>
<Replacement2>$(FSLanguageVersion)</Replacement2>
</EmbeddedResource>

<Compile Include="ProjectPrelude.fs" />
<Compile Include="WaitDialog.fs" />
<Compile Include="MSBuildUtilities.fs" />
Expand Down
6 changes: 3 additions & 3 deletions vsintegration/src/FSharp.ProjectSystem.FSharp/VSPackage.resx
Original file line number Diff line number Diff line change
Expand Up @@ -464,10 +464,10 @@
<value>Customizes the environment to maximize code editor screen space and improve the visibility of F# commands and tool windows.</value>
</data>
<data name="ProductDetails" xml:space="preserve">
<value>Microsoft Visual F# Tools 10.4 for F# 4.6</value>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like the hackery in the project file. I'd rather ProjectSystem.fsproj get reverted and these strings updated to: Microsoft Visual F# Tools {0} for F# {1}, then call string.Format() with the values FSharp.BuildProperties.fsProductVersion/fsLanguageVersion as generated here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@brettfo,

I feel you … unfortunately these values are read by vs from the resource strings. We just tell VS the resource IDs it then grabs the resources and displays them. Here.

We can put the build targets in FSharpBuild.Directory.Build.targets in order to remove the hackery from the project. The bit I'm still trying to figure out, is how to not break xlf, and yet update the localized versions of vspackage ... all in all it is quite touchy.

<value>Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}}</value>
</data>
<data name="9002" xml:space="preserve">
<value>Microsoft Visual F# Tools 10.4 for F# 4.6</value>
<value>Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}}</value>
</data>
<data name="ProductID" xml:space="preserve">
<value>1.0</value>
Expand All @@ -476,7 +476,7 @@
<value>Microsoft Visual F# Tools</value>
</data>
<data name="9001" xml:space="preserve">
<value>Visual F# Tools 10.4 for F# 4.6</value>
<value>Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}}</value>
</data>
<data name="9027" xml:space="preserve">
<value>F# Interactive</value>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -433,13 +433,13 @@
<note />
</trans-unit>
<trans-unit id="ProductDetails">
<source>Microsoft Visual F# Tools 10.4 for F# 4.6</source>
<target state="translated">Nástroje Microsoft Visual F# 10.4 pro F# 4.6</target>
<source>Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}}</source>
<target state="needs-review-translation">Nástroje Microsoft Visual F# {{FSProductVersion}} pro F# {{FSLanguageVersion}}</target>
<note />
</trans-unit>
<trans-unit id="9002">
<source>Microsoft Visual F# Tools 10.4 for F# 4.6</source>
<target state="translated">Nástroje Microsoft Visual F# 10.4 pro F# 4.6</target>
<source>Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}}</source>
<target state="needs-review-translation">Nástroje Microsoft Visual F# {{FSProductVersion}} pro F# {{FSLanguageVersion}}</target>
<note />
</trans-unit>
<trans-unit id="ProductID">
Expand All @@ -453,8 +453,8 @@
<note />
</trans-unit>
<trans-unit id="9001">
<source>Visual F# Tools 10.4 for F# 4.6</source>
<target state="translated">Nástroje Visual F# 10.4 pro F# 4.6</target>
<source>Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}}</source>
<target state="needs-review-translation">Nástroje Visual F# {{FSProductVersion}} pro F# {{FSLanguageVersion}}</target>
<note />
</trans-unit>
<trans-unit id="9027">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -433,13 +433,13 @@
<note />
</trans-unit>
<trans-unit id="ProductDetails">
<source>Microsoft Visual F# Tools 10.4 for F# 4.6</source>
<target state="translated">Microsoft Visual F# Tools 10.4 für f# 4.6</target>
<source>Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}}</source>
<target state="needs-review-translation">Microsoft Visual F# Tools {{FSProductVersion}} für f# {{FSLanguageVersion}}</target>
<note />
</trans-unit>
<trans-unit id="9002">
<source>Microsoft Visual F# Tools 10.4 for F# 4.6</source>
<target state="translated">Microsoft Visual F# Tools 10.4 für f# 4.6</target>
<source>Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}}</source>
<target state="needs-review-translation">Microsoft Visual F# Tools {{FSProductVersion}} für f# {{FSLanguageVersion}}</target>
<note />
</trans-unit>
<trans-unit id="ProductID">
Expand All @@ -453,8 +453,8 @@
<note />
</trans-unit>
<trans-unit id="9001">
<source>Visual F# Tools 10.4 for F# 4.6</source>
<target state="translated">Visual F# Tools 10.4 für F# 4.6</target>
<source>Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}}</source>
<target state="needs-review-translation">Visual F# Tools {{FSProductVersion}} für F# {{FSLanguageVersion}}</target>
<note />
</trans-unit>
<trans-unit id="9027">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -433,13 +433,13 @@
<note />
</trans-unit>
<trans-unit id="ProductDetails">
<source>Microsoft Visual F# Tools 10.4 for F# 4.6</source>
<target state="translated">Herramientas de Microsoft Visual F# 10.4 para F# 4.6</target>
<source>Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}}</source>
<target state="needs-review-translation">Herramientas de Microsoft Visual F# {{FSProductVersion}} para F# {{FSLanguageVersion}}</target>
<note />
</trans-unit>
<trans-unit id="9002">
<source>Microsoft Visual F# Tools 10.4 for F# 4.6</source>
<target state="translated">Herramientas de Microsoft Visual F# 10.4 para F# 4.6</target>
<source>Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}}</source>
<target state="needs-review-translation">Herramientas de Microsoft Visual F# {{FSProductVersion}} para F# {{FSLanguageVersion}}</target>
<note />
</trans-unit>
<trans-unit id="ProductID">
Expand All @@ -453,8 +453,8 @@
<note />
</trans-unit>
<trans-unit id="9001">
<source>Visual F# Tools 10.4 for F# 4.6</source>
<target state="translated">Visual F# Tools 10.4 para F# 4.6</target>
<source>Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}}</source>
<target state="needs-review-translation">Visual F# Tools {{FSProductVersion}} para F# {{FSLanguageVersion}}</target>
<note />
</trans-unit>
<trans-unit id="9027">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -433,13 +433,13 @@
<note />
</trans-unit>
<trans-unit id="ProductDetails">
<source>Microsoft Visual F# Tools 10.4 for F# 4.6</source>
<target state="translated">Microsoft Visual F# Tools 10.4 pour F# 4.6</target>
<source>Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}}</source>
<target state="needs-review-translation">Microsoft Visual F# Tools {{FSProductVersion}} pour F# {{FSLanguageVersion}}</target>
<note />
</trans-unit>
<trans-unit id="9002">
<source>Microsoft Visual F# Tools 10.4 for F# 4.6</source>
<target state="translated">Microsoft Visual F# Tools 10.4 pour F# 4.6</target>
<source>Microsoft Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}}</source>
<target state="needs-review-translation">Microsoft Visual F# Tools {{FSProductVersion}} pour F# {{FSLanguageVersion}}</target>
<note />
</trans-unit>
<trans-unit id="ProductID">
Expand All @@ -453,8 +453,8 @@
<note />
</trans-unit>
<trans-unit id="9001">
<source>Visual F# Tools 10.4 for F# 4.6</source>
<target state="translated">Visual F# Tools 10.4 pour F# 4.6</target>
<source>Visual F# Tools {{FSProductVersion}} for F# {{FSLanguageVersion}}</source>
<target state="needs-review-translation">Visual F# Tools {{FSProductVersion}} pour F# {{FSLanguageVersion}}</target>
<note />
</trans-unit>
<trans-unit id="9027">
Expand Down
Loading