@shelken/pi-co-authored-by 0.2.8 → 0.2.9
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 +1 -1
- package/lib/commit.ts +121 -32
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ Co-Authored-By: <model> <noreply@pi.dev>
|
|
|
7
7
|
Generated-By: pi <version>
|
|
8
8
|
```
|
|
9
9
|
|
|
10
|
-
实现:
|
|
10
|
+
实现:bash 期间在真实 hooks 目录临时安装 `prepare-commit-msg`(不改 `core.hooksPath`);pid 引用计数,shell 退出时最后一个引用卸装并恢复原 hook。
|
|
11
11
|
|
|
12
12
|
初始 fork 自 [bruno-garcia/pi-co-authored-by](https://github.com/bruno-garcia/pi-co-authored-by)。
|
|
13
13
|
|
package/lib/commit.ts
CHANGED
|
@@ -20,7 +20,10 @@ export function removeCommitHookDirectory(hooksDir: string | undefined): void {
|
|
|
20
20
|
rmSync(hooksDir, { recursive: true, force: true });
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* 注入 trailer 元数据,并在当前仓库临时安装 prepare-commit-msg。
|
|
25
|
+
* 不设置 core.hooksPath,避免污染 git config;shell 退出时恢复原 hook。
|
|
26
|
+
*/
|
|
24
27
|
export function wrapBashWithCommitHook(
|
|
25
28
|
cmd: string,
|
|
26
29
|
hooksDir: string,
|
|
@@ -38,24 +41,129 @@ function buildEnvironmentPrefix(
|
|
|
38
41
|
coAuthor: string,
|
|
39
42
|
generatedBy: string,
|
|
40
43
|
): string {
|
|
41
|
-
|
|
42
|
-
export
|
|
43
|
-
export PI_CO_AUTHORED_BY_CO_AUTHOR=${shellQuote(coAuthor)}
|
|
44
|
+
const hookSrc = join(hooksDir, "prepare-commit-msg");
|
|
45
|
+
return `export PI_CO_AUTHORED_BY_CO_AUTHOR=${shellQuote(coAuthor)}
|
|
44
46
|
export PI_CO_AUTHORED_BY_GENERATED_BY=${shellQuote(generatedBy)}
|
|
45
|
-
export
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
export PI_CO_AUTHORED_BY_HOOK_SRC=${shellQuote(hookSrc)}
|
|
48
|
+
|
|
49
|
+
__pi_co_authored_by_installed_hooks=""
|
|
50
|
+
|
|
51
|
+
__pi_co_authored_by_resolve_hooks_dir() {
|
|
52
|
+
local configured hooks_dir toplevel
|
|
53
|
+
configured="$(command git config --get core.hooksPath 2>/dev/null || true)"
|
|
54
|
+
if [ -n "$configured" ]; then
|
|
55
|
+
case "$configured" in
|
|
56
|
+
/*) hooks_dir="$configured" ;;
|
|
57
|
+
*)
|
|
58
|
+
toplevel="$(command git rev-parse --show-toplevel 2>/dev/null)" || return 1
|
|
59
|
+
hooks_dir="$toplevel/$configured"
|
|
60
|
+
;;
|
|
61
|
+
esac
|
|
62
|
+
else
|
|
63
|
+
hooks_dir="$(command git rev-parse --git-path hooks 2>/dev/null)" || return 1
|
|
64
|
+
fi
|
|
65
|
+
# 绝对路径,避免 cwd 变化后 cleanup 找不到
|
|
66
|
+
case "$hooks_dir" in
|
|
67
|
+
/*) ;;
|
|
68
|
+
*) hooks_dir="$(CDPATH= cd -- "$hooks_dir" 2>/dev/null && pwd)" || return 1 ;;
|
|
69
|
+
esac
|
|
70
|
+
printf '%s' "$hooks_dir"
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
# 清掉已死进程的 ref,避免 SIGKILL 后永远占坑
|
|
74
|
+
__pi_co_authored_by_prune_refs() {
|
|
75
|
+
local refs_dir="$1" f pid
|
|
76
|
+
[ -d "$refs_dir" ] || return 0
|
|
77
|
+
for f in "$refs_dir"/*; do
|
|
78
|
+
[ -e "$f" ] || continue
|
|
79
|
+
pid="\${f##*/}"
|
|
80
|
+
case "$pid" in
|
|
81
|
+
''|*[!0-9]*) rm -f "$f" ;;
|
|
82
|
+
*) kill -0 "$pid" 2>/dev/null || rm -f "$f" ;;
|
|
83
|
+
esac
|
|
84
|
+
done
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
# 登记本 shell 对 hooks_dir 的引用(见 marker 也要登记,否则 sticky dirty)
|
|
88
|
+
__pi_co_authored_by_register() {
|
|
89
|
+
local hooks_dir="$1" refs_dir
|
|
90
|
+
refs_dir="$hooks_dir/.pi-co-authored-by-refs"
|
|
91
|
+
mkdir -p "$refs_dir" 2>/dev/null || return 0
|
|
92
|
+
__pi_co_authored_by_prune_refs "$refs_dir"
|
|
93
|
+
: > "$refs_dir/$$" 2>/dev/null || return 0
|
|
94
|
+
case "
|
|
95
|
+
$__pi_co_authored_by_installed_hooks
|
|
96
|
+
" in
|
|
97
|
+
*"
|
|
98
|
+
$hooks_dir
|
|
99
|
+
"*) ;;
|
|
100
|
+
*)
|
|
101
|
+
__pi_co_authored_by_installed_hooks="$__pi_co_authored_by_installed_hooks
|
|
102
|
+
$hooks_dir"
|
|
103
|
+
;;
|
|
104
|
+
esac
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
__pi_co_authored_by_ensure_hook() {
|
|
108
|
+
local hooks_dir hook
|
|
109
|
+
hooks_dir="$(__pi_co_authored_by_resolve_hooks_dir)" || return 0
|
|
110
|
+
hook="$hooks_dir/prepare-commit-msg"
|
|
111
|
+
mkdir -p "$hooks_dir" 2>/dev/null || return 0
|
|
112
|
+
|
|
113
|
+
if [ -f "$hook" ] && grep -q 'PI_CO_AUTHORED_BY_HOOK_MARKER' "$hook" 2>/dev/null; then
|
|
114
|
+
__pi_co_authored_by_register "$hooks_dir"
|
|
115
|
+
return 0
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
if [ -e "$hook" ] && [ ! -e "$hooks_dir/prepare-commit-msg.pi-user" ]; then
|
|
119
|
+
mv "$hook" "$hooks_dir/prepare-commit-msg.pi-user"
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
cp "$PI_CO_AUTHORED_BY_HOOK_SRC" "$hook"
|
|
123
|
+
chmod +x "$hook"
|
|
124
|
+
__pi_co_authored_by_register "$hooks_dir"
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
__pi_co_authored_by_cleanup() {
|
|
128
|
+
local hooks_dir hook refs_dir
|
|
129
|
+
printf '%s\n' "$__pi_co_authored_by_installed_hooks" | while IFS= read -r hooks_dir; do
|
|
130
|
+
[ -n "$hooks_dir" ] || continue
|
|
131
|
+
refs_dir="$hooks_dir/.pi-co-authored-by-refs"
|
|
132
|
+
rm -f "$refs_dir/$$" 2>/dev/null || true
|
|
133
|
+
__pi_co_authored_by_prune_refs "$refs_dir"
|
|
134
|
+
# 仍有活进程占用:只退自己的 ref,不卸 hook
|
|
135
|
+
if [ -n "$(ls -A "$refs_dir" 2>/dev/null)" ]; then
|
|
136
|
+
continue
|
|
137
|
+
fi
|
|
138
|
+
rmdir "$refs_dir" 2>/dev/null || true
|
|
139
|
+
hook="$hooks_dir/prepare-commit-msg"
|
|
140
|
+
if [ -f "$hook" ] && grep -q 'PI_CO_AUTHORED_BY_HOOK_MARKER' "$hook" 2>/dev/null; then
|
|
141
|
+
rm -f "$hook"
|
|
142
|
+
if [ -e "$hooks_dir/prepare-commit-msg.pi-user" ]; then
|
|
143
|
+
mv "$hooks_dir/prepare-commit-msg.pi-user" "$hook"
|
|
144
|
+
fi
|
|
145
|
+
fi
|
|
146
|
+
done
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
trap '__pi_co_authored_by_cleanup' EXIT
|
|
150
|
+
__pi_co_authored_by_ensure_hook
|
|
151
|
+
|
|
152
|
+
git() {
|
|
153
|
+
__pi_co_authored_by_ensure_hook
|
|
154
|
+
command git "$@"
|
|
155
|
+
}`;
|
|
49
156
|
}
|
|
50
157
|
|
|
51
158
|
function buildPrepareCommitMsgHook(): string {
|
|
52
159
|
return `#!/bin/sh
|
|
160
|
+
# PI_CO_AUTHORED_BY_HOOK_MARKER
|
|
53
161
|
set -u
|
|
54
162
|
|
|
55
163
|
message_file="$1"
|
|
56
164
|
|
|
57
165
|
if [ -n "\${PI_CO_AUTHORED_BY_CO_AUTHOR:-}" ] && [ -n "\${PI_CO_AUTHORED_BY_GENERATED_BY:-}" ]; then
|
|
58
|
-
git \
|
|
166
|
+
command git \
|
|
59
167
|
-c trailer.co-authored-by.ifExists=addIfDifferent \
|
|
60
168
|
-c trailer.generated-by.ifExists=replace \
|
|
61
169
|
interpret-trailers \
|
|
@@ -65,25 +173,10 @@ if [ -n "\${PI_CO_AUTHORED_BY_CO_AUTHOR:-}" ] && [ -n "\${PI_CO_AUTHORED_BY_GENE
|
|
|
65
173
|
"$message_file"
|
|
66
174
|
fi
|
|
67
175
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
export GIT_CONFIG_COUNT="$__pi_config_index"
|
|
73
|
-
fi
|
|
74
|
-
|
|
75
|
-
original_hooks_path="$(git config --get core.hooksPath || true)"
|
|
76
|
-
if [ -n "$original_hooks_path" ]; then
|
|
77
|
-
case "$original_hooks_path" in
|
|
78
|
-
/*) original_hook="$original_hooks_path/prepare-commit-msg" ;;
|
|
79
|
-
*) original_hook="$(git rev-parse --show-toplevel)/$original_hooks_path/prepare-commit-msg" ;;
|
|
80
|
-
esac
|
|
81
|
-
else
|
|
82
|
-
original_hook="$(git rev-parse --git-path hooks/prepare-commit-msg)"
|
|
83
|
-
fi
|
|
84
|
-
|
|
85
|
-
if [ -x "$original_hook" ] && [ "$original_hook" != "$0" ]; then
|
|
86
|
-
"$original_hook" "$@"
|
|
176
|
+
hooks_dir="$(dirname "$0")"
|
|
177
|
+
user_hook="$hooks_dir/prepare-commit-msg.pi-user"
|
|
178
|
+
if [ -x "$user_hook" ]; then
|
|
179
|
+
"$user_hook" "$@"
|
|
87
180
|
fi
|
|
88
181
|
`;
|
|
89
182
|
}
|
|
@@ -91,7 +184,3 @@ fi
|
|
|
91
184
|
function shellQuote(value: string): string {
|
|
92
185
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
93
186
|
}
|
|
94
|
-
|
|
95
|
-
function escapeDoubleQuotedAssignmentValue(value: string): string {
|
|
96
|
-
return value.replace(/[\\"$`]/g, "\\$&");
|
|
97
|
-
}
|