1
0
Fork 0
virtualbox/doc/manual/build_id_to_file_mapping.py
Daniel Baumann 2b3ba1f3e4
Merging upstream version 7.1.8-dfsg.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-24 20:41:59 +02:00

150 lines
5 KiB
Python
Executable file

# -*- coding: utf-8 -*-
# $Id: build_id_to_file_mapping.py $
"""
Scans the given files (globbed) for topic id and stores records the filename
in the output file.
This is used by add_file_to_id_only_references.py after converting man_V*.xml
refentry files to dita to correct links.
"""
__copyright__ = \
"""
Copyright (C) 2023-2024 Oracle and/or its affiliates.
This file is part of VirtualBox base platform packages, as
available from https://www.virtualbox.org.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation, in version 3 of the
License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, see <https://www.gnu.org/licenses>.
SPDX-License-Identifier: GPL-3.0-only
"""
__version__ = "$Revision: 164827 $"
# Standard python imports.
import glob;
import os;
import re;
import sys;
g_oReDita = re.compile(r'<topic[^><]*\sid=("[^">]+"|\'[^\'>]+\')');
def scanDitaFileForIds(dIdToFile, sContent, sFile):
"""
Scans the given content of a .dita-file for topic IDs that can be referenced.
"""
for oMatch in g_oReDita.finditer(sContent):
sId = oMatch.group(1)[1:-1];
if sId:
dIdToFile[sId] = sFile;
g_oReRefentry = re.compile(r'<(refentry\b|refsect[12345]\b|cmdsynopsis\b)[^><]*\sid=("[^">]+"|\'[^\'>]+\')');
def scanDocbookRefentryForIds(dIdToFile, sContent, sFile):
"""
Scans the given content of a Docbook refentry file for topic IDs that can be referenced.
"""
for oMatch in g_oReRefentry.finditer(sContent):
sId = oMatch.group(2)[1:-1];
if sId:
#dIdToFile[sId] = sFile;
dIdToFile[sId] = '%s.dita' % (sId,);
def isDocbook(sContent):
"""
Check if the file is a Docbook one.
"""
return sContent.find('<refentry ') >= 0 and sContent.find('<refentryinfo>');
def error(sMessage):
""" Reports an error. """
print('build_id_to_file_mapping.py: error: %s' % sMessage, file = sys.stderr);
return 1;
def syntax(sMessage):
""" Reports a syntax error. """
print('build_id_to_file_mapping.py: syntax error: %s' % sMessage, file = sys.stderr);
return 2;
def usage():
""" Reports usage. """
print('usage: build_id_to_file_mapping.py --output <map.db> file1.dita docbook2.xml wild*card.* [...]');
return 0;
def main(asArgs):
"""
C-like main function.
"""
#
# Process arguments.
#
dIdToFile = {};
sOutput = None;
fEndOfArgs = False;
iArg = 1;
while iArg < len(asArgs):
sArg = asArgs[iArg];
if sArg[0] == '-' and not fEndOfArgs:
# Options.
if sArg == '--':
fEndOfArgs = True;
elif sArg in ('--help', '-h', '-?'):
return usage();
elif sArg in ('--version', '-V' ):
print(__version__[__version__.find(':') + 2:-2]);
elif sArg in ('--output', '-o'):
iArg += 1;
if iArg >= len(asArgs):
return syntax('Expected filename following "--output"!');
sOutput = asArgs[iArg];
else:
return syntax('Unknown option: %s' % (sArg,));
else:
# Input files.
if sArg[0] == '@':
with open(sArg[1:], 'r', encoding = 'utf-8') as oFile:
asFiles = oFile.read().split();
else:
asFiles = glob.glob(sArg);
if not asFiles:
return error('File not found: %s' % (sArg,));
for sFile in asFiles:
try:
with open(sFile, 'r', encoding = 'utf-8') as oFile:
sContent = oFile.read();
except Exception as oXcpt: # pylint: disable=broad-exception-caught
return error('Failed to open and read "%s": %s' % (sFile, oXcpt,));
if isDocbook(sContent):
scanDocbookRefentryForIds(dIdToFile, sContent, os.path.splitext(os.path.basename(sFile))[0] + '.dita');
else:
scanDitaFileForIds(dIdToFile, sContent, os.path.basename(sFile));
iArg += 1;
# Dump the dictionary.
asDict = sorted(['%s=%s' % (sKey, sValue) for sKey, sValue in dIdToFile.items()]);
if sOutput is not None:
try:
with open(sOutput, 'w', encoding = 'utf-8') as oFile:
oFile.write('\n'.join(asDict));
except Exception as oXcpt: # pylint: disable=broad-exception-caught
return error('Failed to open and write "%s": %s' % (sFile, oXcpt,));
else:
sys.stdout.write('\n'.join(asDict));
return 0;
if __name__ == "__main__":
sys.exit(main(sys.argv));