Beta1: Add update and postinstall scripts

Summary:
  * Automatic download and installation
    via `Update.ps1` and `Postinstall.ps1`
This commit is contained in:
Urs Roesch
2020-03-22 14:31:49 +01:00
parent 8b203e3a19
commit 79ce865831
7 changed files with 640 additions and 3 deletions
+1
View File
@@ -1,3 +1,4 @@
*.exe
Data/
App/Git
Download
+2 -2
View File
@@ -1,4 +1,4 @@
[Format]
[Format]
Type=PortableApps.comFormat
Version=3.5
@@ -43,4 +43,4 @@ ShellCommand=
[FileTypeIcons]
[Version]
PackageVersion=2.25.1.0
DisplayVersion=2.25.1-beta0-uroesch
DisplayVersion=2.25.1-beta1-uroesch
+9
View File
@@ -0,0 +1,9 @@
[Version]
Package = 2.25.1.0
Display = 2.25.1-beta1-uroesch
[Archive]
URL1 = https://github.com/git-for-windows/git/releases/download/v2.25.1.windows.1/PortableGit-2.25.1-32-bit.7z.exe
Checksum1 = SHA256:9054e283465ca1153043bae4cf515782b3e0a3bd95c28bfb20f66de3922da1d0
TargetName1 = Git
ExtractName1 =
+20
View File
@@ -0,0 +1,20 @@
# Run the post-install script
$_PostInstall = "$AppDir\Git\post-install.bat"
If (Test-Path $_PostInstall) {
Switch (Is-Unix) {
$True { $_Prefix = 'wine'; break }
default { $_Prefix = ''; break }
}
Try {
Debug info "Run post install command $_Prefix $_PostInstall"
# Will always throw an error as the post-install script
# is removing itself at the end.
Invoke-Expression "$_Prefix $_PostInstall" 2>&1 | Out-Null
}
Catch {
Debug fatal "Failed to run command $_PostInstall"
Exit 127
}
}
+413
View File
@@ -0,0 +1,413 @@
# -----------------------------------------------------------------------------
# Description: Generic Update Script for PortableApps
# Author: Urs Roesch <github@bun.ch>
# -----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
# Globals
# -----------------------------------------------------------------------------
$Version = "0.0.11-alpha"
$AppRoot = "$PSScriptRoot\..\.."
$AppDir = "$AppRoot\App"
$AppInfoDir = "$AppDir\AppInfo"
$AppInfoIni = "$AppInfoDir\appinfo.ini"
$UpdateIni = "$AppInfoDir\update.ini"
$Debug = $True
# -----------------------------------------------------------------------------
# Classes
# -----------------------------------------------------------------------------
Class IniConfig {
[string] $File
[object] $Table
[bool] $Verbose = $False
[bool] $Parsed = $False
IniConfig(
[string] $f
) {
$This.File = $f
}
[void] Log([string] $Message) {
If ($This.Verbose) {
Write-Host "IniConfig: $Message"
}
}
[void] Parse() {
If ($this.Parsed) { return }
$Content = Get-Content $This.File
$Section = ''
$This.Log($Content)
$This.Table = @()
Foreach ($Line in $Content) {
$This.Log("Processing '$Line'")
If ($Line[0] -eq ";") {
$This.Log("Skip comment line")
}
ElseIf ($Line[0] -eq "[") {
$Section = $Line -replace "[\[\]]", ""
$This.Log("Found new section: '$Section'")
}
ElseIf ($Line -like "*=*") {
$This.Log("Found Keyline")
$This.Table += @{
Section = $Section
Key = $Line.split("=")[0].Trim()
Value = $Line.split("=")[1].Trim()
}
}
}
$This.Parsed = $True
}
[object] Section([string] $Key) {
$This.Parse()
$Section = @{}
Foreach ($Item in $This.Table) {
If ($Item["Section"] -eq $Key) {
$Section += @{ $Item["Key"] = $Item["Value"] }
}
}
return $Section
}
}
# -----------------------------------------------------------------------------
Class Download {
[string] $URL
[string] $ExtractName
[string] $TargetName
[string] $Checksum
[string] $DownloadDir = "$PSScriptRoot\..\..\Download"
Download(
[string] $u,
[string] $en,
[string] $tn,
[string] $c
){
$This.URL = $u
$This.ExtractName = $en
$This.TargetName = $tn
$This.Checksum = $c
}
[string] Basename() {
$Elements = $This.URL.split('/')
$Basename = $Elements[$($Elements.Length-1)]
return $Basename
}
[string] ExtractTo() {
# If Extract name is empty the downloaded archive has all files
# placed in the root of the archive. In that case we use the
# TargetName and and attach it to the script location
If ($This.ExtractName -eq "") {
return "$($This.DownloadDir)\$($This.TargetName)"
}
return $This.DownloadDir
}
[string] MoveFrom() {
If ($This.ExtractName -eq "") {
return "$($This.DownloadDir)\$($This.TargetName)"
}
return "$($This.DownloadDir)\$($This.ExtractName)"
}
[string] MoveTo() {
return "$PSScriptRoot\..\..\App\$($This.TargetName)"
}
[string] OutFile() {
return "$($This.DownloadDir)\$($This.Basename())"
}
}
# -----------------------------------------------------------------------------
# Functions
# -----------------------------------------------------------------------------
Function Debug() {
param(
[string] $Severity,
[string] $Message
)
$Color = 'White'
$Severity = $Severity.ToUpper()
Switch ($Severity) {
'INFO' { $Color = 'Green'; break }
'WARN' { $Color = 'Yellow'; break }
'ERROR' { $Color = 'Orange'; break }
'FATAL' { $Color = 'Red'; break }
default { $Color = 'White'; break }
}
If (-Not($Debug)) { return }
Write-Host "$(Get-Date -Format u) - " -NoNewline
Write-Host $Severity": " -NoNewline -ForegroundColor $Color
Write-Host $Message.Replace("$AppRoot\", '')
}
# -----------------------------------------------------------------------------
Function Is-Unix() {
($PSScriptRoot)[0] -eq '/'
}
# -----------------------------------------------------------------------------
Function Which-7Zip() {
$Locations = @(
"$Env:ProgramFiles\7-Zip",
"$Env:ProgramFiles(x86)\7-Zip",
"$AppRoot\..\7-ZipPortable\App\7-Zip"
)
Switch (Is-Unix) {
$True {
$Prefix = 'wine'
$Binary = '7z'
break
}
default {
$Prefix = ''
$Binary = '7z.exe'
}
}
Try {
$Path = $(Get-Command $Binary).Source.ToString()
}
Catch {
Foreach ($Location in $Locations) {
If (Test-Path "$Location\$Binary") {
$Path = "$Prefix $Location\$Binary"
}
}
}
Finally {
If (!($Path)) {
Debug fatal "Could not locate $Binary"
Exit 76
}
}
return $Path
}
# -----------------------------------------------------------------------------
Function Check-Sum {
param(
[object] $Download
)
($Algorithm, $Sum) = $Download.Checksum.Split(':')
$Result = (Get-FileHash -Path $Download.OutFile() -Algorithm $Algorithm).Hash
Debug info "Checksum of INI ($($Sum.ToUpper())) and download ($Result)"
return ($Sum.ToUpper() -eq $Result)
}
# -----------------------------------------------------------------------------
Function Download-File {
param(
[object] $Download
)
If (!(Test-Path $Download.DownloadDir)) {
Debug info "Create directory $($Download.DownloadDir)"
New-Item -Path $Download.DownloadDir -Type directory | Out-Null
}
If (!(Test-Path $Download.OutFile())) {
Debug info "Download URL $($Download.URL) to $($Download.OutFile()).part"
Invoke-WebRequest -Uri $Download.URL `
-OutFile "$($Download.OutFile()).part"
Debug info "Move file $($Download.OutFile).part to $($Download.OutFile())"
Move-Item -Path "$($Download.OutFile()).part" `
-Destination $Download.OutFile()
}
If (!(Check-Sum -Download $Download)) {
Debug fatal "Checksum for $($Download.OutFile()) does not match '$Checksum'"
Exit 1
}
Debug info "Downloaded file '$($Download.OutFile())'"
}
# -----------------------------------------------------------------------------
Function Expand-Download {
param(
[object] $Download
)
If (!(Test-Path $Download.ExtractTo())) {
Debug info "Create extract directory $($Download.ExtractTo())"
New-Item -Path $Download.ExtractTo() -Type "directory" | Out-Null
}
Debug info "Extract $($Download.OutFile()) to $($Download.ExtractTo())"
Expand-Archive -LiteralPath $Download.OutFile() `
-DestinationPath $Download.ExtractTo() -Force
}
# -----------------------------------------------------------------------------
Function Expand-7Zip {
param(
[object] $Download
)
$7ZipExe = $(Which-7Zip)
If (!(Test-Path $Download.ExtractTo())) {
Debug info "Create extract directory $($Download.ExtractTo())"
New-Item -Path $Download.ExtractTo() -Type "directory" | Out-Null
}
Debug info "Extract $($Download.OutFile()) to $($Download.ExtractTo())"
$Command = "$7ZipExe x -r -y " +
" -o""$($Download.ExtractTo())"" " +
" ""$($Download.OutFile())"""
Debug info "Running command '$Command'"
Invoke-Expression $Command | Out-Null
}
# -----------------------------------------------------------------------------
Function Update-Release {
param(
[object] $Download
)
Switch -regex ($Download.Basename()) {
'\.[Zz][Ii][Pp]$' {
Expand-Download -Download $Download
break
}
'\.7[Zz]\.[Ee][Xx][Ee]$' {
Expand-7Zip -Download $Download
break
}
}
If (Test-Path $Download.MoveTo()) {
Debug info "Cleanup $($Download.MoveTo())"
Remove-Item -Path $Download.MoveTo() `
-Force `
-Recurse
}
Debug info `
"Move release from $($Download.MoveFrom()) to $($Download.MoveTo())"
Move-Item -Path $Download.MoveFrom() `
-Destination $Download.MoveTo() `
-Force
}
# -----------------------------------------------------------------------------
Function Update-Appinfo-Item() {
param(
[string] $IniFile,
[string] $Match,
[string] $Replace
)
If (Test-Path $IniFile) {
Debug info "Update INI File $IniFile with $Match -> $Replace"
$Content = (Get-Content $IniFile)
$Content -replace $Match, $Replace | `
Out-File -Encoding UTF8 -FilePath $IniFile
}
}
# -----------------------------------------------------------------------------
Function Update-Appinfo() {
$Version = $Config.Section("Version")
Update-Appinfo-Item `
-IniFile $AppInfoIni `
-Match '^PackageVersion\s*=.*' `
-Replace "PackageVersion=$($Version['Package'])"
Update-Appinfo-Item `
-IniFile $AppInfoIni `
-Match '^DisplayVersion\s*=.*' `
-Replace "DisplayVersion=$($Version['Display'])"
}
# -----------------------------------------------------------------------------
Function Update-Application() {
$Archive = $Config.Section('Archive')
$Position = 1
While ($True) {
If (-Not ($Archive.ContainsKey("URL$Position"))) {
Break
}
$Download = [Download]::new(
$Archive["URL$Position"],
$Archive["ExtractName$Position"],
$Archive["TargetName$Position"],
$Archive["Checksum$Position"]
)
Download-File -Download $Download
Update-Release -Download $Download
$Position += 1
}
}
# -----------------------------------------------------------------------------
Function Postinstall() {
$Postinstall = "$PSScriptRoot\Postinstall.ps1"
If (Test-Path $Postinstall) {
. $Postinstall
}
}
# -----------------------------------------------------------------------------
Function Windows-Path() {
param( [string] $Path )
$Path = $Path -replace ".*drive_(.*)", '$1'
$Path = $Path.Replace("/", "\")
return $Path
}
# -----------------------------------------------------------------------------
Function Create-Launcher() {
Set-Location $AppRoot
$AppPath = (Get-Location)
Try {
Invoke-Helper -Command `
"..\PortableApps.comLauncher\PortableApps.comLauncherGenerator.exe"
}
Catch {
Debug fatal "Unable to create PortableApps Launcher"
Exit 21
}
}
# -----------------------------------------------------------------------------
Function Create-Installer() {
Try {
Invoke-Helper -Sleep 5 -Command `
"..\PortableApps.comInstaller\PortableApps.comInstaller.exe"
}
Catch {
Debug fatal "Unable to create installer for PortableApps"
Exit 42
}
}
# -----------------------------------------------------------------------------
Function Invoke-Helper() {
param(
[string] $Command,
[int] $Sleep = $Null
)
Set-Location $AppRoot
$AppPath = (Get-Location)
If (Is-Unix) {
Debug info "Run PA Command: wine $Command $(Windows-Path $AppPath)"
Invoke-Expression "wine $Command $(Windows-Path $AppPath)"
}
Else {
# Windows seems to need a bit of break before
# writing the file completely to disk
Write-FileSystemCache $AppPath.Drive.Name
If ($Sleep) {
Debug info "Waiting for filsystem cache to catch up"
Sleep $Sleep
}
Debug info "Run PA Command '$Command $AppPath'"
Invoke-Expression "$Command $AppPath"
}
}
# -----------------------------------------------------------------------------
# Main
# -----------------------------------------------------------------------------
$Config = [IniConfig]::new($UpdateIni)
Update-Application
Update-Appinfo
Postinstall
Create-Launcher
Create-Installer
+18 -1
View File
@@ -8,4 +8,21 @@ This project is in early beta stage.
## Todo
- [ ] Documentation
- [ ] Download script to fetch the application ZIP file
- [x] Download script to fetch the application ZIP file
## Build
### Prerequisites
* [PortableApps.com Launcher](https://portableapps.com/apps/development/portableapps.com_launcher)
* [PortableApps.com Installer](https://portableapps.com/apps/development/portableapps.com_installer)
* [Powershell](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell-core-on-linux?view=powershell-7)
* [Wine (Linux / MacOS only)](https://www.winehq.org/)
### Build
To build the installer run the following command in the root of the git repository.
```
powershell Other/Update/Update.ps1
```
+177
View File
@@ -0,0 +1,177 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"
<html lang="en-US"><head><title>Git for Windows Portable Help</title>
<link rel="alternate" type="application/rss+xml" title="PortableApps.com" href="http://portableapps.com/feeds/general">
<link rel="SHORTCUT ICON" href="Other/Help/images/favicon.ico">
<style>body {
font-family: Verdana,Arial,Helvetica,sans-serif;
font-size: 76%;
color: #000;
margin: 20px;
background: #E6E8EA;
text-align: center;
}
a
{
color: #B31616;
font-weight: bold;
}
a:link {
}
a:visited {
}
a:active {
}
a:hover {
color: red;
}
h1, h2, h3, h4, h5, h6 {
font-family: Arial, sans-serif;
font-weight: normal;
}
h1 {
color: #B31616;
font-weight: bold;
letter-spacing: -2px;
font-size: 2.2em;
border-bottom: 1px solid silver;
padding-bottom: 5px;
}
h2 {
font-size: 1.5em;
border-bottom: 1px solid silver;
padding-bottom: 3px;
clear: both;
}
h3 {
font-size: 1.2em;
}
h4 {
font-size: 1.1em;
}
h5 {
font-size: 1.0em;
}
h6 {
font-size: 0.8em;
}
img {
border: 0;
}
ol, ul, li {
font-size: 1.0em;
}
p, table, tr, td, th {
font-size: 1.0em;
}
pre {
font-family: Courier New,Courier,monospace;
font-size: 1.0em;
}
strong, b {
font-weight: bold;
}
table, tr, td {
font-size: 1.0em;
border-collapse: collapse;
}
td, th {
border: 1px solid #aaaaaa;
border-collapse: collapse;
padding: 3px;
}
th {
background: #3667A8;
color: white;
}
ol ol {
list-style-type: lower-alpha;
}
.content {
text-align: left;
margin-left: auto;
margin-right: auto;
width: 780px;
background-color: #FFFFFF;
border-left: 1px solid Black;
border-right: 1px solid Black;
padding: 12px 30px;
line-height: 150%;
}
.logo {
background: #ffffff url("Other/Help/images/help_background_header.png") repeat-x;
width: 840px;
margin-top: 20px;
margin-left: auto;
margin-right: auto;
text-align: left;
border-right: 1px solid black;
border-left: 1px solid black;
}
.footer {
background: #ffffff url("Other/Help/images/help_background_footer.png") repeat-x;
width: 840px;
height: 16px;
margin-left: auto;
margin-right: auto;
text-align: left;
border-right: 1px solid black;
border-left: 1px solid black;
}
.logo img {
padding-left: 0px;
border: none;
position: relative;
top: -4px;
}
* html .content {
width: 760px;
}
* html .logo, * html .footer {
width: 820px;
}
.content h1 {
margin: 0px;
}
h1.hastagline {
border: 0;
}
h2.tagline {
color: #747673;
clear: none;
margin-top: 0em;
}
/*printer styles*/
@media print{
body, .content {margin: 0; padding: 0;}
.navigation, .locator, .footer a, .message, .footer-links {display:none;}
.footer, .content, .header {border: none;}
a {text-decoration: none; font-weight: normal; color: black;}
}</style>
</head>
<body>
<div class="logo"><a href="http://portableapps.com/"><img src="Other/Help/images/help_logo_top.png" width="229" height="47" alt="PortableApps.com - Your Digital Life, Anywhere"></a></div>
<div class="content">
<h1 class="hastagline">Git for Windows Portable Help</h1>
<h2 class="tagline">compare files on the go</h2>
<p>Git for Windows Portable allows you to compare and diff files on the go. <a href="https://gitforwindows.org/">Learn more about Git for Windows...</a></p>
<a href="http://portableapps.com/donate"><img src="Other/Help/images/donation_button.png" width="110" height="23" border="0" align="top" alt="Make a Donation"></a> - Support PortableApps.com's Hosting and Development
<p><a href="http://github.com/uroesch/GitPortable">Go to the Git for Windows Portable Homepage &gt;&gt;</a></p>
<p><a href="http://portableapps.com/">Get more portable apps at PortableApps.com</a></p>
<p>This software is OSI Certified Open Source Software. OSI Certified is a certification mark of the Open Source Initiative.</p>
<h2>Git for Windows Portable-Specific Issues</h2>
<ul>
<li><a href="http://portableapps.com/support/portable_app#downloading">Downloading a Portable App</a></li>
<li><a href="http://portableapps.com/support/portable_app#installing">Installing a Portable App</a></li>
<li><a href="http://portableapps.com/support/portable_app#using">Using a Portable App</a></li>
<li><a href="http://portableapps.com/support/portable_app#upgrading">Upgrading a Portable App</a></li>
</ul>
</div>
<div class="footer"></div>
</body>
</html>