Author: dsahlberg
Date: Sun Jul 19 09:53:20 2026
New Revision: 1936309
Log:
Remove automatic editing of STATUS from the script and cleanup code.
* tools/dev/nominate-backport.py
(check_local_mods_to_STATUS): Remove, we don't care if STATUS is modified
since editing is up to the user
(get_availid): Make sure we only return from the correct realm.
Reorganise so we try direct file read if svn auth succeed
but nothing is found (wrong locale?).
(usage): Update documentation.
(warned_cannot_commit): Function name doesn't make sense. Removed and moved
code into...
(main): ... here. Also remove STATUS file editing and just output the new
nomination to stdout.
(): Remove unused knobs YES and MAY_COMMIT.
Modified:
subversion/trunk/tools/dist/nominate-backport.py
Modified: subversion/trunk/tools/dist/nominate-backport.py
==============================================================================
--- subversion/trunk/tools/dist/nominate-backport.py Sun Jul 19 08:30:15
2026 (r1936308)
+++ subversion/trunk/tools/dist/nominate-backport.py Sun Jul 19 09:53:20
2026 (r1936309)
@@ -22,10 +22,8 @@ Nominate revision(s) for backport.
This script should be run interactively, to nominate code for backport.
-Run this script from the root of a stable branch's working copy (e.g.,
-a working copy of /branches/1.9.x). This script will add an entry to the
-STATUS file and optionally commit the changes.
-"""
+It will output a properly formatted nomination that can be copied into
+STATUS."""
import sys
assert sys.version_info[0] == 3, "This script targets Python 3"
@@ -41,22 +39,6 @@ import backport.merger
import backport.status
import backport.wc
-# Constants
-STATUS = './STATUS'
-LINELENGTH = 79
-
-def check_local_mods_to_STATUS():
- (exit_code, status, stderr) = backport.merger.run_svn(['diff', './STATUS'])
- if status != "":
- print(f"Local mods to STATUS file {STATUS}")
- print(status)
- if YES:
- sys.exit(1)
- input("Press Enter to continue or Ctrl-C to abort...")
- return True
-
- return False
-
def get_availid():
"""Try to get the AVAILID of the current user"""
@@ -67,32 +49,44 @@ def get_availid():
return os.environ["AVAILID"]
except KeyError:
- try:
- # Failing, try executing svn auth
- (exitcode, auth, stderr) = backport.merger.run_svn(['auth',
'svn.apache.org:443'])
+ pass
+
+ except:
+ raise
+
+ try:
+ # Failing, try executing svn auth
+ (exitcode, auth, stderr) = backport.merger.run_svn(['auth',
+ 'svn.apache.org:443'],
+ "E200009")
+ if exitcode == 0:
correct_realm = False
for line in auth.split('\n'):
line = line.strip()
if line.startswith('Authentication realm:'):
- correct_realm = line.find(SVN_A_O_REALM)
- elif line.startswith('Username:'):
+ correct_realm = True if line.find(SVN_A_O_REALM) > 0 else False
+ elif correct_realm and line.startswith('Username:'):
return line[10:]
- except OSError as e:
- try:
- # Last resort, read from ~/.subversion/auth/svn.simple
- dir = os.environ["HOME"] + "/.subversion/auth/svn.simple/"
- filename = hashlib.md5(SVN_A_O_REALM.encode('utf-8')).hexdigest()
- with open(dir+filename, 'r') as file:
- lines = file.readlines()
- for i in range(0, len(lines), 4):
- if lines[i].strip() == "K 8" and lines[i+1].strip() == 'username':
- return lines[i+3]
-
- except:
- raise
- except:
- raise
+ except OSError:
+ pass
+
+ except:
+ raise
+
+ try:
+ # Last resort, read from ~/.subversion/auth/svn.simple
+ dir = os.environ["HOME"] + "/.subversion/auth/svn.simple/"
+ filename = hashlib.md5(SVN_A_O_REALM.encode('utf-8')).hexdigest()
+ with open(dir+filename, 'r') as file:
+ lines = file.readlines()
+ for i in range(0, len(lines), 4):
+ if lines[i].strip() == "K 8" and lines[i+1].strip() == 'username':
+ return lines[i+3]
+
+ except FileNotFoundError:
+ pass
+
except:
raise
@@ -101,14 +95,15 @@ def usage():
Usage: ./tools/dist/nominate-backport.py "r42, r43, r45" "$Some_justification"
-Will add:
+Will output:
* r42, r43, r45
(log message of r42)
Justification:
$Some_justification
Votes:
+1: {AVAILID}
-to STATUS. Backport branches are detected automatically.
+
+Backport branches are detected automatically and is added accordingly.
The revisions argument may contain arbitrary text (besides the revision
numbers); it will be ignored. For example,
@@ -120,28 +115,15 @@ Revision numbers within the last thousan
the last three digits only.
The justification can be an arbitrarily-long string; if it is wider than the
-available width, this script will wrap it for you (and allow you to review
-the result before committing).
-
-The STATUS file in the current directory is used.
- """)
-
-def warned_cannot_commit(message):
- if AVAILID is None:
- print(message + ": Unable to determine your username via $AVAILID or svn
auth or ~/.subversion/auth/.")
- return True
- return False
+available width, this script will wrap it for you.
+""")
def main():
# Pre-requisite
- if warned_cannot_commit("Nominating failed"):
- print("Unable to proceed.\n")
+ if AVAILID is None:
+ print("Nominating failed: Unable to determine your username via $AVAILID
or svn auth or ~/.subversion/auth/.\n", file=sys.stderr)
+ print("Unable to proceed.\n", file=sys.stderr)
sys.exit(1)
- had_local_mods = check_local_mods_to_STATUS()
-
- # Update existing status file and load it
- backport.merger.run_svn_quiet(['update'])
- sf = backport.status.StatusFile(open(STATUS, encoding="UTF-8"))
# Argument parsing.
if len(sys.argv) < 3:
@@ -203,48 +185,19 @@ def main():
break
logmsg += split_logmsg[i].strip() + " "
- # Create new status entry and add to STATUS
+ # Create new status entry and print
e = backport.status.StatusEntry(None)
e.revisions = revisions
e.logsummary = textwrap.wrap(logmsg)
e.justification_str = "\n" + textwrap.fill(justification, initial_indent='
', subsequent_indent=' ') + "\n"
e.votes_str = f" +1: {AVAILID}\n"
e.branch = branch
- if not sf.insert(e, "Other candidate changes", False):
- sf.insert(e, "Candidate changes")
-
- # Write new STATUS file
- with open(STATUS, mode='w', encoding="UTF-8") as f:
- sf.unparse(f)
-
- # Check for changes to commit
- (exit_code, diff , stderr) = backport.merger.run_svn(['diff', STATUS])
- print(diff)
- answer = input("Commit this nomination [y/N]? ")
- if answer.lower() == "y":
- backport.merger.run_svn_quiet(['commit', STATUS, '-m',
- '* STATUS: Nominate r' +
- ', r'.join(map(str, revisions))])
- else:
- answer = input("Revert STATUS (destroying local mods) [y/N]? ")
- if answer.lower() == "y":
- backport.merger.run_svn_quiet(['revert', STATUS])
+ print(e)
sys.exit(0)
AVAILID = get_availid()
-# Load the various knobs
-try:
- YES = True if os.environ["YES"].lower() in ["true", "1", "yes"] else False
-except:
- YES = False
-
-try:
- MAY_COMMIT = True if os.environ["MAY_COMMIT"].lower() in ["true", "1",
"yes"] else False
-except:
- MAY_COMMIT = False
-
if __name__ == "__main__":
try:
main()