mirror of
https://github.com/uroesch/GitPortable.git
synced 2026-08-24 10:04:09 -05:00
Beta1: Add update and postinstall scripts
Summary:
* Automatic download and installation
via `Update.ps1` and `Postinstall.ps1`
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
*.exe
|
*.exe
|
||||||
Data/
|
Data/
|
||||||
App/Git
|
App/Git
|
||||||
|
Download
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
[Format]
|
[Format]
|
||||||
Type=PortableApps.comFormat
|
Type=PortableApps.comFormat
|
||||||
Version=3.5
|
Version=3.5
|
||||||
|
|
||||||
@@ -43,4 +43,4 @@ ShellCommand=
|
|||||||
[FileTypeIcons]
|
[FileTypeIcons]
|
||||||
[Version]
|
[Version]
|
||||||
PackageVersion=2.25.1.0
|
PackageVersion=2.25.1.0
|
||||||
DisplayVersion=2.25.1-beta0-uroesch
|
DisplayVersion=2.25.1-beta1-uroesch
|
||||||
|
|||||||
@@ -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 =
|
||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -8,4 +8,21 @@ This project is in early beta stage.
|
|||||||
|
|
||||||
## Todo
|
## Todo
|
||||||
- [ ] Documentation
|
- [ ] 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
|
||||||
|
```
|
||||||
|
|||||||
@@ -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 >></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>
|
||||||
|
|||||||
Reference in New Issue
Block a user