<p>Benjamin Keith Ford has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/10941">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">build: Improve handling of CHANGES and UPGRADE.txt for releases.<br><br>The release script now handles the merging of the CHANGES and<br>UPGRADE.txt files for us! When a release is being done, the script will<br>go through the staging changes in the Asterisk working directory<br>(<asterisk-home>/doc/<file>-staging) and add each change to the<br>corresponding file. A separate script (process-staging-changes) has also<br>been added that can be used when creating a new version from master. It<br>takes 3 arguments: -l/--local-root, which is optional,<br>-s/--start-version, and -e/--end-version. You can use -h for more<br>information on each option.<br><br>This means that there's a new way to document our major changes. All<br>changes for CHANGES will go into doc/CHANGES-staging and all changes for<br>UPGRADE.txt will go into doc/UPGRADE-staging. Each of these files should<br>have a meaningful name related to what the change is. For example, if<br>you made a change to something in pjsip, your file might be called<br>"res_pjsip_relative_title", where "relative_title" will be something a<br>little more descriptive than that. Inside of each file, you will have a<br>subject line followed by a blank line, with the description of the<br>change following that. You can have multiple subject lines in one file.<br>For example, it may look something like this:<br><br> Subject: res_pjsip<br><br> This is a detailed description of what I changed.<br><br> You can have new lines in between as well, spacing is handled by the<br> release script!<br><br> Subject: res_pjsip<br><br> You can have another subject as well!<br><br> Subject: Core<br><br> The subjects don't have to be the same either!<br><br>The header lines (Subject:) are case sensative.<br><br>Fore more information, check out the wiki page:<br>https://wiki.asterisk.org/wiki/display/AST/CHANGES+and+UPGRADE.txt<br><br>Change-Id: I6dc084afedaeecaf36aaec66c3cf6a5a8ed4ef3c<br>---<br>M mkrelease.py<br>A process-staging-changes<br>A staging_changes.py<br>3 files changed, 227 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/repotools refs/changes/41/10941/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/mkrelease.py b/mkrelease.py</span><br><span>index 10e1a7e..fd9a272 100755</span><br><span>--- a/mkrelease.py</span><br><span>+++ b/mkrelease.py</span><br><span>@@ -23,6 +23,7 @@</span><br><span> from release_summary import ReleaseSummary, ReleaseSummaryOptions</span><br><span> from alembic_creator import create_db_script</span><br><span> from testsuite import update_testsuite</span><br><span style="color: hsl(120, 100%, 40%);">+from staging_changes import StagingChangesExtractor</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> </span><br><span>@@ -692,6 +693,16 @@</span><br><span> prev_version))</span><br><span> create_tag(options, repo)</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ # At this point, we should be on the correct branch with everything ready except</span><br><span style="color: hsl(120, 100%, 40%);">+ # for the staging changes for CHANGES and UPGRADE.txt. Get those changes now</span><br><span style="color: hsl(120, 100%, 40%);">+ # before we push everything upstream.</span><br><span style="color: hsl(120, 100%, 40%);">+ extractor = StagingChangesExtractor(path=options.local_root, start_version=prev_version,</span><br><span style="color: hsl(120, 100%, 40%);">+ end_version=version)</span><br><span style="color: hsl(120, 100%, 40%);">+ ret = extractor.run()</span><br><span style="color: hsl(120, 100%, 40%);">+ if ret != 0:</span><br><span style="color: hsl(120, 100%, 40%);">+ print "Error while trying to get staging changes!"</span><br><span style="color: hsl(120, 100%, 40%);">+ sys.exit(1)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> prompt_to_continue("Tag created, pushing changes to remote.")</span><br><span> repo.push_changes()</span><br><span> </span><br><span>diff --git a/process-staging-changes b/process-staging-changes</span><br><span>new file mode 100755</span><br><span>index 0000000..79e33f8</span><br><span>--- /dev/null</span><br><span>+++ b/process-staging-changes</span><br><span>@@ -0,0 +1,26 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#!/usr/bin/env python</span><br><span style="color: hsl(120, 100%, 40%);">+'''</span><br><span style="color: hsl(120, 100%, 40%);">+Manually get the staging changes from <asterisk_home>/doc/<file>-staging</span><br><span style="color: hsl(120, 100%, 40%);">+and add them to <file>.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Ben Ford <bford@digium.com></span><br><span style="color: hsl(120, 100%, 40%);">+'''</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+from staging_changes import StagingChangesExtractor</span><br><span style="color: hsl(120, 100%, 40%);">+from argparse import ArgumentParser</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+if __name__ == "__main__":</span><br><span style="color: hsl(120, 100%, 40%);">+ parser = ArgumentParser(description="Processes changes in working tree and updates files")</span><br><span style="color: hsl(120, 100%, 40%);">+ parser.add_argument("-l", "--local-root", dest="path", help="The local root to work from", default="/tmp")</span><br><span style="color: hsl(120, 100%, 40%);">+ parser.add_argument("-s", "--start-version", dest="start", help="The version to start from", required=True)</span><br><span style="color: hsl(120, 100%, 40%);">+ parser.add_argument("-e", "--end-version", dest="end", help="The version to end on", required=True)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ args = parser.parse_args()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ sce = StagingChangesExtractor(ast_path=args.path, start_version=args.start, end_version=args.end)</span><br><span style="color: hsl(120, 100%, 40%);">+ ret = sce.run()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if ret == 0:</span><br><span style="color: hsl(120, 100%, 40%);">+ print "Done!"</span><br><span style="color: hsl(120, 100%, 40%);">+ else:</span><br><span style="color: hsl(120, 100%, 40%);">+ print "Uh oh - omething went wrong!"</span><br><span>diff --git a/staging_changes.py b/staging_changes.py</span><br><span>new file mode 100644</span><br><span>index 0000000..876bc2f</span><br><span>--- /dev/null</span><br><span>+++ b/staging_changes.py</span><br><span>@@ -0,0 +1,190 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#!/usr/bin/env python</span><br><span style="color: hsl(120, 100%, 40%);">+'''</span><br><span style="color: hsl(120, 100%, 40%);">+Used to extract information from <asterisk_home>/doc/<file>-staging/</span><br><span style="color: hsl(120, 100%, 40%);">+and add that information to <asterisk_home>/<file></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Ben Ford <bford@digium.com></span><br><span style="color: hsl(120, 100%, 40%);">+'''</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+import logging</span><br><span style="color: hsl(120, 100%, 40%);">+import os</span><br><span style="color: hsl(120, 100%, 40%);">+import fileinput</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+LOGGER = logging.getLogger(__name__)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+MODES = ["CHANGES", "UPGRADE"]</span><br><span style="color: hsl(120, 100%, 40%);">+FUNCTIONALITY_SEPARATOR_DASH_COUNT = 78</span><br><span style="color: hsl(120, 100%, 40%);">+CATEGORY_SEPARATOR_DASH_COUNT = 18</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+class StagingChangesExtractor:</span><br><span style="color: hsl(120, 100%, 40%);">+ '''</span><br><span style="color: hsl(120, 100%, 40%);">+ Holds all the information needed to update the target files.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ Currently there is support for CHANGES and UPGRADE.txt</span><br><span style="color: hsl(120, 100%, 40%);">+ '''</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def __init__(self, ast_path, start_version, end_version):</span><br><span style="color: hsl(120, 100%, 40%);">+ '''</span><br><span style="color: hsl(120, 100%, 40%);">+ Initializer</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_path The location of the Asterisk directory we are working with</span><br><span style="color: hsl(120, 100%, 40%);">+ start_version The version we are starting from</span><br><span style="color: hsl(120, 100%, 40%);">+ end_version The version we are ending on</span><br><span style="color: hsl(120, 100%, 40%);">+ '''</span><br><span style="color: hsl(120, 100%, 40%);">+ if ast_path is None:</span><br><span style="color: hsl(120, 100%, 40%);">+ raise Exception("ast_path cannot be NULL")</span><br><span style="color: hsl(120, 100%, 40%);">+ if start_version is None:</span><br><span style="color: hsl(120, 100%, 40%);">+ raise Exception("start_version cannot be NULL")</span><br><span style="color: hsl(120, 100%, 40%);">+ if end_version is None:</span><br><span style="color: hsl(120, 100%, 40%);">+ raise Exception("end_version cannot be NULL")</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ self.data = dict()</span><br><span style="color: hsl(120, 100%, 40%);">+ # If the path doesn't end with '/', go ahead and add one for get_staging_changes</span><br><span style="color: hsl(120, 100%, 40%);">+ if ast_path.endswith('/') == False:</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_path += '/'</span><br><span style="color: hsl(120, 100%, 40%);">+ self.ast_path = ast_path</span><br><span style="color: hsl(120, 100%, 40%);">+ self.start_version = start_version</span><br><span style="color: hsl(120, 100%, 40%);">+ self.end_version = end_version</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def gen_separator(self, count):</span><br><span style="color: hsl(120, 100%, 40%);">+ '''</span><br><span style="color: hsl(120, 100%, 40%);">+ Generate a number of dashes to be used as a separator</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ count The number of dashes to generate</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ returns A string with <count> dash(es)</span><br><span style="color: hsl(120, 100%, 40%);">+ '''</span><br><span style="color: hsl(120, 100%, 40%);">+ ret = ""</span><br><span style="color: hsl(120, 100%, 40%);">+ for num in range(count):</span><br><span style="color: hsl(120, 100%, 40%);">+ ret += "-"</span><br><span style="color: hsl(120, 100%, 40%);">+ return ret</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def gen_header(self, mode):</span><br><span style="color: hsl(120, 100%, 40%);">+ '''</span><br><span style="color: hsl(120, 100%, 40%);">+ Generate the header that will precede data in the target file</span><br><span style="color: hsl(120, 100%, 40%);">+ '''</span><br><span style="color: hsl(120, 100%, 40%);">+ if mode is "CHANGES":</span><br><span style="color: hsl(120, 100%, 40%);">+ header = "--- Functionality changes from Asterisk {0} to Asterisk {1} ".format(self.start_version, self.end_version)</span><br><span style="color: hsl(120, 100%, 40%);">+ remaining = FUNCTIONALITY_SEPARATOR_DASH_COUNT - len(header)</span><br><span style="color: hsl(120, 100%, 40%);">+ header += self.gen_separator(remaining)</span><br><span style="color: hsl(120, 100%, 40%);">+ separator = self.gen_separator(FUNCTIONALITY_SEPARATOR_DASH_COUNT)</span><br><span style="color: hsl(120, 100%, 40%);">+ header = separator + "\n" + header + "\n" + separator + "\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ elif mode is "UPGRADE":</span><br><span style="color: hsl(120, 100%, 40%);">+ header = "From {0} to {1}:\n\n".format(self.start_version, self.end_version)</span><br><span style="color: hsl(120, 100%, 40%);">+ else:</span><br><span style="color: hsl(120, 100%, 40%);">+ return None</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return header</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def get_staging_changes(self, mode):</span><br><span style="color: hsl(120, 100%, 40%);">+ '''</span><br><span style="color: hsl(120, 100%, 40%);">+ Retrieve changes from <self.ast_path>/doc/<mode>-staging/</span><br><span style="color: hsl(120, 100%, 40%);">+ </span><br><span style="color: hsl(120, 100%, 40%);">+ returns 0 on success</span><br><span style="color: hsl(120, 100%, 40%);">+ returns -1 on failure</span><br><span style="color: hsl(120, 100%, 40%);">+ '''</span><br><span style="color: hsl(120, 100%, 40%);">+ if mode is not "CHANGES" and mode is not "UPGRADE":</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ staging_path = "{0}/doc/{1}-staging".format(self.ast_path, mode)</span><br><span style="color: hsl(120, 100%, 40%);">+ try:</span><br><span style="color: hsl(120, 100%, 40%);">+ for filename in os.listdir(staging_path):</span><br><span style="color: hsl(120, 100%, 40%);">+ if not os.path.isfile(staging_path + "/" + filename) or filename == "README":</span><br><span style="color: hsl(120, 100%, 40%);">+ continue</span><br><span style="color: hsl(120, 100%, 40%);">+ with open(staging_path + "/" + filename, 'r') as f:</span><br><span style="color: hsl(120, 100%, 40%);">+ subject = ""</span><br><span style="color: hsl(120, 100%, 40%);">+ line = f.readline()</span><br><span style="color: hsl(120, 100%, 40%);">+ while line != "":</span><br><span style="color: hsl(120, 100%, 40%);">+ # Get the subject</span><br><span style="color: hsl(120, 100%, 40%);">+ if line.startswith("Subject:"):</span><br><span style="color: hsl(120, 100%, 40%);">+ if subject != "":</span><br><span style="color: hsl(120, 100%, 40%);">+ # In the case of trailing space of any kind, remove it. For example,</span><br><span style="color: hsl(120, 100%, 40%);">+ # double new line characters make the format mess up.</span><br><span style="color: hsl(120, 100%, 40%);">+ self.data.update({subject: self.data[subject].rstrip() + "\n"})</span><br><span style="color: hsl(120, 100%, 40%);">+ subject = line.split("Subject:")[1].lstrip()</span><br><span style="color: hsl(120, 100%, 40%);">+ if subject not in self.data:</span><br><span style="color: hsl(120, 100%, 40%);">+ self.data.update({subject: "{0}{1}\n".format(subject, self.gen_separator(CATEGORY_SEPARATOR_DASH_COUNT))})</span><br><span style="color: hsl(120, 100%, 40%);">+ else:</span><br><span style="color: hsl(120, 100%, 40%);">+ self.data.update({subject: self.data[subject] + "\n"})</span><br><span style="color: hsl(120, 100%, 40%);">+ f.readline()</span><br><span style="color: hsl(120, 100%, 40%);">+ line = f.readline()</span><br><span style="color: hsl(120, 100%, 40%);">+ self.data.update({subject: self.data[subject] + " * " + line})</span><br><span style="color: hsl(120, 100%, 40%);">+ elif line == "\n":</span><br><span style="color: hsl(120, 100%, 40%);">+ # This is a special case because if there is an empty line separating some</span><br><span style="color: hsl(120, 100%, 40%);">+ # text, we don't want to add 3 spaces and then a new line.</span><br><span style="color: hsl(120, 100%, 40%);">+ self.data.update({subject: self.data[subject] + "\n"})</span><br><span style="color: hsl(120, 100%, 40%);">+ else:</span><br><span style="color: hsl(120, 100%, 40%);">+ self.data.update({subject: self.data[subject] + " " + line})</span><br><span style="color: hsl(120, 100%, 40%);">+ line = f.readline()</span><br><span style="color: hsl(120, 100%, 40%);">+ # Clean up the staging directory as we cycle through the files</span><br><span style="color: hsl(120, 100%, 40%);">+ os.remove(os.path.join(staging_path, filename))</span><br><span style="color: hsl(120, 100%, 40%);">+ except:</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGGER.debug("Could not extract data from {0}".format(staging_path))</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def add_staging_changes(self, mode):</span><br><span style="color: hsl(120, 100%, 40%);">+ '''</span><br><span style="color: hsl(120, 100%, 40%);">+ Add the changes retrieved to <self.ast_path/<mode>(.txt)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ returns 0 on success</span><br><span style="color: hsl(120, 100%, 40%);">+ returns -1 on failure</span><br><span style="color: hsl(120, 100%, 40%);">+ '''</span><br><span style="color: hsl(120, 100%, 40%);">+ if mode is not "CHANGES" and mode is not "UPGRADE":</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if bool(self.data) is False:</span><br><span style="color: hsl(120, 100%, 40%);">+ # There was no data to retrieve during get_staging_changes</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ header = self.gen_header(mode)</span><br><span style="color: hsl(120, 100%, 40%);">+ if header is None:</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ file_path = "{0}/{1}".format(self.ast_path, mode)</span><br><span style="color: hsl(120, 100%, 40%);">+ if mode is "UPGRADE":</span><br><span style="color: hsl(120, 100%, 40%);">+ file_path += ".txt"</span><br><span style="color: hsl(120, 100%, 40%);">+ try:</span><br><span style="color: hsl(120, 100%, 40%);">+ insert = 0</span><br><span style="color: hsl(120, 100%, 40%);">+ for line in fileinput.FileInput(file_path, inplace = 1):</span><br><span style="color: hsl(120, 100%, 40%);">+ if insert is 0 and line in ["\n", "\r\n"]:</span><br><span style="color: hsl(120, 100%, 40%);">+ insert = 1</span><br><span style="color: hsl(120, 100%, 40%);">+ continue</span><br><span style="color: hsl(120, 100%, 40%);">+ if insert is 1:</span><br><span style="color: hsl(120, 100%, 40%);">+ for entry in self.data:</span><br><span style="color: hsl(120, 100%, 40%);">+ line = line.replace(line, self.data[entry] + "\n" + line)</span><br><span style="color: hsl(120, 100%, 40%);">+ line = line.replace(line, "\n" + header + line)</span><br><span style="color: hsl(120, 100%, 40%);">+ insert = 2</span><br><span style="color: hsl(120, 100%, 40%);">+ print line,</span><br><span style="color: hsl(120, 100%, 40%);">+ except:</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGGER.debug("Could not add data to {0}".format(file_path))</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def run(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ '''</span><br><span style="color: hsl(120, 100%, 40%);">+ Put everything together and run it</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ returns 0 on success</span><br><span style="color: hsl(120, 100%, 40%);">+ returns -1 on failure</span><br><span style="color: hsl(120, 100%, 40%);">+ '''</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ for mode in MODES:</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGGER.debug("Extracting changes for {0}".format(mode))</span><br><span style="color: hsl(120, 100%, 40%);">+ self.data.clear()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ret = self.get_staging_changes(mode)</span><br><span style="color: hsl(120, 100%, 40%);">+ if ret is not 0:</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGGER.debug("Failed during {0} get_staging_changes step - aborting "</span><br><span style="color: hsl(120, 100%, 40%);">+ "(working directory probably needs to be reset!!!)".format(mode))</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ret = self.add_staging_changes(mode)</span><br><span style="color: hsl(120, 100%, 40%);">+ if ret is not 0:</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGGER.debug("Failed during {0} add_staging_changes step - aborting "</span><br><span style="color: hsl(120, 100%, 40%);">+ "(working directory probably needs to be reset!!!)".format(mode))</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/10941">change 10941</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/10941"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: repotools </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I6dc084afedaeecaf36aaec66c3cf6a5a8ed4ef3c </div>
<div style="display:none"> Gerrit-Change-Number: 10941 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Benjamin Keith Ford <bford@digium.com> </div>