Skip to content

Commit d1ecde3

Browse files
Beta of v1.0.3
1 parent 5a79539 commit d1ecde3

File tree

2 files changed

+66
-51
lines changed

2 files changed

+66
-51
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# PSTimeMachine Change Log
22

3+
## Version 1.0.3 (in progress)
4+
- If a file is in use and can't be copied, PSTimeMachine will now keep running instead of terminating.
5+
- If a copy-only backup is performed, file names will now be written to the log file.
6+
- Resolve-Path has replaced -Replace for calculating relative paths.
7+
38
## Version 1.0.2 (2019-06-03)
49
- Fixed a bug where an initial or -NoHardLinks backup would not show verbose errors when -Verbose was supplied.
510
- Fixed a bug where the script would terminate before completion if transcription were not enabled.

PSTimeMachine.ps1

Lines changed: 61 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<#
22
.NOTES
3-
PSTimeMachine.ps1 - Version 1.0.2
3+
PSTimeMachine.ps1 - Version 1.0.3-beta6
44
(c) 2019 Colin Cogle <colin@colincogle.name>
55
66
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
@@ -91,16 +91,19 @@ Param(
9191
[Switch]$NoStatistics = $false
9292
)
9393

94-
# Save the old error preference. It's rude to clobber the user's environment.
94+
# Save the old error preference and location. It's rude to clobber the user's environment.
9595
New-Variable -Option Constant -Name OldErrorActionPreference -Value $ErrorActionPreference
96+
New-Variable -Option Constant -Name OldLocation -Value (Get-Location)
9697
$ErrorActionPreference = "Stop"
98+
Set-Location -Path $SourcePath
9799

98100
# We're going to create a folder to hold the backup, named for the current date and time.
99101
# Format everything except the year with leading zeroes.
100102
New-Variable -Option Constant -Name Today -Value (Get-Date)
101103
New-Variable -Option Constant -Name FolderName -Value (("{0:yyyy}-{0:MM}-{0:dd}T{0:hh}-{0:mm}-{0:ss}" -f $Today) + ".inProgress")
102104

