~skin/zippm

2fe903222a1215d34151b46e263d31d807597bda — Daniel Jay Haskin 6 months ago e85a676
Finished matches-requirement
3 files changed, 406 insertions(+), 379 deletions(-)

M qlfile
M src/resolve.lisp
M tests/resolve.lisp
M qlfile => qlfile +0 -1
@@ 7,4 7,3 @@ ql esrap
ql parachute
git cl-i git@git.sr.ht:~skin/cl-i :branch main
git nrdl git@git.sr.ht:~skin/nrdl :ref 0.3.0


M src/resolve.lisp => src/resolve.lisp +191 -253
@@ 16,12 16,12 @@
  (:import-from #:alexandria)
  (:import-from #:cl-semver)
  (:import-from #:esrap
		#:defrule
		#:character-ranges
		#:parse
		#:?)
                #:defrule
                #:character-ranges
                #:parse
                #:?)
  (:export #:make-package-info
	   #:package-info=))
           #:package-info=))

(in-package #:skin.djha.zippm/resolve)



@@ 57,7 57,7 @@

(defmethod print-object ((obj version-predicate) strm)
  (format strm "~a"
	  (gethash (relation obj) relation-strings))
          (gethash (relation obj) relation-strings))
  (cl-semver:print-version (version obj) strm)
  obj)



@@ 67,30 67,30 @@

(defclass package-info ()
  ((name :initarg :name
	 :initform (error "a package name is required.")
	 :type string
	 :reader name)
         :initform (error "a package name is required.")
         :type string
         :reader name)
   (version :initarg :version
	    :type cl-semver:semantic-version
	    :initform (error "a package version is required.")
	    :reader version)
            :type cl-semver:semantic-version
            :initform (error "a package version is required.")
            :reader version)
   (location :initarg :location
	     :type string
	     :initform (error "a package location is required.")
	     :reader location)
   (requirements :initarg :requirements
		 :initform nil
		 :type list ;; of lists of version requirements
		 :reader requirements))
             :type string
             :initform (error "a package location is required.")
             :reader location)
   (req-cnf :initarg :req-cnf
            :initform nil
            :type list                     ; of lists of requirements
            :reader req-cnf))
  (:documentation "a class to represent package information."))

(defmethod print-object ((obj package-info) strm)
  (format strm "~a:"
	  (name obj))
          (name obj))
  (cl-semver:print-version (version obj) strm)
  (format strm "@~a(~{~{~a~^|~}~^&~})"
	  (location obj)
	  (requirements obj))
          (location obj)
          (req-cnf obj))
  obj)

(deftype requirer ()


@@ 98,186 98,179 @@

(defparameter *requirer* :root
  "
  the requirer that will be used as the default requirer for requirements.
  the requirer that will be used as the default requirer for req-cnf.
  this field is mostly important when building the dependency graph, at the end.
  ")

(defclass requirement ()
  ((status :initarg :status
	   :type requirement-status
	   :reader status)
           :type requirement-status
           :reader status)
   (name :initarg :name
	 :type string
	 :reader name)
   (spec :initarg :spec
	 :type list
	 :reader spec)
         :type string
         :reader name)
   ;; This is a DNF of version-predicates.
   (vp-dnf :initarg :vp-dnf
           :type list
           :reader vp-dnf)
   (requirer :initarg :requirer
	     :type requirer
	     :initform *requirer*
	     :reader requirer))
             :type requirer
             :initform *requirer*
             :reader requirer))
  (:documentation "a package requirement."))

(defmethod print-object ((obj requirement) strm)
  (format strm "~:[!~;~]~a~{~{~a~^,~}~^;~}"
	  (eql :present (status obj))
	  (name obj)
	  (spec obj))
  (format strm "~:[!~;~]~A~{~{~A~^,~}~^;~}"
          (eql :present (status obj))
          (name obj)
          (vp-dnf obj))
  obj)

