Skip to content

Commit

Permalink
contrib: format gen-manpages.py
Browse files Browse the repository at this point in the history
  • Loading branch information
willcl-ark committed Mar 7, 2024
1 parent ca3a2dc commit 681c4c0
Showing 1 changed file with 76 additions and 30 deletions.
106 changes: 76 additions & 30 deletions contrib/devtools/gen-manpages.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,71 +12,117 @@
vbin = namedtuple("bin", ["path", "name", "description", "version", "copyright"])

BINARIES: list[bin] = [
bin('src/bitcoind', "bitcoind(1)", "The Bitcoin Core daemon (bitcoind) is a headless program that connects to the Bitcoin network to validate and relay addresses, transactions and blocks. It provides the backbone of the Bitcoin network's security and is used for wallet services, transaction broadcasting, and block creation in a headless environment or as part of a server setup."),
bin('src/bitcoin-cli', "bitcoin-cli(1)", "The bitcoin-cli utility provides a command line interface to interact with a bitcoind/bitcoin-qt RPC service. It allows users to query network information, manage wallets, create or broadcast transactions, and control the bitcoind server."),
bin('src/bitcoin-tx', "bitcoin-tx(1)", "The bitcoin-tx tool is used for creating and modifying Bitcoin transactions."),
bin('src/bitcoin-wallet', "bitcoin-wallet(1)", "This utility is a headless tool for managing Bitcoin wallets. It allows for creating new wallets, restoring wallets from backups, salvaging wallets and getting wallet information without the need for a bitcoind instance."),
bin('src/bitcoin-util', "bitcoin-util(1)", "The bitcoin-util tool is used to grind proof of work on a hex header for signet"),
bin('src/qt/bitcoin-qt', "bitcoin-qt(1)", "The bitcoin-qt application provides a graphical interface for interacting with Bitcoin Core. It combines the core functionalities of bitcoind with a user-friendly interface for wallet management, transaction history, and network statistics. It is suitable for desktop users preferring a graphical over a command-line interface."),
bin(
"src/bitcoind",
"bitcoind(1)",
"The Bitcoin Core daemon (bitcoind) is a headless program that connects to the Bitcoin network to validate and relay addresses, transactions and blocks. It provides the backbone of the Bitcoin network's security and is used for wallet services, transaction broadcasting, and block creation in a headless environment or as part of a server setup.",
),
bin(
"src/bitcoin-cli",
"bitcoin-cli(1)",
"The bitcoin-cli utility provides a command line interface to interact with a bitcoind/bitcoin-qt RPC service. It allows users to query network information, manage wallets, create or broadcast transactions, and control the bitcoind server.",
),
bin(
"src/bitcoin-tx",
"bitcoin-tx(1)",
"The bitcoin-tx tool is used for creating and modifying Bitcoin transactions.",
),
bin(
"src/bitcoin-wallet",
"bitcoin-wallet(1)",
"This utility is a headless tool for managing Bitcoin wallets. It allows for creating new wallets, restoring wallets from backups, salvaging wallets and getting wallet information without the need for a bitcoind instance.",
),
bin(
"src/bitcoin-util",
"bitcoin-util(1)",
"The bitcoin-util tool is used to grind proof of work on a hex header for signet",
),
bin(
"src/qt/bitcoin-qt",
"bitcoin-qt(1)",
"The bitcoin-qt application provides a graphical interface for interacting with Bitcoin Core. It combines the core functionalities of bitcoind with a user-friendly interface for wallet management, transaction history, and network statistics. It is suitable for desktop users preferring a graphical over a command-line interface.",
),
]

# Paths to external utilities.
git = os.getenv('GIT', 'git')
help2man = os.getenv('HELP2MAN', 'help2man')
git = os.getenv("GIT", "git")
help2man = os.getenv("HELP2MAN", "help2man")

