Skip to content

Commit

Permalink
Bring scripts and autocomplete data into main repository
Browse files Browse the repository at this point in the history
  • Loading branch information
KaliumPuceon committed Nov 6, 2023
1 parent 6ac8362 commit c1180a2
Show file tree
Hide file tree
Showing 4 changed files with 921 additions and 0 deletions.
26 changes: 26 additions & 0 deletions utils/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
Space for utilities for extracting detailed documentation and other details for
hints.

extract_docs.py
---------------

This file generates the contents of ``autocomplete_data.json`` from a copy of
``spec.md``, which is taken from `here
<https://github.com/rpm-software-management/rpm/blob/master/docs/manual/spec.md>`

Run it in this directory to generate a new version fo
``autocomplete_data.json``. There is no guarantee that the layout of
``spec.md`` is stable so this script is very liable to change.

spec.md
-------
A local copy of the `source markdown for the specfile manual page
<https://github.com/rpm-software-management/rpm/blob/master/docs/manual/spec.md>`
which is used to generate detailed help as LSP documentation entries.

autocomplete_data.json
---------------------
A simple array of tuples pairing keywords with their original documentation
entries as taken from ``spec.md``, generated by ``extract_docs.py``.


1 change: 1 addition & 0 deletions utils/autocomplete_data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[["Name", "The Name tag contains the proper name of the package. Names must not\ninclude whitespace and may include a hyphen '-' (unlike version and release\ntags). Names should not include any numeric operators ('<', '>','=') as\nfuture versions of rpm may need to reserve characters other than '-'."], ["Version", "Version of the packaged content, typically software.\n\nThe version string consists of alphanumeric characters, which can optionally\nbe segmented with the separators `.`, `_` and `+`, plus `~` and `^` (see below).\n\nTilde (`~`) can be used to force sorting lower than base (1.1\\~201601 < 1.1).\nCaret (`^`) can be used to force sorting higher than base (1.1^201601 > 1.1).\nThese are useful for handling pre- and post-release versions, such as\n1.0\\~rc1 and 2.0^a."], ["Release", "Package release, used for distinguishing between different builds\nof the same software version.\n\nSee Version for allowed characters and modifiers."], ["Epoch", "Optional numerical value which can be used to override normal version-release\nsorting order. It's use should be avoided if at all possible.\n\nNon-existent epoch is exactly equal to zero epoch in all version comparisons."], ["License", "Short (< 70 characters) summary of the package license. For example:\n```\n\tLicense: GPLv3\n```"], ["SourceLicense", "If license of the sources differ from the main package the license tag\nof the source package can be set with this. If not given the license\ntag of the source and the main package are the same."], ["Group", "Optional, short (< 70 characters) group of the package.\n```\n\tGroup: Development/Libraries\n```"], ["Summary", "Short (< 70 characters) summary of the package. \n```\n\tSummary: Utility for converting mumbles into giggles\n```"], ["Source", "If license of the sources differ from the main package the license tag\nof the source package can be set with this. If not given the license\ntag of the source and the main package are the same."], ["Patch", "Used to declare patches applied on top of sources. All patches declared\nwill be packaged into source rpms."], ["Icon", "Used to attach an icon to an rpm package file. Obsolete."], ["NoSource", ""], ["NoPatch", "Files ending in .nosrc.rpm are generally source RPM packages whose spec\nfiles have one or more NoSource: or NoPatch: directives in them. Both\ndirectives use the named source or patch file to build the resulting\nbinary RPM package as usual, but they are not included in the source\nRPM package.\n\nThe original intent of this ability of RPM was to allow proprietary or\nnon-distributable software to be built using RPM, but to keep the\nproprietary or non-distributable parts out of the resulting source RPM\npackage, so that they would not get distributed.\n\nThey also have utility if you are building RPM packages for software\nwhich is archived at a well-known location and does not require that\nyou distribute the source with the binary, for example, for an\norganization's internal use, where storing large quantities of source\nis not as meaningful.\n\nThe end result of all this, though, is that you can't rebuild\n``no-source'' RPM packages using `rpm --rebuild' unless you also have\nthe sources or patches which are not included in the .nosrc.rpm."], ["URL", "URL supplying further information about the package, typically upstream\nwebsite."], ["BugURL", "Bug reporting URL for the package."], ["ModularityLabel", ""], ["DistTag", ""], ["VCS", ""], ["Distribution", ""], ["Vendor", ""], ["Packager", "Optional package distribution/vendor/maintainer name / contact information.\nRarely used in specs, typically filled in by buildsystem macros."], ["BuildRoot", "Obsolete and unused in rpm >= 4.6.0, but permitted for compatibility\nwith old packages that might still depend on it.\n\nDo not use in new packages."], ["AutoReqProv", ""], ["AutoReq", ""], ["AutoProv", "Control per-package automatic dependency generation for provides and requires. \nAccepted values are 1/0 or yes/no, default is always \"yes\". Autoreqprov is\nequal to specifying Autoreq and Autoprov separately."], ["Requires", "Capabilities this package requires to function at all. Besides ensuring\nrequired packages get installed, this is also used to order installs\nand erasures. \n\nAdditional context can be supplied using `Requires(qualifier)` syntax,\naccepted qualifiers are:\n\n* `pre`\n\n Denotes the dependency must be present in before the package is\n is installed, and is used a strong ordering hint to break possible\n dependency loops. A pre-dependency is free to be removed\n once the install-transaction completes.\n\n Also relates to `%pre` scriptlet execution.\n\n* `post`\n\n Denotes the dependency must be present right after the package is\n is installed, and is used a strong ordering hint to break possible\n dependency loops. A post-dependnecy is free to be removed\n once the install-transaction completes.\n\n Also relates to `%post` scriptlet execution.\n\n* `preun`\n\n Denotes the dependency must be present in before the package is\n is removed, and is used a strong ordering hint to break possible\n dependency loops.\n\n Also relates to `%preun` scriptlet execution.\n\n* `postun`\n\n Denotes the dependency must be present right after the package is\n is removed, and is used a strong ordering hint to break possible\n dependency loops.\n\n Also relates to `%postun` scriptlet execution.\n\n* `pretrans`\n\n Denotes the dependency must be present before the transaction starts,\n and cannot be satisified by added packages in a transaction. As such,\n it does not affect transaction ordering. A pretrans-dependency is\n free to be removed after the install-transaction completes.\n\n Also relates to `%pretrans` and `%preuntrans` scriptlet execution.\n\n* `posttrans`\n\n Denotes the dependency must be present at the end of transaction, ie\n cannot be removed during the transaction. As such, it does not affect\n transaction ordering. A posttrans-dependency is free to be removed\n after the the install-transaction completes.\n\n Also relates to `%posttrans` and `%postuntrans` scriptlet execution.\n\n* `verify`\n\n Relates to `%verify` scriptlet execution. As `%verify` scriptlet is not\n executed during install/erase, this does not affect transaction ordering.\n\n* `interp`\n\n Denotes a scriptlet interpreter dependency, usually added automatically\n by rpm. Used as a strong ordering hint for breaking dependency loops.\n\n* `meta` (since rpm >= 4.16)\n\n Denotes a \"meta\" dependency, which must not affect transaction ordering.\n Typical use-cases would be meta-packages and sub-package cross-dependencies\n whose purpose is just to ensure the sub-packages stay on common version.\n\nMultiple qualifiers can be supplied separated by comma, as long as\nthey're not semantically contradictory: `meta` qualifier contradicts any\nordered qualifier, eg `meta` and `verify` can be combined, and `pre` and\n`verify` can be combined, but `pre` and `meta` can not.\n\nAs noted above, dependencies qualified as install-time only (`pretrans`,\n`pre`, `post`, `posttrans` or combination of them) can be removed after the\ninstallation transaction completes if there are no other dependencies\nto prevent that. This is a common source of confusion."], ["Provides", "Capabilities provided by this package.\n\n`name = [epoch:]version-release` is automatically added to all packages."], ["Conflicts", "Capabilities this package conflicts with, typically packages with\nconflicting paths or otherwise conflicting functionality."], ["Obsoletes", "Packages obsoleted by this package. Used for replacing and renaming\npackages."], ["Recommends", ""], ["Suggests", ""], ["Supplements", ""], ["Enhances", ""], ["OrderWithRequires", ""], ["Prereq", "Obsolete, do not use."], ["BuildPrereq", "Obsolete, do not use."], ["BuildRequires", "Capabilities required to build the package.\n\nBuild dependencies are identical to install dependencies except:\n\n```\n 1) they are prefixed with build (e.g. BuildRequires: rather than Requires:)\n 2) they are resolved before building rather than before installing.\n```\n\nSo, if you were to write a specfile for a package that requires gcc to build,\nyou would add\n```\n\tBuildRequires: gcc\n```\nto your spec file.\n\nIf your package was like dump and could not be built w/o a specific version of\nthe libraries to access an ext2 file system, you could express this as\n```\n\tBuildRequires: e2fsprofs-devel = 1.17-1\n```"], ["BuildConflicts", "Capabilities which conflict, ie cannot be installed during the package\npackage build.\n\nFor example if somelib-devel presence causes the package to fail build,\nyou would add\n```\n\tBuildConflicts: somelib-devel\n```"], ["ExcludeArch", "Package is not buildable on architectures listed here.\nUsed when software is portable across most architectures except some,\nfor example due to endianess issues."], ["ExclusiveArch", "Package is only buildable on architectures listed here.\nFor example, it's probably not possible to build an i386-specific BIOS\nutility on ARM, and even if it was it probably would not make any sense."], ["ExcludeOS", "Package is not buildable on specific OSes listed here."], ["ExclusiveOS", "Package is only buildable on OSes listed here."], ["BuildArch", "Specifies the architecture which the resulting binary package\nwill run on. Typically this is a CPU architecture like sparc,\ni386. The string 'noarch' is reserved for specifying that the\nresulting binary package is platform independent. Typical platform\nindependent packages are html, perl, python, java, and ps packages.\n\nAs a special case, `BuildArch: noarch` can be used on sub-package\nlevel to allow eg. documentation of otherwise arch-specific package\nto be shared across multiple architectures.\n\nNote that `BuildArch` causes the spec parsing to recurse from the start,\ncausing any macros before that line to be expanded twice. This can yield\nunexpected results, in particular with `%global`."], ["Prefixes", "Specify prefixes this package may be installed into, used to make\npackages relocatable. Very few packages are."], ["DocDir", "Declare a non-default documentation directory for the package.\nUsually not needed."], ["RemovePathPostfixes", "Colon separated lists of path postfixes that are removed from the end\nof file names when adding those files to the package. Used on sub-package\nlevel.\n\nUsed for creating sub-packages with conflicting files, such as different\nvariants of the same content (eg minimal and full versions of the same\nsoftware)."]]
105 changes: 105 additions & 0 deletions utils/extract_docs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#! /usr/bin/env python3.11

