mirror of
https://gitlab.com/khumba/nvd.git
synced 2024-11-23 13:21:46 +01:00
Add semver sorting (issue #17).
This commit is contained in:
parent
4ae4ae9fae
commit
c0ed21c632
3 changed files with 72 additions and 2 deletions
|
@ -6,7 +6,8 @@
|
||||||
profile, issue #18. Big thanks to Felix Uhl for the idea and implementation!
|
profile, issue #18. Big thanks to Felix Uhl for the idea and implementation!
|
||||||
|
|
||||||
- Added `--sort` option for controlling the order packages are listed in, for
|
- Added `--sort` option for controlling the order packages are listed in, for
|
||||||
issue #17.
|
issue #17. Supported sort options are package name, and the level of semver
|
||||||
|
version change.
|
||||||
|
|
||||||
- In the "Version changes" section of a diff, highlight the portions of version
|
- In the "Version changes" section of a diff, highlight the portions of version
|
||||||
numbers that have changed, i.e., everything after the part common to all
|
numbers that have changed, i.e., everything after the part common to all
|
||||||
|
|
52
src/nvd
52
src/nvd
|
@ -253,6 +253,9 @@ class Version:
|
||||||
"""Returns the version string, empty (not None) if there is no version."""
|
"""Returns the version string, empty (not None) if there is no version."""
|
||||||
return self._text
|
return self._text
|
||||||
|
|
||||||
|
def chunks(self) -> list[VersionChunk]:
|
||||||
|
return self._chunks
|
||||||
|
|
||||||
class Package:
|
class Package:
|
||||||
def __init__(self, *, pname: str, version: Version, store_path: StorePath):
|
def __init__(self, *, pname: str, version: Version, store_path: StorePath):
|
||||||
assert isinstance(pname, str), f"Not a string: {pname!r}"
|
assert isinstance(pname, str), f"Not a string: {pname!r}"
|
||||||
|
@ -405,6 +408,8 @@ class PackageListEntry:
|
||||||
self._left_packages = left_packages
|
self._left_packages = left_packages
|
||||||
self._right_packages = right_packages
|
self._right_packages = right_packages
|
||||||
|
|
||||||
|
self._first_changed_version_chunk: Optional[int] = None
|
||||||
|
|
||||||
def get_pname(self) -> str:
|
def get_pname(self) -> str:
|
||||||
if self._right_packages:
|
if self._right_packages:
|
||||||
return self._right_packages[0].pname()
|
return self._right_packages[0].pname()
|
||||||
|
@ -417,6 +422,31 @@ class PackageListEntry:
|
||||||
def get_right_packages(self) -> Optional[list[Package]]:
|
def get_right_packages(self) -> Optional[list[Package]]:
|
||||||
return self._right_packages
|
return self._right_packages
|
||||||
|
|
||||||
|
def find_first_changed_version_chunk(self) -> int:
|
||||||
|
"""
|
||||||
|
Returns the position of the earliest version chunk that differs when
|
||||||
|
comparing the maximum version on the left, with the maximum version on
|
||||||
|
the right.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self._right_packages is None:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
if self._first_changed_version_chunk is not None:
|
||||||
|
return self._first_changed_version_chunk
|
||||||
|
|
||||||
|
max_left_ver = self.get_left_packages()[-1].version()
|
||||||
|
max_right_ver = self.get_right_packages()[-1].version()
|
||||||
|
chunks_in_common = 0
|
||||||
|
for left_chunk, right_chunk in zip(max_left_ver.chunks(), max_right_ver.chunks()):
|
||||||
|
if left_chunk == right_chunk:
|
||||||
|
chunks_in_common += 1
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
self._first_changed_version_chunk = chunks_in_common
|
||||||
|
return chunks_in_common
|
||||||
|
|
||||||
class PackageListEntryComparator:
|
class PackageListEntryComparator:
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
|
@ -443,6 +473,8 @@ class PackageListEntryReverseComparator(PackageListEntryComparator):
|
||||||
return self._delegate
|
return self._delegate
|
||||||
|
|
||||||
class PackageListEntryNameComparator(PackageListEntryComparator):
|
class PackageListEntryNameComparator(PackageListEntryComparator):
|
||||||
|
"""Sorts package list entries by pname."""
|
||||||
|
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
return "name"
|
return "name"
|
||||||
|
|
||||||
|
@ -452,11 +484,31 @@ class PackageListEntryNameComparator(PackageListEntryComparator):
|
||||||
b.get_left_packages()[0].pname(),
|
b.get_left_packages()[0].pname(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
class PackageListEntrySemVerChangeComparator(PackageListEntryComparator):
|
||||||
|
"""
|
||||||
|
Sorts package list entries by the level of version change according to
|
||||||
|
Semantic Versioning.
|
||||||
|
|
||||||
|
The maximum version on the left is compared with the maximum version on the
|
||||||
|
right. Packages whose first version chunks differ are sorted first,
|
||||||
|
followed by packages whose second chunks differ, and so on.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def name(self) -> str:
|
||||||
|
return "semver"
|
||||||
|
|
||||||
|
def cmp_packages(self, a: PackageListEntry, b: PackageListEntry) -> int:
|
||||||
|
return cmp(
|
||||||
|
a.find_first_changed_version_chunk(),
|
||||||
|
b.find_first_changed_version_chunk(),
|
||||||
|
)
|
||||||
|
|
||||||
ALL_SORTS: dict[str, PackageListEntryComparator] = {
|
ALL_SORTS: dict[str, PackageListEntryComparator] = {
|
||||||
sk.name(): sk
|
sk.name(): sk
|
||||||
for sk in (
|
for sk in (
|
||||||
# The first one listed here is the default.
|
# The first one listed here is the default.
|
||||||
PackageListEntryNameComparator(),
|
PackageListEntryNameComparator(),
|
||||||
|
PackageListEntrySemVerChangeComparator(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
19
src/nvd.1
19
src/nvd.1
|
@ -193,7 +193,24 @@ break ties, in order. Each keyword may be preceeded by a hyphen
|
||||||
.B \-
|
.B \-
|
||||||
to reverse the regular sort order of the keyword. The default order is
|
to reverse the regular sort order of the keyword. The default order is
|
||||||
.B name,
|
.B name,
|
||||||
which sorts by package name. Currently only this keyword is supported.
|
which sorts by package name.
|
||||||
|
.IP
|
||||||
|
The keyword
|
||||||
|
.B semver
|
||||||
|
sorts packages according to how significant their version changes are, by the
|
||||||
|
rules of Semantic Versioning, when versions are being compared (with the
|
||||||
|
.B diff
|
||||||
|
and
|
||||||
|
.B history
|
||||||
|
commands). Each package's highest old version is compared with its highest new
|
||||||
|
version. Packages where the first component of these two versions have changed
|
||||||
|
are sorted first. Packages where the second version components differ are
|
||||||
|
sorted second, and so on. Components here are consecutive runs of digits, or of
|
||||||
|
letters (but not both), as per the Nix version handling rules. Only the
|
||||||
|
position of the first difference is used; the numeric difference between version
|
||||||
|
numbers does not matter. Because only the highest old and new versions are
|
||||||
|
compared, this sort type may not produce ideal results if multiple versions of a
|
||||||
|
package are present.
|
||||||
.TP
|
.TP
|
||||||
-r|--root <store-path>
|
-r|--root <store-path>
|
||||||
For the
|
For the
|
||||||
|
|
Loading…
Reference in a new issue