dsh-plugin-git-commit-push 0.0.0-stage → 1.0.1
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/LICENSE +21 -0
- package/README.en.md +473 -0
- package/README.md +381 -2
- package/SKILL.md +79 -0
- package/capture-git-format.mjs +93 -0
- package/cordis.patch.yml +35 -0
- package/e2e-check.mjs +26 -0
- package/git-commit-push.config.json +17 -0
- package/icon.svg +1 -0
- package/index.js +908 -0
- package/lib/analyze.js +517 -0
- package/lib/config.js +300 -0
- package/lib/git.js +562 -0
- package/lib/profile-edit.mjs +118 -0
- package/lib/schema.js +111 -0
- package/lib/skill.js +95 -0
- package/lib/survey.js +225 -0
- package/lib/test-fixture.mjs +64 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +81 -4
- package/self-test-git.mjs +442 -0
- package/self-test.mjs +913 -0
- package/setup.ps1 +226 -0
- package/setup.sh +190 -0
package/setup.ps1
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
<#
|
|
2
|
+
.SYNOPSIS
|
|
3
|
+
Install a local CHECKOUT of dsh-plugin-git-commit-push into a DSH profile.
|
|
4
|
+
|
|
5
|
+
.DESCRIPTION
|
|
6
|
+
Wires the plugin into the profile's bundle stack in two deliberate steps:
|
|
7
|
+
|
|
8
|
+
1. adds the plugin to the profile's package.json as a `link:` dependency;
|
|
9
|
+
2. appends the package to `dsh.profile.bundles`.
|
|
10
|
+
|
|
11
|
+
Installing from npm does not need this script: use Settings > Plugins (type
|
|
12
|
+
`dsh-plugin-git-commit-push`) or
|
|
13
|
+
`dsh plugin --profile <profile> add dsh-plugin-git-commit-push`.
|
|
14
|
+
This script is for a checkout you are editing, which should be linked rather
|
|
15
|
+
than copied into node_modules.
|
|
16
|
+
|
|
17
|
+
The mount row is deliberately NOT written into the profile's patch file: it
|
|
18
|
+
comes from the package's own bundle patch (`cordis.patch.yml`, declared as
|
|
19
|
+
`dsh.bundle.patch` in this package's package.json), which the launcher applies
|
|
20
|
+
for every profile that selects the bundle. That declaration is also what makes
|
|
21
|
+
the package manageable: the Plugins page can enable, disable and uninstall a
|
|
22
|
+
bundle, and refuses every action on a package without one with the diagnostic
|
|
23
|
+
"这个包没有声明组合包,不能作为插件管理" (`not-bundle`).
|
|
24
|
+
|
|
25
|
+
A profile set up by an earlier revision of this script still carries a
|
|
26
|
+
hand-written mount row in its cordis.patch.yml under the marker block below.
|
|
27
|
+
Loader `insert` is append-only — two inserts of the same id mount the plugin
|
|
28
|
+
twice — so this script strips that legacy block whenever it finds one.
|
|
29
|
+
|
|
30
|
+
Steps 1 and 2 change the bundle set, which a running profile does not pick up:
|
|
31
|
+
DSH must be restarted afterwards. Every write is idempotent — run this as many
|
|
32
|
+
times as you like — and a backup of each file is written before the first
|
|
33
|
+
modification.
|
|
34
|
+
|
|
35
|
+
Nothing here touches your git configuration, your repositories, or any DSH
|
|
36
|
+
setting other than the edits above.
|
|
37
|
+
|
|
38
|
+
.PARAMETER Profile
|
|
39
|
+
Profile name under $env:USERPROFILE\.dsh\profiles. Defaults to `desktop`.
|
|
40
|
+
|
|
41
|
+
.PARAMETER Uninstall
|
|
42
|
+
Reverses the two edits, strips a legacy mount row and removes the linked package.
|
|
43
|
+
|
|
44
|
+
.EXAMPLE
|
|
45
|
+
powershell -ExecutionPolicy Bypass -File .\setup.ps1
|
|
46
|
+
powershell -ExecutionPolicy Bypass -File .\setup.ps1 -Profile web
|
|
47
|
+
powershell -ExecutionPolicy Bypass -File .\setup.ps1 -Uninstall
|
|
48
|
+
#>
|
|
49
|
+
[CmdletBinding()]
|
|
50
|
+
param(
|
|
51
|
+
[string]$Profile = 'desktop',
|
|
52
|
+
[switch]$Uninstall
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
$ErrorActionPreference = 'Stop'
|
|
56
|
+
|
|
57
|
+
$pluginDir = $PSScriptRoot
|
|
58
|
+
$pluginName = 'dsh-plugin-git-commit-push'
|
|
59
|
+
$dshHome = Join-Path $env:USERPROFILE '.dsh'
|
|
60
|
+
$profileDir = Join-Path $dshHome "profiles\$Profile"
|
|
61
|
+
$nodeExe = Join-Path $dshHome 'dsh-runtimes\dsh-primary-runtime\dependencies\node\bin\node.exe'
|
|
62
|
+
$pnpmCli = Join-Path $dshHome 'dsh-runtimes\dsh-primary-runtime\dependencies\pnpm\bin\pnpm.mjs'
|
|
63
|
+
|
|
64
|
+
function Write-Step([string]$Text) { Write-Host " $Text" }
|
|
65
|
+
function Write-Ok([string]$Text) { Write-Host " [ok] $Text" -ForegroundColor Green }
|
|
66
|
+
function Write-Info([string]$Text) { Write-Host " [info] $Text" -ForegroundColor Cyan }
|
|
67
|
+
function Write-Warn2([string]$Text) { Write-Host " [warn] $Text" -ForegroundColor Yellow }
|
|
68
|
+
|
|
69
|
+
Write-Host ''
|
|
70
|
+
Write-Host "dsh-plugin-git-commit-push $(if ($Uninstall) { 'uninstall' } else { 'install' })" -ForegroundColor White
|
|
71
|
+
Write-Host ''
|
|
72
|
+
|
|
73
|
+
# --- 1. Preconditions ------------------------------------------------------
|
|
74
|
+
if (-not (Test-Path -LiteralPath $profileDir)) {
|
|
75
|
+
throw "Profile directory not found: $profileDir"
|
|
76
|
+
}
|
|
77
|
+
if (-not (Test-Path -LiteralPath (Join-Path $profileDir 'package.json'))) {
|
|
78
|
+
throw "Not a DSH profile (no package.json): $profileDir"
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
$packageJsonPath = Join-Path $profileDir 'package.json'
|
|
82
|
+
$patchPath = Join-Path $profileDir 'cordis.patch.yml'
|
|
83
|
+
if (-not (Test-Path -LiteralPath $patchPath)) {
|
|
84
|
+
throw "Not a DSH profile (no cordis.patch.yml): $profileDir"
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
$gitCmd = Get-Command git -ErrorAction SilentlyContinue
|
|
88
|
+
if ($null -eq $gitCmd) {
|
|
89
|
+
Write-Warn2 'git was not found on PATH. The plugin needs it at runtime; install Git before using it.'
|
|
90
|
+
} else {
|
|
91
|
+
Write-Ok "git found: $($gitCmd.Source)"
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (-not (Test-Path -LiteralPath $nodeExe)) {
|
|
95
|
+
throw "Bundled node not found: $nodeExe`nSet it manually, or install the package with your own pnpm instead."
|
|
96
|
+
}
|
|
97
|
+
if (-not (Test-Path -LiteralPath $pnpmCli)) {
|
|
98
|
+
throw "Bundled pnpm not found: $pnpmCli"
|
|
99
|
+
}
|
|
100
|
+
Write-Ok 'bundled node + pnpm located'
|
|
101
|
+
|
|
102
|
+
# --- 2. Back up once -------------------------------------------------------
|
|
103
|
+
# NOTE: the concatenation must be `$file + '.suffix'`, NOT "$file.suffix".
|
|
104
|
+
# Inside an expandable string PowerShell reads `.git-commit-plugin` as a
|
|
105
|
+
# PROPERTY access on $file, which yields $null — the backup would silently land
|
|
106
|
+
# in the current directory under a mangled name and the second file would never
|
|
107
|
+
# be backed up at all.
|
|
108
|
+
#
|
|
109
|
+
# The patch file is backed up further down, and only when this run actually has
|
|
110
|
+
# to change it (the legacy mount-row migration). A fresh install leaves it
|
|
111
|
+
# untouched.
|
|
112
|
+
$manifestBackup = $packageJsonPath + '.git-commit-plugin.bak'
|
|
113
|
+
if (-not (Test-Path -LiteralPath $manifestBackup)) {
|
|
114
|
+
Copy-Item -LiteralPath $packageJsonPath -Destination $manifestBackup
|
|
115
|
+
Write-Ok "backed up package.json -> $(Split-Path -Leaf $manifestBackup)"
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
# --- 3. Edit the profile manifest and patch layer --------------------------
|
|
119
|
+
# The manifest edit is delegated to lib/profile-edit.mjs, the SAME code setup.sh
|
|
120
|
+
# runs on macOS/Linux. Editing a user's profile package.json is the one step that
|
|
121
|
+
# must not go wrong, and two hand-written implementations of it would drift: this
|
|
122
|
+
# way one reviewed implementation (idempotent, keeps unknown fields, no BOM,
|
|
123
|
+
# self-verifying) serves both platforms.
|
|
124
|
+
$editArgs = @(
|
|
125
|
+
"$pluginDir\lib\profile-edit.mjs"
|
|
126
|
+
'--profile-dir', $profileDir
|
|
127
|
+
'--package', $pluginName
|
|
128
|
+
)
|
|
129
|
+
if ($Uninstall) { $editArgs += '--remove' } else { $editArgs += @('--link', $pluginDir) }
|
|
130
|
+
|
|
131
|
+
& $nodeExe @editArgs
|
|
132
|
+
if ($LASTEXITCODE -ne 0) { throw "profile manifest edit failed with exit code $LASTEXITCODE" }
|
|
133
|
+
Write-Ok 'package.json updated'
|
|
134
|
+
|
|
135
|
+
# The plugin is mounted by the bundle patch this package ships
|
|
136
|
+
# (cordis.patch.yml, declared as dsh.bundle.patch). Nothing is written into the
|
|
137
|
+
# profile's own cordis.patch.yml on a fresh install.
|
|
138
|
+
#
|
|
139
|
+
# What this step does is the MIGRATION: an earlier revision of this script wrote
|
|
140
|
+
# a mount row into the profile patch instead, and Loader `insert` is
|
|
141
|
+
# append-only — leaving that row in place next to the bundle's own row would
|
|
142
|
+
# mount the plugin twice. So the marker block is stripped whenever it is found;
|
|
143
|
+
# the edit is idempotent (it is stripped and never rewritten) and the profile
|
|
144
|
+
# patch is backed up first, because this is the only run that may change it.
|
|
145
|
+
$beginMarker = '# >>> dsh-plugin-git-commit-push'
|
|
146
|
+
$endMarker = '# <<< dsh-plugin-git-commit-push'
|
|
147
|
+
$patchText = Get-Content -LiteralPath $patchPath -Raw
|
|
148
|
+
$existingBlock = [regex]::Match($patchText, "(?s)\s*$([regex]::Escape($beginMarker)).*?$([regex]::Escape($endMarker))")
|
|
149
|
+
if ($existingBlock.Success) {
|
|
150
|
+
$patchBackup = $patchPath + '.git-commit-plugin.bak'
|
|
151
|
+
if (-not (Test-Path -LiteralPath $patchBackup)) {
|
|
152
|
+
Copy-Item -LiteralPath $patchPath -Destination $patchBackup
|
|
153
|
+
Write-Ok "backed up cordis.patch.yml -> $(Split-Path -Leaf $patchBackup)"
|
|
154
|
+
}
|
|
155
|
+
$patchText = $patchText.Remove($existingBlock.Index, $existingBlock.Length)
|
|
156
|
+
$patchText = $patchText -replace "(\r?\n){3,}", "`n`n"
|
|
157
|
+
[System.IO.File]::WriteAllText($patchPath, "$($patchText.TrimEnd())`n", (New-Object System.Text.UTF8Encoding($false)))
|
|
158
|
+
Write-Ok 'cordis.patch.yml: legacy mount row removed (the bundle patch mounts the plugin now)'
|
|
159
|
+
} else {
|
|
160
|
+
Write-Ok 'cordis.patch.yml: no legacy mount row to remove'
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
# --- 4. Link the package ---------------------------------------------------
|
|
164
|
+
Write-Step 'running pnpm install in the profile (this may take a moment)...'
|
|
165
|
+
Push-Location $profileDir
|
|
166
|
+
# pnpm writes progress and warnings to stderr routinely. With
|
|
167
|
+
# $ErrorActionPreference = 'Stop' and a `2>&1` redirect, Windows PowerShell turns
|
|
168
|
+
# those into terminating errors, so the script would die before it could read
|
|
169
|
+
# $LASTEXITCODE. Relax the preference for the duration of the native call.
|
|
170
|
+
$previousPreference = $ErrorActionPreference
|
|
171
|
+
$ErrorActionPreference = 'Continue'
|
|
172
|
+
try {
|
|
173
|
+
& $nodeExe $pnpmCli install
|
|
174
|
+
$pnpmExit = $LASTEXITCODE
|
|
175
|
+
} finally {
|
|
176
|
+
$ErrorActionPreference = $previousPreference
|
|
177
|
+
Pop-Location
|
|
178
|
+
}
|
|
179
|
+
if ($pnpmExit -ne 0) { throw "pnpm install failed with exit code $pnpmExit" }
|
|
180
|
+
Write-Ok 'package linked into the profile'
|
|
181
|
+
|
|
182
|
+
# --- 5. Verify -------------------------------------------------------------
|
|
183
|
+
# On uninstall the linked directory is expected to be gone (pnpm pruned it in
|
|
184
|
+
# step 4); reporting that as a warning would read like a failure.
|
|
185
|
+
$linkedModule = Join-Path $profileDir "node_modules\$pluginName"
|
|
186
|
+
if ($Uninstall) {
|
|
187
|
+
if (Test-Path -LiteralPath $linkedModule) {
|
|
188
|
+
Write-Warn2 "node_modules\$pluginName is still present; run pnpm install in the profile to prune it"
|
|
189
|
+
} else {
|
|
190
|
+
Write-Ok "module removed from node_modules\$pluginName"
|
|
191
|
+
}
|
|
192
|
+
} elseif (Test-Path -LiteralPath $linkedModule) {
|
|
193
|
+
Write-Ok "module present at node_modules\$pluginName"
|
|
194
|
+
} else {
|
|
195
|
+
Write-Warn2 "node_modules\$pluginName is missing; the profile will not find the plugin"
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (-not $Uninstall) {
|
|
199
|
+
Write-Host ''
|
|
200
|
+
Write-Host 'Done. Restart DeepSeek Harness to load the bundle.' -ForegroundColor White
|
|
201
|
+
Write-Host ''
|
|
202
|
+
Write-Host ' Close DeepSeek Harness first if it is running: a bundle addition is' -ForegroundColor Gray
|
|
203
|
+
Write-Host ' read at profile start, not live. Then start it again.' -ForegroundColor Gray
|
|
204
|
+
Write-Host ''
|
|
205
|
+
Write-Host ' After the restart you get:' -ForegroundColor Gray
|
|
206
|
+
Write-Host ' - a tool named git_commit_push (prepare / apply / auto)' -ForegroundColor Gray
|
|
207
|
+
Write-Host ' - a slash command /git-commit-push (runs without the model, 0 tokens)' -ForegroundColor Gray
|
|
208
|
+
Write-Host ''
|
|
209
|
+
Write-Host ' The plugin is a declared bundle, so Settings > Plugins can now' -ForegroundColor Gray
|
|
210
|
+
Write-Host ' enable, disable and uninstall it without this script.' -ForegroundColor Gray
|
|
211
|
+
Write-Host ''
|
|
212
|
+
Write-Host ' Settings live in:' -ForegroundColor Gray
|
|
213
|
+
Write-Host " $(Join-Path $pluginDir 'git-commit-push.config.json')" -ForegroundColor Gray
|
|
214
|
+
Write-Host ''
|
|
215
|
+
Write-Host ' If anything goes wrong, restore the backed-up profile files:' -ForegroundColor Gray
|
|
216
|
+
Write-Host " $(Join-Path $profileDir 'package.json.git-commit-plugin.bak')" -ForegroundColor Gray
|
|
217
|
+
Write-Host ' cordis.patch.yml.git-commit-plugin.bak (only if the migration touched it)' -ForegroundColor Gray
|
|
218
|
+
Write-Host ''
|
|
219
|
+
} else {
|
|
220
|
+
Write-Host ''
|
|
221
|
+
Write-Host 'Uninstalled. Restart DeepSeek Harness for the bundle set to change.' -ForegroundColor White
|
|
222
|
+
Write-Host 'Backups of your original profile files are next to them (*.git-commit-plugin.bak).' -ForegroundColor Gray
|
|
223
|
+
Write-Host ''
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
exit 0
|
package/setup.sh
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Install a local CHECKOUT of dsh-plugin-git-commit-push into a DSH profile on
|
|
4
|
+
# macOS or Linux. The Windows equivalent is setup.ps1; both do the same two
|
|
5
|
+
# things and both delegate the profile-manifest edit to lib/profile-edit.mjs, so
|
|
6
|
+
# the risky step is the same reviewed code on every platform.
|
|
7
|
+
#
|
|
8
|
+
# 1. links the plugin into the profile's package.json as a `link:` dependency;
|
|
9
|
+
# 2. appends the package to `dsh.profile.bundles`.
|
|
10
|
+
#
|
|
11
|
+
# Installing from npm does not need this script: use Settings > Plugins, or
|
|
12
|
+
# dsh plugin --profile <profile> add dsh-plugin-git-commit-push
|
|
13
|
+
# This script is for a checkout you are editing, which should be linked rather
|
|
14
|
+
# than copied into node_modules.
|
|
15
|
+
#
|
|
16
|
+
# The mount row is deliberately NOT written here. It comes from the package's own
|
|
17
|
+
# bundle patch (cordis.patch.yml, declared as `dsh.bundle.patch`), which the
|
|
18
|
+
# launcher applies for every profile that selects the bundle. That declaration is
|
|
19
|
+
# also what makes the package manageable: without it the Plugins page answers
|
|
20
|
+
# every request with "这个包没有声明组合包,不能作为插件管理" (`not-bundle`).
|
|
21
|
+
#
|
|
22
|
+
# What this script does add is the migration: an earlier revision wrote the mount
|
|
23
|
+
# row into the profile's cordis.patch.yml instead, and Loader `insert` is
|
|
24
|
+
# append-only — two inserts of one id mount the plugin twice — so that legacy
|
|
25
|
+
# block is stripped whenever it is found.
|
|
26
|
+
#
|
|
27
|
+
# Restart DSH afterwards. `patchReload: live` re-reads the mount row but does
|
|
28
|
+
# NOT re-import an ESM module, so code changes need a restart.
|
|
29
|
+
#
|
|
30
|
+
# Usage:
|
|
31
|
+
# ./setup.sh [profile] install (default profile: desktop)
|
|
32
|
+
# ./setup.sh [profile] --uninstall
|
|
33
|
+
#
|
|
34
|
+
# Environment:
|
|
35
|
+
# DSH_HOME DSH home directory (default: ~/.dsh)
|
|
36
|
+
|
|
37
|
+
set -eu
|
|
38
|
+
|
|
39
|
+
plugin_dir=$(cd -- "$(dirname -- "$0")" && pwd)
|
|
40
|
+
plugin_name='dsh-plugin-git-commit-push'
|
|
41
|
+
dsh_home=${DSH_HOME:-"$HOME/.dsh"}
|
|
42
|
+
|
|
43
|
+
profile='desktop'
|
|
44
|
+
uninstall=0
|
|
45
|
+
for arg in "$@"; do
|
|
46
|
+
case "$arg" in
|
|
47
|
+
--uninstall|-u) uninstall=1 ;;
|
|
48
|
+
--help|-h)
|
|
49
|
+
sed -n '2,35p' "$0" | sed 's/^# \{0,1\}//'
|
|
50
|
+
exit 0
|
|
51
|
+
;;
|
|
52
|
+
-*) printf 'unknown option: %s\n' "$arg" >&2; exit 2 ;;
|
|
53
|
+
*) profile=$arg ;;
|
|
54
|
+
esac
|
|
55
|
+
done
|
|
56
|
+
|
|
57
|
+
profile_dir="$dsh_home/profiles/$profile"
|
|
58
|
+
|
|
59
|
+
ok() { printf ' [ok] %s\n' "$1"; }
|
|
60
|
+
info() { printf ' [info] %s\n' "$1"; }
|
|
61
|
+
warn() { printf ' [warn] %s\n' "$1"; }
|
|
62
|
+
die() { printf ' [fail] %s\n' "$1" >&2; exit 1; }
|
|
63
|
+
|
|
64
|
+
printf '\n%s %s\n\n' "$plugin_name" "$([ "$uninstall" = 1 ] && echo uninstall || echo install)"
|
|
65
|
+
|
|
66
|
+
# ---------------------------------------------------------------- preconditions
|
|
67
|
+
[ -d "$profile_dir" ] || die "profile directory not found: $profile_dir"
|
|
68
|
+
manifest="$profile_dir/package.json"
|
|
69
|
+
patch_file="$profile_dir/cordis.patch.yml"
|
|
70
|
+
[ -f "$manifest" ] || die "not a DSH profile (no package.json): $profile_dir"
|
|
71
|
+
[ -f "$patch_file" ] || die "not a DSH profile (no cordis.patch.yml): $profile_dir"
|
|
72
|
+
|
|
73
|
+
if command -v git >/dev/null 2>&1; then
|
|
74
|
+
ok "git found: $(command -v git)"
|
|
75
|
+
else
|
|
76
|
+
warn 'git was not found on PATH. The plugin needs it at runtime; install Git before using it.'
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
# Prefer a node already on PATH; otherwise use the runtime DSH ships with.
|
|
80
|
+
node_bin=''
|
|
81
|
+
if command -v node >/dev/null 2>&1; then
|
|
82
|
+
node_bin=$(command -v node)
|
|
83
|
+
else
|
|
84
|
+
for candidate in \
|
|
85
|
+
"$dsh_home/dsh-runtimes/dsh-primary-runtime/dependencies/node/bin/node" \
|
|
86
|
+
"/Applications/DeepSeek Harness.app/Contents/Resources/app.asar.unpacked/dsh/dsh-runtimes/dsh-primary-runtime/dependencies/node/bin/node"
|
|
87
|
+
do
|
|
88
|
+
if [ -x "$candidate" ]; then node_bin=$candidate; break; fi
|
|
89
|
+
done
|
|
90
|
+
fi
|
|
91
|
+
[ -n "$node_bin" ] || die 'no node executable found. Install Node 20+, or set DSH_HOME to your DSH home.'
|
|
92
|
+
ok "node: $node_bin"
|
|
93
|
+
|
|
94
|
+
pnpm_cli="$dsh_home/dsh-runtimes/dsh-primary-runtime/dependencies/pnpm/bin/pnpm.mjs"
|
|
95
|
+
|
|
96
|
+
# ------------------------------------------------------------------- backups
|
|
97
|
+
stamp=$(date +%Y%m%d-%H%M%S)
|
|
98
|
+
for file in "$manifest" "$patch_file"; do
|
|
99
|
+
backup="$file.git-commit-plugin.bak"
|
|
100
|
+
if [ ! -f "$backup" ]; then
|
|
101
|
+
# `cp -p` preserves the mode; a plain cp is fine but this keeps parity with
|
|
102
|
+
# the Windows installer's intent (never overwrite an existing backup).
|
|
103
|
+
cp -p "$file" "$backup"
|
|
104
|
+
ok "backed up $(basename "$file") -> $(basename "$backup")"
|
|
105
|
+
fi
|
|
106
|
+
cp -p "$file" "$file.pre-install-$stamp"
|
|
107
|
+
done
|
|
108
|
+
info "pre-install snapshots written as *.pre-install-$stamp"
|
|
109
|
+
|
|
110
|
+
# ------------------------------------------------------- 1+2. profile manifest
|
|
111
|
+
if [ "$uninstall" = 1 ]; then
|
|
112
|
+
"$node_bin" "$plugin_dir/lib/profile-edit.mjs" \
|
|
113
|
+
--profile-dir "$profile_dir" --package "$plugin_name" --remove || die 'manifest edit failed'
|
|
114
|
+
else
|
|
115
|
+
"$node_bin" "$plugin_dir/lib/profile-edit.mjs" \
|
|
116
|
+
--profile-dir "$profile_dir" --package "$plugin_name" --link "$plugin_dir" || die 'manifest edit failed'
|
|
117
|
+
fi
|
|
118
|
+
ok 'package.json updated'
|
|
119
|
+
|
|
120
|
+
# ------------------------------------------------------- 3. legacy mount row
|
|
121
|
+
# The mount row comes from this package's bundle patch (cordis.patch.yml), so
|
|
122
|
+
# nothing is added to the profile patch here. What is removed is the row an
|
|
123
|
+
# earlier revision of this script wrote: Loader `insert` is append-only, so
|
|
124
|
+
# leaving it next to the bundle's own row would mount the plugin twice.
|
|
125
|
+
begin_marker='# >>> dsh-plugin-git-commit-push'
|
|
126
|
+
end_marker='# <<< dsh-plugin-git-commit-push'
|
|
127
|
+
|
|
128
|
+
# Strip any previous block (POSIX awk, no GNU-only flags, no in-place sed: the
|
|
129
|
+
# `-i` flag differs between BSD/macOS and GNU, which is exactly the kind of
|
|
130
|
+
# portability trap this avoids). The file is only replaced when the block was
|
|
131
|
+
# actually there, so a fresh install leaves cordis.patch.yml byte-identical.
|
|
132
|
+
awk -v begin="$begin_marker" -v end="$end_marker" '
|
|
133
|
+
$0 == begin { skipping = 1 }
|
|
134
|
+
skipping != 1 { print }
|
|
135
|
+
$0 == end { skipping = 0; next }
|
|
136
|
+
' "$patch_file" > "$patch_file.tmp"
|
|
137
|
+
|
|
138
|
+
if cmp -s "$patch_file" "$patch_file.tmp"; then
|
|
139
|
+
rm -f "$patch_file.tmp"
|
|
140
|
+
ok 'cordis.patch.yml: no legacy mount row to remove'
|
|
141
|
+
else
|
|
142
|
+
backup="$patch_file.git-commit-plugin.bak"
|
|
143
|
+
if [ ! -f "$backup" ]; then
|
|
144
|
+
cp -p "$patch_file" "$backup"
|
|
145
|
+
ok "backed up $(basename "$patch_file") -> $(basename "$backup")"
|
|
146
|
+
fi
|
|
147
|
+
mv "$patch_file.tmp" "$patch_file"
|
|
148
|
+
ok 'cordis.patch.yml: legacy mount row removed (the bundle patch mounts the plugin now)'
|
|
149
|
+
fi
|
|
150
|
+
|
|
151
|
+
# ---------------------------------------------------------------- 4. link it
|
|
152
|
+
if [ "$uninstall" = 1 ]; then
|
|
153
|
+
info 'skipping pnpm install (removal)'
|
|
154
|
+
else
|
|
155
|
+
if [ -f "$pnpm_cli" ]; then
|
|
156
|
+
info 'running pnpm install in the profile (this may take a moment)...'
|
|
157
|
+
( cd "$profile_dir" && "$node_bin" "$pnpm_cli" install ) || die 'pnpm install failed'
|
|
158
|
+
ok 'package linked into the profile'
|
|
159
|
+
else
|
|
160
|
+
warn "bundled pnpm not found at $pnpm_cli"
|
|
161
|
+
warn "run this yourself to link the package: cd '$profile_dir' && pnpm install"
|
|
162
|
+
fi
|
|
163
|
+
|
|
164
|
+
if [ -e "$profile_dir/node_modules/$plugin_name" ]; then
|
|
165
|
+
ok "module present at node_modules/$plugin_name"
|
|
166
|
+
else
|
|
167
|
+
warn "node_modules/$plugin_name is missing; the profile will not find the plugin"
|
|
168
|
+
warn 'run `pnpm install` inside the profile directory and try again'
|
|
169
|
+
fi
|
|
170
|
+
fi
|
|
171
|
+
|
|
172
|
+
# --------------------------------------------------------------------- report
|
|
173
|
+
printf '\n'
|
|
174
|
+
if [ "$uninstall" = 1 ]; then
|
|
175
|
+
printf 'Uninstalled. Restart DeepSeek Harness for the bundle set to change.\n'
|
|
176
|
+
printf 'Backups: %s\n\n' "$manifest.git-commit-plugin.bak"
|
|
177
|
+
else
|
|
178
|
+
printf 'Done. Restart DeepSeek Harness to load the plugin.\n\n'
|
|
179
|
+
printf ' A bundle change is read at profile start, not live, and a host-code\n'
|
|
180
|
+
printf ' change needs a fresh ESM import. Quit DSH first, then start it again.\n\n'
|
|
181
|
+
printf ' After the restart you get:\n'
|
|
182
|
+
printf ' - tool git_commit_push (prepare / apply / auto) [costs model tokens]\n'
|
|
183
|
+
printf ' - command /git-commit-push (no model involved) [0 model tokens]\n\n'
|
|
184
|
+
printf ' The plugin is a declared bundle, so Settings > Plugins can now enable,\n'
|
|
185
|
+
printf ' disable and uninstall it without this script.\n\n'
|
|
186
|
+
printf ' Settings: %s\n' "$plugin_dir/git-commit-push.config.json"
|
|
187
|
+
printf ' Backups : %s\n\n' "$manifest.git-commit-plugin.bak"
|
|
188
|
+
fi
|
|
189
|
+
|
|
190
|
+
exit 0
|