# We're only extracting preamble tags and dependencies here for now

# Scriptlets probably can be done easily but conditionals, comments, and
# triggers will have to be done manually or someone will have to expand this
# script because they are laid out totally differently. Fortunately there's
# not as many of those so it could just be done by hand.

# Sub-sections should be pretty easy but I'm leaving it out for now

# There's no standard layout here so this is Ultra Custom

import json

def get_index_of_line(document, line):
return list(filter(lambda entry: entry[1].startswith(line), enumerate(document)))[0][0]

def split_document(document):
preamble_start = get_index_of_line(document, '### Preamble tags')

dependencies_start = get_index_of_line(document, '### Dependencies')
subsections_start = get_index_of_line(document, '### Sub-sections')

scriptlets_start = get_index_of_line(document, '## Build scriptlets')

preamble = document[preamble_start:dependencies_start]
dependencies = document[dependencies_start:subsections_start]
scriptlets = document[scriptlets_start:]

return preamble, dependencies, scriptlets

def get_preamble_or_dependencies_keywords(chunk):
keywords = []
for line in chunk:
if line.startswith('#### '):
keywords.append(line.strip().split(' ')[1])

return(keywords)

def get_preamble_or_dependencies_doc(keyword, chunk):
entered_doc = False
doc = ''
for line in chunk:
if ((not entered_doc) and line.startswith('#### ') and (keyword in line)):
entered_doc = True
continue
if ((entered_doc) and line.startswith('#### ')):
entered_doc = False
break

