Restore

O Operator
Restore

Restore file to captured state

Every captured change carries its SHA-256-addressed content in BLOB_STORE. Restoring writes that content back to the original path — current file gets backed up to <path>.drift_restore_backup_<epoch> before overwrite.

What will change
Preview -- nothing has been written yet.
Target file/var/www/vhosts/3dshawn.com/site1/TEMPLATES/diff.html
SiteDriftSense self-monitor on local
Kindlocal
Captured at2026-07-11 23:34:36
Captured SHA4bae2d788795b64a6d0aa5fd455465dabe8d59d48e496627fc35ff81258e8cba
Current state on disk
Live check just now. If SHAs match, the restore is a no-op.
File presentyes
Size6255 bytes
Current SHA595c27907b0d
Same as captured?no -- restore will change it
What restore will change — live diff
Left column shows current on-disk content; right shows what restore will write. +1 additions, -65 deletions, 50 unchanged context lines.
11<div class="page-head">
22 <span class="page-eyebrow"><span class="dot"></span> Diff</span>
33 <h1 class="page-title">$title</h1>
44 <p class="page-subtitle">$subtitle</p>
55</div>
66
77<div class="dash-grid" style="grid-template-columns:repeat(4,1fr);margin-bottom:16px">
88 <div class="module glow-emerald"><div class="module-head"><div class="left"><div class="module-title">Added</div></div></div><div class="module-body kpi kpi-emerald"><div class="num">+$ct_add</div><div class="lbl">lines</div></div></div>
99 <div class="module glow-rose"><div class="module-head"><div class="left"><div class="module-title">Removed</div></div></div><div class="module-body kpi kpi-rose"><div class="num">-$ct_del</div><div class="lbl">lines</div></div></div>
1010 <div class="module glow-teal"><div class="module-head"><div class="left"><div class="module-title">Context</div></div></div><div class="module-body kpi kpi-teal"><div class="num">$ct_context</div><div class="lbl">unchanged</div></div></div>
1111 <div class="module glow-sky"><div class="module-head"><div class="left"><div class="module-title">Blobs</div></div></div><div class="module-body kpi kpi-sky"><div class="num" style="font-size:14px;letter-spacing:0"><span class="dim">from</span> $prev_sha<br><span class="dim">to</span> $curr_sha</div></div></div>
1212</div>
1313
1414[if:$restore_url]
15<div style="display:flex;justify-content:flex-end;gap:8px;margin:-4px 0 12px">
16 <button type="button" id="dsCompileBtn" class="tr-chip"
17 data-id="$id" data-kind="$kind"
18 style="border-color:var(--accent-warn);color:var(--accent-warn-hi)">
19 Test compile &nbsp;<span style="font-size:9.5px;letter-spacing:1px;color:var(--text-muted)">(perl / node / bash / py)</span>
20 </button>
15<div style="display:flex;justify-content:flex-end;margin:-4px 0 12px">
2116 <a href="$restore_url" class="tr-chip" style="border-color:var(--accent);color:var(--accent-hi)">Restore this content &rarr;</a>
2217</div>
23
24<div id="dsCompileResult" style="display:none;margin:0 0 16px;padding:12px 16px;border-radius:10px;font-family:var(--mono);font-size:12.5px;line-height:1.55"></div>
25
26<script>
27(function () {
28 var btn = document.getElementById('dsCompileBtn');
29 var out = document.getElementById('dsCompileResult');
30 if (!btn) return;
31 btn.addEventListener('click', async function () {
32 if (btn.getAttribute('data-kind') !== 'file') {
33 alert('Compile check only supports file changes.');
34 return;
35 }
36 var origText = btn.innerHTML;
37 btn.disabled = true;
38 btn.textContent = 'Checking...';
39 out.style.display = 'block';
40 out.style.background = 'var(--bg-2)';
41 out.style.border = '1px solid var(--border)';
42 out.style.color = 'var(--text-dim)';
43 out.textContent = 'Running compile check...';
44
45 try {
46 var r = await fetch('/diff.cgi?op=compile&id=' + btn.getAttribute('data-id'), { cache: 'no-store' });
47 var j = await r.json();
48 var color = j.status === 'ok' ? 'rgba(52,211,153,'
49 : j.status === 'error' ? 'rgba(244,63,94,'
50 : 'rgba(245,158,11,';
51 out.style.background = color + '0.08)';
52 out.style.border = '1px solid ' + color + '0.35)';
53 out.style.color = j.status === 'error' ? '#fda4af'
54 : j.status === 'ok' ? '#86efac'
55 : '#fcd34d';
56 var head = document.createElement('div');
57 head.style.marginBottom = '6px';
58 head.style.fontWeight = '700';
59 head.style.fontFamily = 'var(--sans)';
60 head.textContent = (j.status === 'ok' ? '✓ Compiles cleanly'
61 : j.status === 'error' ? '✗ Syntax errors'
62 : '⚠ Unchecked')
63 + ' (' + (j.language || '?') + ')';
64 out.innerHTML = '';
65 out.appendChild(head);
66 var body = document.createElement('pre');
67 body.style.margin = '0';
68 body.style.whiteSpace = 'pre-wrap';
69 body.style.wordWrap = 'break-word';
70 body.style.fontSize = '12px';
71 body.textContent = j.message || '';
72 out.appendChild(body);
73 } catch (e) {
74 out.textContent = 'Compile check failed: ' + e.message;
75 } finally {
76 btn.disabled = false;
77 btn.innerHTML = origText;
78 }
79 });
80})();
81</script>
8218[/if]
8319
8420<div class="module glow-teal">
8521 <div class="module-head"><div class="left"><div class="module-title">Unified diff</div><span class="module-subtitle">Naive LCS-based line diff. Additions in emerald, deletions in rose. Both sides decompressed live from BLOB_STORE.</span></div></div>
8622 <div class="module-body tight">
8723 [if:$has_diff]
8824 <style>
8925 .diff-tbl { width:100%; border-collapse:collapse; font-family:var(--mono); font-size:12.5px; line-height:1.5; }
9026 .diff-tbl td { padding:1px 8px; vertical-align:top; white-space:pre-wrap; word-wrap:break-word; }
9127 .diff-tbl .ln { color:var(--text-muted); text-align:right; width:44px; user-select:none; border-right:1px solid var(--border); font-size:11px; }
9228 .diff-tbl tr.op-add td.text { background:rgba(52,211,153,.10); color:#a7f3d0; }
9329 .diff-tbl tr.op-add td.ln { background:rgba(52,211,153,.05); color:var(--accent-ok); }
9430 .diff-tbl tr.op-add td.text::before { content:'+'; color:var(--accent-ok); padding-right:6px; }
9531 .diff-tbl tr.op-del td.text { background:rgba(244,63,94,.10); color:var(--accent-danger-hi); }
9632 .diff-tbl tr.op-del td.ln { background:rgba(244,63,94,.05); color:var(--accent-danger); }
9733 .diff-tbl tr.op-del td.text::before { content:'-'; color:var(--accent-danger); padding-right:6px; }
9834 .diff-tbl tr.op-ctx td { color:var(--text-dim); }
9935 .diff-tbl tr.op-ctx td.text::before { content:' '; padding-right:6px; }
10036 </style>
10137 <div style="max-height:70vh;overflow:auto">
10238 <table class="diff-tbl">
10339 <tbody>
10440 [loop:@lines]<tr class="op-$op"><td class="ln">$old_n</td><td class="ln">$new_n</td><td class="text">$text</td></tr>[/loop]
10541 </tbody>
10642 </table>
10743 </div>
10844 [/if]
10945 [if:!$has_diff]
11046 <div style="padding:36px 14px;text-align:center;color:var(--text-dim);font-size:13.5px">
11147 Nothing to diff. Blob may have been auto-purged, or this is the first snapshot.
11248 </div>
11349 [/if]
11450 </div>
11551</div>
Confirm restore
Backs current content to <target>.drift_restore_backup_<epoch>, writes the captured content, verifies SHA post-write.
Cancel Logged to RESTORE_LOG regardless of outcome.