(defun decorate (requirement requirer)
  (make-instance 'requirement
		 :status (status requirement)
		 :name (name requirement)
		 :spec (spec requirement)
		 :requirer requirer))
                 :status (status requirement)
                 :name (name requirement)
                 :vp-dnf (vp-dnf requirement)
                 :requirer requirer))

;; todo test
(defun make-package-info (name version location requirements)
(defun make-package-info (name version location req-cnf)
  (let* ((base-instance (make-instance 'package-info
				       :name name
				       :version version
				       :location location))
	 (*requirer* base-instance)
	 (decorated-requirements
	   (mapcar
	     (lambda (conjunction)
	       (mapcar
		 (lambda (disjunction)
		   (decorate disjunction base-instance))
		 conjunction))
	     requirements)))

    (setf (slot-value base-instance 'requirements) decorated-requirements)
                                       :name name
                                       :version version
                                       :location location))
         (*requirer* base-instance)
         (decorated-req-cnf
           (mapcar
             (lambda (conjunction)
               (mapcar
                 (lambda (disjunction)
                   (decorate disjunction base-instance))
                 conjunction))
             req-cnf)))

    (setf (slot-value base-instance 'req-cnf) decorated-req-cnf)
    base-instance))


(defrule pess-greater "><"
	 (:constant :pess-greater))

;;;; make sure I'm in good territory
;;;; with that one roswell bug.
#+(or)
(parse 'pess-greater "><")

  (:constant :pess-greater))

(defrule greater-equal ">="
	 (:constant :greater-equal))
  (:constant :greater-equal))

(defrule greater-than ">"
	 (:constant :greater-than))
  (:constant :greater-than))

(defrule matches "<>"
	 (:constant :matches))
  (:constant :matches))

(defrule less-equal "<="
	 (:constant :less-equal))
  (:constant :less-equal))

(defrule less-than "<"
	 (:constant :less-than))
  (:constant :less-than))

(defrule equal-to "=="
	 (:constant :equal-to))
  (:constant :equal-to))

(defrule not-equal "!="
	 (:constant :not-equal))
  (:constant :not-equal))

