2
0
mirror of https://expo.survex.com/repositories/troggle/.git synced 2026-03-27 18:51:48 +00:00

nearly done cave edit commit thing with cookie

This commit is contained in:
2024-12-28 19:47:28 +00:00
parent 09a16fed3b
commit ecd187e88e
3 changed files with 164 additions and 110 deletions

View File

@@ -45,6 +45,13 @@ sha = hashlib.new('sha256')
COOKIE_MAX_AGE = 12*60*60 # seconds
throw = 35.0
DEV_OK = """On branch master
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
"""
class DatabaseResetOngoing(Exception):
"""Exception class for errors while the server is reimporting everything"""
@@ -126,7 +133,7 @@ def make_new_expo_dir(year):
def current_expo():
"""Returns the current expo year, but also checks if the most recent expo year is the same
as this year. If it is not, then it creates an empty Expedition and fixes some files and
folders. If were are more than one year out of date, it creates all intervening Expo objects
folders. If we are more than one year out of date, it creates all intervening Expo objects
and folders. You will need to tidy this up manually.
"""
expos = Expedition.objects.all().order_by('-year')
@@ -191,61 +198,10 @@ def parse_aliases(aliasfile):
return [(None, None)], "Fail on file reading"
return aliases, report
def only_commit(fname, message, editor=None):
"""Only used to commit a survex file edited and saved in view/survex.py"""
git = settings.GIT
cwd = fname.parent
filename = fname.name
# print(f'{fname=} ')
if editor:
editor = git_string(editor)
else:
# cannot happen as form verification has this as an obligatory field
editor = "Anathema Device <a.device@potatohut.expo>"
try:
print(f"git add {filename}")
cp_add = subprocess.run([git, "add", filename], cwd=cwd, capture_output=True, text=True)
if cp_add.returncode != 0:
msgdata = f"Ask a nerd to fix this problem in only_commit().\n--{cp_add.stderr}\n--{cp_add.stdout}\n--return code:{str(cp_add.returncode)}"
raise WriteAndCommitError(
f"CANNOT git ADD on server for this file {filename}. Edits saved but not added to git.\n\n" + msgdata
)
print(f"git commit {filename}")
print(f"Committing:\n{message=}\n{editor=}")
cmd_commit = [git, "commit", "-m", message, "--author", f"{editor}"]
cp_commit = subprocess.run(cmd_commit, cwd=cwd, capture_output=True, text=True)
# This produces return code = 1 if it commits OK, but when the local repo still needs to be pushed to origin/loser
# which will be the case when running a test troggle system on a development machine
devok_text = """On branch master
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
"""
if cp_commit.returncode == 1 and cp_commit.stdout == devok_text:
pass
else:
if cp_commit.returncode != 0 and not cp_commit.stdout.strip().endswith(
"nothing to commit, working tree clean"
):
msgdata = f'--Ask a nerd to fix this problem in only_commit().\n--{cp_commit.stderr}\n--"{cp_commit.stdout}"\n--return code:{str(cp_commit.returncode)}'
print(msgdata)
raise WriteAndCommitError(
f"Error code with git on server for this file {filename}. Edits saved, added to git, but NOT committed.\n\n"
+ msgdata
)
except subprocess.SubprocessError:
msg = f"CANNOT git COMMIT on server for this file {filename}. Subprocess error. Edits not saved.\nAsk a nerd to fix this."
print(msg)
raise WriteAndCommitError(msg)
def git_string(author_string):
"""Rewrites the supplied editor string intoa git-complient author string
Uses a regular expression for a git-compatible author string
Uses a regular expression for a git-compatible author string written mostly by Copilot
valid example "John Doe <john.doe@example.com>"
"""
author_regex = re.compile(r'^[a-zA-Z][\w\s\_\.\-]* <[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-_]+\.[a-zA-Z]{2,}>$')
@@ -259,25 +215,103 @@ def git_string(author_string):
editor += f" <{editor}@potatohut.expo>"
print(f"Not git-compatible author string, replacing as '{editor}'")
return editor
def git_add(filename, cwd, commands=[]):
"""Add a file to the list of Staged files ready for a later git commit
"""
git = settings.GIT
# what is the purpose of this 'git diff' ? To prevent merge conflicts happening I guess,
# so we do not have to reverse a 'git add'
print(f"git diff {filename}")
cmd_diff = [git, "diff", filename]
commands.append(cmd_diff)
cp_diff = subprocess.run(cmd_diff, cwd=cwd, capture_output=True, text=True)
if cp_diff.returncode != 0:
msgdata = f"Ask a nerd to fix this DIFF problem in git_add().\n--{cp_diff.stderr}\n--{cp_diff.stdout}\n--return code:{str(cp_diff.returncode)}"
raise WriteAndCommitError(
f"CANNOT git ADD on server for this file {filename}.\n\n" + msgdata
)
print(f"git add {filename}")
cmd_add = [git, "add", filename]
commands.append(cmd_add)
cp_add = subprocess.run(cmd_add, cwd=cwd, capture_output=True, text=True)
if cp_add.returncode != 0:
msgdata = f"Ask a nerd to fix this ADD problem in git_add().\n--{cp_add.stderr}\n--{cp_add.stdout}\n--return code:{str(cp_add.returncode)}"
raise WriteAndCommitError(
f"CANNOT git ADD on server for this file {filename}.\n\n" + msgdata
)
return commands
def git_commit(cwd, message, editor, commands=[]):
"""Commits whatever has been Staged by git in this directory
"""
git = settings.GIT
print(f"git commit in {cwd}")
print(f"Committing:\n{message=}\n{editor=}")
cmd_commit = [git, "commit", "-m", message, "--author", f"{editor}"]
commands.append(cmd_commit)
cp_commit = subprocess.run(cmd_commit, cwd=cwd, capture_output=True, text=True)
# This produces return code = 1 if it commits OK, but when the local repo still needs to be pushed to origin/repo
# which will be the case when running a test troggle system on a development machine
if cp_commit.returncode == 1 and cp_commit.stdout == DEV_OK: # only good for 1 commit ahead of origin/repo
pass
else:
if cp_commit.returncode != 0 and not cp_commit.stdout.strip().endswith(
"nothing to commit, working tree clean"
):
msgdata = f'--Ask a nerd to fix this problem in add_commit().\n--{cp_commit.stderr}\n--"{cp_commit.stdout}"\n--return code:{str(cp_commit.returncode)}'
print(msgdata)
raise WriteAndCommitError(
f"Error code with git on server in this directory: {cwd}. Edits saved, added to git, but NOT committed.\n\n"
+ msgdata
)
return commands
def add_commit(fname, message, editor=None):
"""Only used to commit a survex file edited and saved in view/survex.py"""
cwd = fname.parent
filename = fname.name
commands = []
if editor:
editor = git_string(editor)
else:
# 'cannot happen' as form verification has this as an obligatory field
editor = "Anathema Device <a.device@potatohut.expo>"
try:
commands = git_add(filename, cwd, commands)
commands = git_commit(cwd, message, editor, commands)
except subprocess.SubprocessError:
msg = f"CANNOT git ADD or COMMIT on server for this file {filename}.\nSubprocess error: {commands}\nEdits probably not saved.\nAsk a nerd to fix this."
print(msg)
raise WriteAndCommitError(msg)
def write_and_commit(files, message, editor=None):
"""Writes the content to the filepath and adds and commits the file to git. If this fails, a WriteAndCommitError is raised.
This needs refactoring to just write and then call only_commit()
This needs refactoring to just write and then call add_commit()
"""
# GIT see also core/views/uploads.py dwgupload()
# GIT see also core/views/expo.py editexpopage()
git = settings.GIT
commands = []
if editor:
editor = git_string(editor)
else:
# cannot happen as form verification has this as an obligatory field
editor = "Automatic <automaton@potatohut.expo>"
editor = "Write_and_commit <automaton@potatohut.expo>"
try:
for filepath, content, encoding in files:
cwd = filepath.parent
filename = filepath.name
# GIT see also core/views/uploads.py dwgupload()
# GIT see also core/views/expo.py editexpopage()
os.makedirs(os.path.dirname(filepath), exist_ok = True)
if filepath.is_dir():
raise WriteAndCommitError(
@@ -301,7 +335,10 @@ def write_and_commit(files, message, editor=None):
except Exception as e:
raise WriteAndCommitError(
f"CANNOT write this file {filepath}. Ask a nerd to fix this: {e}"
)
)
# what is the purpose of this 'git diff' ? To prevent merge conflicts happening I guess,
# so we do not have to reverse a 'git add'
cmd_diff = [git, "diff", filename]
cp_diff = subprocess.run(cmd_diff, cwd=cwd, capture_output=True, text=True)
commands.append(cmd_diff)
@@ -328,41 +365,27 @@ def write_and_commit(files, message, editor=None):
print(f"No change {filepath}")
filepaths = [filepath for filepath, content, encoding in files]
# message = message + " " + str(filepaths)
print([git, "commit", "-m", message, "--author", f"{editor}"])
cmd_commit = [git, "commit", "-m", message, "--author", f"{editor}"]
cm_status = subprocess.run(cmd_commit, cwd=cwd, capture_output=True, text=True)
commands.append(cmd_commit)
if cm_status.returncode != 0:
msgdata = (
"Commands: " + str(commands) +
"Ask a nerd to fix this.\n\n"
+ "Stderr: " + cm_status.stderr
+ "\n\n"
+ "Stdout: " + cm_status.stdout
+ "\n\nreturn code: " + str(cm_status.returncode)
+ "\n\ngit add return code in previous operation was: " + git_add_returncode
)
raise WriteAndCommitError(
f"ERROR committing. Edits saved, [maybe] added to git, but NOT committed.\n\n"
+ msgdata
)
cmd_status = [git, "status"] # + filepaths
cp_status = subprocess.run(cmd_status, cwd=cwd, capture_output=True, text=True)
commands.append(cp_status)
#This produces return code = 1 if it commits OK, but when the repo still needs to be pushed to origin/expoweb
if (not cp_status.stdout) or len(cp_status.stdout) < 2 or cp_status.stdout.split("\n")[-2] != "nothing to commit, working tree clean":
msgdata = (
str(commands) +
"Ask a nerd to fix this.\n\n"
+ "Stderr: " + cp_status.stderr
+ "\n\n"
+ "Stdout: " + cp_status.stdout
+ "\n\nreturn code: " + str(cp_status.returncode)
)
raise WriteAndCommitError(
f"Error code with git on server for this file {filename}. Edits saved, added to git, but NOT committed. Git status not clean.\n\n"
+ msgdata
)
commands = git_commit(cwd, message, editor, commands)
if False:
cmd_status = [git, "status"] # + filepaths
cp_status = subprocess.run(cmd_status, cwd=cwd, capture_output=True, text=True)
commands.append(cp_status)
#This produces return code = 1 if it commits OK, but when the repo still needs to be pushed to origin/expoweb
if (not cp_status.stdout) or len(cp_status.stdout) < 2 or cp_status.stdout.split("\n")[-2] != "nothing to commit, working tree clean":
msgdata = (
str(commands) +
"Ask a nerd to fix this.\n\n"
+ "Stderr: " + cp_status.stderr
+ "\n\n"
+ "Stdout: " + cp_status.stdout
+ "\n\nreturn code: " + str(cp_status.returncode)
)
raise WriteAndCommitError(
f"Error code with git on server for this file {filename}. Edits saved, added to git, but NOT committed. Git status not clean.\n\n"
+ msgdata
)
except subprocess.SubprocessError:
raise WriteAndCommitError(
f"CANNOT git on server for this file {filename}. Subprocess error. Edits not saved.\nAsk a nerd to fix this."
@@ -387,13 +410,13 @@ def writetrogglefile(filepath, filecontent, commit_msg=None):
core/models/caves.py
and by
make_new_expo_dir(year)
but NOT by core/views/caves.py
Commit the new saved file to git
Callers to cave.writeDataFile() or entrance.writeDataFile() should handle the exception PermissionsError explicitly
"""
# GIT see also core/views/expo.py editexpopage()
# GIT see also core/views/uploads.py dwgupload()
# Called from core/models/caves.py Cave.writeDataFile() Entrance.writeDataFile()
filepath = Path(filepath)
cwd = filepath.parent
filename = filepath.name