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:
213
core/utils.py
213
core/utils.py
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user