From 579506e272cf68649ec68ad8a976a17426ea630c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= Date: Sun, 10 Jan 2021 11:53:43 +0100 Subject: [PATCH] utils: Add 'version-unique-prefix'. * guix/utils.scm (version-unique-prefix): New procedure. * tests/utils.scm ("version-unique-prefix"): New test. --- guix/utils.scm | 35 ++++++++++++++++++++++++++++++++++- tests/utils.scm | 8 +++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/guix/utils.scm b/guix/utils.scm index f8b05e7e80..a85e2f495c 100644 --- a/guix/utils.scm +++ b/guix/utils.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès +;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès ;;; Copyright © 2013, 2014, 2015 Mark H Weaver ;;; Copyright © 2014 Eric Bavier ;;; Copyright © 2014 Ian Denhardt @@ -88,6 +88,7 @@ (define-module (guix utils) version-major+minor+point version-major+minor version-major + version-unique-prefix guile-version>? version-prefix? string-replace-substring @@ -589,6 +590,38 @@ (define (version-major version-string) "Return the major version number as string from the version-string." (version-prefix version-string 1)) +(define (version-unique-prefix version versions) + "Return the shortest version prefix to unambiguously identify VERSION among +VERSIONS. For example: + + (version-unique-prefix \"2.0\" '(\"3.0\" \"2.0\")) + => \"2\" + + (version-unique-prefix \"2.2\" '(\"3.0.5\" \"2.0.9\" \"2.2.7\")) + => \"2.2\" + + (version-unique-prefix \"27.1\" '(\"27.1\")) + => \"\" +" + (define not-dot + (char-set-complement (char-set #\.))) + + (define other-versions + (delete version versions)) + + (let loop ((prefix '()) + (components (string-tokenize version not-dot))) + (define prefix-str + (string-join prefix ".")) + + (if (any (cut string-prefix? prefix-str <>) other-versions) + (match components + ((head . tail) + (loop `(,@prefix ,head) tail)) + (() + version)) + prefix-str))) + (define (version>? a b) "Return #t when A denotes a version strictly newer than B." (eq? '> (version-compare a b))) diff --git a/tests/utils.scm b/tests/utils.scm index 9bce446d98..62ec7e8b4c 100644 --- a/tests/utils.scm +++ b/tests/utils.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès +;;; Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Ludovic Courtès ;;; Copyright © 2014 Eric Bavier ;;; Copyright © 2016 Mathieu Lirzin ;;; @@ -78,6 +78,12 @@ (define temp-file (not (version-prefix? "4.1" "4.16.2")) (not (version-prefix? "4.1" "4")))) +(test-equal "version-unique-prefix" + '("2" "2.2" "") + (list (version-unique-prefix "2.0" '("3.0" "2.0")) + (version-unique-prefix "2.2" '("3.0.5" "2.0.9" "2.2.7")) + (version-unique-prefix "27.1" '("27.1")))) + (test-equal "string-tokenize*" '(("foo") ("foo" "bar" "baz")