103105
# Start logging?
106+
$DoVerboseCopy = $VerbosePreference -eq "Continue"
104107
If (-Not $NoLogging) {
105108
$script:LogFile = (New-TemporaryFile)
106109
Start-Transcript -Path (($script:LogFile).Name)
@@ -131,63 +134,69 @@ $bytesCopied = 0
131134
$bytesTotal = 0
132135

133136
Try {
134-
# Has hardlinking support been disabled? If so, just do a copy.
135-
If ($NoHardLinks) {
136-
Write-Verbose "Hard-linking is disabled at user request. Copying all files."
137-
Copy-Item -Path (Join-Path -Path $SourcePath "*") -Destination (Join-Path -Path $DestinationPath $FolderName) -Recurse
137+
$DoCopyOnlyBackup = $NoHardLinks
138+
139+
# Look for old backups in the same destination.
140+
$PreviousBackups = (Get-ChildItem -Attributes Directory -Path $DestinationPath -Exclude "*.inProgress" -ErrorAction SilentlyContinue `
141+
| Where-Object {$_.Name -CMatch "\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}(\.inProgress)?"} `
142+
| Sort-Object -Descending CreationTime
143+
)
144+
If ($PreviousBackups.Count -gt 0) {
145+
Write-Verbose "Previous backup found. Doing an incremental backup."
146+
$DoCopyOnlyBackup = $false
147+
$PreviousBackup = $PreviousBackups[0].Name
138148
}
139149
Else {
140-
# Look for old backups in the same destination.
141-
$PreviousBackups = (Get-ChildItem -Attributes Directory -Path $DestinationPath -Exclude "*.inProgress" -ErrorAction SilentlyContinue `
142-
| Where-Object {$_.Name -CMatch "\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}(\.inProgress)?"} `
143-
| Sort-Object -Descending CreationTime
144-
)
145-
If ($PreviousBackups.Count -eq 0) {
146-
If ($FailIfOldBackupsAreMissing) {
147-
Throw [System.Management.Automation.ItemNotFoundException] "No previous backups were found. Exiting at user request."
148-
}
149-
Write-Verbose "No previous backups exist. Creating an initial backup."
150-
151-
$DoVerboseCopy = $VerbosePreference -eq "Continue"
152-
Copy-Item -Path (Join-Path -Path $SourcePath "*") -Destination (Join-Path -Path $DestinationPath $FolderName) -Recurse -Verbose:$DoVerboseCopy
150+
If ($FailIfOldBackupsAreMissing) {
151+
Throw [System.Management.Automation.ItemNotFoundException] "No previous backups were found. Exiting at user request."
153152
}
154-
Else {
155-
# Get the most recent backup name.
156-
$PreviousBackup = $PreviousBackups[0].Name
153+
Write-Verbose "Previous backups not found. Doing a copy-only backup."
154+
$DoCopyOnlyBackup = $true
155+
}
157156

158-
Get-ChildItem -Path "$SourcePath\" -Recurse -ErrorAction Stop | ForEach-Object {
159-
$RelativeSourceItemPath = (($_.FullName) -Replace [regex]::Escape("$((Get-Item $SourcePath).FullName)"),"")
157+
Get-ChildItem -Path "$SourcePath\" -Recurse -FollowSymLink | ForEach-Object {
158+
$RelativeSourceItemPath = $_.FullName | Resolve-Path -Relative
159+
Write-Debug "Analyzing $_"
160160

161-
# Create directories, but compare files.
162-
If ($_.Attributes -CMatch "Directory") {
163-
Write-Debug "Creating folder $(Join-Path -Path $DestinationPath $FolderName $RelativeSourceItemPath)"
164-
New-Item -Type Directory -Path (Join-Path -Path $DestinationPath $FolderName $RelativeSourceItemPath) | Out-Null
161+
# Don't copy the log file.
162+
If ($_.Name -eq (($script:LogFile).Name)) {
163+
Continue
164+
}
165+
166+
# Create directories, but compare files.
167+
If ($_.Attributes -CMatch "Directory") {
168+
Write-Debug "Creating folder $(Join-Path -Path $DestinationPath $FolderName $RelativeSourceItemPath)"
169+
New-Item -Type Directory -Path (Join-Path -Path $DestinationPath $FolderName $RelativeSourceItemPath) | Out-Null
170+
}
171+
Else {
172+
# Compare file sizes and dates to determine if something has changed.
173+
If (-Not $DoCopyOnlyBackup) {
174+
$PreviousCopyOfFile = Get-Item -Path (Join-Path -Path $DestinationPath $PreviousBackup $RelativeSourceItemPath)
175+
If (($_.LastWriteTime -eq $PreviousCopyOfFile.LastWriteTime) -And ($_.Length -eq $PreviousCopyOfFile.Length)) {
176+
# The file has not changed since the last backup. Create a hard link.
177+
$DestinationHardlink = @{
178+
ItemType = "HardLink"
179+
Target = ($PreviousCopyOfFile.FullName)
180+
Path = ($PreviousCopyOfFile | Split-Path -Parent) -Replace [regex]::Escape($PreviousBackup),$FolderName
181+
Name = ($PreviousCopyOfFile.Name)
182+
}
183+
Write-Verbose "Linking: $RelativeSourceItemPath"
184+
New-Item @DestinationHardlink | Out-Null
165185
}
166186
Else {
167-
# Compare file sizes and dates to determine if something has changed.
168-
$PreviousCopyOfFile = Get-Item -Path (Join-Path -Path $DestinationPath $PreviousBackup $RelativeSourceItemPath)
169-
If (($_.LastWriteTime -eq $PreviousCopyOfFile.LastWriteTime) -And ($_.Length -eq $PreviousCopyOfFile.Length)) {
170-
# The file has not changed since the last backup. Create a hard link.
171-
$DestinationHardlink = @{
172-
ItemType = "HardLink"
173-
Target = ($PreviousCopyOfFile.FullName)
174-
Path = ($PreviousCopyOfFile | Split-Path -Parent) -Replace [regex]::Escape($PreviousBackup),$FolderName
175-
Name = ($PreviousCopyOfFile.Name)
176-
ErrorAction = "Stop"
177-
}
178-
Write-Verbose "Linking: $RelativeSourceItemPath"
179-
New-Item @DestinationHardlink | Out-Null
180-
}
181-
Else {
182-
Write-Verbose "Copying: $RelativeSourceItemPath"
183-
Copy-Item -Path $_.FullName -Destination (Join-Path -Path $DestinationPath $FolderName $RelativeSourceItemPath) -ErrorAction Stop
184-
$bytesCopied += $_.Length
185-
}
186-
$bytesTotal += $_.Length
187+
Write-Verbose "Copying: $RelativeSourceItemPath"
188+
Copy-Item -Path $_.FullName -Destination (Join-Path -Path $DestinationPath $FolderName $RelativeSourceItemPath) -Verbose:$DoVerboseCopy
189+
$bytesCopied += $_.Length
187190
}
191+
} Else {
192+
Write-Verbose "Copying: $RelativeSourceItemPath"
193+
Copy-Item -Path $_.FullName -Destination (Join-Path -Path $DestinationPath $FolderName $RelativeSourceItemPath) -Verbose:$DoVerboseCopy
194+
$bytesCopied += $_.Length
188195
}
196+
$bytesTotal += $_.Length
189197
}
190198
}
199+
191200
Write-Output "Backup completed at $(Get-Date)."
192201
Rename-Item -Path (Join-Path -Path $DestinationPath $FolderName) -NewName ($FolderName -CReplace '\.inProgress')
193202
If (-Not $NoStatistics -And $bytesTotal -gt 0) {
@@ -202,11 +211,12 @@ Catch {
202211
Finally {
203212
If (-Not $NoLogging) {
204213
Write-Verbose "Moving log file to backup destination."
205-
Stop-Transcript -ErrorAction SilentlyContinue
214+
Stop-Transcript -ErrorAction SilentlyContinue | Out-Null
206215
Write-Debug "Moving $($_.FullName) to $(Join-Path -Path $DestinationPath 'PSTimeMachine.log')"
207216
Move-Item -Path (($script:LogFile).Name) -Destination (Join-Path -Path $DestinationPath $FolderName "PSTimeMachine.log") -ErrorAction Continue
208217
}
209218

210-
# Restore the user's preferred error action preference.
219+
# Restore the user's environment.
211220
$ErrorActionPreference = $OldErrorActionPreference
212-
}
221+
Set-Location -Path $OldLocation
222+
}

0 commit comments

Comments
 (0)