Private/WebsiteRootFunctions.ps1

function BackupWebsiteRoot
{
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory=$true)]
        [ValidateScript({
            if (Test-Path $_) { $true }
            else { Throw "'$_' path is not valid. Please, provide a valid value" }})]
        [string]$SourceDir,

        [Parameter(Mandatory=$true)]
        [ValidateScript({
            if (Test-Path $_) { $true }
            else { Throw "'$_' path is not valid. Please, provide a valid value" }})]
        [string]$TargetDir,
        
        [string]$ExcludedDirs,

        [string]$LogFile
    )

    WriteLog -Path $LogFile -Message "Creating unique backup directory"
    $uniqueDir = NewUniqueDir -Directory "$TargetDir" -SubDirectory "WebsiteRootBackups"
    WriteLog -Path $LogFile -Message "Unique backup directory created '$uniqueDir'"
    
    # Always create log directory
    # Only backups which cotain log directory (created from Sitecore.Powershell) are considered valid for restore
    WriteLog -Path $LogFile -Message "Creating Robocopy log directory"
    $logDir = NewLogDir -Directory $uniqueDir
    WriteLog -Path $LogFile -Message "Robocopy log directory created '$logDir'"

    $excludedDirsArray = @()
    $еxcludedDirsOption = $null

    if(![String]::IsNullOrWhiteSpace($ExcludedDirs))
    {
        WriteLog -Path $LogFile -Message "Excluded directories '$ExcludedDirs'"
        $excludedDirsArray = $ExcludedDirs.Split(',').Trim()
        $еxcludedDirsOption = ,"/XD" + $excludedDirsArray
    }
    else 
    {
        WriteLog -Path $LogFile -Message "Backup without excluded directories"
    }

    WriteLog -Path $LogFile -Message "OUTPUT: Copy started. Please, wait"
    
    $robocopyLogFile = "$logDir\RobocopyBackupLog.txt"
    WriteLog -Path $LogFile -Message "'$robocopyLogFile' Robocopy log file will be used"

    if($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent)
    {
        Robocopy $SourceDir $uniqueDir /MIR $еxcludedDirsOption /LOG+:"$robocopyLogFile" /TEE
    }
    else 
    {
        Robocopy $SourceDir $uniqueDir /MIR $еxcludedDirsOption /LOG+:"$robocopyLogFile"
    }
    WriteLog -Path $LogFile -Message "OUTPUT: Copy finished. Please, wait finalizing the backup"

    if($excludedDirsArray.count -gt 0)
    {
        $excludedRelativeDirs = @()

        ForEach($dir in $excludedDirsArray)
        {
            $excludedRelativeDirs += $dir.Replace($SourceDir, "")
        }

        WriteLog -Path $LogFile -Message "Excluded directories (relative paths) '$excludedRelativeDirs'"

        # Excluded directories file is used on restore
        # Creates the file after Robocopy is finished, because otherwise the MIR option will delete it
        WriteLog -Path $LogFile -Message "Creating new excluded directories file"
        $excludedDirsFile = NewExcludedDirsFile -Directory $logDir -ExcludedDirs $excludedRelativeDirs
        WriteLog -Path $LogFile -Message "New excluded directories file created '$excludedDirsFile'"
        
        # Creates empty directories for each excluded directory to be able to exclude them on restore and keep them untouched.
        WriteLog -Path $LogFile -Message "Creating empty backup excluded directories"
        NewEmptyDirs -Directory $uniqueDir -RelativeDirs $excludedRelativeDirs
        WriteLog -Path $LogFile -Message "Empty backup excluded directories created"
    }
}

function BackupWebsiteRootRemotely
{
    [CmdletBinding()]
    Param
    (      
        [Parameter(Mandatory=$true)]
        [ValidateScript({
            if (Test-Path $_) { $true }
            else { Throw "'$_' path is not valid. Please, provide a valid value" }})]
        [string]$SourceDir,

        [Parameter(Mandatory=$true)]
        [ValidateScript({
            if (Test-Path $_) { $true }
            else { Throw "'$_' path is not valid. Please, provide a valid value" }})]
        [string]$TargetDir,
        
        [string]$ExcludedDirs,

        $VerboseRemote    
    )

    try
    {
        $VerbosePreference = $VerboseRemote

        Write-Verbose "VERBOSE: Importing 'Sitecore.Deployment'" *>&1
        Import-Module -Name Sitecore.Deployment -ErrorAction Stop
        Write-Verbose "VERBOSE: 'Sitecore.Deployment' imported" *>&1

        Backup-WebsiteRoot -SourceDir $SourceDir -TargetDir $TargetDir -ExcludedDirs $ExcludedDirs
    }
    catch 
    {
        Write-Warning "ERROR: 'Sitecore.Deployment' is not installed" *>&1
        $message = $_.Exception | Format-List -Force | Out-String
        Write-Verbose "VERBOSE_ERROR: $message" *>&1
    }
}

