Subject: bug#45570: [PATCH] system: Assert, that user and group names are unique.

From: Ludovic Courtès <[email-masked]>
Date: Wed, 06 Jan 2021 10:56:23 +0100

Hi,

Leo Prikler <[email-masked]> skribis:

> *gnu/system/shadow.scm (find-duplicates): New variable.
> (assert-unique-account-names, assert-unique-group-names): New variables.
> (account-activation): Use them here.

[...]

> +(define (find-duplicates list =)
> +  (match list
> +    ('() '())

This should be:

  (match list
    (() '())
    …)

I’m surprised '() works as a pattern.

> +    ((first . rest)
> +     (if (member first rest =) ; (srfi srfi-1) member
> +         (cons first (find-duplicates rest =))
> +         (find-duplicates rest =)))))

Note that this is quadratic; it’s fine as long as we don’t have “too
many” users, which may be the case in general.

> +(define (assert-unique-account-names users)
> +  (for-each
> +   (lambda (account)
> +     (raise (condition
> +             (&message
> +              (message
> +               (format #f (G_ "account with name '~a' found twice.")
> +                       (user-account-name account)))))))
> +   (find-duplicates users (lambda (alice bob)
> +                            (string=? (user-account-name alice)
> +                                      (user-account-name bob))))))

‘for-each’ looks awkward since we’ll stop on the first one.  How about
something like:

  (define (assert-unique-account-names users)
    (match (find-duplicates things …)
      (() #t)
      (lst
       (raise (formatted-message (G_ "the following accounts appear more than once:~{ ~a~}~%"
                                 lst))))))

?

Thanks!

Ludo’.