fix: attach_command from one builder, no kill/start_command, row-less stop, one herdr name rule, registry format 2 (Issue #71) #73
+18
-9
@@ -39,7 +39,8 @@ AGENT_SESSIONS_YAML="${AGENT_SESSIONS_YAML:-$WORKSPACE_ROOT/.mam/agent-sessions.
|
|||||||
# shasum, sha1sum, openssl or python3 to make it, this fails (stderr, nonzero)
|
# shasum, sha1sum, openssl or python3 to make it, this fails (stderr, nonzero)
|
||||||
# rather than return a name herdr never registered. A name that is not ASCII
|
# rather than return a name herdr never registered. A name that is not ASCII
|
||||||
# is lowercased and replaced by python3 (tr/sed differ from str.lower() there),
|
# is lowercased and replaced by python3 (tr/sed differ from str.lower() there),
|
||||||
# and fails the same way without it.
|
# and fails the same way without it. Line breaks become '-' before sed (which
|
||||||
|
# works line by line) and before $(...) could drop a trailing one.
|
||||||
_sanitize_herdr_agent_name() {
|
_sanitize_herdr_agent_name() {
|
||||||
local n="$1"
|
local n="$1"
|
||||||
if [ -z "$n" ]; then
|
if [ -z "$n" ]; then
|
||||||
@@ -48,7 +49,7 @@ _sanitize_herdr_agent_name() {
|
|||||||
fi
|
fi
|
||||||
local s=""
|
local s=""
|
||||||
if [ -z "$(printf '%s' "$n" | LC_ALL=C tr -d '\000-\177')" ]; then
|
if [ -z "$(printf '%s' "$n" | LC_ALL=C tr -d '\000-\177')" ]; then
|
||||||
s=$(printf '%s' "$n" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9_-]/-/g')
|
s=$(printf '%s' "$n" | tr '\n' '-' | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9_-]/-/g')
|
||||||
elif command -v python3 >/dev/null 2>&1; then
|
elif command -v python3 >/dev/null 2>&1; then
|
||||||
s=$(python3 -c 'import re,sys; sys.stdout.write(re.sub(r"[^a-z0-9_-]", "-", sys.argv[1].lower()))' "$n") || s=""
|
s=$(python3 -c 'import re,sys; sys.stdout.write(re.sub(r"[^a-z0-9_-]", "-", sys.argv[1].lower()))' "$n") || s=""
|
||||||
fi
|
fi
|
||||||
@@ -1590,10 +1591,14 @@ herdr() {
|
|||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# NOTE: Retained as small inline PYEOF block (39 lines) per Plan Rev.2 (Job 98393a97).
|
# NOTE: Retained as small inline PYEOF block (39 lines) per Plan Rev.2 (Job 98393a97).
|
||||||
# Small blocks have minimal overhead and high local cohesion; extraction into lib_py is reserved for large blocks (>200 lines).
|
# Small blocks have minimal overhead and high local cohesion; extraction into lib_py is reserved for large blocks (>200 lines).
|
||||||
|
# `load_state_json strict` (Issue #71) fails (stderr, exit 1) when the YAML or
|
||||||
|
# DB cannot be read, instead of printing {} - for a caller that acts on a
|
||||||
|
# session being absent.
|
||||||
load_state_json() {
|
load_state_json() {
|
||||||
env_python "$AGENT_SESSIONS_YAML" <<'PYEOF'
|
env_python "$AGENT_SESSIONS_YAML" "MAM_STATE_READ=${1:-}" <<'PYEOF'
|
||||||
import os, sys, sqlite3, json, yaml
|
import os, sys, sqlite3, json, yaml
|
||||||
yaml_path = os.environ['YAML_PATH']
|
yaml_path = os.environ['YAML_PATH']
|
||||||
|
strict = os.environ.get('MAM_STATE_READ') == 'strict'
|
||||||
db_path = os.path.splitext(yaml_path)[0] + '.db'
|
db_path = os.path.splitext(yaml_path)[0] + '.db'
|
||||||
d = {}
|
d = {}
|
||||||
db_sessions = []
|
db_sessions = []
|
||||||
@@ -1605,21 +1610,25 @@ try:
|
|||||||
row = conn.execute('SELECT data FROM state WHERE id=1').fetchone()
|
row = conn.execute('SELECT data FROM state WHERE id=1').fetchone()
|
||||||
if row:
|
if row:
|
||||||
d = json.loads(row[0])
|
d = json.loads(row[0])
|
||||||
except sqlite3.OperationalError:
|
except sqlite3.OperationalError as e:
|
||||||
pass
|
if strict and 'no such table' not in str(e):
|
||||||
|
raise
|
||||||
try:
|
try:
|
||||||
cursor = conn.execute('SELECT data FROM sessions')
|
cursor = conn.execute('SELECT data FROM sessions')
|
||||||
for r in cursor.fetchall():
|
for r in cursor.fetchall():
|
||||||
db_sessions.append(json.loads(r[0]))
|
db_sessions.append(json.loads(r[0]))
|
||||||
d['herdr_sessions'] = db_sessions
|
d['herdr_sessions'] = db_sessions
|
||||||
except sqlite3.OperationalError:
|
except sqlite3.OperationalError as e:
|
||||||
pass
|
if strict and 'no such table' not in str(e):
|
||||||
|
raise
|
||||||
conn.close()
|
conn.close()
|
||||||
elif os.path.exists(yaml_path):
|
elif os.path.exists(yaml_path):
|
||||||
with open(yaml_path) as f:
|
with open(yaml_path) as f:
|
||||||
d = yaml.safe_load(f) or {}
|
d = yaml.safe_load(f) or {}
|
||||||
except Exception:
|
except Exception as e:
|
||||||
pass
|
if strict:
|
||||||
|
print('ERROR: cannot read the registry %s: %s' % (yaml_path, e), file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
# Clean lone surrogates to prevent UnicodeEncodeError on stdout print
|
# Clean lone surrogates to prevent UnicodeEncodeError on stdout print
|
||||||
def clean_surrogates(obj):
|
def clean_surrogates(obj):
|
||||||
if isinstance(obj, str):
|
if isinstance(obj, str):
|
||||||
|
|||||||
Reference in new issue
Block a user