Changeset - r26240:362f75d604f5
[Not reviewed]
.github/workflows/release.yml
Show inline comments
 
@@ -850,6 +850,189 @@ jobs:
 
        path: build/bundles
 
        retention-days: 5
 

	
 
  windows-appx:
 
    name: Windows Store
 
    needs:
 
    - source
 
    - windows
 

	
 
    if: needs.source.outputs.is_tag == 'true'
 
    runs-on: windows-latest
 

	
 
    steps:
 
    - name: Download source
 
      uses: actions/download-artifact@v2
 
      with:
 
        name: internal-source
 

	
 
    - name: Unpack source
 
      shell: bash
 
      run: |
 
        tar -xf source.tar.gz --strip-components=1
 

	
 
    - name: Download x86 build
 
      uses: actions/download-artifact@v2
 
      with:
 
        name: openttd-windows-x86
 

	
 
    - name: Download x64 build
 
      uses: actions/download-artifact@v2
 
      with:
 
        name: openttd-windows-x64
 

	
 
    - name: Download arm64 build
 
      uses: actions/download-artifact@v2
 
      with:
 
        name: openttd-windows-arm64
 

	
 
    - name: Unpack builds
 
      shell: bash
 
      run: |
 
        mkdir builds
 
        cd builds
 

	
 
        function extract {
 
            mkdir $1
 

	
 
            # Extract the zip version of the release
 
            unzip ../openttd-*-windows-$2.zip -d $1
 

	
 
            # Remove the extraneous directory
 
            mv $1/openttd-*-windows-$2/* $1/
 
            rmdir $1/openttd-*-windows-$2
 

	
 
            # Move the openttd.exe to the '{arch}-binaries' folder
 
            mkdir $1-binaries
 
            mv $1/openttd.exe $1-binaries/
 
        }
 

	
 
        extract x86 win32
 
        extract x64 win64
 
        extract arm64 arm64
 

	
 
        # Use the "x86" folder as the source of the common binaries (lang files, etc) and remove the others
 
        mv x86 common-binaries
 
        rm -rf x64 arm64
 

	
 
    - name: Install OpenGFX
 
      shell: bash
 
      run: |
 
        mkdir -p builds/common-binaries/baseset
 
        cd builds/common-binaries/baseset
 

	
 
        echo "::group::Download OpenGFX"
 
        curl -L https://cdn.openttd.org/opengfx-releases/7.1/opengfx-7.1-all.zip -o opengfx-all.zip
 
        echo "::endgroup::"
 

	
 
        echo "::group::Unpack OpenGFX"
 
        unzip opengfx-all.zip
 
        tar xf opengfx-*.tar
 
        echo "::endgroup::"
 

	
 
        rm -f opengfx-all.zip opengfx-*.tar
 

	
 
    - name: Install OpenMSX
 
      shell: bash
 
      run: |
 
        mkdir -p builds/common-binaries/baseset
 
        cd builds/common-binaries/baseset
 

	
 
        echo "::group::Download OpenMSX"
 
        curl -L https://cdn.openttd.org/openmsx-releases/0.4.2/openmsx-0.4.2-all.zip -o openmsx-all.zip
 
        echo "::endgroup::"
 

	
 
        echo "::group::Unpack OpenGFX"
 
        unzip openmsx-all.zip
 
        tar xf openmsx-*.tar
 
        echo "::endgroup::"
 

	
 
        rm -f openmsx-all.zip openmsx-*.tar
 

	
 
    - name: Install OpenSFX
 
      shell: bash
 
      run: |
 
        mkdir -p builds/common-binaries/baseset/opensfx
 
        cd builds/common-binaries/baseset/opensfx
 

	
 
        echo "::group::Download OpenSFX"
 
        curl -L https://cdn.openttd.org/opensfx-releases/1.0.3/opensfx-1.0.3-all.zip -o opensfx-all.zip
 
        echo "::endgroup::"
 

	
 
        echo "::group::Unpack OpenSFX"
 
        unzip opensfx-all.zip
 
        tar xf opensfx-*.tar
 
        echo "::endgroup::"
 

	
 
        rm -f opensfx-all.zip opensfx-*.tar
 

	
 
    - name: Generate signing certificate
 
      shell: cmd
 
      run: |
 
        cd builds
 

	
 
        REM We need to provide a signed .appx to the Windows Store, so generate a certificate with password 'password'
 
        call ..\os\windows\winstore\generate-key.bat "CN=78024DA8-4BE4-4C77-B12E-547BBF7359D2" password cert.pfx
 

	
 
    - name: Generate assets
 
      shell: cmd
 
      run: |
 
        cd os\windows\winstore
 
        call generate-assets.bat
 

	
 
    - name: Prepare manifests
 
      shell: cmd
 
      run: |
 
        cd builds
 
        mkdir manifests
 

	
 
        REM Set the version environment variable
 
        call ..\os\windows\winstore\set-version.bat x86-binaries\openttd.exe
 

	
 
        call ..\os\windows\winstore\prepare-manifests.bat manifests "CN=78024DA8-4BE4-4C77-B12E-547BBF7359D2" "57420OpenTTDDevelopers.OpenTTDofficial"
 

	
 
    - name: Prepare binaries
 
      shell: bash
 
      run: |
 
        cd builds
 

	
 
        # Copy the Windows Store assets
 
        mkdir common-binaries/Assets
 
        cp -R ../os/windows/winstore/assets-common/* common-binaries/Assets/
 

	
 
        mkdir Assets
 
        cp -R ../os/windows/winstore/assets/* Assets/
 

	
 
        cp manifests/*.xml .
 

	
 
    - name: Build
 
      shell: cmd
 
      run: |
 
        REM Add the Windows SDK tools to the PATH
 

	
 
        echo|set /p="SET VS_INSTALLDIR=" > _vspath.bat
 
        vswhere -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath >> _vspath.bat
 
        call _vspath.bat
 
        call "%VS_INSTALLDIR%\Common7\Tools\VsDevCmd.bat"
 

	
 
        REM Set the version environment variable
 
        call os\windows\winstore\set-version.bat builds\x86-binaries\openttd.exe
 

	
 
        cd builds
 
        mkdir output
 

	
 
        REM Build and sign the package
 
        makeappx build /v /f PackagingLayout.xml /op output\ /bv %OTTD_VERSION% /pv %OTTD_VERSION% /ca
 
        SignTool sign /fd sha256 /a /f cert.pfx /p password "output\OpenTTD.appxbundle"
 

	
 
    - name: Store appx
 
      uses: actions/upload-artifact@v2
 
      with:
 
        name: openttd-windows-store
 
        path: |
 
          builds/output/OpenTTD.appxbundle
 
          builds/cert.pfx
 
        retention-days: 5
 

	
 
  upload:
 
    name: Upload (AWS)
 
    needs:
os/windows/winstore/generate-assets.bat
Show inline comments
 
new file 100644
 
@echo off
 
powershell -File "%~dp0generate-assets.ps1"
os/windows/winstore/generate-assets.ps1
Show inline comments
 
new file 100644
 
function ResizeImage() {
 
    param([String]$sourcePath, [Int]$targetWidth, [Int]$targetHeight, [String]$targetPath)
 

	
 
    Add-Type -AssemblyName "System.Drawing"
 

	
 
    $img = [System.Drawing.Image]::FromFile($sourcePath)
 

	
 
    $ratioX = $targetWidth / $img.Width;
 
    $ratioY = $targetHeight / $img.Height;
 

	
 
    $ratio = $ratioY
 

	
 
    if ($ratioX -le $ratioY) {
 
        $ratio = $ratioX
 
    }
 

	
 
    $newWidth = [int] ($img.Width * $ratio)
 
    $newHeight = [int] ($img.Height * $ratio)
 

	
 
    $resizedImage = New-Object System.Drawing.Bitmap($targetWidth, $targetHeight)
 
    $graph = [System.Drawing.Graphics]::FromImage($resizedImage)
 
    $graph.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic
 

	
 
    $graph.Clear([System.Drawing.Color]::Transparent)
 
    $graph.DrawImage($img, $targetWidth / 2 - $newWidth / 2, $targetHeight / 2 - $newHeight / 2, $newWidth, $newHeight)
 

	
 
    $resizedImage.Save($targetPath)
 
    $resizedImage.Dispose()
 
    $img.Dispose()
 
}
 

	
 
$logoPath = "..\..\..\media\openttd.2048.png"
 

	
 
# Create the main image assets required for the Windows Store
 
New-Item -Path "." -Name "assets" -ItemType "directory" -Force
 
ResizeImage $logoPath 1240 1240 "assets\LargeTile.png"
 
ResizeImage $logoPath 284 284 "assets\SmallTile.png"
 
ResizeImage $logoPath 2480 1200 "assets\SplashScreen.png"
 
ResizeImage $logoPath 176 176 "assets\Square44x44Logo.png"
 
Copy-Item "assets\Square44x44Logo.png" -Destination "assets\Square44x44Logo.targetsize-44_altform-unplated.png"
 
ResizeImage $logoPath 600 600 "assets\Square150x150Logo.png"
 
Copy-Item "assets\Square150x150Logo.png" -Destination "assets\Square150x150Logo.targetsize-150_altform-unplated.png"
 
ResizeImage $logoPath 200 200 "assets\StoreLogo.png"
 
ResizeImage $logoPath 1240 600 "assets\Wide310x150Logo.png"
 

	
 
# Copy the logo for the store for the common package
 
New-Item -Path "." -Name "assets-common" -ItemType "directory" -Force
 
Copy-Item "assets\StoreLogo.png" -Destination "assets-common\StoreLogo.png"
os/windows/winstore/generate-key.bat
Show inline comments
 
new file 100644
 
@echo off
 
powershell -File "%~dp0generate-key.ps1" %1 %2 %3
os/windows/winstore/generate-key.ps1
Show inline comments
 
new file 100644
 
[CmdletBinding()]
 
[Alias()]
 
Param
 
(
 
    # Publisher ("CN=xyz")
 
    [Parameter(Mandatory=$true, Position=0)]
 
    $Publisher,
 

	
 
    # Password
 
    [Parameter(Mandatory=$true, Position=1)]
 
    $PasswordParam,
 

	
 
    # Filename
 
    [Parameter(Mandatory=$true, Position=2)]
 
    $OutputFilename
 
)
 

	
 
$cert = New-SelfSignedCertificate -Type Custom -Subject $Publisher -KeyUsage DigitalSignature -FriendlyName "OpenTTD signing certificate" -CertStoreLocation "Cert:\CurrentUser\My" -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.3", "2.5.29.19={text}")
 

	
 
$password = ConvertTo-SecureString -String $PasswordParam -Force -AsPlainText
 
Export-PfxCertificate -cert "Cert:\CurrentUser\My\$($cert.Thumbprint)" -FilePath $OutputFilename -Password $password
os/windows/winstore/manifests/AssetsPackage.appxmanifest
Show inline comments
 
new file 100644
 
<?xml version="1.0" encoding="UTF-8"?>
 
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:uap6="http://schemas.microsoft.com/appx/manifest/uap/windows10/6" IgnorableNamespaces="uap uap6">
 
   <Identity Name="$IDENTITY_NAME$" Publisher="$PUBLISHER$" Version="$VERSION$" ResourceId="OpenTTD-common" />
 
   <Properties>
 
      <uap6:AllowExecution>false</uap6:AllowExecution>
 
      <DisplayName>OpenTTD (official)</DisplayName>
 
      <PublisherDisplayName>OpenTTD Developers</PublisherDisplayName>
 
      <Logo>Assets\StoreLogoCommon.png</Logo>
 
   </Properties>
 
   <Resources>
 
      <Resource Language="en-gb" />
 
      <Resource Language="en-us" />
 
      <Resource Language="en-au" />
 
      <Resource Language="af-za" />
 
      <Resource Language="ar-eg" />
 
      <Resource Language="eu-es" />
 
      <Resource Language="be-by" />
 
      <Resource Language="pt-br" />
 
      <Resource Language="bg-bg" />
 
      <Resource Language="ca-es" />
 
      <Resource Language="hr-hr" />
 
      <Resource Language="cs-cz" />
 
      <Resource Language="da-dk" />
 
      <Resource Language="nl-nl" />
 
      <Resource Language="et-ee" />
 
      <Resource Language="fo-fo" />
 
      <Resource Language="fr-fr" />
 
      <Resource Language="gd-gb" />
 
      <Resource Language="gl-es" />
 
      <Resource Language="de-de" />
 
      <Resource Language="el-gr" />
 
      <Resource Language="he-il" />
 
      <Resource Language="hu-hu" />
 
      <Resource Language="is-is" />
 
      <Resource Language="id-id" />
 
      <Resource Language="ga-ie" />
 
      <Resource Language="it-it" />
 
      <Resource Language="ja-jp" />
 
      <Resource Language="ko-kr" />
 
      <Resource Language="lv-lv" />
 
      <Resource Language="lt-lt" />
 
      <Resource Language="lb-lu" />
 
      <Resource Language="ms-my" />
 
      <Resource Language="nb-no" />
 
      <Resource Language="no-no" />
 
      <Resource Language="pl-pl" />
 
      <Resource Language="pt-pt" />
 
      <Resource Language="ro-ro" />
 
      <Resource Language="ru-ru" />
 
      <Resource Language="sr-latn-rs" />
 
      <Resource Language="zh-cn" />
 
      <Resource Language="sk-sk" />
 
      <Resource Language="sl-si" />
 
      <Resource Language="es-es" />
 
      <Resource Language="es-mx" />
 
      <Resource Language="sv-se" />
 
      <Resource Language="ta-in" />
 
      <Resource Language="th-th" />
 
      <Resource Language="zh-tw" />
 
      <Resource Language="tr-tr" />
 
      <Resource Language="uk-ua" />
 
      <Resource Language="vi-vn" />
 
      <Resource Language="cy-gb" />
 
   </Resources>
 
   <Dependencies>
 
      <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17134.0" MaxVersionTested="10.0.18363.0" />
 
   </Dependencies>
 
</Package>
os/windows/winstore/manifests/Package.appxmanifest
Show inline comments
 
new file 100644
 
<?xml version="1.0" encoding="utf-8"?>
 
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" IgnorableNamespaces="uap mp rescap">
 
  <Identity Name="$IDENTITY_NAME$" Publisher="$PUBLISHER$" Version="$VERSION$" ProcessorArchitecture="$ARCHITECTURE$" />
 
  <Properties>
 
    <DisplayName>OpenTTD (official)</DisplayName>
 
    <PublisherDisplayName>OpenTTD Developers</PublisherDisplayName>
 
    <Logo>Assets\StoreLogo.png</Logo>
 
  </Properties>
 
  <Dependencies>
 
    <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17134.0" MaxVersionTested="10.0.18363.0" />
 
  </Dependencies>
 
  <Resources>
 
    <Resource Language="en-gb" />
 
    <Resource Language="en-us" />
 
    <Resource Language="en-au" />
 
    <Resource Language="af-za" />
 
    <Resource Language="ar-eg" />
 
    <Resource Language="eu-es" />
 
    <Resource Language="be-by" />
 
    <Resource Language="pt-br" />
 
    <Resource Language="bg-bg" />
 
    <Resource Language="ca-es" />
 
    <Resource Language="hr-hr" />
 
    <Resource Language="cs-cz" />
 
    <Resource Language="da-dk" />
 
    <Resource Language="nl-nl" />
 
<!--    <Resource Language="eo-eo" />-->
 
    <Resource Language="et-ee" />
 
    <Resource Language="fo-fo" />
 
<!--    <Resource Language="fi-fi" />-->
 
    <Resource Language="fr-fr" />
 
    <Resource Language="gd-gb" />
 
    <Resource Language="gl-es" />
 
    <Resource Language="de-de" />
 
    <Resource Language="el-gr" />
 
    <Resource Language="he-il" />
 
    <Resource Language="hu-hu" />
 
    <Resource Language="is-is" />
 
    <Resource Language="id-id" />
 
    <Resource Language="ga-ie" />
 
    <Resource Language="it-it" />
 
    <Resource Language="ja-jp" />
 
    <Resource Language="ko-kr" />
 
<!--	<Resource Language="la-va" />-->
 
    <Resource Language="lv-lv" />
 
    <Resource Language="lt-lt" />
 
    <Resource Language="lb-lu" />
 
    <Resource Language="ms-my" />
 
    <Resource Language="nb-no" />
 
    <Resource Language="no-no" />
 
    <Resource Language="pl-pl" />
 
    <Resource Language="pt-pt" />
 
    <Resource Language="ro-ro" />
 
    <Resource Language="ru-ru" />
 
    <Resource Language="sr-latn-rs" />
 
    <Resource Language="zh-cn" />
 
    <Resource Language="sk-sk" />
 
    <Resource Language="sl-si" />
 
    <Resource Language="es-es" />
 
    <Resource Language="es-mx" />
 
    <Resource Language="sv-se" />
 
    <Resource Language="ta-in" />
 
    <Resource Language="th-th" />
 
    <Resource Language="zh-tw" />
 
    <Resource Language="tr-tr" />
 
    <Resource Language="uk-ua" />
 
    <Resource Language="vi-vn" />
 
    <Resource Language="cy-gb" />
 
  </Resources>
 
  <Applications>
 
    <Application Id="OpenTTD" Executable="openttd.exe" EntryPoint="Windows.FullTrustApplication">
 
      <uap:VisualElements DisplayName="OpenTTD (official)" Description="OpenTTD is an open source simulation game based upon Transport Tycoon Deluxe." BackgroundColor="transparent" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png">
 
        <uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png" Square310x310Logo="Assets\LargeTile.png" Square71x71Logo="Assets\SmallTile.png">
 
        </uap:DefaultTile>
 
        <uap:SplashScreen Image="Assets\SplashScreen.png" />
 
      </uap:VisualElements>
 
    </Application>
 
  </Applications>
 
  <Capabilities>
 
    <Capability Name="internetClientServer" />
 
    <rescap:Capability Name="runFullTrust" />
 
  </Capabilities>
 
</Package>
os/windows/winstore/manifests/PackagingLayout.xml
Show inline comments
 
new file 100644
 
<PackagingLayout xmlns="http://schemas.microsoft.com/appx/makeappx/2017">
 
    <!-- Main game -->
 
    <PackageFamily ID="OpenTTD" FlatBundle="false" ManifestPath="manifests\Package.appxmanifest" ResourceManager="false">
 
        <!-- x86 code package-->
 
        <Package ID="OpenTTD-x86" ProcessorArchitecture="x86" ManifestPath="manifests\Package-x86.appxmanifest">
 
            <Files>
 
                <File DestinationPath="**" SourcePath="x86-binaries\**"/>
 
                <File DestinationPath="Assets\**" SourcePath="Assets\**"/>
 
            </Files>
 
        </Package>
 

	
 
        <!-- x64 code package-->
 
        <Package ID="OpenTTD-x64" ProcessorArchitecture="x64" ManifestPath="manifests\Package-x64.appxmanifest">
 
            <Files>
 
                <File DestinationPath="**" SourcePath="x64-binaries\**"/>
 
                <File DestinationPath="Assets\**" SourcePath="Assets\**"/>
 
            </Files>
 
        </Package>
 

	
 
        <!-- ARM64 code package-->
 
        <Package ID="OpenTTD-ARM64" ProcessorArchitecture="arm64" ManifestPath="manifests\Package-ARM64.appxmanifest">
 
            <Files>
 
                <File DestinationPath="**" SourcePath="ARM64-binaries\**"/>
 
                <File DestinationPath="Assets\**" SourcePath="Assets\**"/>
 
            </Files>
 
        </Package>
 

	
 
        <!-- Common asset package-->
 
        <AssetPackage ID="OpenTTD-common" AllowExecution="false" ManifestPath="manifests\AssetsPackage.appxmanifest">
 
            <Files>
 
                <File DestinationPath="**" SourcePath="common-binaries\**"/>
 
            </Files>
 
        </AssetPackage>
 
    </PackageFamily>
 
</PackagingLayout>
os/windows/winstore/prepare-manifests.bat
Show inline comments
 
new file 100644
 
@echo off
 
powershell -File "%~dp0prepare-manifests.ps1" %1 %2 %3 %OTTD_VERSION%
os/windows/winstore/prepare-manifests.ps1
Show inline comments
 
new file 100644
 
[CmdletBinding()]
 
[Alias()]
 
Param
 
(
 
    # Output folder
 
    [Parameter(Mandatory=$true, Position=0)]
 
    $OutputFolder,
 

	
 
    # Publisher ("CN=xyz")
 
    [Parameter(Mandatory=$true, Position=1)]
 
    $Publisher,
 

	
 
    # IdentityName
 
    [Parameter(Mandatory=$true, Position=2)]
 
    $IdentityName,
 

	
 
    # Version
 
    [Parameter(Mandatory=$true, Position=3)]
 
    $AppVersion
 
)
 

	
 
function Prepare-Manifest {
 
    param (
 
        $Architecture
 
    )
 

	
 
    (Get-Content "$($PSScriptRoot)\manifests\Package.appxmanifest").replace('$PUBLISHER$', $Publisher).replace('$IDENTITY_NAME$', $IdentityName).replace('$VERSION$', $AppVersion).replace('$ARCHITECTURE$', $Architecture) | Set-Content "$($OutputFolder)\Package-$($Architecture).appxmanifest"
 
}
 

	
 
# Prepare the application binary manifests
 
Prepare-Manifest x86
 
Prepare-Manifest x64
 
Prepare-Manifest arm64
 

	
 
# Prepare the assets package manifest
 
(Get-Content "$($PSScriptRoot)\manifests\AssetsPackage.appxmanifest").replace('$PUBLISHER$', $Publisher).replace('$IDENTITY_NAME$', $IdentityName).replace('$VERSION$', $AppVersion) | Set-Content "$($OutputFolder)\AssetsPackage.appxmanifest"
 

	
 
# Prepare the overall package manifest
 
(Get-Content "$($PSScriptRoot)\manifests\Package.appxmanifest").replace('$PUBLISHER$', $Publisher).replace('$IDENTITY_NAME$', $IdentityName).replace('$VERSION$', $AppVersion).replace(' ProcessorArchitecture="$ARCHITECTURE$"', '') | Set-Content "$($OutputFolder)\Package.appxmanifest"
 

	
 
# Copy the PackagingLayout XML file
 
(Get-Content "$($PSScriptRoot)\manifests\PackagingLayout.xml") | Set-Content "$($OutputFolder)\PackagingLayout.xml"
os/windows/winstore/set-version.bat
Show inline comments
 
new file 100644
 
@echo off
 
if [%1]==[] goto err
 

	
 
powershell -File "%~dp0set-version.ps1" %1 > "%temp%\ottd-set-version.bat"
 
if not errorlevel 0 goto err
 
call "%temp%\ottd-set-version.bat"
 
del /q "%temp%\ottd-set-version.bat"
 

	
 
@rem Version number will now be in %OTTD_VERSION%
 

	
 
goto :eof
 

	
 
:err
 
echo Please supply the path of openttd.exe as the argument to this batch file.
os/windows/winstore/set-version.ps1
Show inline comments
 
new file 100644
 
[CmdletBinding()]
 
[Alias()]
 
Param
 
(
 
    # EXE path
 
    [Parameter(Mandatory=$true, Position=0)]
 
    $ExePath
 
)
 

	
 
try
 
{
 
    $versionInfo = (Get-Item "$ExePath").VersionInfo
 

	
 
    # Generate the app version - the build number (MS calls it revision) is always 0 because the Windows Store requires that
 
    $AppVersion = "$($versionInfo.FileMajorPart).$($versionInfo.FileMinorPart).$($versionInfo.FileBuildPart).0"
 

	
 
    Write-Output "SET OTTD_VERSION=$($AppVersion)"
 
}
 
catch
 
{
 
    Write-Output "@ECHO Error retrieving EXE version - did you provide a path?"
 
    exit 1
 
}
0 comments (0 inline, 0 general)