function RestoreWebsiteRoot
{
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory=$true)]
        [ValidateScript({
            if (Test-Path $_) { $true }
            else { Throw "'$_' path is not valid. Please, provide a valid value" }})]
        [string]$SourceDir,

        [Parameter(Mandatory=$true)]
        [ValidateScript({
            if (Test-Path $_) { $true }
            else { Throw "'$_' path is not valid. Please, provide a valid value" }})]
        [string]$TargetDir,

        [string]$LogFile
    )

    try 
    {
        WriteLog -Path $LogFile -Message "Getting the most recent backup"
        $websiteRootBackups = Join-Path -Path $SourceDir -ChildPath "WebsiteRootBackups"
        $lastBackup = GetLastCreatedDir -Directory $websiteRootBackups
        if([String]::IsNullOrWhiteSpace($lastBackup))
        {
            Throw "No backup found"
        }
        WriteLog -Path $LogFile -Message "Most recent backup found '$lastBackup'"

        WriteLog -Path $LogFile -Message "Checking if the backup is valid"
        # Only backups which cotain log directory (created from Sitecore.Powershell) are considered valid for restore.
        $logDir = GetLogDir -Directory $lastBackup
        if([String]::IsNullOrWhiteSpace($logDir))
        {
            Throw "The last created folder in backups root folder is not a valid backup. If you have created some backup manually, please restore it manually"
        }
        WriteLog -Path $LogFile -Message "Backup is valid"

        WriteLog -Path $LogFile -Message "Restore source: '$lastBackup'"
        WriteLog -Path $LogFile -Message "Restore target: '$TargetDir'"

        WriteLog -Path $LogFile -Message "Checking for excluded directories"
        $excludedDirsOption = @("/XD", $logDir)
        $excludedRelativeDirs = GetExcludedDirs -Directory $logDir
        ForEach($dir in $excludedRelativeDirs)
        {
            $excludedDirsOption += Join-Path -Path $lastBackup -ChildPath $dir
        }
        WriteLog -Path $LogFile -Message "Excluded directories '$excludedDirsOption'"

        WriteLog -Path $LogFile -Message "OUTPUT: Copy started. Please, wait"

        $robocopyLogFile = "$logDir\RobocopyRestoreLog.txt"
        WriteLog -Path $LogFile -Message "'$robocopyLogFile' Robocopy log file will be used "

        if($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent)
        {
            Robocopy $lastBackup $TargetDir /MIR $excludedDirsOption /LOG+:"$robocopyLogFile" /TEE
        }
        else 
        {
            Robocopy $lastBackup $TargetDir /MIR $excludedDirsOption /LOG+:"$robocopyLogFile"
        }

        WriteLog -Path $LogFile -Message "OUTPUT: Copy finished"
    }
    catch
    {
        RegisterException
    }
}

function RestoreWebsiteRootRemotely
{
    [CmdletBinding()]
    Param
    (      
        [Parameter(Mandatory=$true)]
        [ValidateScript({
            if (Test-Path $_) { $true }
            else { Throw "'$_' path is not valid. Please, provide a valid value" }})]
        [string]$SourceDir,

        [Parameter(Mandatory=$true)]
        [ValidateScript({
            if (Test-Path $_) { $true }
            else { Throw "'$_' path is not valid. Please, provide a valid value" }})]
        [string]$TargetDir,

        $VerboseRemote    
    )

    try
    {
        $VerbosePreference = $VerboseRemote

        Write-Verbose "VERBOSE: Importing 'Sitecore.Deployment'" *>&1
        Import-Module -Name Sitecore.Deployment -ErrorAction Stop
        Write-Verbose "VERBOSE: 'Sitecore.Deployment' imported" *>&1

        Restore-WebsiteRoot -SourceDir $SourceDir -TargetDir $TargetDir
    }
    catch 
    {
        Write-Warning "ERROR: 'Sitecore.Deployment' is not installed" *>&1
        $message = $_.Exception | Format-List -Force | Out-String
        Write-Verbose "VERBOSE_ERROR: $message" *>&1
    }
}