if entered_doc:
doc += line

return(doc.strip())

def get_build_scriptlets_keywords(chunk):
keywords = []
for line in chunk:
if (line.startswith('###') or line.startswith(' * `%')) and ('%' in line):
transtable = str.maketrans({
'*': None,
'`': None,
'#': None,
'(': ' ',
})
keywords.append(str.split(line.translate(transtable).strip())[0])

for k in keywords:
print(k)

def get_build_scriptlets_doc(keyword, chunk):
pass

document = []

print('Opening ./spec.md')
try:
with open('./spec.md') as specdocs:
document = specdocs.readlines()
except FileNotFoundError:
print('spec.md not found in this directory, you can download it from https://github.com/rpm-software-management/rpm/blob/master/docs/manual/spec.md')

preamble, dependencies, build_scriptlets = split_document(document)

preamble_keywords = get_preamble_or_dependencies_keywords(preamble)
dependencies_keywords = get_preamble_or_dependencies_keywords(dependencies)
#build_scriptlets_keywords = get_build_scriptlets_keywords(build_scriptlets)

preamble_data = []
dependencies_data = []

for keyword in preamble_keywords:
preamble_data.append((keyword, get_preamble_or_dependencies_doc(keyword, preamble)))

for keyword in dependencies_keywords:
dependencies_data.append((keyword, get_preamble_or_dependencies_doc(keyword, dependencies)))

autocomplete_data = preamble_data + dependencies_data

print('Writing autocomplete data to autocomplete_data.json')
with open('./autocomplete_data.json', 'w') as adata:
adata.write(json.dumps(autocomplete_data))

print('done!')
Loading

0 comments on commit c1180a2

Please sign in to comment.