(defrule version-predicate
	 (and
	   (or
	     pess-greater
	     greater-equal
	     greater-than
	     matches
	     less-equal
	     less-than
	     not-equal
	     equal-to)
	   cl-semver:version)
	 (:destructure (relation version)
		       (make-instance 'version-predicate :relation relation :version version)))
  (and
    (or
      pess-greater
      greater-equal
      greater-than
      matches
      less-equal
      less-than
      not-equal
      equal-to)
    cl-semver:version)
  (:destructure (relation version)
   (make-instance 'version-predicate :relation relation :version version)))

(defrule vp-conjunction
	 (and
	   version-predicate
	   (*
	     (and
	       #\,
	       version-predicate)))
	 (:destructure (vp others)
		       (cons vp
			     (loop for (_ vps) in others
				   collect vps))))
  (and
    version-predicate
    (*
      (and
        #\,
        version-predicate)))
  (:destructure (vp others)
   (cons vp
         (loop for (_ vps) in others
               collect vps))))

(defrule vp-disjunction
	 (and
	   vp-conjunction
	   (*
	     (and
	       #\;
	       vp-conjunction)))
	 (:destructure (vpc others)
		       (cons vpc
			     (loop for (_ vpcs) in others
				   collect vpcs))))
  (and
    vp-conjunction
    (*
      (and
        #\;
        vp-conjunction)))
  (:destructure (vpc others)
   (cons vpc
         (loop for (_ vpcs) in others
               collect vpcs))))

(defrule package-name
	 (+ (not (or #\: #\@ #\( #\) #\& #\| #\! #\, #\; #\> #\< #\=)))
	 (:lambda (name)
		  (coerce name 'string)))


(defrule version-requirement
	 (and
	   (? #\!)
	   package-name
	   (? vp-disjunction))
	 (:destructure (flag name spec)
		       (make-instance
			 'requirement
			 :status
			 (if flag :absent :present)
			 :name (coerce name 'string)
			 :spec spec)))

(defrule vr-conjunction
	 (and
	   vr-disjunction
	   (*
	     (and
	       #\&
	       vr-disjunction)))
	 (:destructure (vrc others)
		       (cons vrc
			     (loop for (_ vrcs) in others
				   collect vrcs))))

(defrule vr-disjunction
	 (and
	   version-requirement
	   (*
	     (and
	       #\|
	       version-requirement)))
	 (:destructure (vr others)
		       (cons vr
			     (loop for (_ vrs) in others
				   collect vrs))))
  (+ (not (or #\: #\@ #\( #\) #\& #\| #\! #\, #\; #\> #\< #\=)))
  (:lambda (name)
    (coerce name 'string)))

(defrule requirement
  (and
    (? #\!)
    package-name
    (? vp-disjunction))
  (:destructure (flag name vp-dnf)
   (make-instance
     'requirement
     :status
     (if flag :absent :present)
     :name (coerce name 'string)
     :vp-dnf vp-dnf)))

(defrule req-conjunction
  (and
    req-disjunction
    (*
      (and
        #\&
        req-disjunction)))
  (:destructure (reqc others)
   (cons reqc
         (loop for (_ reqcs) in others
               collect reqcs))))

(defrule req-disjunction
  (and
    requirement
    (*
      (and
        #\|
        requirement)))
  (:destructure (req others)
   (cons req
         (loop for (_ reqs) in others
               collect reqs))))

(defrule package-info
	 (and
	   package-name
	   #\:
	   cl-semver:version
	   #\@
	   (+ (not #\())
	   #\(
	   (? vr-conjunction)
	   #\)
	   )
	 (:destructure (name colon version at location open-paren requirements close-paren)
		       (declare (ignore colon at open-paren close-paren))
		       (make-package-info name version (coerce location 'string) requirements)))
  (and
    package-name
    #\:
    cl-semver:version
    #\@
    (+ (not #\())
    #\(
    (? req-conjunction)
    #\)
    )
  (:destructure (name colon version at location open-paren req-cnf close-paren)
   (declare (ignore colon at open-paren close-paren))
   (make-package-info name version (coerce location 'string) req-cnf)))

(defun version-predicate= (a b)
  (declare (type version-predicate a b))


@@ 286,20 279,20 @@
    (cl-semver:version= (version a) (version b))))


;; this does not test requirer equality, as that would cause an infinite loop,
;; since it represents a cycle in the graph.
;;; This does not test requirer equality, as that would cause an infinite loop,
;;; since it represents a cycle in the graph.
(defun requirement= (a b)
  (declare (type requirement a b))
  (and
    (eql (status a) (status b))
    (string= (name a) (name b))
    (every (lambda (x y)
	     (every (lambda (x y)
		      (version-predicate= x y))
		    x
		    y))
	   (spec a)
	   (spec b))))
             (every (lambda (x y)
                      (version-predicate= x y))
                    x
                    y))
           (vp-dnf a)
           (vp-dnf b))))

(defun package-info= (a b)
  (declare (type package-info a b))


@@ 308,56 301,24 @@
    (cl-semver:version= (version a) (version b))
    (string= (location a) (location b))
    (every (lambda (x y)
	     (every (lambda (u v)
		      (and (requirement= u v)
			   (eq (requirer u) a)
			   (eq (requirer v) b)))
		    x
		    y))
	   (requirements a)
	   (requirements b))))
             (every (lambda (u v)
                      (and (requirement= u v)
                           (eq (requirer u) a)
                           (eq (requirer v) b)))
                    x
                    y))
           (req-cnf a)
           (req-cnf b))))

#+(or)
(progn

  (multiple-value-bind (production position succeeded)
    (parse 'version-predicate ">=1.2.3")
    (list production position succeeded))
  (+ (parse 'version-predicate ">=1.2.3") 3)
  (parse 'vp-disjunction ">=1.2.3,<=2.0.0,>=1.5.0;><3.0.0,!=3.2.3")
  (requirer (parse 'version-requirement "!foo>=1.2.3,<=2.0.0,=>1.5.0;><3.0.0,!=3.2.3"))
  (parse 'version-requirement "foo>=1.2.3,<=2.0.0,>1.5.0;><3.0.0,!=3.2.3")
  )

#+(or)
;; => seven-bros:1.2.3@/tmp/foo(adam>=1.2.3,<=1.9.7,!=1.5.0;><3.0.0|benjamin==89.1.0;==89.5.0;==94.1.0&!caleb|caleb>=5.0.0-alpha.3,<5.0.0&daniel)

;; This was for an older version that used parse, but we're going to use parse
;; elsewhere instead.
#+(or)
(make-instance 'package-info
	       :name "foo"
	       :version (cl-semver:read-version-from-string "1.2.3")
	       :location "/tmp/foo"
	       :requirements
	       (list
		 (list
		   (parse 'version-requirement "bar>=1.2.3,<=2.0.0,>=1.5.0;><3.0.0,!=3.2.3")
		   (parse 'version-requirement "il>=1.2.3,<=2.0.0,=>1.5.0;><3.0.0,!=3.2.3"))
		 (list
		   (parse 'version-requirement "for>=1.2.3,<=2.0.0,=>1.5.0;><3.0.0,!=3.2.3")
		   (parse 'version-requirement "baz>=1.2.3,<=2.0.0,=>1.5.0;><3.0.0,!=3.2.3"))))

(defun present (name &key spec)
  (make-instance 'requirement :status :present :name name :spec spec))

(defun absent (name &key spec)
  (make-instance 'requirement :status :absent :name name :spec spec))
(defun present (name &key vp-dnf)
  (make-instance 'requirement :status :present :name name :vp-dnf vp-dnf))

(defun absent (name &key vp-dnf)
  (make-instance 'requirement :status :absent :name name :vp-dnf vp-dnf))

(defun version-passes (ver pred)
  (declare (type cl-semver:semantic-version version)
	   (type version-predicate pred))
           (type version-predicate pred))
  (case (relation pred)
    (:greater-than (cl-semver:version> ver (version pred)))
    (:greater-equal (cl-semver:version>= ver (version pred)))


@@ 366,45 327,22 @@
    (:less-equal (cl-semver:version<= ver (version pred)))
    (:less-than (cl-semver:version< ver (version pred)))
    (:pess-greater (and
		     (cl-semver:version>= ver (version pred))
		     (cl-semver:version<
		       ver
		       (cl-semver:make-semantic-version
			 (1+ (cl-semver:version-major (version pred))) 0 0))))))

;(defun requirement-fulfills (req pkg)
;  (declare (type requirement req)
;           (type package-info pkg))
;  (and
;    (eql (status requirement) :present)
;    (string= (name requirement) (name package))
;    (every (lambda (spec)
;             (some (lambda (predicate)
;                     (cl-semver:satisfies? (version package) predicate))
;                   spec))
;           (spec requirement))))
;
;  (with-slots (name version requirements) package
;    (if (string= (name requirement) name)
;      (every (lambda (spec)
;               (some (lambda (predicate)
;                       (cl-semver:satisfies? version predicate))
;                     spec))
;             (spec requirement))
;      nil)))
;  (let ((name (name package))
;        (version (version package))
;        (requirements (requirements package)))
;    (if (string= (name requirement) name)
;      (every (lambda (spec)
;               (some (lambda (predicate)
;                       (cl-semver:satisfies? version predicate))
;                     spec))
;             (spec requirement))
;      nil)))
;
;
;
;
;(defgeneric fulfills (requirement package)
;  (:documentation "A generic function to determine if a package fulfills a requirement."))
                     (cl-semver:version>= ver (version pred))
                     (cl-semver:version<
                       ver
                       (cl-semver:make-semantic-version
                         (1+ (cl-semver:version-major (version pred))) 0 0))))))

(defun matches-requirement (pkg req)
  (declare (type package-info pkg)
           (type requirement req))
  (and
    (string= (name req) (name pkg))
    (if (null (vp-dnf req))
        t
        (some (lambda (vp-dnf-clause)
                (every (lambda (predicate)
                         (version-passes (version pkg) predicate))
                       vp-dnf-clause))
              (vp-dnf req)))))


M tests/resolve.lisp => tests/resolve.lisp +215 -125
@@ 37,29 37,125 @@
(define-test basic-structures)

(defparameter +over1+ (make-instance 'skin.djha.zippm/resolve::version-predicate
				     :relation :greater-equal
				     :version #v"1.0"))
                                     :relation :greater-equal
                                     :version #v"1.0"))
(defparameter +under2+ (make-instance 'skin.djha.zippm/resolve::version-predicate
				      :relation :less-than
				      :version #v"2.0"))
                                      :relation :less-than
                                      :version #v"2.0"))
(defparameter +at23+ (make-instance 'skin.djha.zippm/resolve::version-predicate
				    :relation :equal-to
				    :version #v"2.3"))
                                    :relation :equal-to
                                    :version #v"2.3"))

(defparameter +present-r+ (make-instance 'skin.djha.zippm/resolve::requirement
					 :status :present
					 :name "foo"
					 :spec
					 `(
					   (,+over1+ ,+under2+)
					   (,+at23+))))
                                         :status :present
                                         :name "foo"
                                         :vp-dnf
                                         `(
                                           (,+over1+ ,+under2+)
                                           (,+at23+))))
#+(or)
(test *)

(define-test "Make a version predicate"
	     :parent basic-structures
	     (is string= (format nil "~A" +over1+) ">=1.0.0")
	     (is string= (format nil "~A" +under2+) "<2.0.0")
	     (is string= (format nil "~A" +at23+) "==2.3.0")
	     (is string= (format nil "~A" +present-r+) "foo>=1.0.0,<2.0.0;==2.3.0"))
  :parent basic-structures
  (is string= (format nil "~A" +over1+) ">=1.0.0")
  (is string= (format nil "~A" +under2+) "<2.0.0")
  (is string= (format nil "~A" +at23+) "==2.3.0")
  (is string= (format nil "~A" +present-r+) "foo>=1.0.0,<2.0.0;==2.3.0"))

(defparameter +adam-requirement+
  (make-instance
    'resolve::requirement
    :status :present
    :name "adam"
    :vp-dnf
    (list
      (list
        (make-instance
          'resolve::version-predicate
          :relation :greater-equal
          :version (cl-semver:read-version-from-string "1.2.3"))
        (make-instance
          'resolve::version-predicate
          :relation :less-equal
          :version (cl-semver:read-version-from-string "1.9.7"))
        (make-instance
          'resolve::version-predicate
          :relation :not-equal
          :version (cl-semver:read-version-from-string "1.5.0"))
        )
      (list
        (make-instance
          'resolve::version-predicate
          :relation :pess-greater
          :version (cl-semver:read-version-from-string "3.0.0"))
        )
      )))

(defparameter +benjamin-requirement+
  (make-instance
    'resolve::requirement
    :status :present
    :name "benjamin"
    :vp-dnf
    (list
      (list
        (make-instance
          'resolve::version-predicate
          :relation :equal-to
          :version
          (cl-semver:read-version-from-string
            "89.1.0")))
      (list
        (make-instance
          'resolve::version-predicate
          :relation :equal-to
          :version
          (cl-semver:read-version-from-string
            "89.5.0")))
      (list
        (make-instance
          'resolve::version-predicate
          :relation :equal-to
          :version
          (cl-semver:read-version-from-string
            "94.1.0"))))))

(defparameter
  +no-caleb-requirement+
  (make-instance
    'resolve::requirement
    :status :absent
    :name "caleb"
    :vp-dnf nil))

(defparameter
  +caleb-requirement+
  (make-instance
    'resolve::requirement
    :status :present
    :name "caleb"
    :vp-dnf
    (list
      (list
        (make-instance
          'resolve::version-predicate
          :relation :greater-equal
          :version (cl-semver:read-version-from-string
                     "5.0.0-alpha.3"))
        (make-instance
          'resolve::version-predicate
          :relation :less-than
          :version
          (cl-semver:read-version-from-string
            "5.0.0"))))))

(defparameter +daniel-requirement+
  (make-instance 'resolve::requirement
                 :status :present
                 :name "daniel"
                 :vp-dnf
                 nil))

(defparameter
  +seven-bros+


@@ 69,143 165,137 @@
    "/tmp/foo"
    (list
      (list
	(make-instance
	  'resolve::requirement
	  :status :present
	  :name "adam"
	  :spec
	  (list
	    (list
	      (make-instance
		'resolve::version-predicate
		:relation :greater-equal
		:version (cl-semver:read-version-from-string "1.2.3"))
	      (make-instance
		'resolve::version-predicate
		:relation :less-equal
		:version (cl-semver:read-version-from-string "1.9.7"))
	      (make-instance
		'resolve::version-predicate
		:relation :not-equal
		:version (cl-semver:read-version-from-string "1.5.0"))
	      )
	    (list
	      (make-instance
		'resolve::version-predicate
		:relation :pess-greater
		:version (cl-semver:read-version-from-string "3.0.0"))
	      )
	    )
	  )
	(make-instance
	  'resolve::requirement
	  :status :present
	  :name "benjamin"
	  :spec
	  (list
	    (list
	      (make-instance
		'resolve::version-predicate
		:relation :equal-to
		:version
		(cl-semver:read-version-from-string
		  "89.1.0")))
	    (list
	      (make-instance
		'resolve::version-predicate
		:relation :equal-to
		:version
		(cl-semver:read-version-from-string
		  "89.5.0")))
	    (list
	      (make-instance
		'resolve::version-predicate
		:relation :equal-to
		:version
		(cl-semver:read-version-from-string
		  "94.1.0"))))))
        +adam-requirement+
        +benjamin-requirement+)
      (list
	(make-instance
	  'resolve::requirement
	  :status :absent
	  :name "caleb"
	  :spec nil)
	(make-instance
	  'resolve::requirement
	  :status :present
	  :name "caleb"
	  :spec
	  (list
	    (list
	      (make-instance
		'resolve::version-predicate
		:relation :greater-equal
		:version (cl-semver:read-version-from-string
			   "5.0.0-alpha.3"))
	      (make-instance
		'resolve::version-predicate
		:relation :less-than
		:version
		(cl-semver:read-version-from-string
		  "5.0.0"))))))
        +no-caleb-requirement+
        +caleb-requirement+)
      (list
	(make-instance 'resolve::requirement
		       :status :present
		       :name "daniel"
		       :spec
		       nil)))))
        +daniel-requirement+))))

(defparameter +seven-bros-string+  "seven-bros:1.2.3@/tmp/foo(adam>=1.2.3,<=1.9.7,!=1.5.0;><3.0.0|benjamin==89.1.0;==89.5.0;==94.1.0&!caleb|caleb>=5.0.0-alpha.3,<5.0.0&daniel)")

#+(or)
(test *)
(define-test
  "Make a package information object"
  :parent basic-structures
  ;; TODO: Make tests use the parse stuff
  (is string= (format nil "~A" +seven-bros+)
		 +seven-bros-string+)
      +seven-bros-string+)
  (is resolve:package-info=
	  (esrap:parse 'resolve::package-info +seven-bros-string+)
	  +seven-bros+)
      (esrap:parse 'resolve::package-info +seven-bros-string+)
      +seven-bros+)
  (is string=
	  (format nil "~A"
		  (esrap:parse
		    'resolve::package-info
		    +seven-bros-string+))
	  +seven-bros-string+))
      (format nil "~A"
              (esrap:parse
                'resolve::package-info
                +seven-bros-string+))
      +seven-bros-string+))

(define-test fulfillments)

(defparameter +past-2+
  (make-instance 'skin.djha.zippm/resolve::version-predicate
		 :relation :greater-equal
		 :version #v"2.0"))
                 :relation :greater-equal
                 :version "2.0"))

(defparameter +under-3+
  (make-instance 'skin.djha.zippm/resolve::version-predicate
		 :relation :less-than
		 :version #v"3.0"))
                 :relation :less-than
                 :version #v"3.0"))

(defparameter +at-3.3+
  (make-instance 'skin.djha.zippm/resolve::version-predicate
		 :relation :equal-to
		 :version #v"3.3"))
                 :relation :equal-to
                 :version #v"3.3"))

(defparameter +between-2-3+
  (make-instance 'skin.djha.zippm/resolve::version-predicate
		 :relation :pess-greater
		 :version #v"2.0"))
                 :relation :pess-greater
                 :version #v"2.0"))

(defparameter +between-1-2+
  (make-instance 'skin.djha.zippm/resolve::version-predicate
		 :relation :pess-greater
		 :version #v"1.0"))
                 :relation :pess-greater
                 :version #v"1.0"))

(defparameter +version-2.5+ #v"2.5")

#+(or)
(test *)

(define-test "version passes"
	     :parent fulfillments
	     (true (resolve::version-passes +version-2.5+ +past-2+))
	     (true (resolve::version-passes +version-2.5+ +under-3+))
	     (false (resolve::version-passes +version-2.5+ +at-3.3+))
	     (true (resolve::version-passes +version-2.5+ +between-2-3+))
	     (false (resolve::version-passes +version-2.5+ +between-1-2+)))
  :parent fulfillments
  (true (resolve::version-passes +version-2.5+ +past-2+))
  (true (resolve::version-passes +version-2.5+ +under-3+))
  (false (resolve::version-passes +version-2.5+ +at-3.3+))
  (true (resolve::version-passes +version-2.5+ +between-2-3+))
  (false (resolve::version-passes +version-2.5+ +between-1-2+)))

(define-test "matches requirement"
  :parent fulfillments
  (false (resolve::matches-requirement
           (resolve:make-package-info
             "adam"
             (cl-semver:read-version-from-string "1.2.2")
             "/tmp/adam"
             nil)
           +adam-requirement+))
  (true (resolve::matches-requirement
          (resolve:make-package-info
            "adam"
            (cl-semver:read-version-from-string "1.2.3")
            "/tmp/adam"
            nil)
          +adam-requirement+))
  (false (resolve::matches-requirement 
           (resolve:make-package-info
             "adam"
             (cl-semver:read-version-from-string "1.5.0")
             "/tmp/adam"
             nil)
           +adam-requirement+))
  (true (resolve::matches-requirement
          (resolve:make-package-info
            "adam"
            (cl-semver:read-version-from-string "1.9.7")
            "/tmp/adam"
            nil)
          +adam-requirement+))
  (false (resolve::matches-requirement
           (resolve:make-package-info
             "adam"
             (cl-semver:read-version-from-string "1.9.8")
             "/tmp/adam"
             nil)
           +adam-requirement+))
  (true (resolve::matches-requirement
          (resolve:make-package-info
            "adam"
            (cl-semver:read-version-from-string "3.0.0")
            "/tmp/adam"
            nil)
          +adam-requirement+))
  (false (resolve::matches-requirement
           (resolve:make-package-info
             "adam"
             (cl-semver:read-version-from-string "4.0.0")
             "/tmp/adam"
             nil)
           +adam-requirement+))
  (false (resolve::matches-requirement
           (resolve:make-package-info
             "caleb"
             (cl-semver:read-version-from-string "1.5.1")
             "/tmp/adam"
             nil)
           +adam-requirement+))
  (true (resolve::matches-requirement
          (resolve:make-package-info
            "caleb"
            (cl-semver:read-version-from-string "1.5.1")
            "/tmp/adam"
            nil)
          +no-caleb-requirement+)))

(cl-semver:disable-version-syntax)