Compare commits
1 Commits
v0.2.9
...
59061a9c03
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
59061a9c03 |
@@ -9,6 +9,7 @@ INDEX_FILE="$KUGETSU_DIR/index.json"
|
|||||||
NOTIFICATIONS_FILE="$KUGETSU_DIR/notifications.json"
|
NOTIFICATIONS_FILE="$KUGETSU_DIR/notifications.json"
|
||||||
LOGS_DIR="$KUGETSU_DIR/logs"
|
LOGS_DIR="$KUGETSU_DIR/logs"
|
||||||
ENV_DIR="${ENV_DIR:-$KUGETSU_DIR/env}"
|
ENV_DIR="${ENV_DIR:-$KUGETSU_DIR/env}"
|
||||||
|
LOCKS_DIR="$KUGETSU_DIR/locks"
|
||||||
MAX_CONCURRENT_AGENTS="${MAX_CONCURRENT_AGENTS:-3}"
|
MAX_CONCURRENT_AGENTS="${MAX_CONCURRENT_AGENTS:-3}"
|
||||||
|
|
||||||
# Load user config overrides (~/.kugetsu/config)
|
# Load user config overrides (~/.kugetsu/config)
|
||||||
@@ -56,6 +57,87 @@ count_active_dev_sessions() {
|
|||||||
echo "$count"
|
echo "$count"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
acquire_lock() {
|
||||||
|
local issue_ref="$1"
|
||||||
|
local session_id="$2"
|
||||||
|
local lock_file="$LOCKS_DIR/${issue_ref//[^a-zA-Z0-9._-]/_}.lock"
|
||||||
|
|
||||||
|
mkdir -p "$LOCKS_DIR"
|
||||||
|
|
||||||
|
if [ -f "$lock_file" ]; then
|
||||||
|
local lock_pid=$(cat "$lock_file" 2>/dev/null | cut -d: -f1)
|
||||||
|
local lock_session=$(cat "$lock_file" 2>/dev/null | cut -d: -f2)
|
||||||
|
|
||||||
|
if [ -n "$lock_pid" ] && ! kill -0 "$lock_pid" 2>/dev/null; then
|
||||||
|
echo "Stale lock detected, removing..."
|
||||||
|
rm -f "$lock_file"
|
||||||
|
elif [ "$lock_session" = "$session_id" ]; then
|
||||||
|
echo "Already holding lock for $issue_ref"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
echo "Error: $issue_ref is locked by session $lock_session (PID $lock_pid)" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "${BASHPID}:${session_id}:$(date +%s)" > "$lock_file"
|
||||||
|
echo "Lock acquired for $issue_ref: $lock_file"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
release_lock() {
|
||||||
|
local issue_ref="$1"
|
||||||
|
local lock_file="$LOCKS_DIR/${issue_ref//[^a-zA-Z0-9._-]/_}.lock"
|
||||||
|
|
||||||
|
if [ ! -f "$lock_file" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local lock_pid=$(cat "$lock_file" 2>/dev/null | cut -d: -f1)
|
||||||
|
|
||||||
|
if [ "$lock_pid" = "$BASHPID" ]; then
|
||||||
|
rm -f "$lock_file"
|
||||||
|
echo "Lock released for $issue_ref"
|
||||||
|
else
|
||||||
|
echo "Error: Cannot release lock held by PID $lock_pid (current: $BASHPID)" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
release_all_locks() {
|
||||||
|
local session_id="$1"
|
||||||
|
if [ ! -d "$LOCKS_DIR" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
for lock_file in "$LOCKS_DIR"/*.lock; do
|
||||||
|
[ -f "$lock_file" ] || continue
|
||||||
|
local lock_session=$(cat "$lock_file" 2>/dev/null | cut -d: -f2)
|
||||||
|
if [ "$lock_session" = "$session_id" ]; then
|
||||||
|
rm -f "$lock_file"
|
||||||
|
echo "Released stale lock: $(basename "$lock_file")"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
check_lock() {
|
||||||
|
local issue_ref="$1"
|
||||||
|
local lock_file="$LOCKS_DIR/${issue_ref//[^a-zA-Z0-9._-]/_}.lock"
|
||||||
|
|
||||||
|
if [ -f "$lock_file" ]; then
|
||||||
|
local lock_pid=$(cat "$lock_file" 2>/dev/null | cut -d: -f1)
|
||||||
|
local lock_session=$(cat "$lock_file" 2>/dev/null | cut -d: -f2)
|
||||||
|
|
||||||
|
if [ -n "$lock_pid" ] && ! kill -0 "$lock_pid" 2>/dev/null; then
|
||||||
|
echo "Stale lock detected, removing..."
|
||||||
|
rm -f "$lock_file"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
echo "Locked by session $lock_session (PID $lock_pid)"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
cat << 'EOF'
|
cat << 'EOF'
|
||||||
kugetsu - OpenCode Session Manager (Issue-Driven)
|
kugetsu - OpenCode Session Manager (Issue-Driven)
|
||||||
@@ -1097,6 +1179,14 @@ cmd_start() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
local worktree_path=$(issue_ref_to_worktree_path "$issue_ref")
|
local worktree_path=$(issue_ref_to_worktree_path "$issue_ref")
|
||||||
|
|
||||||
|
trap 'release_lock "$issue_ref" 2>/dev/null; exit' EXIT INT TERM
|
||||||
|
|
||||||
|
if ! acquire_lock "$issue_ref" "$base_session_id"; then
|
||||||
|
echo "Error: Could not acquire lock for '$issue_ref'" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
create_worktree "$issue_ref"
|
create_worktree "$issue_ref"
|
||||||
|
|
||||||
local session_file="$(issue_ref_to_filename "$issue_ref").json"
|
local session_file="$(issue_ref_to_filename "$issue_ref").json"
|
||||||
@@ -1163,6 +1253,8 @@ cmd_start() {
|
|||||||
|
|
||||||
echo "Session started for '$issue_ref': $new_session_id"
|
echo "Session started for '$issue_ref': $new_session_id"
|
||||||
echo "Worktree: $worktree_path"
|
echo "Worktree: $worktree_path"
|
||||||
|
|
||||||
|
release_lock "$issue_ref"
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd_continue() {
|
cmd_continue() {
|
||||||
@@ -1416,6 +1508,7 @@ cmd_destroy() {
|
|||||||
|
|
||||||
if [ "$force" = true ]; then
|
if [ "$force" = true ]; then
|
||||||
remove_worktree_for_issue "$target"
|
remove_worktree_for_issue "$target"
|
||||||
|
release_lock "$target" 2>/dev/null || true
|
||||||
rm -f "$session_path"
|
rm -f "$session_path"
|
||||||
remove_issue_from_index "$target"
|
remove_issue_from_index "$target"
|
||||||
echo "Session for '$target' destroyed"
|
echo "Session for '$target' destroyed"
|
||||||
@@ -1425,6 +1518,7 @@ cmd_destroy() {
|
|||||||
read reply
|
read reply
|
||||||
if [ "$reply" = "y" ] || [ "$reply" = "Y" ]; then
|
if [ "$reply" = "y" ] || [ "$reply" = "Y" ]; then
|
||||||
remove_worktree_for_issue "$target"
|
remove_worktree_for_issue "$target"
|
||||||
|
release_lock "$target" 2>/dev/null || true
|
||||||
rm -f "$session_path"
|
rm -f "$session_path"
|
||||||
remove_issue_from_index "$target"
|
remove_issue_from_index "$target"
|
||||||
echo "Session for '$target' destroyed"
|
echo "Session for '$target' destroyed"
|
||||||
|
|||||||
Reference in New Issue
Block a user