# If not otherwise specified, get top directory from git.
topdir = os.getenv('TOPDIR')
topdir = os.getenv("TOPDIR")
if not topdir:
r = subprocess.run([git, 'rev-parse', '--show-toplevel'], stdout=subprocess.PIPE, check=True, text=True)
r = subprocess.run(
[git, "rev-parse", "--show-toplevel"],
stdout=subprocess.PIPE,
check=True,
text=True,
)
topdir = r.stdout.rstrip()

# Get input and output directories.
builddir = os.getenv('BUILDDIR', topdir)
mandir = os.getenv('MANDIR', os.path.join(topdir, 'doc/man'))
builddir = os.getenv("BUILDDIR", topdir)
mandir = os.getenv("MANDIR", os.path.join(topdir, "doc/man"))

# Verify that all the required binaries are usable, and extract copyright
# message in a first pass.
versions: list[vbin] = []
for bin in BINARIES:
abspath = os.path.join(builddir, bin.path)
try:
r = subprocess.run([abspath, "--version"], stdout=subprocess.PIPE, check=True, text=True)
r = subprocess.run(
[abspath, "--version"], stdout=subprocess.PIPE, check=True, text=True
)
except IOError:
print(f'{abspath} not found or not an executable', file=sys.stderr)
print(f"{abspath} not found or not an executable", file=sys.stderr)
sys.exit(1)
# take first line (which must contain version)
verstr = r.stdout.splitlines()[0]
# last word of line is the actual version e.g. v22.99.0-5c6b3d5b3508
verstr = verstr.split()[-1]
assert verstr.startswith('v')
assert verstr.startswith("v")
# remaining lines are copyright
bitcoin_copyright = r.stdout.split('\n')[1:]
assert bitcoin_copyright[0].startswith('Copyright (C)')
bitcoin_copyright = r.stdout.split("\n")[1:]
assert bitcoin_copyright[0].startswith("Copyright (C)")

versions.append(vbin(*bin, verstr, bitcoin_copyright))

if any(vbin.version.endswith('-dirty') for vbin in versions):
if any(vbin.version.endswith("-dirty") for vbin in versions):
print("WARNING: Binaries were built from a dirty tree.")
print('man pages generated from dirty binaries should NOT be committed.')
print('To properly generate man pages, please commit your changes (or discard them), rebuild, then run this script again.')
print("man pages generated from dirty binaries should NOT be committed.")
print(
"To properly generate man pages, please commit your changes (or discard them), rebuild, then run this script again."
)
print()

with tempfile.NamedTemporaryFile('w', suffix='.h2m') as footer:
with tempfile.NamedTemporaryFile("w", suffix=".h2m") as footer:
# Create copyright footer, and write it to a temporary include file.
# Copyright is the same for all binaries, so just use the first.
footer.write('[COPYRIGHT]\n')
footer.write('\n'.join(versions[0].copyright).strip())
footer.write('\n')
footer.write("[COPYRIGHT]\n")
footer.write("\n".join(versions[0].copyright).strip())
footer.write("\n")
footer.flush()

# Call the binaries through help2man to produce a manual page for each of them.
for vbin in versions:
# Create a description section for all binaries
with tempfile.NamedTemporaryFile('w+', suffix='.h2m') as description:
description.write('[DESCRIPTION]\n')
with tempfile.NamedTemporaryFile("w+", suffix=".h2m") as description:
description.write("[DESCRIPTION]\n")
description.write(vbin.description)
description.write('\n')
description.write("\n")
description.flush()
outname = os.path.join(mandir, os.path.basename(vbin.path) + '.1')
print(f'Generating {outname}…')
subprocess.run([help2man, '-N', '--name=' + vbin.name, '--version-string=' + vbin.version, '--include=' + footer.name, '--include=' + description.name, '-o', outname, vbin.path], check=True)
outname = os.path.join(mandir, os.path.basename(vbin.path) + ".1")
print(f"Generating {outname}…")
subprocess.run(
[
help2man,
"-N",
"--name=" + vbin.name,
"--version-string=" + vbin.version,
"--include=" + footer.name,
"--include=" + description.name,
"-o",
outname,
vbin.path,
],
check=True,
)

0 comments on commit 681c4c0

Please sign in to comment.