Continue migrating functionality from backport.pl to backport.py

* tools/dist/nominate-backport.py
  (subprocess_output): Remove local function affecting...
  (check_local_mods_to_STATUS),
  (get_availid),
  (main): ... these functions, replacing with a call to
    backport.merger.run_svn() or one of its close friends.
  (main): Moving local code figuring out some wc data from here...
* backport/wc.py
  (get_wc_info): ... to here to enable future re-use (parsing additional
    data at the same time).



git-svn-id: https://svn.apache.org/repos/asf/subversion/trunk@1925156 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/tools/dist/backport/wc.py b/tools/dist/backport/wc.py
new file mode 100644
index 0000000..adb09bd
--- /dev/null
+++ b/tools/dist/backport/wc.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python3
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+"""
+backport.wc - library for performing actions on the current WC
+"""
+
+import backport.merger
+
+import logging
+
+logger = logging.getLogger(__name__)
+
+
+def get_wc_info():
+  """Run svn info. Return a dictionary with the following elements:
+  URL: The WC url
+  BASE_revision: The WC base revision
+  Repository_root: The WC repository root
+  """
+  (exit_code, stdout, stderr) = backport.merger.run_svn(["info"])
+  URL = ""
+  BASE_revision = ""
+  Repository_root = ""
+  for line in stdout.split('\n'):
+    if line.startswith('URL:'):
+      URL = line.split('URL:')[1].strip()
+    elif line.startswith('Revision:'):
+      BASE_revision = line.split('Revision:')[1].strip()
+    elif line.startswith('Repository Root:'):
+      Repository_root = line.split('Repository Root:')[1].strip()
+  return {"URL": URL,
+          "BASE_revision": BASE_revision,
+          "Repository_root": Repository_root,
+          }
+
+
+def setUpModule():
+  "Set-up function, invoked by 'python -m unittest'."
+  # Suppress warnings generated by the test data.
+  # TODO: some test functions assume .assertLogs is available, they fail with
+  # AttributeError if it's absent (e.g., on python < 3.4).
+  try:
+    unittest.TestCase.assertLogs
+  except AttributeError:
+    logger.setLevel(logging.ERROR)
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/tools/dist/nominate-backport.py b/tools/dist/nominate-backport.py
index 95a0735..c21db19 100755
--- a/tools/dist/nominate-backport.py
+++ b/tools/dist/nominate-backport.py
@@ -44,12 +44,8 @@
 STATUS = './STATUS'
 LINELENGTH = 79
 
-def subprocess_output(args):
-  result = subprocess.run(args, capture_output = True, text = True)
-  return result.stdout
-
 def check_local_mods_to_STATUS():
-  status = subprocess_output(['svn', 'diff', './STATUS'])
+  (exit_code, status, stderr) = backport.merger.run_svn(['diff', './STATUS'])
   if status != "":
     print(f"Local mods to STATUS file {STATUS}")
     print(status)
@@ -72,7 +68,7 @@
   except KeyError:
     try:
       # Failing, try executing svn auth
-      auth = subprocess_output(['svn', 'auth', 'svn.apache.org:443'])
+      (exitcode, auth, stderr) = backport.merger.run_svn(['auth', 'svn.apache.org:443'])
       correct_realm = False
       for line in auth.split('\n'):
         line = line.strip()
@@ -154,18 +150,11 @@
   justification = sys.argv[2]
 
   # Get some WC info
-  info = subprocess_output(['svn', 'info'])
-  BASE_revision = ""
-  URL = ""
-  for line in info.split('\n'):
-    if line.startswith('URL:'):
-      URL = line.split('URL:')[1]
-    elif line.startswith('Revision:'):
-      BASE_revision = line.split('Revision:')[1]
+  wcinfo = backport.wc.get_wc_info()
 
   # To save typing, require just the last three digits if they're unambiguous.
-  if BASE_revision != "":
-    BASE_revision = int(BASE_revision)
+  if wcinfo["BASE_revision"] != "":
+    BASE_revision = int(wcinfo["BASE_revision"])
     if BASE_revision > 1000:
       residue = BASE_revision % 1000
       thousands = BASE_revision - residue
@@ -176,12 +165,13 @@
   revisions.sort()
 
   # Determine whether a backport branch exists
-  branch = subprocess_output(['svn', 'info', '--show-item', 'url', '--', URL+'-r'+str(revisions[0])]).replace('\n', '')
+  (exit_code, branch, stderr) = backport.merger.run_svn(['info', '--show-item', 'url', '--',
+                              wcinfo["URL"] + '-r'+str(revisions[0])]).replace('\n', '')
   if branch == "":
     branch = None
 
   # Get log message from first revision
-  logmsg = subprocess_output(['svn', 'propget', '--revprop', '-r',
+  (exit_code, logmsg, stderr) = backport.merger.run_svn(['propget', '--revprop', '-r',
                               str(revisions[0]), '--strict', 'svn:log', '^/'])
   if (logmsg == ""):
     print("Can't fetch log message of r" + revisions[0])
@@ -225,17 +215,17 @@
     sf.unparse(f)
 
   # Check for changes to commit
-  diff = subprocess_output(['svn', 'diff', STATUS])
+  (exit_code, diff , stderr) = backport.merger.run_svn(['diff', STATUS])
   print(diff)
   answer = input("Commit this nomination [y/N]? ")
   if answer.lower() == "y":
-    subprocess_output(['svn', 'commit', STATUS, '-m',
+    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":
-      subprocess_output(['svn', 'revert', STATUS])
+      backport.merger.run_svn_quiet(['revert', STATUS])
   
   sys.exit(0)