0
0
Fork 0
Codesys-MCP-SP21-plus/src/scripts/git_commit.py
Karstein Phobic Nyvold Kvistad e6cfa5730b fix(git_*): persist binding/state with project.save() after every mutating op
Second RTFM remediation. The helpme-codesys.com Git scripting page
(https://content.helpme-codesys.com/en/CODESYS%20Git/_git_using_scripting.html)
says explicitly:

  "Project Save: Call project.save() after operations to persist
   changes. Appears after operations like push() and merge() to
   persist changes."

The example flows on that page show project.save() interleaved with
init / commit / push / merge. None of the git_* wrappers shipped so
far called save(), which means binding info, configured remotes,
upstream tracking, and post-commit state could fail to persist when
the IDE closes -- silently degrading every flow that spans more than
one CODESYS session.

This commit adds a soft-fail primary_project.save() after every
mutating op:

  git_init                    after git.init(...)
  git_commit                  after git.commit_complete(...)
  git_remote_add              after git.remote_add(...)
  git_branch_set_upstream_to  after git.branch_set_upstream_to(...)
  git_push                    after git.push(...)

git_status is unchanged -- it's read-only.

Soft-fail rationale: a save() failure does NOT undo a successful git
op. We log a WARNING and continue, so the visible result still
reflects what actually happened in the repo. Bubbling save errors
would risk telling the user "init failed" when in fact the .git/ is
on disk and the only loss is the in-memory binding. The honest
failure mode is "git op succeeded, persistence may not have."
2026-04-25 20:46:57 +02:00

79 lines
3.2 KiB
Python

import sys, scriptengine as script_engine, os, traceback
COMMIT_MESSAGE = """{COMMIT_MESSAGE}"""
AUTHOR_NAME = "{AUTHOR_NAME}"
AUTHOR_EMAIL = "{AUTHOR_EMAIL}"
try:
print("DEBUG: git_commit: Project='%s', Author='%s <%s>'" % (
PROJECT_FILE_PATH, AUTHOR_NAME, AUTHOR_EMAIL))
print("DEBUG: message (%d chars):" % len(COMMIT_MESSAGE))
print(COMMIT_MESSAGE)
if not COMMIT_MESSAGE.strip():
raise ValueError("Commit message is empty.")
if not AUTHOR_NAME.strip():
raise ValueError("Author name is empty.")
if not AUTHOR_EMAIL.strip():
raise ValueError("Author email is empty.")
primary_project = ensure_project_open(PROJECT_FILE_PATH)
git = getattr(primary_project, 'git', None)
if git is None:
raise RuntimeError(
"Project '%s' is not bound to a Git repository (primary_project.git "
"is None). Run git_init first." % PROJECT_FILE_PATH)
if not hasattr(git, 'commit_complete'):
attrs = sorted([a for a in dir(git) if not a.startswith('_')])
raise AttributeError(
"project.git does not expose commit_complete(). "
"Available attributes: %s" % attrs)
# commit_complete signature per docs: (message, user, mail).
# Stages all working-tree changes and commits in one shot.
print("DEBUG: calling git.commit_complete(message, '%s', '%s')" % (AUTHOR_NAME, AUTHOR_EMAIL))
git.commit_complete(COMMIT_MESSAGE, AUTHOR_NAME, AUTHOR_EMAIL)
print("DEBUG: commit_complete returned without exception.")
# Per helpme-codesys.com Git scripting docs: persist project state after
# commits. Soft-fail (git op already succeeded).
try:
primary_project.save()
print("DEBUG: project.save() succeeded after commit.")
except Exception as save_e:
print("WARNING: project.save() after commit raised: %s -- project state may not persist across IDE sessions." % save_e)
# Best-effort: report current branch after commit
branch = "?"
if hasattr(git, 'branch_show_current'):
try:
branch = str(git.branch_show_current())
except Exception:
pass
print("Committed on branch: %s" % branch)
print("Author: %s <%s>" % (AUTHOR_NAME, AUTHOR_EMAIL))
print("SCRIPT_SUCCESS: git_commit complete.")
sys.exit(0)
except Exception as e:
detailed = traceback.format_exc()
raw = "%s" % e
if 'HasGitLicense' in raw or 'HasGitLicense' in detailed:
msg = (
"CODESYS Git scripting requires an active CODESYS Professional "
"Developer Edition subscription license. The plug-in is installed "
"but the runtime 'HasGitLicense' rule returned False, so every "
"project.git.* operation (init/commit/status/...) is gated. "
"Activate a Professional Developer Edition subscription on this "
"CODESYS install (see https://store.codesys.com/en/codesys-git.html, "
"sections 'Additional Requirements' and 'Licensing'). Underlying "
"error from CODESYS: %s" % e
)
else:
msg = "Error in git_commit for project '%s': %s\n%s" % (
PROJECT_FILE_PATH, e, detailed)
print(msg)
print("SCRIPT_ERROR: %s" % msg)
sys.exit(1)