dsh-autorestart 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +137 -6
- package/client.js +387 -0
- package/cordis.patch.yml +7 -0
- package/docs/README.zh.md +83 -5
- package/docs/platform-matrix.md +92 -0
- package/docs/rescue-drill.md +606 -0
- package/index.js +598 -3
- package/lib/diagnostics.js +8 -0
- package/lib/rescue-paths.js +253 -0
- package/lib/rescue.js +596 -0
- package/lib/scheduler-capability.js +300 -0
- package/lib/watchdog-arbiter.js +117 -0
- package/lib/watchdog-schedule.js +310 -0
- package/lib/watchdog-tier.js +182 -0
- package/lib/watchdog.js +479 -0
- package/locale/en.json +28 -1
- package/locale/zh.json +28 -1
- package/package.json +1 -1
- package/scripts/README.md +65 -0
- package/scripts/drill-rescue.ps1 +508 -0
- package/scripts/emergency-toggle.ps1 +136 -65
- package/scripts/restore-profile.cmd +44 -0
- package/scripts/restore-profile.ps1 +608 -0
- package/scripts/run-tests.ps1 +1 -1
|
@@ -1,22 +1,37 @@
|
|
|
1
|
-
|
|
1
|
+
<#
|
|
2
2
|
.SYNOPSIS
|
|
3
|
-
dsh-autorestart
|
|
3
|
+
The dsh-autorestart emergency switch: take this plugin out (or put it back)
|
|
4
|
+
when DSH does not come up.
|
|
4
5
|
|
|
5
6
|
.DESCRIPTION
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
7
|
+
"I enabled the plugin and DSH does not start any more" is the hardest moment
|
|
8
|
+
for a plugin: fixing it needs the plugin itself. This script touches ONE
|
|
9
|
+
file - the package.json of the desktop profile - and ONE array in it:
|
|
10
|
+
`dsh.profile.bundles`.
|
|
11
|
+
|
|
12
|
+
- disable: take "dsh-autorestart" out of the bundles (it was not there
|
|
13
|
+
anyway -> report "already disabled", that is not a failure);
|
|
14
|
+
- enable : put "dsh-autorestart" back into the bundles (it was already
|
|
15
|
+
there -> report "already enabled");
|
|
16
|
+
- status : read only, prints whether it is in the bundles right now.
|
|
17
|
+
|
|
18
|
+
Two hard rules:
|
|
19
|
+
|
|
20
|
+
1. the file is backed up as `package.json.bak-emergency-<yyyyMMdd-HHmmss>`
|
|
21
|
+
before anything is written;
|
|
22
|
+
2. after writing, the JSON is parsed again and checked; if the check
|
|
23
|
+
fails, the backup is put back and the failure is reported honestly.
|
|
24
|
+
|
|
25
|
+
The indentation, the line endings and the trailing newline of the file are
|
|
26
|
+
kept as they are (the text is edited, the JSON is not re-serialized).
|
|
27
|
+
|
|
28
|
+
LANGUAGE: this file is pure ASCII on purpose. Windows PowerShell 5.1 reads a
|
|
29
|
+
UTF-8 file without a byte order mark as ANSI, so one Chinese character
|
|
30
|
+
inside the script turns into mojibake and the script dies with a ParserError
|
|
31
|
+
before it does anything. The Chinese wording lives in
|
|
32
|
+
scripts\rescue-strings.zh.json (UTF-8, no BOM) and is read at runtime; if
|
|
33
|
+
that file is missing or broken, every message falls back to English and the
|
|
34
|
+
script says so.
|
|
20
35
|
|
|
21
36
|
.EXAMPLE
|
|
22
37
|
powershell -NoProfile -ExecutionPolicy Bypass -File .\emergency-toggle.ps1 -Action status
|
|
@@ -25,29 +40,76 @@
|
|
|
25
40
|
powershell -NoProfile -ExecutionPolicy Bypass -File .\emergency-toggle.ps1 -Action disable
|
|
26
41
|
|
|
27
42
|
.NOTES
|
|
28
|
-
Windows PowerShell 5.1
|
|
43
|
+
Windows PowerShell 5.1 is enough (nothing from 6.0+ is used); the .cmd entry
|
|
44
|
+
point double-clicked by the user is that one too.
|
|
29
45
|
#>
|
|
30
46
|
[CmdletBinding()]
|
|
31
47
|
param(
|
|
32
|
-
#
|
|
48
|
+
# What to do.
|
|
33
49
|
[ValidateSet('disable', 'enable', 'status')]
|
|
34
50
|
[string] $Action = 'status',
|
|
35
51
|
|
|
36
|
-
#
|
|
52
|
+
# Only print what would be written, change nothing.
|
|
37
53
|
[switch] $DryRun,
|
|
38
54
|
|
|
39
|
-
#
|
|
55
|
+
# The package.json to work on (for tests and for other profiles).
|
|
40
56
|
[string] $PackageJson = (Join-Path $env:USERPROFILE '.dsh\profiles\desktop\package.json')
|
|
41
57
|
)
|
|
42
58
|
|
|
43
59
|
$ErrorActionPreference = 'Stop'
|
|
44
60
|
|
|
45
|
-
#
|
|
61
|
+
# The name of this plugin inside the bundles.
|
|
46
62
|
$PackageName = 'dsh-autorestart'
|
|
47
63
|
|
|
48
|
-
#
|
|
64
|
+
# The anchor it is put back after (the position does not matter, but an anchor
|
|
65
|
+
# is steadier than the end of the array).
|
|
49
66
|
$AnchorName = 'dsh-github-guard'
|
|
50
67
|
|
|
68
|
+
# ---------------------------------------------------------------------------
|
|
69
|
+
# The Chinese strings: read from rescue-strings.zh.json, fall back to English.
|
|
70
|
+
# ---------------------------------------------------------------------------
|
|
71
|
+
|
|
72
|
+
$script:Strings = $null
|
|
73
|
+
$script:StringsError = ''
|
|
74
|
+
|
|
75
|
+
function Initialize-Strings {
|
|
76
|
+
$path = Join-Path $PSScriptRoot 'rescue-strings.zh.json'
|
|
77
|
+
if (-not (Test-Path -LiteralPath $path -PathType Leaf)) {
|
|
78
|
+
$script:StringsError = (T 'common.stringsMissingEn' 'the Chinese strings file is missing: {0} (falling back to English messages)') -f $path
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
try {
|
|
82
|
+
# Read as UTF-8 explicitly: Get-Content would use the console code page.
|
|
83
|
+
$text = [System.IO.File]::ReadAllText($path, [System.Text.Encoding]::UTF8)
|
|
84
|
+
$script:Strings = $text | ConvertFrom-Json
|
|
85
|
+
} catch {
|
|
86
|
+
$script:StringsError = (T 'common.stringsBrokenEn' 'the Chinese strings file could not be read: {0} (falling back to English messages)') -f $_.Exception.Message
|
|
87
|
+
$script:Strings = $null
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
# Look a string up. The English fallback is right here in the script, so a
|
|
92
|
+
# missing key (or a broken strings file) never stops the rescue.
|
|
93
|
+
function T {
|
|
94
|
+
param([string] $Key, [string] $Fallback)
|
|
95
|
+
if ($null -ne $script:Strings) {
|
|
96
|
+
$node = $script:Strings
|
|
97
|
+
foreach ($part in $Key.Split('.')) {
|
|
98
|
+
if ($null -eq $node) { break }
|
|
99
|
+
$property = $node.PSObject.Properties[$part]
|
|
100
|
+
if ($null -eq $property) { $node = $null; break }
|
|
101
|
+
$node = $property.Value
|
|
102
|
+
}
|
|
103
|
+
if ($null -ne $node) {
|
|
104
|
+
$text = [string] $node
|
|
105
|
+
if ($text -ne '') { return $text }
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return $Fallback
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
Initialize-Strings
|
|
112
|
+
|
|
51
113
|
function Say {
|
|
52
114
|
param([string] $Text, [string] $Color = 'Gray')
|
|
53
115
|
Write-Host $Text -ForegroundColor $Color
|
|
@@ -55,22 +117,22 @@ function Say {
|
|
|
55
117
|
|
|
56
118
|
function Fail {
|
|
57
119
|
param([string] $Text)
|
|
58
|
-
Write-Host ('
|
|
120
|
+
Write-Host ((T 'emergency.failed' 'the emergency switch failed: {0}') -f $Text) -ForegroundColor Red
|
|
59
121
|
exit 1
|
|
60
122
|
}
|
|
61
123
|
|
|
62
124
|
# ---------------------------------------------------------------------------
|
|
63
|
-
#
|
|
125
|
+
# Text helpers: only the bundles array is touched, every other byte stays.
|
|
64
126
|
# ---------------------------------------------------------------------------
|
|
65
127
|
|
|
66
|
-
# bundles
|
|
128
|
+
# The square brackets of the bundles array.
|
|
67
129
|
function Get-ArrayRange {
|
|
68
130
|
param([string] $Text)
|
|
69
131
|
$marker = '"bundles"'
|
|
70
132
|
$markerIndex = $Text.IndexOf($marker)
|
|
71
|
-
if ($markerIndex -lt 0) { throw 'package.json
|
|
133
|
+
if ($markerIndex -lt 0) { throw 'package.json has no bundles entry' }
|
|
72
134
|
$open = $Text.IndexOf('[', $markerIndex)
|
|
73
|
-
if ($open -lt 0) { throw 'bundles
|
|
135
|
+
if ($open -lt 0) { throw 'bundles is not an array' }
|
|
74
136
|
$depth = 0
|
|
75
137
|
$inString = $false
|
|
76
138
|
$escaped = $false
|
|
@@ -89,10 +151,11 @@ function Get-ArrayRange {
|
|
|
89
151
|
if ($depth -eq 0) { return @($open, $i) }
|
|
90
152
|
}
|
|
91
153
|
}
|
|
92
|
-
throw 'bundles
|
|
154
|
+
throw 'the bundles array is not closed'
|
|
93
155
|
}
|
|
94
156
|
|
|
95
|
-
#
|
|
157
|
+
# Every item of the array: the name, the indentation, the comma, the position
|
|
158
|
+
# in the text.
|
|
96
159
|
function Get-Items {
|
|
97
160
|
param([string] $Text, [int] $Open, [int] $Close)
|
|
98
161
|
$body = $Text.Substring($Open + 1, $Close - $Open - 1)
|
|
@@ -101,7 +164,7 @@ function Get-Items {
|
|
|
101
164
|
foreach ($match in [regex]::Matches($body, $pattern)) {
|
|
102
165
|
$lineStart = $Open + 1 + $match.Index
|
|
103
166
|
$lineEnd = $lineStart + $match.Length
|
|
104
|
-
#
|
|
167
|
+
# The line ending of that line (\r\n or \n) belongs to the line.
|
|
105
168
|
if ($lineEnd -lt $Text.Length -and $Text[$lineEnd] -eq "`n") { $lineEnd++ }
|
|
106
169
|
$nameGroup = $match.Groups['name']
|
|
107
170
|
$commaGroup = $match.Groups['comma']
|
|
@@ -110,7 +173,8 @@ function Get-Items {
|
|
|
110
173
|
Indent = $match.Groups['indent'].Value
|
|
111
174
|
HasComma = ($commaGroup.Value -eq ',')
|
|
112
175
|
CommaIndex = $commaGroup.Index
|
|
113
|
-
#
|
|
176
|
+
# The position right after the closing quote of the name (where the
|
|
177
|
+
# comma goes).
|
|
114
178
|
ContentEnd = $nameGroup.Index + $nameGroup.Length + 1
|
|
115
179
|
LineStart = $lineStart
|
|
116
180
|
LineEnd = $lineEnd
|
|
@@ -119,7 +183,7 @@ function Get-Items {
|
|
|
119
183
|
return $items
|
|
120
184
|
}
|
|
121
185
|
|
|
122
|
-
#
|
|
186
|
+
# The indentation of a line (so a new line can look the same).
|
|
123
187
|
function Get-LineIndent {
|
|
124
188
|
param([string] $Text, [int] $Index)
|
|
125
189
|
$start = $Text.LastIndexOf("`n", [Math]::Max(0, $Index - 1))
|
|
@@ -133,7 +197,7 @@ function Get-LineIndent {
|
|
|
133
197
|
return $indent
|
|
134
198
|
}
|
|
135
199
|
|
|
136
|
-
#
|
|
200
|
+
# The line ending the file uses.
|
|
137
201
|
function Get-LineEnding {
|
|
138
202
|
param([string] $Text)
|
|
139
203
|
if ($Text.Contains("`r`n")) { return "`r`n" }
|
|
@@ -141,11 +205,15 @@ function Get-LineEnding {
|
|
|
141
205
|
}
|
|
142
206
|
|
|
143
207
|
# ---------------------------------------------------------------------------
|
|
144
|
-
#
|
|
208
|
+
# Start.
|
|
145
209
|
# ---------------------------------------------------------------------------
|
|
146
210
|
|
|
211
|
+
if ($script:StringsError -ne '') {
|
|
212
|
+
Write-Host ('WARNING: ' + $script:StringsError) -ForegroundColor Yellow
|
|
213
|
+
}
|
|
214
|
+
|
|
147
215
|
if (-not (Test-Path -LiteralPath $PackageJson -PathType Leaf)) {
|
|
148
|
-
Fail ('
|
|
216
|
+
Fail ((T 'emergency.notFound' 'the package.json of the profile cannot be found: {0}') -f $PackageJson)
|
|
149
217
|
}
|
|
150
218
|
|
|
151
219
|
$path = (Resolve-Path -LiteralPath $PackageJson).Path
|
|
@@ -156,7 +224,7 @@ $raw = [System.IO.File]::ReadAllText($path)
|
|
|
156
224
|
try {
|
|
157
225
|
$document = $raw | ConvertFrom-Json
|
|
158
226
|
} catch {
|
|
159
|
-
Fail ('
|
|
227
|
+
Fail ((T 'emergency.badJson' 'this package.json is not valid JSON: {0}') -f $_.Exception.Message)
|
|
160
228
|
}
|
|
161
229
|
|
|
162
230
|
$bundles = @()
|
|
@@ -168,20 +236,20 @@ if ($null -ne $document -and $null -ne $document.dsh -and $null -ne $document.ds
|
|
|
168
236
|
|
|
169
237
|
$present = ($bundles -contains $PackageName)
|
|
170
238
|
|
|
171
|
-
Say ('
|
|
239
|
+
Say ((T 'emergency.file' 'file: {0}') -f $path)
|
|
172
240
|
|
|
173
241
|
if ($Action -eq 'status') {
|
|
174
|
-
if ($present) { Say ('
|
|
175
|
-
else { Say ('
|
|
242
|
+
if ($present) { Say ((T 'emergency.enabled' 'enabled: {0} is in the bundles.') -f $PackageName) 'Green' }
|
|
243
|
+
else { Say ((T 'emergency.disabled' 'disabled: {0} is not in the bundles.') -f $PackageName) 'Yellow' }
|
|
176
244
|
exit 0
|
|
177
245
|
}
|
|
178
246
|
|
|
179
247
|
if ($Action -eq 'enable' -and -not $hasBundles) {
|
|
180
|
-
Fail '
|
|
248
|
+
Fail (T 'emergency.noBundles' 'this profile has no dsh.profile.bundles list, so the plugin cannot be put back (please add a line "dsh-autorestart" by hand).')
|
|
181
249
|
}
|
|
182
250
|
|
|
183
251
|
# ---------------------------------------------------------------------------
|
|
184
|
-
#
|
|
252
|
+
# Work out the new text.
|
|
185
253
|
# ---------------------------------------------------------------------------
|
|
186
254
|
|
|
187
255
|
$new = $raw
|
|
@@ -191,14 +259,15 @@ $eol = Get-LineEnding $raw
|
|
|
191
259
|
|
|
192
260
|
if ($Action -eq 'disable') {
|
|
193
261
|
if (-not $present) {
|
|
194
|
-
Say ('
|
|
262
|
+
Say ((T 'emergency.alreadyDisabled' 'already disabled: {0} was not in the bundles anyway (no file was changed).') -f $PackageName) 'Yellow'
|
|
195
263
|
exit 0
|
|
196
264
|
}
|
|
197
265
|
$target = $items | Where-Object { $_.Name -eq $PackageName } | Select-Object -First 1
|
|
198
|
-
if ($null -eq $target) { Fail ('
|
|
266
|
+
if ($null -eq $target) { Fail ((T 'emergency.notInBundles' '{0} cannot be found in the bundles') -f $PackageName) }
|
|
199
267
|
$shift = 0
|
|
200
268
|
if (-not $target.HasComma) {
|
|
201
|
-
#
|
|
269
|
+
# It is the last item of the array: the comma of the item before it has to
|
|
270
|
+
# go, otherwise the JSON is invalid.
|
|
202
271
|
$previous = $items | Where-Object { $_.LineEnd -le $target.LineStart } | Select-Object -Last 1
|
|
203
272
|
if ($null -ne $previous -and $previous.HasComma) {
|
|
204
273
|
$new = $new.Remove($previous.CommaIndex, 1)
|
|
@@ -206,11 +275,11 @@ if ($Action -eq 'disable') {
|
|
|
206
275
|
}
|
|
207
276
|
}
|
|
208
277
|
$new = $new.Remove($target.LineStart + $shift, $target.LineEnd - $target.LineStart)
|
|
209
|
-
$summary = ('
|
|
278
|
+
$summary = (T 'emergency.summaryRemove' 'take {0} out of the bundles') -f $PackageName
|
|
210
279
|
} else {
|
|
211
280
|
# enable
|
|
212
281
|
if ($present) {
|
|
213
|
-
Say ('
|
|
282
|
+
Say ((T 'emergency.alreadyEnabled' 'already enabled: {0} was in the bundles anyway (no file was changed).') -f $PackageName) 'Yellow'
|
|
214
283
|
exit 0
|
|
215
284
|
}
|
|
216
285
|
$anchor = $items | Where-Object { $_.Name -eq $AnchorName } | Select-Object -First 1
|
|
@@ -221,7 +290,8 @@ if ($Action -eq 'disable') {
|
|
|
221
290
|
$insertAt = $anchor.LineEnd
|
|
222
291
|
$line = $anchor.Indent + '"' + $PackageName + '",'
|
|
223
292
|
} else {
|
|
224
|
-
#
|
|
293
|
+
# The anchor is the last item: give it a comma first, then insert the new
|
|
294
|
+
# item (the new one has no comma).
|
|
225
295
|
$new = $new.Insert($anchor.ContentEnd, ',')
|
|
226
296
|
$insertAt = $anchor.LineEnd + 1
|
|
227
297
|
$line = $anchor.Indent + '"' + $PackageName + '"'
|
|
@@ -237,39 +307,40 @@ if ($Action -eq 'disable') {
|
|
|
237
307
|
}
|
|
238
308
|
$line = $last.Indent + '"' + $PackageName + '"'
|
|
239
309
|
} else {
|
|
240
|
-
#
|
|
310
|
+
# The array is empty.
|
|
241
311
|
$insertAt = $range[1]
|
|
242
312
|
$line = (Get-LineIndent $raw $range[1]) + ' "' + $PackageName + '"'
|
|
243
313
|
}
|
|
244
314
|
}
|
|
245
315
|
$new = $new.Insert($insertAt, $line + $eol)
|
|
246
|
-
$summary = ('
|
|
316
|
+
$summary = (T 'emergency.summaryAdd' 'put {0} back into the bundles') -f $PackageName
|
|
247
317
|
}
|
|
248
318
|
|
|
249
319
|
if ($DryRun) {
|
|
250
|
-
Say ('[
|
|
251
|
-
Say ('[
|
|
252
|
-
Say ('[
|
|
253
|
-
Say ('[
|
|
320
|
+
Say ((T 'emergency.dryRunWill' '[dry run] would {0}.') -f $summary) 'Cyan'
|
|
321
|
+
Say ((T 'emergency.dryRunWrite' '[dry run] would write: {0}') -f $path) 'Cyan'
|
|
322
|
+
Say ((T 'emergency.dryRunBackup' '[dry run] would back it up as: {0}.bak-emergency-<timestamp>') -f $path) 'Cyan'
|
|
323
|
+
Say (T 'emergency.dryRunNoChange' '[dry run] no file was changed.') 'Cyan'
|
|
254
324
|
exit 0
|
|
255
325
|
}
|
|
256
326
|
|
|
257
327
|
# ---------------------------------------------------------------------------
|
|
258
|
-
#
|
|
328
|
+
# Write: back up first, write, then parse and check again; on a failure, roll
|
|
329
|
+
# back.
|
|
259
330
|
# ---------------------------------------------------------------------------
|
|
260
331
|
|
|
261
332
|
$backup = $path + '.bak-emergency-' + (Get-Date -Format 'yyyyMMdd-HHmmss')
|
|
262
333
|
try {
|
|
263
334
|
Copy-Item -LiteralPath $path -Destination $backup -Force
|
|
264
335
|
} catch {
|
|
265
|
-
Fail ('
|
|
336
|
+
Fail ((T 'emergency.backupFailed' 'the backup failed (the original file was not touched): {0}') -f $_.Exception.Message)
|
|
266
337
|
}
|
|
267
338
|
|
|
268
339
|
try {
|
|
269
340
|
$encoding = New-Object System.Text.UTF8Encoding($hasBom)
|
|
270
341
|
[System.IO.File]::WriteAllText($path, $new, $encoding)
|
|
271
342
|
} catch {
|
|
272
|
-
Fail ('
|
|
343
|
+
Fail ((T 'emergency.writeFailed' 'the write failed (the backup is at {0}): {1}') -f $backup, $_.Exception.Message)
|
|
273
344
|
}
|
|
274
345
|
|
|
275
346
|
try {
|
|
@@ -280,23 +351,23 @@ try {
|
|
|
280
351
|
$names = @($parsed.dsh.profile.bundles)
|
|
281
352
|
}
|
|
282
353
|
if ($Action -eq 'enable' -and -not ($names -contains $PackageName)) {
|
|
283
|
-
throw '
|
|
354
|
+
throw ('after writing, the bundles still do not hold ' + $PackageName)
|
|
284
355
|
}
|
|
285
356
|
if ($Action -eq 'disable' -and ($names -contains $PackageName)) {
|
|
286
|
-
throw '
|
|
357
|
+
throw ('after writing, the bundles still hold ' + $PackageName)
|
|
287
358
|
}
|
|
288
359
|
} catch {
|
|
289
|
-
#
|
|
360
|
+
# The check failed: put the original file back, then report honestly.
|
|
290
361
|
try {
|
|
291
362
|
Copy-Item -LiteralPath $backup -Destination $path -Force
|
|
292
|
-
Say ('
|
|
363
|
+
Say ((T 'emergency.rolledBack' 'the backup was put back: {0}') -f $backup) 'Yellow'
|
|
293
364
|
} catch {
|
|
294
|
-
Fail ('
|
|
365
|
+
Fail ((T 'emergency.verifyFailedNoRollback' 'the check failed and the rollback failed too (the backup is at {0}): {1}') -f $backup, $_.Exception.Message)
|
|
295
366
|
}
|
|
296
|
-
Fail ('
|
|
367
|
+
Fail ((T 'emergency.verifyFailedRolledBack' 'the check failed (it was rolled back): {0}') -f $_.Exception.Message)
|
|
297
368
|
}
|
|
298
369
|
|
|
299
|
-
Say ('
|
|
300
|
-
Say ('
|
|
301
|
-
Say ('
|
|
370
|
+
Say ((T 'emergency.done' 'done: {0}.') -f $summary) 'Green'
|
|
371
|
+
Say ((T 'emergency.backup' 'backup: {0}') -f $backup) 'Gray'
|
|
372
|
+
Say (T 'emergency.restartHint' 'restart DSH for it to take effect.') 'Gray'
|
|
302
373
|
exit 0
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
@echo off
|
|
2
|
+
rem dsh-autorestart - restore the profile snapshot.
|
|
3
|
+
rem
|
|
4
|
+
rem Double-click this file when DSH does not start any more (a plugin upgrade
|
|
5
|
+
rem broke the profile, the configuration was damaged, node_modules is a mess):
|
|
6
|
+
rem it puts the newest snapshot that carries a manifest back over the profile.
|
|
7
|
+
rem
|
|
8
|
+
rem What it does, in this order:
|
|
9
|
+
rem 1. finds the newest snapshot with a manifest under <stateDir>\backups
|
|
10
|
+
rem 2. MOVES the current profile to <profile>\.broken-<timestamp> (nothing is
|
|
11
|
+
rem deleted, the evidence stays)
|
|
12
|
+
rem 3. copies the configuration files and the plugin tree back
|
|
13
|
+
rem 4. reads the result back: package.json, dsh.profile.bundles and the
|
|
14
|
+
rem version of dsh-autorestart have to be readable
|
|
15
|
+
rem
|
|
16
|
+
rem It never restarts DSH for you - you do that yourself.
|
|
17
|
+
rem
|
|
18
|
+
rem Optional arguments are passed straight to the PowerShell script, e.g.
|
|
19
|
+
rem restore-profile.cmd -DryRun
|
|
20
|
+
rem restore-profile.cmd -ProfileDir C:\temp\drill\profile -StateDir C:\temp\drill\state
|
|
21
|
+
rem
|
|
22
|
+
rem NOTE: this file is ASCII on purpose. cmd.exe reads a batch file with the
|
|
23
|
+
rem console code page, and a UTF-8 character in it would shift the rest of the
|
|
24
|
+
rem line and be run as a command. The Chinese explanation comes from the
|
|
25
|
+
rem PowerShell script below (and from scripts\README.md).
|
|
26
|
+
setlocal
|
|
27
|
+
set "SCRIPT=%~dp0restore-profile.ps1"
|
|
28
|
+
if not exist "%SCRIPT%" (
|
|
29
|
+
echo Cannot find "%SCRIPT%".
|
|
30
|
+
echo The rescue kit is incomplete - keep the plugin folder together.
|
|
31
|
+
pause
|
|
32
|
+
exit /b 1
|
|
33
|
+
)
|
|
34
|
+
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%SCRIPT%" %*
|
|
35
|
+
set "RC=%ERRORLEVEL%"
|
|
36
|
+
echo.
|
|
37
|
+
if "%RC%"=="0" (
|
|
38
|
+
echo Done. The result is above - open DSH again.
|
|
39
|
+
) else (
|
|
40
|
+
echo The restore did NOT finish. Read the red lines above.
|
|
41
|
+
echo Your old profile was not deleted - it is kept as a ".broken-<timestamp>" folder.
|
|
42
|
+
)
|
|
43
|
+
pause
|
|
44
|
+
exit /b %RC%
|