<# .SYNOPSIS Installer for Lepton .DESCRIPTION Installs Lepton onto selected Firefox profiles .INPUTS TODO: input directories for installation? Would need to discuss a non-interactive install system .OUTPUTS TODO: output directories that Lepton has been installed to? .PARAMETER u Specifies whether to update a current installation Defaults to false .PARAMETER f Specifies a custom path to look for Firefox profiles in .PARAMETER p Specifies a custom name to use when creating a profile .PARAMETER h Shows this help message .PARAMETER ? Shows this help message .PARAMETER WhatIf Runs the installer without actioning any file copies/moves Equivelant to a dry-run .EXAMPLE PS> .\Install.ps1 -u -f C:\Users\someone\ff-profiles Updates current installations in the profile directory 'C:\Users\someone\ff-profiles' .LINK https://github.com/black7375/Firefox-UI-Fix#readme #> [CmdletBinding( SupportsShouldProcess = $true, PositionalBinding = $false )] param( [Alias("u")] [switch]$updateMode, [Alias("f")] [string]$profileDir, [Alias("p")] [string]$profileName, [Alias("h")] [switch]$help = $false ) #** Helper Utils *************************************************************** #== Message ==================================================================== function Lepton-ErrorMessage() { Write-Error "FAILED: ${args}" exit -1 } function Lepton-OKMessage() { $local:SIZE = 50 $local:FILLED = "" for ($i = 0; $i -le ($SIZE - 2); $i++) { $FILLED += "." } $FILLED += "OK" $local:message = "${args}" Write-Host ${message}(${FILLED}.Substring(${message}.Length)) } $PSMinSupportedVersion = 2 function Verify-PowerShellVersion { Write-Host -NoNewline "Checking PowerShell version... " $PSVersion = [int](Select-Object -Property Major -First 1 -ExpandProperty Major -InputObject $PSVersionTable.PSVersion) Write-Host "[$PSVersion]" if ($PSVersion -lt $PSMinSupportedVersion) { Write-Error -Category NotInstalled "You need a minimum PowerShell version of [$PSMinSupportedVersion] to use this installer" exit -1 } } #== Required Tools ============================================================= function Install-Choco() { # https://chocolatey.org/install # https://docs.chocolatey.org/en-us/choco/setup#non-administrative-install $InstallDir='C:\ProgramData\chocoportable' $env:ChocolateyInstall="$InstallDir" Set-ExecutionPolicy Bypass -Scope Process -Force [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) $env:Path += ";C:\ProgramData\chocoportable" # Adimin: ";C:\ProgramData\chocolatey" refreshenv } function Check-Git() { if ( -Not (Get-Command git -errorAction SilentlyContinue) ) { if ( -Not (Get-Command choco -errorAction SilentlyContinue) ) { Install-Choco } choco install git.commandline -y $env:Path += ";C:\tools\git\bin" # Adimin: ";C:\Program Files\Git\bin" refreshenv } Lepton-OKMessage "Required - git" } #== PATH / File ================================================================ $PSDefaultParameterValues['Out-File:Encoding'] = 'utf8' $currentDir = (Get-Location).path function Filter-Path() { Param ( [Parameter(Mandatory=$true, Position=0)] [string[]] $pathList, [Parameter(Position=1)] [string] $option = "Any" ) return $pathList.Where({ Test-Path -Path "$_" -PathType "${option}" }) } function Copy-Auto() { Param ( [Parameter(Mandatory=$true, Position=0)] [string] $file, [Parameter(Mandatory=$true, Position=1)] [string] $target ) if ( "${file}" -eq "${target}" ) { Write-Host "'${file}' and ${target} are same file" return 0 } if ( Test-Path -Path "${target}" ) { Write-Host "${target} already exists." Write-Host "Now making a backup.." Copy-Auto "${target}" "${target}.bak" Remove-Item "${target}" -Recurse -Force Write-Host "" } Copy-Item -Path "${file}" -Destination "${target}" -Force -Recurse } function Move-Auto() { Param ( [Parameter(Mandatory=$true, Position=0)] [string] $file, [Parameter(Mandatory=$true, Position=1)] [string] $target ) if ( "${file}" -eq "${target}" ) { Write-Host "'${file}' and ${target} are same file" return 0 } if ( Test-Path -Path "${target}" ) { Write-Host "${target} already exists." Write-Host "Now making a backup.." Move-Auto "${target}" "${target}.bak" Write-Host "" } Get-ChildItem -Path "${target}" -Recurse | Move-Item -Path "${file}" -Destination "${target}" -Force } function Restore-Auto() { Param ( [Parameter(Mandatory=$true, Position=0)] [string] $file ) $local:target = "${file}.bak" if ( Test-Path -Path "${file}" ) { Remove-Item "${file}" -Recurse -Force } Get-ChildItem -Path "${target}" -Recurse | Move-Item -Destination "${file}" -Force $local:lookupTarget = "${target}.bak" if ( Test-Path -Path "${lookupTarget}" ) { Restore-Auto "${target}" } } function Write-File() { Param ( [Parameter(Mandatory=$true, Position=0)] [string] $filePath, [Parameter(Position=1)] [string] $fileContent = "" ) if ( "${fileContent}" -eq "" ) { New-Item -Path "${filePath}" -Force } else { Out-File -FilePath "${filePath}" -InputObject "${fileContent}" -Force } } #== INI File ================================================================ # https://devblogs.microsoft.com/scripting/use-powershell-to-work-with-any-ini-file/ function Get-IniContent () { Param ( [Parameter(Mandatory=$true, Position=0)] [string] $filePath ) $ini = @{} switch -regex -file $filePath { "^\[(.+)\]" { # Section $section = $matches[1] $ini[$section] = @{} $CommentCount = 0 } "^(;.*)$" { # Comment $value = $matches[1] $CommentCount = $CommentCount + 1 $name = “Comment” + $CommentCount $ini[$section][$name] = $value } "(.+?)\s*=(.*)" { # For compatibility if ( $section -eq $null ) { $section = "Info" $ini[$section] = @{} } # Key $name,$value = $matches[1..2] $ini[$section][$name] = $value } } return $ini } function Out-IniFile() { Param ( [Parameter(Mandatory=$true, Position=0)] [string] $filePath, [Parameter(Position=1)] [hashtable] $iniObject = @{} ) # Create new file $local:outFile = New-Item -ItemType file -Path "${filepath}" -Force foreach ($i in $iniObject.keys) { if (!($($iniObject[$i].GetType().Name) -eq "Hashtable")) { #No Sections Add-Content -Path $outFile -Value "$i=$($iniObject[$i])" } else { #Sections Add-Content -Path $outFile -Value "[$i]" Foreach ($j in ($iniObject[$i].keys | Sort-Object)) { if ($j -match "^Comment[\d]+") { Add-Content -Path $outFile -Value "$($iniObject[$i][$j])" } else { Add-Content -Path $outFile -Value "$j=$($iniObject[$i][$j])" } } Add-Content -Path $outFile -Value "" } } } #** Select Menu **************************************************************** # https://github.com/chrisseroka/ps-menu function Check-PsMenu() { if(-Not (Get-InstalledModule ps-menu -ErrorAction silentlycontinue)) { Set-PSRepository PSGallery -InstallationPolicy Trusted Install-Module -Name ps-menu -Confirm:$False -Force } } function DrawMenu { param ($menuItems, $menuPosition, $Multiselect, $selection) $l = $menuItems.length for ($i = 0; $i -le $l; $i++) { if ($menuItems[$i] -ne $null){ $item = $menuItems[$i] if ($Multiselect) { if ($selection -contains $i){ $item = '[x] ' + $item } else { $item = '[ ] ' + $item } } if ($i -eq $menuPosition) { Write-Host "> $($item)" -ForegroundColor Green } else { Write-Host " $($item)" } } } } function Toggle-Selection { param ($pos, [array]$selection) if ($selection -contains $pos){ $result = $selection | where {$_ -ne $pos} } else { $selection += $pos $result = $selection } $result } function Menu { param ([array]$menuItems, [switch]$ReturnIndex=$false, [switch]$Multiselect) $vkeycode = 0 $pos = 0 $selection = @() if ($menuItems.Length -gt 0) { try { [console]::CursorVisible=$false #prevents cursor flickering DrawMenu $menuItems $pos $Multiselect $selection While ($vkeycode -ne 13 -and $vkeycode -ne 27) { $press = $host.ui.rawui.readkey("NoEcho,IncludeKeyDown") $vkeycode = $press.virtualkeycode If ($vkeycode -eq 38 -or $press.Character -eq 'k') {$pos--} If ($vkeycode -eq 40 -or $press.Character -eq 'j') {$pos++} If ($vkeycode -eq 36) { $pos = 0 } If ($vkeycode -eq 35) { $pos = $menuItems.length - 1 } If ($press.Character -eq ' ') { $selection = Toggle-Selection $pos $selection } if ($pos -lt 0) {$pos = 0} If ($vkeycode -eq 27) {$pos = $null } if ($pos -ge $menuItems.length) {$pos = $menuItems.length -1} if ($vkeycode -ne 27) { $startPos = [System.Console]::CursorTop - $menuItems.Length [System.Console]::SetCursorPosition(0, $startPos) DrawMenu $menuItems $pos $Multiselect $selection } } } finally { [System.Console]::SetCursorPosition(0, $startPos + $menuItems.Length) [console]::CursorVisible = $true } } else { $pos = $null } if ($ReturnIndex -eq $false -and $pos -ne $null) { if ($Multiselect){ return $menuItems[$selection] } else { return $menuItems[$pos] } } else { if ($Multiselect) { return $selection } else { return $pos } } } #** Profile ******************************************************************** #== Profile Dir ================================================================ # $HOME = (get-psprovider 'FileSystem').Home $firefoxProfileDirPaths = @( "${HOME}\AppData\Roaming\Mozilla\Firefox", "${HOME}\AppData\Roaming\Waterfox", "${HOME}\AppData\Roaming\librewolf", "${HOME}\Desktop\Tor Browser\Browser\TorBrowser\Data\Browser" ) function Check-ProfileDir() { Param ( [Parameter(Position=0)] [string] $profileDir = "" ) if ( "${profileDir}" -ne "" ) { $global:firefoxProfileDirPaths = @("${profileDir}") } $global:firefoxProfileDirPaths = Filter-Path $global:firefoxProfileDirPaths "Container" if ( $firefoxProfileDirPaths.Length -eq 0 ) { Lepton-ErrorMessage "Unable to find firefox profile dir." } Lepton-OKMessage "Profiles dir found" } #== Profile Info =============================================================== $PROFILEINFOFILE="profiles.ini" function Check-ProfileIni() { foreach ( $profileDir in $global:firefoxProfileDirPaths ) { if ( -Not (Test-Path -Path "${profileDir}\${PROFILEINFOFILE}" -PathType "Leaf") ) { Lepton-ErrorMessage "Unable to find ${PROFILEINFOFILE} at ${profileDir}" } } Lepton-OKMessage "Profiles info file found" } #== Profile PATH =============================================================== $firefoxProfilePaths = @() function Update-ProfilePaths() { foreach ( $profileDir in $global:firefoxProfileDirPaths ) { $local:iniContent = Get-IniContent "${profileDir}\${PROFILEINFOFILE}" $global:firefoxProfilePaths += $iniContent.Values.Path | ForEach-Object { "${profileDir}\${PSItem}" } } if ( $firefoxProfilePaths.Length -ne 0 ) { Lepton-OkMessage "Profile paths updated" } else { Lepton-ErrorMessage "Doesn't exist profiles" } } # TODO: Multi select support function Select-Profile() { Param ( [Parameter(Position=0)] [string] $profileName = "" ) if ( "${profileName}" -ne "" ) { $local:targetPath = "" foreach ( $profilePath in $global:firefoxProfilePaths ) { if ( "${profilePath}" -like "*${profileName}" ) { $targetPath = "${profilePath}" break } } if ( "${targetPath}" -ne "" ) { Lepton-OkMessage "Profile, `"${profileName}`" found" $global:firefoxProfilePaths = @("${targetPath}") } else { Lepton-ErrorMessage "Unable to find ${profileName}" } } else { if ( $firefoxProfilePaths.Length -eq 1 ) { Lepton-OkMessage "Auto detected profile" } else { $global:firefoxProfilePaths = Menu $firefoxProfilePaths if ( $firefoxProfilePaths.Length -eq 0 ) { Lepton-ErrorMessage "Please select profiles" } Lepton-OkMessage "Selected profile" } } } #** Lepton Info File *********************************************************** # If you interst RFC, see install.sh #== Lepton Info ================================================================ $LEPTONINFOFILE ="lepton.ini" function Check-LeptonIni() { foreach ( $profileDir in $global:firefoxProfileDirPaths ) { if ( -Not (Test-Path -Path "${profileDir}\${LEPTONINFOFILE}") ) { Lepton-ErrorMessage "Unable to find ${LEPTONINFOFILE} at ${profileDir}" } } Lepton-OkMessage "Lepton info file found" } #== Create info file =========================================================== # We should always create a new one, as it also takes into account the possibility of setting it manually. # Updates happen infrequently, so the creation overhead is less significant. function Get-ProfileDir() { Param ( [Parameter(Mandatory=$true, Position=0)] [string] $profilePath ) foreach ( $profileDir in $firefoxProfileDirPaths ) { if ( "$profilePath" -like "${profileDir}*" ) { return "$profileDir" } } } $CHROMEINFOFILE="LEPTON" function Write-LeptonInfo() { # Init info $local:output = @{} $local:prevDir = $firefoxProfileDirPaths[0] $local:latestPath = ( $firefoxProfilePaths | Select-Object -Last 1 ) foreach ( $profilePath in $global:firefoxProfilePaths ) { $local:LEPTONINFOPATH = "${profilePath}\chrome\${CHROMEINFOFILE}" $local:LEPTONGITPATH = "${profilePath}\chrome\.git" # Profile info $local:Type = "" $local:Ver = "" $local:Branch = "" $local:Path = "" if ( Test-Path -Path "${LEPTONINFOPATH}" ) { if ( Test-Path -Path "${LEPTONGITPATH}" -PathType "Container" ) { $Type = "Git" $Ver = $(git --git-dir "${LEPTONGITPATH}" rev-parse HEAD) $Branch = $(git --git-dir "${LEPTONGITPATH}" rev-parse --abbrev-ref HEAD) } else { $local:iniContent = Get-IniContent "${LEPTONINFOPATH}" $Type = $iniContent["Info"]["Type"] $Ver = $iniContent["Info"]["Ver"] $Branch = $iniContent["Info"]["Branch"] if ( "${Type}" -eq "" ) { $Type = "Local" } } $Path = "${profilePath}" } # Flushing $local:profileDir = Get-ProfileDir "${profilePath}" $local:profileName = Split-Path "${profilePath}" -Leaf if ( "${prevDir}" -ne "${profileDir}" ) { Out-IniFile "${prevDir}\${LEPTONINFOFILE}" $output $output = @{} } # Make output contents foreach ( $key in @("Type", "Branch", "Ver", "Path") ) { $local:value = (Get-Variable -Name "${key}").Value if ( "$value" -ne "" ) { $output["${profileName}"] += @{"${key}" = "${value}"} } } # Latest element flushing if ( "${profilePath}" -eq "${latestPath}" ) { Out-IniFile "${profileDir}\${LEPTONINFOFILE}" $output } $prevDir = "${profileDir}" } # Verify Check-LeptonIni Lepton-OkMessage "Lepton info file created" } #** Install ******************************************************************** #== Install Types ============================================================== $updateMode = $false $leptonBranch = "master" function Select-Distribution() { while ( $true ) { $local:selected = $false $local:selectedDistribution = Menu @("Original(default)", "Photon-Style", "Proton-Style", "Update") switch ( $selectedDistribution ) { "Original(default)" { $global:leptonBranch = "master" ; $selected = $true } "Photon-Style" { $global:leptonBranch = "photon-style"; $selected = $true } "Proton-Style" { $global:leptonBranch = "proton-style"; $selected = $true } "Update" { $global:updateMode = $true ; $selected = $true } default { Write-Host "Invalid option, reselect please." } } if ( $selected -eq $true ) { break } } Lepton-OkMessage "Selected ${selectedDistribution}" } $leptonInstallType = "Network" # Other types: Local, Release function Check-InstallType() { Param ( [Parameter(Mandatory=$true, Position=0)] [string[]] $targetList, [Parameter(Mandatory=$true, Position=1)] [string] $installType ) $local:targetCount = $targetList.Length $local:foundCount = (Filter-Path $targetList ).Length if ( "${targetCount}" -eq "${foundCount}" ) { $global:leptonInstallType="${installType}" } } $checkLocalFiles = @( "userChrome.css", "userContent.css", "icons" ) $checkReleaseFiles = @( "user.js" "chrome\userChrome.css" "chrome\userContent.css" "chrome\icons" ) function Check-InstallTypes() { Check-InstallType $checkLocalFiles "Local" Check-InstallType $checkReleaseFiles "Release" Lepton-OkMessage "Checked install type: ${leptonInstallType}" if ( "${leptonInstallType}" -eq "Network" ) { Select-Distribution } if ( "${leptonInstallType}" -eq "Local" ) { if ( Test-Path -Path ".git" -PathType "Container" ) { Select-Distribution git checkout "${leptonBranch}" } } } #== Custom Install ============================================================= $customFiles = @( "user-overrides.js", "userChrome-overrides.css", "userContent-overrides.css" ) $localCustomFiles = $customFiles.Clone() $customFileExist = $false function Check-CustomFiles() { $global:localCustomFiles = Filter-Path $localCustomFiles if ( $global:localCustomFiles.Length -gt 0 ) { $global:customFileExist = $true Lepton-OKMessage "Check custom file detected" foreach ( $customFile in $global:localCustomFiles ) { Write-Host "- ${customFile}" } } } function Copy-CustomFiles() { if ( "${customFileExist}" -eq $true ) { # If Release or Network mode, Local is passed (Already copied) if ( "${leptonInstallType}" -ne "Local" ) { foreach ( $profilePath in $global:firefoxProfilePaths ) { foreach ( $customFile in $global:localCustomFiles ) { if ( "${customFile}" -eq "user-overrides.js" ) { Copy-Auto "${customFile}" "${profilePath}\${customFile}" } else { Copy-Auto "${customFile}" "${profilePath}\chrome\${customFile}" } } } } Lepton-OKMessage "End custom file copy" } } $customMethod = "" $customReset = $false $customAppend = $false function Set-CustomMethod() { $local:menuAppend="Append - Maintain changes in existing files and apply custom" $local:menuOverwrite="Overwrite - After initializing the change, apply only custom" $local:menuNone="None - Maintain changes in existing files" $local:menuReset="Reset- Reset to pure lepton theme without custom" Write-Host "Select custom method" while ( "${customMethod}" -eq "" ) { $local:applyMethod = Menu @("${menuAppend}", "${menuOverwrite}", "${menuNone}", "${menuReset}") switch ( $applyMethod ) { "${menuAppend}" { $global:customMethod = "Append" $global:customAppend = $true } "${menuOverwrite}" { $global:customMethod = "Overwrite" $global:customReset = $true $global:customAppend = $true } "${menuNone}" { $global:customMethod = "None" } "${menuReset}" { $global:customMethod = "Reset" $global:customReset = $true } default { Write-Host "Invalid option, reselect please." } } } Lepton-OKMessage "Selected ${customMethod}" } $customFileApplied = $false function Apply-CustomFile() { Param ( [Parameter(Mandatory=$true, Position=0)] [string] $profilePath, [Parameter(Mandatory=$true, Position=1)] [string] $targetPath, [Parameter(Mandatory=$true, Position=2)] [string] $customPath, [Parameter(Position=3)] [string] $otherCustomPath = "" ) $local:leptonDir = "${profilePath}\chrome" $local:gitDir = "${leptonDir}\.git" if ( Test-Path -Path "${customPath}" -PathType leaf ) { $global:customFileApplied = $true if ( "${customMethod}" -eq "" ) { Set-CustomMethod } if ( "${customReset}" -eq $true ) { if ( "${targetPath}" -like "*user.js" ) { Copy-Item -Path "${leptonDir}\user.js" -Destination "${targetPath}" -Force } else { git --git-dir "${gitDir}" --work-tree "${leptonDir}" checkout HEAD -- "${targetPath}" } } if ( "${customAppend}" -eq $true ) { # Apply without duplication if ( -not (Write-Output "$(Write-Output $(Get-Content -Path "${targetPath}"))" | Select-String -Pattern "$(Write-Output $(Get-Content -Path "${customPath}"))" -SimpleMatch -Quiet) ) { Get-Content -Path "${customPath}" | Out-File -FilePath "${targetPath}" -Append } } } elseif ( "${otherCustomPath}" -ne "" ) { Apply-CustomFile "${profilePath}" "${targetPath}" "${otherCustomPath}" } } function Apply-CustomFiles() { foreach ( $profilePath in $global:firefoxProfilePaths ) { foreach ( $customFile in $global:customFiles ) { $local:targetFile = $customFile.Replace("-overrides", "") if ( "${customFile}" -eq "user-overrides.js" ) { $local:targetPath = "${profilePath}\${targetFile}" $local:customPath = "${profilePath}\user-overrides.js" $local:otherCustomPath = "${profilePath}\chrome\user-overrides.js" Apply-CustomFile "${profilePath}" "${targetPath}" "${customPath}" "${otherCustomPath}" } else { Apply-CustomFile "${profilePath}" "${profilePath}\chrome\${targetFile}" "${profilePath}\chrome\${customFile}" } } } if ( "${customFileApplied}" -eq $true ) { Lepton-OKMessage "End custom file applied" } } #== Install Helpers ============================================================ $chromeDuplicate = $false function Check-ChromeExist() { if ( (Test-Path -Path "chrome") -and (-Not (Test-Path -Path "chrome\${LEPTONINFOFILE}")) ) { $global:chromeDuplicate = $true Move-Auto "chrome" "chrome.bak" Lepton-OkMessage "Backup files" } } function Check-ChromeRestore() { if ( "${chromeDuplicate}" -eq $true ) { Restore-Auto "chrome" Lepton-OkMessage "End restore files" } Lepton-OkMessage "End check restore files" } function Clean-Lepton() { if ( ($chromeDuplicate -ne $true) -and (Test-Path -Path "chrome") ) { Remove-Item -Path "chrome" -Recurse -Force } Lepton-OkMessage "End clean files" } function Clone-Lepton() { Param ( [Parameter(Position=0)] [string] $branch = "" ) if ( "${branch}" -eq "" ) { $branch = "${leptonBranch}" } git clone -b "${branch}" https://github.com/black7375/Firefox-UI-Fix.git chrome if ( -Not (Test-Path -Path "chrome" -PathType "Container") ) { Lepton-ErrorMessage "Unable to find downloaded files" } } function Copy-Lepton() { Param ( [Parameter(Position=0)] [string] $chromeDir = "chrome", [Parameter(Position=0)] [string] $userJSPath = "${chromeDir}\user.js" ) foreach ( $profilePath in $global:firefoxProfilePaths ) { Copy-Auto "${userJSPath}" "${profilePath}\user.js" Copy-Auto "${chromeDir}" "${profilePath}\chrome" } Lepton-OkMessage "End profile copy" } #== Each Install =============================================================== function Install-Local() { Copy-Lepton "${currentDir}" "user.js" Copy-CustomFiles Apply-CustomFiles } function Install-Release() { Copy-Lepton "chrome" "user.js" Copy-CustomFiles Apply-CustomFiles } function Install-Network() { Check-ChromeExist Check-Git Clone-Lepton Copy-Lepton Copy-CustomFiles Clean-Lepton Check-ChromeRestore Apply-CustomFiles } function Install-Profile() { Lepton-OkMessage "Started install" switch ( "${leptonInstallType}" ) { "Local" { Install-Local } "Release" { Install-Release } "Network" { Install-Network } } Lepton-OkMessage "End install" } #** Update ********************************************************************* function Stash-File() { Param ( [Parameter(Mandatory=$true, Position=0)] [string] $leptonDir, [Parameter(Mandatory=$true, Position=1)] [string] $gitDir ) if ( "$(git --git-dir "${gitDir}" --work-tree "${leptonDir}" diff --stat)" -ne '' ) { git --git-dir "${gitDir}" --work-tree "${leptonDir}" stash --quiet return $true } return $false } function Restore-File() { Param ( [Parameter(Mandatory=$true, Position=0)] [string] $leptonDir, [Parameter(Mandatory=$true, Position=1)] [string] $gitDir, [Parameter(Position=2)] [string] $gitDirty = "$false" ) if ( "${gitDirty}" -eq $true ) { git --git-dir "${gitDir}" --work-tree "${leptonDir}" stash pop --quiet } } function Update-Profile() { Check-Git foreach ( $profileDir in $global:firefoxProfileDirPaths ) { $local:LEPTONINFOPATH = "${profileDir}\${LEPTONINFOFILE}" $local:LEPTONINFO = Get-IniContent "${LEPTONINFOPATH}" $local:sections = $LEPTONINFO.Keys if ( $sections.Length -ne 0 ) { foreach ( $section in $sections ) { $local:Type = $LEPTONINFO["${section}"]["Type"] $local:Branch = $LEPTONINFO["${section}"]["Branch"] $local:Path = $LEPTONINFO["${section}"]["Path"] $local:leptonDir = "${Path}\chrome" $local:gitDir = "${leptonDir}\.git" if ( "${Type}" -eq "Git" ) { $local:gitDirty = $(Stash-File "${leptonDir}" "${gitDir}") git --git-dir "${gitDir}" --work-tree "${leptonDir}" checkout "${Branch}" git --git-dir "${gitDir}" --work-tree "${leptonDir}" pull --no-edit Restore-File "${leptonDir}" "${gitDir}" "$gitDirty" } elseif ( "${Type}" -eq "Local" -or "${Type}" -eq "Release" ) { Check-ChromeExist Clone-Lepton $firefoxProfilePaths = @("${Path}") Copy-Lepton if ( "${Branch}" -eq $null ) { $Branch = "${leptonBranch}" } git --git-dir "${gitDir}" --work-tree "${leptonDir}" checkout "${Branch}" if ( "${Type}" -eq "Release" ) { $local:Ver=$(git --git-dir "${gitDir}" describe --tags --abbrev=0) git --git-dir "${gitDir}" --work-tree "${leptonDir}" checkout "tags/${Ver}" } Clean-Lepton Check-ChromeRestore } else { Lepton-ErrorMessage "Unable to find update type, ${Type} at ${section}" } } } } Apply-CustomFiles } #** Main *********************************************************************** function Check-Help { # Cheap and dirty way of getting the same output as '-?' for '-h' and '-Help' if ($help) { Get-Help "$PSCommandPath" exit 0 } } function Install-Lepton { Verify-PowerShellVersion # Check installed version meets minimum Check-InstallTypes Check-ProfileDir $profileDir Check-ProfileIni Update-ProfilePaths Write-LeptonInfo Check-CustomFiles if ( $updateMode ) { Update-Profile } else { Select-Profile $profileName Install-Profile } Write-LeptonInfo } Check-Help Install-Lepton