pax_global_header00006660000000000000000000000064120067256430014517gustar00rootroot0000000000000052 comment=8d2e54398c284dd85d39482449fdadcec7d6d6b4 cudf-0.6.3/000077500000000000000000000000001200672564300124465ustar00rootroot00000000000000cudf-0.6.3/.gitignore000066400000000000000000000000771200672564300144420ustar00rootroot00000000000000_build/ *.byte *.native cudf_822_parser.ml cudf_822_parser.mli cudf-0.6.3/.headache.conf000066400000000000000000000001601200672564300151120ustar00rootroot00000000000000 ".*\\.ml[il]?" -> frame open:"(*" line:"*" close:"*)" | ".*\\.mly" -> frame open:"/*" line:"*" close:"*/" cudf-0.6.3/.ocamlinit-cudf000066400000000000000000000010001200672564300153340ustar00rootroot00000000000000#use "topfind";; #require "extlib";; #require "oUnit";; #load "_build/cudf.cma";; #load "_build/tests.cmo";; open ExtLib;; open Cudf;; open Cudf_checker;; open Cudf_parser;; open Cudf_printer;; open Cudf_types_pp;; let p = Cudf_parser.from_in_channel (open_in "tests/legacy.cudf") let (pre, pkgs, req) as cudf_doc = match Cudf_parser.parse_from_file "examples/legacy.cudf" with | Some pre, pkgs, Some req -> pre, pkgs, req | _ -> assert false ;; let (univ, _) as cudf = Cudf.load_universe pkgs, req cudf-0.6.3/BUGS000066400000000000000000000001621200672564300131300ustar00rootroot00000000000000See issue tracker at http://gforge.info.ucl.ac.be/tracker/index.php?group_id=35&atid=283 for component "libcudf". cudf-0.6.3/COPYING000066400000000000000000000217161200672564300135100ustar00rootroot00000000000000This library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. As a special exception to the GNU Lesser General Public License, you may link, statically or dynamically, a "work that uses the Library" with a publicly distributed version of the Library to produce an executable file containing portions of the Library, and distribute that executable file under terms of your choice, without any of the additional requirements listed in clause 6 of the GNU Lesser General Public License. By "a publicly distributed version of the Library", we mean either the unmodified Library as distributed, or a modified version of the Library that is distributed under the conditions defined in clause 3 of the GNU Lesser General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . ---------------------------------------------------------------------------- GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. cudf-0.6.3/ChangeLog000066400000000000000000000077701200672564300142330ustar00rootroot000000000000002012-08-03 Stefano Zacchiroli * ALL release 0.6.3 * Cudf: bugfix: ensure that Cudf.status sizes are non-bogus * Cudf: new functions to lookup properties as typed values lookup_typed_{package,request,preamble}_property * Cudf: new functions to lookup type declarations for both core and extra package properties * Cudf_conf: offer direct access to per-stanza property schemata * testsuite: add printers to better inspect test failures * Cudf: refactoring, build raw property access on top of typed one * Cudf_conf: refactoring, deduplicate "keep" property enums 2011-11-27 Stefano Zacchiroli * ALL release 0.6.2 * ALL Cudf: add a new mapping between packages and unique integer identifiers, useful to avoid external uid maps (patch by Pietro Abate) * ALL Cudf: who_provides is now more general and can query both installed and available packages (patch by Pietro Abate) * ALL Cudf_printer: expose generic higher order printers 2011-09-15 Stefano Zacchiroli * ALL release 0.6.1 * ALL Cudf_parser: allow parsing of empty universes as well as parsing of documents containing only a (possibly empty) request 2011-06-01 Stefano Zacchiroli * ALL release 0.6 * ALL cudf-check: faster (~ 2x) -dump * ALL Cudf_printer/Cudf_types_pp: speed improvement (~ 3.5x) get rid of Format, output only on strings (_types_pp) or on out_channel (_printer). [ API change ] * ALL Cudf_printer: add IO.output based API * ALL Cudf_types_pp: fix pretty printing of "enum[...]" type * ALL Cudf_printer.pp_cudf: avoid extra blank line before request * doc: clarify is_solution meaning wrt inconsistent universes * c-lib: link caml_hash_variant with -ldl 2010-11-04 Stefano Zacchiroli * ALL parser: add support for ExtLib IO channels Thanks Pietro Abate for the patch. (Closes: #299) * ALL add Cudf.mem_package (Closes: #307) * ALL Development release 0.5.99 2010-06-25 Stefano Zacchiroli * ALL bug fix: do not enforce Keep on uninstalled packages Thanks Ralf Treinen for the patch! (Closes: #266) * ALL bug fix: nicer error message for unknown packages found in solution (Closes: #267) * ALL bug fix: avoid pretty printing some malformed vpkgformulae (Closes: #272) * ALL bug fix: check for duplicate property in 822 stanzas (Closes: #269) * ALL bug fix: comments no longer split stanzas in two (Closes: #250) * ALL bug fix: perform string escape when pretty printing type declarations (Closes: #271) * ALL add several test cases to the test suite * ALL Development release 0.5.98 2010-06-03 Stefano Zacchiroli * ALL bug fix: optional/mandatory extra property management * c-lib bug fix: add handling of vpkgformula extra properties * ALL bug fix: allow empty vpkglist as default values * ALL bug fix: do not accept trivial formulae as v(eq)pkglist * ALL Development release 0.5.97 2010-06-01 Stefano Zacchiroli * c-lib add structured accessors to request fields (patch by Gustavo Gutierrez, thanks!) * doc better explain the role of load_solution * ALL simpler API for solutions: cudf_load_solution_from_file * ALL bug fix: avoid losing ?typedecl in convenience functions * c-lib add bindings for cudf_load_solution_from_file * backward-compatibility enabling compilation with OCaml 3.10.2 * ALL bug fix: support heading '+' when parsing posint * ALL Development release 0.5.96 2009-12-18 Stefano Zacchiroli * c-lib Remove the need of OCaml devel stuff to use the C API * c-lib Provide bindings to OCaml native code, if available * c-lib Hide OCaml "value", it is way more safe (API change) * c-lib O(n^2) -> O(n) speed-up in package list conversion * ALL Development release 0.5.94 2009-11-25 Stefano Zacchiroli * ALL Porting to CUDF 2.0 * ALL Development release 0.5.92 2009-02-24 Stefano Zacchiroli * ALL First public release, version 0.4 cudf-0.6.3/INSTALL000066400000000000000000000024021200672564300134750ustar00rootroot00000000000000 To build ======== Build dependencies: - ocaml >= 3.10.2 (Debian package: "ocaml-nox", RPM: "ocaml") - camlp4 (RPM: "camlp4") - findlib (Debian package: "ocaml-findlib", RPM: "ocaml-findlib") - extlib (Debian package: "libextlib-ocaml-dev", RPM: "ocaml-extlib-devel") - oUnit (only needed to run the test suite Debian package: "libounit-ocaml-dev", RPM: "ocaml-ounit-devel") - glib (only needed to build the C bindings Debian package: "libglib2.0-dev", RPM: "libglib2.0-devel") To build run: $ make all # build bytecode libs and executables $ make opt # build native code libs and executables (if you have ocamlopt) $ make test # run the test suite (need oUnit) C bindings ---------- To build the C bindings to the OCaml library run: $ make -C c-lib # build C bindings (to OCaml bytecode) $ make -C c-lib-opt # build C bindings (to OCaml native code) $ make -C c-lib test # run the test suite for C bindings To install ========== To install run, after compilation: # make install # install libs and executables To install under a non-standard location, say "/my/dest/dir": $ make install DESTDIR=/my/dest/dir To uninstall ============ # make uninstall or: $ make uninstall DESTDIR=/my/dest/dir cudf-0.6.3/META000066400000000000000000000002021200672564300131110ustar00rootroot00000000000000description = "CUDF library" version = "placeholder" archive(byte) = "cudf.cma" archive(native) = "cudf.cmxa" requires = "extlib" cudf-0.6.3/Makefile000066400000000000000000000066721200672564300141210ustar00rootroot00000000000000include Makefile.config NAME = cudf LIBS = _build/cudf.cma LIBS_OPT = _build/cudf.cmxa PROGS = _build/main_cudf_check _build/main_cudf_parse_822 PROGS_BYTE = $(addsuffix .byte,$(PROGS)) PROGS_OPT = $(addsuffix .native,$(PROGS)) RESULTS = $(LIBS) $(PROGS_BYTE) _build/cudf_c.cmo RESULTS_OPT = $(LIBS_OPT) $(PROGS_OPT) _build/cudf_c.cmx SOURCES = $(wildcard *.ml *.mli *.mll *.mly) C_LIB_DIR = c-lib C_LIB_SOURCES = $(wildcard $(C_LIB_DIR)/*.c $(C_LIB_DIR)/*.h) OCAMLBUILD = ocamlbuild OBFLAGS = OCAMLFIND = ocamlfind ifeq ($(DESTDIR),) INSTALL = $(OCAMLFIND) install UNINSTALL = $(OCAMLFIND) remove else INSTALL = $(OCAMLFIND) install -destdir $(DESTDIR)/$(OCAMLLIBDIR) UNINSTALL = $(OCAMLFIND) remove -destdir $(DESTDIR)/$(OCAMLLIBDIR) endif DIST_DIR = $(NAME)-$(VERSION) DIST_TARBALL = $(DIST_DIR).tar.gz all: $(RESULTS) opt: $(RESULTS_OPT) $(RESULTS): $(SOURCES) $(RESULTS_OPT): $(SOURCES) .PHONY: c-lib c-lib-opt c-lib: make -C $(C_LIB_DIR) all c-lib-opt: make -C $(C_LIB_DIR) opt clean: make -C $(C_LIB_DIR) clean $(OCAMLBUILD) $(OBFLAGS) -clean rm -rf $(NAME)-*.gz $(NAME)_*.gz $(NAME)-*/ _build/%: $(OCAMLBUILD) $(OBFLAGS) $* @touch $@ # top-level: _build/cudf.cma _build/tests.cmo top-level: _build/cudf.cma ledit ocaml -I ./_build/ -init ./.ocamlinit-cudf headers: header.txt .headache.conf headache -h header.txt -c .headache.conf $(SOURCES) $(C_LIB_SOURCES) test: _build/test.byte $< -verbose @echo c-lib-test: make -C $(C_LIB_DIR) test _build/test.byte: $(SOURCES) tags: TAGS TAGS: $(SOURCES) otags $^ INSTALL_STUFF = META INSTALL_STUFF += $(wildcard _build/*.cma _build/*.cmxa _build/cudf.a) INSTALL_STUFF += $(wildcard _build/cudf_*.cmi) $(wildcard _build/*.mli) INSTALL_STUFF += $(wildcard _build/cudf_*.cmx _build/cudf_*.o _build/cudf_*.a) INSTALL_STUFF += $(wildcard _build/cudf.o _build/cudf.cmx _build/cudf.cmi) install: test -d $(DESTDIR)/$(OCAMLLIBDIR) || mkdir -p $(DESTDIR)/$(OCAMLLIBDIR) $(INSTALL) -patch-version $(VERSION) $(NAME) $(INSTALL_STUFF) test -d $(DESTDIR)/$(BINDIR) || mkdir -p $(DESTDIR)/$(BINDIR) for p in $(notdir $(PROGS)) ; do \ tgt=`echo $$p | sed -e 's/^main.//' -e 's/_/-/g'` ; \ if [ -f _build/$$p.native ] ; then \ cp _build/$$p.native $(DESTDIR)/$(BINDIR)/$$tgt ; \ else \ cp _build/$$p.byte $(DESTDIR)/$(BINDIR)/$$tgt ; \ fi ; \ echo "Installed $(DESTDIR)/$(BINDIR)/$$tgt" ; \ done if [ -f $(C_LIB_DIR)/cudf.o ] ; then \ $(MAKE) -C c-lib/ -e install ; \ fi uninstall: $(UNINSTALL) $(NAME) for p in $(notdir $(PROGS)) ; do \ tgt=`echo $$p | sed -e 's/^main.//' -e 's/_/-/g'` ; \ if [ -f $(DESTDIR)/$(BINDIR)/$$tgt ] ; then \ rm $(DESTDIR)/$(BINDIR)/$$tgt ; \ fi ; \ echo "Removed $(DESTDIR)/$(BINDIR)/$$tgt" ; \ done -rmdir -p $(DESTDIR)/$(OCAMLLIBDIR) $(DESTDIR)/$(BINDIR) dist: ./$(DIST_TARBALL) ./$(DIST_TARBALL): git archive --format=tar --prefix=$(DIST_DIR)/ HEAD | gzip > $@ @echo "Distribution tarball: ./$(DIST_TARBALL)" rpm: ./$(DIST_TARBALL) rpmbuild --nodeps -ta $< distcheck: ./$(DIST_TARBALL) tar xzf $< $(MAKE) -C ./$(DIST_DIR) all if which ocamlopt > /dev/null ; then $(MAKE) -C ./$(DIST_DIR) opt ; fi $(MAKE) -C ./$(DIST_DIR) test $(MAKE) -C ./$(DIST_DIR)/$(C_LIB_DIR)/ all $(MAKE) -C ./$(DIST_DIR) install DESTDIR=$(CURDIR)/$(DIST_DIR)/tmp rm -rf ./$(DIST_DIR) doc: $(OCAMLBUILD) $(OBFLAGS) cudf.docdir/index.html world: all opt c-lib c-lib-opt doc .PHONY: all opt world clean top-level headers test tags install uninstall .PHONY: dep rpm c-lib c-lib-opt dist doc cudf-0.6.3/Makefile.config000066400000000000000000000004211200672564300153470ustar00rootroot00000000000000VERSION = 0.6.3 export DESTDIR = # all the following variables will be prepended by $(DESTDIR) upon install export OCAMLLIBDIR := $(shell ocamlc -where) export BINDIR = /usr/bin export LIBDIR = /usr/lib export INCDIR = /usr/include export PCDIR = $(LIBDIR)/pkgconfig cudf-0.6.3/README000066400000000000000000000032551200672564300133330ustar00rootroot00000000000000libCUDF - CUDF (Common Upgradeability Description Format) library ================================================================= libCUDF is a library to manipulate so called CUDF documents. A CUDF (Common Upgradeability Description Format) document describes an "upgrade scenario", as faced by package managers in popular package-based FOSS (Free and Open Source Software) distributions. A CUDF document consists of an optional leading "preamble", a "package universe", and a trailing "user request": - The package universe describes all packages known to the package manager, a subset of which (the "package status") denotes the package being currently installed on a given machine. - The user request denotes a change to the package status requested by the user, e.g.: "install package foo", "remove package bar", ... - The preamble contains meta-information such as a typing information for custom package properties, checksums, document unique identifiers, ... A CUDF document is naturally complemented by a "solution" describing the resulting package status (if any) that satisfies the user request, as found by a package manager. libCUDF enables manipulation of CUDF and related documents. Bugs ---- Please report bugs to the gforge bug tracker available at: http://gforge.info.ucl.ac.be/tracker/?group_id=35 when reporting bug, please select the "libcudf" component. Reference --------- libCUDF implements the Common Upgradeability Description Format (CUDF) 2.0 specifications [1], edited by the Mancoosi project [2]. [1] http://www.mancoosi.org/reports/tr3.pdf [2] http://www.mancoosi.org -- Stefano Zacchiroli Thu, 26 Nov 2009 10:49:32 +0100 cudf-0.6.3/TODO000066400000000000000000000001621200672564300131350ustar00rootroot00000000000000See issue tracker at http://gforge.info.ucl.ac.be/tracker/index.php?group_id=35&atid=283 for component "libcudf". cudf-0.6.3/_tags000066400000000000000000000003231200672564300134640ustar00rootroot00000000000000 or : pkg_oUnit or : pkg_oUnit <*.ml> or <*.mli> : pkg_extlib, pp(camlp4o) <*.byte> or <*.native> : pkg_extlib : not_hygienic : not_hygienic cudf-0.6.3/c-lib/000077500000000000000000000000001200672564300134345ustar00rootroot00000000000000cudf-0.6.3/c-lib/.gitignore000066400000000000000000000000741200672564300154250ustar00rootroot00000000000000*.a *.o c-test c-test-opt caml_hash_variant cudf-variants.h cudf-0.6.3/c-lib/Makefile000066400000000000000000000045241200672564300151010ustar00rootroot00000000000000include ../Makefile.config all: libcudf.a c-test opt: libcudf-opt.a c-test-opt include Makefile.variants NULL = CFLAGS = -Wall -DG_LOG_DOMAIN=\"libCUDF\" PROG_CFLAGS = -Wall OCAML_LIBDIR := $(shell ocamlc -where) INCLUDES = -I . -I $(OCAML_LIBDIR) $(shell pkg-config --cflags glib-2.0) CUDF_LDFLAGS = -L$(OCAML_LIBDIR) -L$(CURDIR) CUDF_CLIBS = -lcudf -lm -ldl -lunix -lncurses -lglib-2.0 OCAMLC = ocamlfind ocamlc -package unix,extlib OCAMLOPT = ocamlfind ocamlopt -package unix,extlib INSTALL_STUFF = libcudf.a cudf.h cudf.pc libcudf.a: cudf-caml.o cudf.o cp $(OCAML_LIBDIR)/libcamlrun.a $@ ar r $@ $^ libcudf-opt.a: cudf-caml-opt.o cudf.o cp $(OCAML_LIBDIR)/libasmrun.a $@ ar r $@ $^ ../_build/%: cd .. && ocamlbuild $* cudf-caml.o: ../_build/cudf.cma ../_build/cudf_c.cmo $(OCAMLC) -linkpkg -output-obj -o $@ $^ cudf-caml-opt.o: ../_build/cudf.cmxa ../_build/cudf_c.cmx $(OCAMLOPT) -linkpkg -output-obj -o $@ $^ cudf.o: cudf.c cudf.h cudf-variants.h c-test.o: c-test.c cudf.o $(CC) $(PROG_CFLAGS) $(INCLUDES) -c $< c-test: c-test.o libcudf.a $(CC) $(PROG_CFLAGS) -o $@ $(INCLUDES) $(CUDF_LDFLAGS) $< $(CUDF_CLIBS) c-test-opt: c-test.o libcudf-opt.a $(CC) $(PROG_CFLAGS) -o $@ $(INCLUDES) $(CUDF_LDFLAGS) $< \ $(subst -lcudf,-lcudf-opt,$(CUDF_CLIBS)) test: ../tests/legacy.cudf ../tests/legacy-sol.cudf c-test ./c-test ../tests/legacy.cudf ../tests/legacy-sol.cudf > /dev/null cudf.pc: cudf.pc.in cat $< | sed -e "s,@OCAMLLIBDIR@,$(OCAMLLIBDIR),g" \ -e "s,@VERSION@,$(VERSION),g" \ -e "s,@LIBDIR@,$(LIBDIR),g" \ -e "s,@INCDIR@,$(INCDIR),g" \ > $@ %.o: %.c $(CC) $(CFLAGS) $(INCLUDES) -c $< clean: rm -f *.a *.o *.cmo *.cmi rm -f c-test c-test-opt rm -f cudf.pc install: cudf.pc test -d $(DESTDIR)/$(LIBDIR) || mkdir -p $(DESTDIR)/$(LIBDIR) test -d $(DESTDIR)/$(INCDIR) || mkdir -p $(DESTDIR)/$(INCDIR) test -d $(DESTDIR)/$(PCDIR) || mkdir -p $(DESTDIR)/$(PCDIR) if [ -f libcudf-opt.a ] ; then \ cp libcudf-opt.a $(DESTDIR)/$(LIBDIR)/libcudf.a ; \ else \ cp libcudf.a $(DESTDIR)/$(LIBDIR)/libcudf.a ; \ fi cp libcudf.a $(DESTDIR)/$(LIBDIR) cp cudf.h $(DESTDIR)/$(INCDIR) cp cudf.pc $(DESTDIR)/$(PCDIR) uninstall: rm $(DESTDIR)/$(LIBDIR)/libcudf.a rm $(DESTDIR)/$(INCDIR)/cudf.h rm $(DESTDIR)/$(PCDIR)/cudf.pc -rmdir -p $(DESTDIR)/$(LIBDIR) $(DESTDIR)/$(INCDIR) $(DESTDIR)/$(PCDIR) .PHONY: all opt clean test install uninstall cudf-0.6.3/c-lib/Makefile.variants000066400000000000000000000025561200672564300167320ustar00rootroot00000000000000# OCaml (polymorphic) variants used by the bindings # Will be used to generate cudf-variants.h ML_VARIANTS = \ $(ML_RELOP_VARIANTS) \ $(ML_TYPE_VARIANTS) \ $(ML_KEEP_VARIANTS) \ $(ML_ITEM_VARIANTS) \ $(NULL) ML_RELOP_VARIANTS = \ Eq \ Neq \ Geq \ Gt \ Leq \ Lt \ $(NULL) ML_TYPE_VARIANTS = \ Int \ Posint \ Nat \ Bool \ String \ Enum \ Pkgname \ Ident \ Vpkg \ Vpkgformula \ Vpkglist \ Veqpkg \ Veqpkglist \ Typedecl \ $(NULL) ML_KEEP_VARIANTS = \ Keep_version \ Keep_package \ Keep_feature \ Keep_none \ $(NULL) ML_ITEM_VARIANTS = \ Preamble \ Package \ Request \ $(NULL) cudf.o: cudf-variants.h cudf-variants.h: caml_hash_variant Makefile.variants @echo "/* THIS FILE IS GENERATED, DO NOT EDIT */" > $@ @echo "/* See Makefile.variants for generation logics */" >> $@ @echo >> $@ @echo "#ifndef _CUDF_VARIANTS_H" >> $@ @echo "#define _CUDF_VARIANTS_H" >> $@ @echo >> $@ @(for variant in $(ML_VARIANTS) ; do \ ./$< $$variant ; \ done) >> $@ @echo >> $@ @echo "#endif\t/* end of cudf-variants.h */" >> $@ @echo >> $@ caml_hash_variant: caml_hash_variant.o > dummy.ml ocamlc -o dummy.o -output-obj dummy.ml $(CC) $(CFLAGS) -o $@ $< dummy.o -L$(OCAML_LIBDIR) -lcamlrun -lm -lcurses -ldl @rm -f dummy.* clean: clean-variants clean-variants: rm -f caml_hash_variant cudf-variants.h rm -f dummy.* .PHONY: clean-variants cudf-0.6.3/c-lib/c-test.c000066400000000000000000000166731200672564300150140ustar00rootroot00000000000000/*****************************************************************************/ /* libCUDF - CUDF (Common Upgrade Description Format) manipulation library */ /* Copyright (C) 2009-2012 Stefano Zacchiroli */ /* */ /* This library is free software: you can redistribute it and/or modify */ /* it under the terms of the GNU Lesser General Public License as */ /* published by the Free Software Foundation, either version 3 of the */ /* License, or (at your option) any later version. A special linking */ /* exception to the GNU Lesser General Public License applies to this */ /* library, see the COPYING file for more information. */ /*****************************************************************************/ /* Compile with: cc -o c-test c-test.c `pkg-config --cflags cudf` `pkg-config --libs cudf` */ #include #include #include #include /* Print to stdout a relational operator (on versions) */ void print_relop(int relop) { switch (relop) { case RELOP_EQ : printf("=") ; break ; case RELOP_NEQ : printf("!=") ; break ; case RELOP_GEQ : printf(">=") ; break ; case RELOP_GT : printf(">") ; break ; case RELOP_LEQ : printf("<=") ; break ; case RELOP_LT : printf("<") ; break ; case RELOP_NOP : default : g_error("Unexpected integer, which is not a RELOP_*: %d", relop); } } /* Print to stdout a package version predicate */ void print_vpkg(cudf_vpkg_t *vpkg) { if (vpkg == NULL) return; printf("%s", vpkg->name); if (vpkg->relop) { printf(" "); print_relop(vpkg->relop); printf(" %d", vpkg->version); } } /* Print to stdout a list of package predicates, separated by a given separator */ void print_vpkglist(cudf_vpkglist_t l, const char *sep) { cudf_vpkg_t *vpkg; GList *last; last = g_list_last(l); while (l != NULL) { vpkg = g_list_nth_data(l, 0); print_vpkg(vpkg); if (l != last) printf(sep); l = g_list_next(l); } } /* Print to stdout a package formula */ void print_vpkgformula(cudf_vpkgformula_t fmla) { GList *last; last = g_list_last(fmla); while (fmla != NULL) { print_vpkglist(g_list_nth_data(fmla, 0), " | "); if (fmla != last) printf(", "); fmla = g_list_next(fmla); } } /* Print to stdout a CUDF preamble */ void print_preamble(cudf_doc_t *doc) { char *s; char *props[] = { "preamble", "property", "univ-checksum", "status-checksum", "req-checksum" }; int i; if (! doc->has_preamble) return; for (i=0 ; i<5 ; i++) { s = cudf_pre_property(doc->preamble, props[i]); printf(" %s: %s\n", props[i], s); free(s); } } /* Print to stdout a CUDF request */ void print_request(cudf_doc_t *doc) { char *s; if (! doc->has_request) return; s = cudf_req_property(doc->request, "request"); printf(" request: %s\n", s); free(s); printf(" install: "); print_vpkglist(cudf_req_install(doc->request), ", "); printf("\n"); printf(" upgrade: "); print_vpkglist(cudf_req_upgrade(doc->request), ", "); printf("\n"); printf(" remove: "); print_vpkglist(cudf_req_remove(doc->request), ", "); printf("\n"); } /* Print to stdout a possible value of the "keep" package property */ void print_keep(int keep) { switch (keep) { case KEEP_NONE : printf(" keep: version\n"); break; case KEEP_VERSION : printf(" keep: version\n"); break; case KEEP_PACKAGE : printf(" keep: package\n"); break; case KEEP_FEATURE : printf(" keep: feature\n"); break; default : g_error("Unexpected \"keep\" value: %d", keep); } } void print_value(cudf_value_t *v) { int typ; if (v == NULL) return; typ = v->typ; switch (typ) { case TYPE_INT : case TYPE_POSINT : case TYPE_NAT : printf("%d", v->val.i); break; case TYPE_BOOL : printf("%s", v->val.i ? "true" : "false"); break; case TYPE_STRING : case TYPE_PKGNAME : case TYPE_IDENT : case TYPE_ENUM : printf("%s", v->val.s); break; case TYPE_VPKG : case TYPE_VEQPKG : print_vpkg(v->val.vpkg); break; case TYPE_VPKGLIST : case TYPE_VEQPKGLIST : print_vpkglist(v->val.vpkgs, ", "); break; case TYPE_VPKGFORMULA : print_vpkgformula(v->val.f); break; case TYPE_TYPEDECL : break; default : g_error("Internal error: unexpected variant for type: %d", typ); } } /* Print to stdout a generic property, i.e. a pair */ void print_property(gpointer k, gpointer v, gpointer user_data) { printf(" %s: ", (char *) k); print_value(v); printf("\n"); } /* Print to stdout a set of extra properties */ #define print_extra(e) (g_hash_table_foreach(e, print_property, NULL)) /* Print to stdout a CUDF package */ void print_pkg(cudf_package_t pkg) { cudf_vpkgformula_t fmla; cudf_vpkglist_t vpkglist; cudf_extra_t extra; printf(" package: %s\n", cudf_pkg_name(pkg)); printf(" version: %d\n", cudf_pkg_version(pkg)); printf(" installed: %s\n", cudf_pkg_installed(pkg) ? "true" : "false"); printf(" was-installed: %s\n", cudf_pkg_was_installed(pkg) ? "true" : "false"); fmla = cudf_pkg_depends(pkg); printf(" depends: "); print_vpkgformula(fmla); printf("\n"); cudf_free_vpkgformula(fmla); vpkglist = cudf_pkg_conflicts(pkg); /* conflicts */ printf(" conflicts: "); print_vpkglist(vpkglist, ", "); printf("\n"); cudf_free_vpkglist(vpkglist); vpkglist = cudf_pkg_provides(pkg); /* provides */ printf(" provides: "); print_vpkglist(vpkglist, ", "); printf("\n"); cudf_free_vpkglist(vpkglist); print_keep(cudf_pkg_keep(pkg)); /* keep */ extra = cudf_pkg_extra(pkg); /* extra properties */ print_extra(extra); printf("\n"); cudf_free_extra(extra); } int main(int argc, char **argv) { cudf_doc_t *doc = NULL; cudf_t *cudf = NULL, *sol = NULL; cudf_package_t pkg; cudf_universe_t univ = NULL; GList *l = NULL; cudf_init(); if (argc < 2) { printf("Usage: %s CUDF_FILE [ SOLUTION_FILE ]\n", argv[0]); exit(2); } g_message("Parsing CUDF document %s ...", argv[1]); doc = cudf_parse_from_file(argv[1]); printf("Has preamble: %s\n", doc->has_preamble ? "yes" : "no"); if (doc->has_preamble) { printf("Preamble: \n"); print_preamble(doc); printf("\n"); } printf("Has request: %s\n", doc->has_request ? "yes" : "no"); if (doc->has_request) { printf("Request: \n"); print_request(doc); printf("\n"); } printf("Universe:\n"); l = doc->packages; while (l != NULL) { pkg = (cudf_package_t) g_list_nth_data(l, 0); print_pkg(pkg); l = g_list_next(l); } g_message("Try packages -> universe conversion ..."); univ = cudf_load_universe(doc->packages); printf("Universe size: %d/%d (installed/total)\n", cudf_installed_size(univ), cudf_universe_size(univ)); printf("Universe consistent: %s\n", cudf_is_consistent(univ) ? "yes" : "no"); g_message("Freeing memory ..."); cudf_free_universe(univ); cudf_free_doc(doc); g_message("Try direct CUDF loading ..."); cudf = cudf_load_from_file(argv[1]); printf("Universe size: %d/%d (installed/total)\n", cudf_installed_size(cudf->universe), cudf_universe_size(cudf->universe)); printf("Universe consistent: %s\n", cudf_is_consistent(cudf->universe) ? "yes" : "no"); if (argc >= 3) { g_message("Loading solution %s ...", argv[2]); sol = cudf_load_solution_from_file(argv[2], cudf->universe); printf("Is solution: %s\n", cudf_is_solution(cudf, sol->universe) ? "yes" : "no"); } g_message("Freeing memory (direct loading)..."); cudf_free_cudf(sol); cudf_free_cudf(cudf); g_message("All done."); exit(0); } cudf-0.6.3/c-lib/caml_hash_variant.c000066400000000000000000000025051200672564300172450ustar00rootroot00000000000000/*****************************************************************************/ /* libCUDF - CUDF (Common Upgrade Description Format) manipulation library */ /* Copyright (C) 2009-2012 Stefano Zacchiroli */ /* */ /* This library is free software: you can redistribute it and/or modify */ /* it under the terms of the GNU Lesser General Public License as */ /* published by the Free Software Foundation, either version 3 of the */ /* License, or (at your option) any later version. A special linking */ /* exception to the GNU Lesser General Public License applies to this */ /* library, see the COPYING file for more information. */ /*****************************************************************************/ #include #include int main(int argc, char **argv) { char *shortname, *variant; if (argc == 2) { variant = argv[1]; shortname = argv[1]; } else if (argc == 3) { variant = argv[1]; shortname = argv[2]; } else { printf("Usage: hash_variant VARIANT [SHORT_NAME]\n"); exit(2); } printf("#define\tMLPVAR_%s\t(%d)\t/* caml hash for \"`%s\" */\n", shortname, Int_val(caml_hash_variant(variant)), variant); return 0; } cudf-0.6.3/c-lib/cudf-private.h000066400000000000000000000025351200672564300162030ustar00rootroot00000000000000/*****************************************************************************/ /* libCUDF - CUDF (Common Upgrade Description Format) manipulation library */ /* Copyright (C) 2009-2012 Stefano Zacchiroli */ /* */ /* This library is free software: you can redistribute it and/or modify */ /* it under the terms of the GNU Lesser General Public License as */ /* published by the Free Software Foundation, either version 3 of the */ /* License, or (at your option) any later version. A special linking */ /* exception to the GNU Lesser General Public License applies to this */ /* library, see the COPYING file for more information. */ /*****************************************************************************/ #ifndef _CUDF_PRIVATE_H #define _CUDF_PRIVATE_H /* Instantiation of OCaml-related abstract data types. To be used only libcudf implementation itself. Rationale: all use of OCaml's values from C is very subtle and should be avoided in final C applications; additionally, hiding "value" type removes the need of having OCaml C headers installed. */ typedef value *cudf_preamble_t; typedef value *cudf_request_t; typedef value *cudf_universe_t; typedef value *cudf_package_t; #endif cudf-0.6.3/c-lib/cudf.c000066400000000000000000000405661200672564300145340ustar00rootroot00000000000000/*****************************************************************************/ /* libCUDF - CUDF (Common Upgrade Description Format) manipulation library */ /* Copyright (C) 2009-2012 Stefano Zacchiroli */ /* */ /* This library is free software: you can redistribute it and/or modify */ /* it under the terms of the GNU Lesser General Public License as */ /* published by the Free Software Foundation, either version 3 of the */ /* License, or (at your option) any later version. A special linking */ /* exception to the GNU Lesser General Public License applies to this */ /* library, see the COPYING file for more information. */ /*****************************************************************************/ // TODO should check / handle exceptions for all invoked caml_callback-s // TODO better management of g_error() (not all should be fatal) // TODO property-by-property access for preamble (as per packages) #include #include #include #include #include #include #include "cudf-private.h" // instantiate OCaml-related ADTs #include "cudf-variants.h" #include "cudf.h" #define Val_none Val_int(0) #define Some_val(v) Field(v,0) /* field indexes in the return type of {!Cudf_parser.parse_from_file}, * {!Cudf_parser.load_from_file}, and {!Cudf_parser.load_solution_from_file} */ #define FIELD_PRE 0 #define FIELD_UNIV 1 // universe for load_*, package list for parse_* #define FIELD_REQ 2 // unused for load_solution_from_file /* field indexes in {!Cudf.package} */ #define FIELD_PKG 0 #define FIELD_VERSION 1 #define FIELD_DEPS 2 #define FIELD_CONFL 3 #define FIELD_PROV 4 #define FIELD_INST 5 #define FIELD_WASINST 6 #define FIELD_KEEP 7 #define FIELD_PKGEXTRA 8 /* field indexes in {!Cudf.request} */ #define FIELD_REQID 0 #define FIELD_REQINST 1 #define FIELD_REQREM 2 #define FIELD_REQUP 3 #define FIELD_REQEXTRA 4 /* field indexes in {!Cudf.preamble} */ #define FIELD_PREID 0 #define FIELD_TYPEDECL 1 #define FIELD_UCHECK 2 #define FIELD_SCHECK 3 #define FIELD_RCHECK 4 /* field indexes in the return type of {!Cudf_checker.is_solution} and * {!Cudf_checker.is_consistent} */ #define FIELD_ISSOL 0 /* Initialize a pointer to an OCaml value */ #define NEW_MLVAL(p) \ do { p = malloc(sizeof(value)); \ caml_register_global_root(p); } \ while (0) /* Free a pointer to an OCaml value */ #define FREE_MLVAL(p) \ do { free(p); \ caml_remove_global_root(p); } \ while (0) /** generic OCaml binding helpers */ #if 0 static int caml_list_length(value l) { int length = 0; while (l != Val_emptylist) { length++; l = Field(l, 1); } return length; } #endif /** CUDF-specific binding helpers */ static int relop_val(value v) { CAMLparam1(v); int op; switch (Int_val(v)) { case MLPVAR_Eq : op = RELOP_EQ ; break ; case MLPVAR_Neq : op = RELOP_NEQ ; break ; case MLPVAR_Geq : op = RELOP_GEQ ; break ; case MLPVAR_Gt : op = RELOP_GT ; break ; case MLPVAR_Leq : op = RELOP_LEQ ; break ; case MLPVAR_Lt : op = RELOP_LT ; break ; default : g_error("Internal error: unexpected variant for \"relop\": %d", Int_val(v)); } CAMLreturnT(int, op); } cudf_vpkg_t *cudf_vpkg_val(value ml_vpkg) { CAMLparam1(ml_vpkg); CAMLlocal1(ml_constr); cudf_vpkg_t *vpkg; vpkg = malloc(sizeof(cudf_vpkg_t)); vpkg->name = strdup(String_val(Field(ml_vpkg, 0))); if (Field(ml_vpkg, 1) != Val_none) { /* version constraint */ ml_constr = Some_val(Field(ml_vpkg, 1)); vpkg->relop = relop_val(Field(ml_constr, 0)); vpkg->version = Int_val(Field(ml_constr, 1)); } else { /* no version constraint */ vpkg->relop = 0; vpkg->version = -1; } CAMLreturnT(cudf_vpkg_t *, vpkg); } cudf_vpkglist_t cudf_vpkglist_val(value ml_vpkgs) { CAMLparam1(ml_vpkgs); CAMLlocal1(ml_vpkg); GList *l = NULL; cudf_vpkg_t *vpkg; while (ml_vpkgs != Val_emptylist) { ml_vpkg = Field(ml_vpkgs, 0); vpkg = cudf_vpkg_val(ml_vpkg); l = g_list_append(l, vpkg); ml_vpkgs = Field(ml_vpkgs, 1); } CAMLreturnT(cudf_vpkglist_t, l); } cudf_vpkgformula_t cudf_vpkgformula_val(value ml_fmla) { CAMLparam1(ml_fmla); CAMLlocal2(ml_and, ml_or); GList *and_l = NULL; /* top-level formula (CNF) */ GList *or_l; /* OR-ed deps */ /* ml_and: iterates over OR-ed deps (which are AND-ed together) */ /* ml_or: iterates over vpkg-s (which are OR-ed together) */ cudf_vpkg_t *vpkg; ml_and = ml_fmla; while (ml_and != Val_emptylist) { ml_or = Field(ml_and, 0); or_l = NULL; while (ml_or != Val_emptylist) { vpkg = cudf_vpkg_val(Field(ml_or, 0)); or_l = g_list_append(or_l, vpkg); ml_or = Field(ml_or, 1); } and_l = g_list_append(and_l, or_l); ml_and = Field(ml_and, 1); } CAMLreturnT(cudf_vpkgformula_t, and_l); } cudf_value_t *cudf_value_val(value ml_v) { CAMLparam1(ml_v); CAMLlocal1(ml_payload); cudf_value_t *v; int typ; v = malloc(sizeof(cudf_value_t)); typ = Int_val(Field(ml_v, 0)); ml_payload = Field(ml_v, 1); v->typ = typ; switch (typ) { case MLPVAR_Int : v->typ = TYPE_INT; v->val.i = Int_val(ml_payload); break; case MLPVAR_Posint : v->typ = TYPE_POSINT; v->val.i = Int_val(ml_payload); break; case MLPVAR_Nat : v->typ = TYPE_NAT; v->val.i = Int_val(ml_payload); break; case MLPVAR_Bool : v->typ = TYPE_BOOL; v->val.i = Bool_val(ml_payload); break; case MLPVAR_String : v->typ = TYPE_STRING; v->val.s = strdup(String_val(ml_payload)); case MLPVAR_Pkgname : v->typ = TYPE_PKGNAME; v->val.s = strdup(String_val(ml_payload)); case MLPVAR_Ident : v->typ = TYPE_IDENT; v->val.s = strdup(String_val(ml_payload)); break; case MLPVAR_Enum : v->typ = TYPE_ENUM; /* Skip enum list and jump to the actual enum. Enum list is * currently not accessible using C bindings. */ v->val.s = strdup(String_val(Field(ml_payload, 1))); break; case MLPVAR_Vpkg : v->typ = TYPE_VPKG; v->val.vpkg = cudf_vpkg_val(ml_payload); break; case MLPVAR_Veqpkg : v->typ = TYPE_VEQPKG; v->val.vpkg = cudf_vpkg_val(ml_payload); break; case MLPVAR_Vpkglist : v->typ = TYPE_VPKGLIST; v->val.vpkgs = cudf_vpkglist_val(ml_payload); break; case MLPVAR_Veqpkglist : v->typ = TYPE_VEQPKGLIST; v->val.vpkgs = cudf_vpkglist_val(ml_payload); break; case MLPVAR_Vpkgformula : v->typ = TYPE_VPKGFORMULA; v->val.f = cudf_vpkgformula_val(ml_payload); break; case MLPVAR_Typedecl : v->typ = TYPE_TYPEDECL; break; default : g_error("Internal error: unexpected variant for type: %d", typ); } CAMLreturnT(cudf_value_t *, v); } /** libCUDF binding public interface */ void cudf_init() { char *fake_argv[] = {"", NULL}; static int cudf_initialized = 0; if (cudf_initialized) return; caml_startup(fake_argv); cudf_initialized = 1; } cudf_doc_t *cudf_parse_from_file(char *fname) { CAMLparam0(); CAMLlocal2(ml_doc, ml_pkgs); static value *closure_f = NULL; cudf_doc_t *doc; GList *l = NULL; cudf_package_t pkg; doc = malloc(sizeof(cudf_doc_t)); if (closure_f == NULL) closure_f = caml_named_value("parse_from_file"); ml_doc = caml_callback(*closure_f, caml_copy_string(fname)); NEW_MLVAL(doc->preamble); /* preamble */ if (Field(ml_doc, FIELD_PRE) != Val_none) { doc->has_preamble = 1; *(doc->preamble) = Some_val(Field(ml_doc, FIELD_PRE)); } else { doc->has_preamble = 0; *(doc->preamble) = Val_none; } NEW_MLVAL(doc->request); /* request */ if (Field(ml_doc, FIELD_REQ) != Val_none) { doc->has_request = 1; *(doc->request) = Some_val(Field(ml_doc, FIELD_REQ)); } else { doc->has_request = 0; *(doc->request) = Val_none; } ml_pkgs = Field(ml_doc, FIELD_UNIV); /* packages */ while (ml_pkgs != Val_emptylist) { NEW_MLVAL(pkg); *pkg = Field(ml_pkgs, 0); l = g_list_prepend(l, pkg); ml_pkgs = Field(ml_pkgs, 1); } doc->packages = g_list_reverse(l); CAMLreturnT(cudf_doc_t *, doc); } cudf_t *cudf_load_from_file(char *fname) { CAMLparam0(); CAMLlocal1(ml_cudf); static value *closure_f = NULL; cudf_t *cudf; cudf = malloc(sizeof(cudf_t)); if (closure_f == NULL) closure_f = caml_named_value("load_from_file"); ml_cudf = caml_callback(*closure_f, caml_copy_string(fname)); NEW_MLVAL(cudf->preamble); /* preamble */ if (Field(ml_cudf, FIELD_PRE) != Val_none) { cudf->has_preamble = 1; *(cudf->preamble) = Some_val(Field(ml_cudf, FIELD_PRE)); } else { cudf->has_preamble = 0; *(cudf->preamble) = Val_none; } NEW_MLVAL(cudf->request); /* request */ if (Field(ml_cudf, FIELD_REQ) != Val_none) { cudf->has_request = 1; *(cudf->request) = Some_val(Field(ml_cudf, FIELD_REQ)); } else { cudf->has_request = 0; *(cudf->request) = Val_none; } NEW_MLVAL(cudf->universe); /* universe */ *(cudf->universe) = Field(ml_cudf, FIELD_UNIV); CAMLreturnT(cudf_t *, cudf); } cudf_t *cudf_load_solution_from_file(char *fname, cudf_universe_t ref_univ) { CAMLparam0(); CAMLlocal1(ml_cudf); static value *closure_f = NULL; cudf_t *cudf; cudf = malloc(sizeof(cudf_t)); if (closure_f == NULL) closure_f = caml_named_value("load_solution_from_file"); ml_cudf = caml_callback2(*closure_f, caml_copy_string(fname), *ref_univ); NEW_MLVAL(cudf->preamble); /* preamble */ if (Field(ml_cudf, FIELD_PRE) != Val_none) { cudf->has_preamble = 1; *(cudf->preamble) = Some_val(Field(ml_cudf, FIELD_PRE)); } else { cudf->has_preamble = 0; *(cudf->preamble) = Val_none; } NEW_MLVAL(cudf->request); /* request */ cudf->has_request = 0; /* solutions have no request */ *(cudf->request) = Val_none; NEW_MLVAL(cudf->universe); /* universe */ *(cudf->universe) = Field(ml_cudf, FIELD_UNIV); CAMLreturnT(cudf_t *, cudf); } char *cudf_pkg_name(cudf_package_t pkg) { return String_val(Field(*pkg, FIELD_PKG)); } int cudf_pkg_version(cudf_package_t pkg) { return Int_val(Field(*pkg, FIELD_VERSION)); } int cudf_pkg_installed(cudf_package_t pkg) { return Int_val(Field(*pkg, FIELD_INST)); } int cudf_pkg_was_installed(cudf_package_t pkg) { return Int_val(Field(*pkg, FIELD_WASINST)); } int cudf_pkg_keep(cudf_package_t pkg) { CAMLparam0(); CAMLlocal1(keep); int k; keep = Field(*pkg, FIELD_KEEP); switch (Int_val(keep)) { case MLPVAR_Keep_none : k = KEEP_NONE ; break ; case MLPVAR_Keep_version : k = KEEP_VERSION ; break ; case MLPVAR_Keep_package : k = KEEP_PACKAGE ; break ; case MLPVAR_Keep_feature : k = KEEP_FEATURE ; break ; default : g_error("Internal error: unexpected variant for \"keep\": %d", Int_val(keep)); } CAMLreturnT(int, k); } cudf_vpkgformula_t cudf_pkg_depends(cudf_package_t pkg) { return cudf_vpkgformula_val(Field(*pkg, FIELD_DEPS)); } cudf_vpkglist_t cudf_pkg_conflicts(cudf_package_t pkg) { return cudf_vpkglist_val(Field(*pkg, FIELD_CONFL)); } cudf_vpkglist_t cudf_pkg_provides(cudf_package_t pkg) { return cudf_vpkglist_val(Field(*pkg, FIELD_PROV)); } char *cudf_pkg_property(cudf_package_t pkg, const char *prop) { CAMLparam0(); CAMLlocal1(prop_val); static value *closure_f = NULL; if (closure_f == NULL) closure_f = caml_named_value("lookup_package_property"); prop_val = caml_callback2_exn(*closure_f, *pkg, caml_copy_string(prop)); CAMLreturnT(char *, Is_exception_result(prop_val) ? NULL : strdup(String_val(prop_val))); } char *cudf_req_property(cudf_request_t req, const char *prop) { CAMLparam0(); CAMLlocal1(prop_val); static value *closure_f = NULL; if (closure_f == NULL) closure_f = caml_named_value("lookup_request_property"); prop_val = caml_callback2_exn(*closure_f, *req, caml_copy_string(prop)); CAMLreturnT(char *, Is_exception_result(prop_val) ? NULL : strdup(String_val(prop_val))); } cudf_vpkglist_t cudf_req_install(cudf_request_t req) { return cudf_vpkglist_val(Field(*req, FIELD_REQINST)); } cudf_vpkglist_t cudf_req_remove(cudf_request_t req) { return cudf_vpkglist_val(Field(*req, FIELD_REQREM)); } cudf_vpkglist_t cudf_req_upgrade(cudf_request_t req) { return cudf_vpkglist_val(Field(*req, FIELD_REQUP)); } char *cudf_pre_property(cudf_preamble_t pre, const char *prop) { CAMLparam0(); CAMLlocal1(prop_val); static value *closure_f = NULL; if (closure_f == NULL) closure_f = caml_named_value("lookup_preamble_property"); prop_val = caml_callback2_exn(*closure_f, *pre, caml_copy_string(prop)); CAMLreturnT(char *, Is_exception_result(prop_val) ? NULL : strdup(String_val(prop_val))); } cudf_extra_t cudf_pkg_extra(cudf_package_t pkg) { CAMLparam0(); CAMLlocal2(ml_extras, ml_prop); GHashTable *h = NULL; h = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify) cudf_free_value); ml_extras = Field(*pkg, FIELD_PKGEXTRA); while (ml_extras != Val_emptylist) { ml_prop = Field(ml_extras, 0); g_hash_table_insert(h, strdup(String_val(Field(ml_prop, 0))), cudf_value_val(Field(ml_prop, 1))); ml_extras = Field(ml_extras, 1); } CAMLreturnT(cudf_extra_t, h); } /** Universe management */ cudf_universe_t cudf_load_universe(GList *packages) { CAMLparam0(); CAMLlocal2(ml_pkgs, cons); static value *closure_f = NULL; GList *l = packages; cudf_universe_t univ = NULL; ml_pkgs = Val_emptylist; while (l != NULL) { cons = caml_alloc(2, 0); Store_field(cons, 0, * (cudf_package_t) g_list_nth_data(l, 0)); Store_field(cons, 1, ml_pkgs); ml_pkgs = cons; l = g_list_next(l); } if (closure_f == NULL) closure_f = caml_named_value("load_universe"); NEW_MLVAL(univ); *univ = caml_callback(*closure_f, ml_pkgs); CAMLreturnT(cudf_universe_t, univ); } int cudf_universe_size(cudf_universe_t univ) { static value *closure_f = NULL; if (closure_f == NULL) closure_f = caml_named_value("universe_size"); return Int_val(caml_callback(*closure_f, *univ)); } int cudf_installed_size(cudf_universe_t univ) { static value *closure_f = NULL; if (closure_f == NULL) closure_f = caml_named_value("installed_size"); return Int_val(caml_callback(*closure_f, *univ)); } int cudf_is_consistent(cudf_universe_t univ) { static value *closure_f = NULL; if (closure_f == NULL) closure_f = caml_named_value("is_consistent"); return Bool_val(Field(caml_callback(*closure_f, *univ), FIELD_ISSOL)); } int cudf_is_solution(cudf_t *cudf, cudf_universe_t sol) { CAMLparam0(); CAMLlocal1(ml_cudf); static value *closure_f = NULL; if (closure_f == NULL) closure_f = caml_named_value("is_solution"); if (! cudf->has_request) g_error("Given CUDF has no request: cannot compare it with a solution."); ml_cudf = caml_alloc(2, 0); Store_field(ml_cudf, 0, *(cudf->universe)); Store_field(ml_cudf, 1, *(cudf->request)); CAMLreturnT(int, Bool_val(Field(caml_callback2(*closure_f, ml_cudf, *sol), FIELD_ISSOL))); } /** Memory management. free-like functions to free binding-specific data structures */ void cudf_free_doc(cudf_doc_t *doc) { GList *l; if (doc == NULL) return; FREE_MLVAL(doc->preamble); FREE_MLVAL(doc->request); l = doc->packages; while (l != NULL) { FREE_MLVAL(g_list_nth_data(l, 0)); l = g_list_next(l); } g_list_free(l); free(doc); } void cudf_free_cudf(cudf_t *cudf) { if (cudf == NULL) return; FREE_MLVAL(cudf->preamble); FREE_MLVAL(cudf->request); FREE_MLVAL(cudf->universe); free(cudf); } void cudf_free_universe(cudf_universe_t univ) { if (univ == NULL) return; FREE_MLVAL(univ); } void cudf_free_vpkg(cudf_vpkg_t *vpkg) { if (vpkg == NULL) return; if (vpkg->name != NULL) free(vpkg->name); free(vpkg); } void cudf_free_vpkglist(cudf_vpkglist_t vpkgs) { GList *l = vpkgs; while (l != NULL) { cudf_free_vpkg(g_list_nth_data(l, 0)); l = g_list_next(l); } g_list_free(vpkgs); } void cudf_free_vpkgformula(cudf_vpkgformula_t fmla) { GList *l = fmla; while (l != NULL) { cudf_free_vpkglist(g_list_nth_data(l, 0)); l = g_list_next(l); } g_list_free(fmla); } void cudf_free_value(cudf_value_t *v) { int typ; if (v == NULL) return; typ = v->typ; switch (typ) { case TYPE_INT : case TYPE_POSINT : case TYPE_NAT : case TYPE_BOOL : break; /* integers don't require any freeing */ case TYPE_STRING : case TYPE_PKGNAME : case TYPE_IDENT : case TYPE_ENUM : free(v->val.s); break; case TYPE_VPKG : case TYPE_VEQPKG : cudf_free_vpkg(v->val.vpkg); break; case TYPE_VPKGLIST : case TYPE_VEQPKGLIST : cudf_free_vpkglist(v->val.vpkgs); break; case TYPE_VPKGFORMULA : cudf_free_vpkgformula(v->val.f); break; case TYPE_TYPEDECL : break; default : g_error("Internal error: unexpected variant for type: %d", typ); } free(v); } void cudf_free_extra(cudf_extra_t extra) { g_hash_table_destroy(extra); } cudf-0.6.3/c-lib/cudf.h000066400000000000000000000224521200672564300145330ustar00rootroot00000000000000/*****************************************************************************/ /* libCUDF - CUDF (Common Upgrade Description Format) manipulation library */ /* Copyright (C) 2009-2012 Stefano Zacchiroli */ /* */ /* This library is free software: you can redistribute it and/or modify */ /* it under the terms of the GNU Lesser General Public License as */ /* published by the Free Software Foundation, either version 3 of the */ /* License, or (at your option) any later version. A special linking */ /* exception to the GNU Lesser General Public License applies to this */ /* library, see the COPYING file for more information. */ /*****************************************************************************/ #ifndef _CUDF_H #define _CUDF_H #include #ifndef _CUDF_PRIVATE_H /* Abstract data types. You should access them only with the functions given below. Really (or you will face the anger of OCaml GC).*/ typedef void *cudf_preamble_t; /* preamble of a CUDF document */ typedef void *cudf_request_t; /* request of a CUDF document */ typedef void *cudf_universe_t; /* package universe (i.e. all known packages) */ typedef void *cudf_package_t; /* single package from the universe */ #endif typedef GList *cudf_packages_t; /* List of CUDF packages */ typedef struct __cudf_doc { int has_preamble; /* Whether user request was provided or not */ int has_request; /* Whether request was provided or not */ cudf_preamble_t preamble; /* Preamble (iff has_preamble != 0) */ cudf_request_t request; /* User request (iff has_request != 0) */ cudf_packages_t packages; /* List of packages */ } cudf_doc_t; typedef struct __cudf { int has_preamble; /* Whether user request was provided or not */ int has_request; /* Whether request was provided or not */ cudf_preamble_t preamble; /* Preamble (iff has_preamble != 0) */ cudf_request_t request; /* User request (iff has_request != 0) */ cudf_universe_t universe; /* Abstract package universe */ } cudf_t; /* Initialization */ /* Call cudf_init() before doing anything else with libCUDF. (Or you will get a * segfault, you've been warned.) */ void cudf_init(); /* Parsing */ /* Parse a CUDF document from file, without doing any further processing. */ cudf_doc_t *cudf_parse_from_file(char *fname); /* Load a CUDF document from file, i.e. parse it and then store the contained * packages as an universe structure. * * Note: to load solutions you should prefer cudf_load_solution_from_file, * which can be invoked after CUDF document loading. */ cudf_t *cudf_load_from_file(char *fname); /* Load from file a CUDF universe representing a solution to an upgrade * scenario. Solution format is as per Appendix B of CUDF 2.0 spec * (i.e. package/version pairs, together with installation status). * * @param ref_univ is the reference universe to be used to expand package * information, usually it is the universe of the original CUDF */ cudf_t *cudf_load_solution_from_file(char *fname, cudf_universe_t ref_univ); /* Package predicate Examples: - bar ---> { name="bar" ; relop=0 ; version=UNSPECIFIED } - foo >= 2 ---> { name="foo" ; relop=RELOP_GEQ ; version=2 } */ typedef struct __cudf_vpkg { char *name; /* Package name */ int relop; /* Version constraint operator, see RELOP_* constants. 0 (i.e. RELOP_NOP) means no constraint */ int version; /* Version constraint value (iff constr != 0) */ } cudf_vpkg_t; typedef GList *cudf_vpkglist_t; /* List of cudf_vpkg */ /* Hash table mapping property names (char *) to typed values (cudf_value_t). */ typedef GHashTable *cudf_extra_t; /* List of (cudf_vpkg_t *) lists. CNF encoding: the inner lists are OR-ed, while the outer are AND-ed */ typedef GList *cudf_vpkgformula_t; /* Version comparison operators */ #define RELOP_EQ 1 /* "=" */ #define RELOP_NEQ 2 /* "!=" */ #define RELOP_GEQ 3 /* ">=" */ #define RELOP_GT 4 /* ">" */ #define RELOP_LEQ 5 /* "<=" */ #define RELOP_LT 6 /* "<" */ #define RELOP_NOP 0 /* dummy operator */ /* CUDF types */ #define TYPE_INT 1 /* type "int" */ #define TYPE_POSINT 2 /* type "posint" */ #define TYPE_NAT 3 /* type "nat" */ #define TYPE_BOOL 4 /* type "bool" */ #define TYPE_STRING 5 /* type "string" */ #define TYPE_ENUM 6 /* type "enum" (whichever enum list) */ #define TYPE_PKGNAME 7 /* type "pkgname" */ #define TYPE_IDENT 8 /* type "ident" */ #define TYPE_VPKG 9 /* type "vpkg" */ #define TYPE_VPKGFORMULA 10 /* type "vpkgformula" */ #define TYPE_VPKGLIST 11 /* type "vpkglist" */ #define TYPE_VEQPKG 12 /* type "veqpkg" */ #define TYPE_VEQPKGLIST 13 /* type "veqpkglist" */ #define TYPE_TYPEDECL 14 /* type "typedecl" */ #define TYPE_NOTYPE 0 /* dummy type */ /* Typed CUDF value */ typedef struct __cudf_value { int typ; /* CUDF type, one of the TYPE_* constants */ union { int i; char *s; cudf_vpkg_t *vpkg; cudf_vpkgformula_t f; cudf_vpkglist_t vpkgs; /* cudf_typedecl types; */ /* currently not supported */ } val; /* CUDF value depending on typ above, one of the above union field is set: typ | val field -----------------+------------------- TYPE_INT | int i TYPE_POSINT | int i TYPE_NAT | int i TYPE_BOOL | int i TYPE_STRING | char *s TYPE_ENUM | char *s TYPE_PKGNAME | char *s TYPE_IDENT | char *s TYPE_VPKG | cudf_vpkg_t *pkg TYPE_VEQPKG | cudf_vpkg_t *pkg TYPE_VPKGLIST | cudf_vpkglist_t pkgs TYPE_VEQPKGLIST | cudf_vpkglist_t pkgs TYPE_VPKGFORMULA | cudf_vpkgformula_t f TYPE_TYPEDECL | cudf_typedecl_t types */ } cudf_value_t; /* Macros for accessing cudf_package values */ /* Get package name of a cudf_pkg */ char *cudf_pkg_name(cudf_package_t pkg); /* Get package version of a cudf_pkg */ int cudf_pkg_version(cudf_package_t pkg); /* Get (current) installation status of a cudf_pkg */ int cudf_pkg_installed(cudf_package_t pkg); /* Get (past) installation status of a cudf_pkg */ int cudf_pkg_was_installed(cudf_package_t pkg); /* Possible values returned by cudf_pkg_keep() */ #define KEEP_NONE 0 /* keep: none */ #define KEEP_VERSION 1 /* keep: version */ #define KEEP_PACKAGE 2 /* keep: package */ #define KEEP_FEATURE 3 /* keep: feature */ /* Get "keep" property from a cudf_pkg. See KEEP_* macros */ int cudf_pkg_keep(cudf_package_t pkg); /* Get dependencies of a package */ cudf_vpkgformula_t cudf_pkg_depends(cudf_package_t pkg); /* Get conflicts of a package */ cudf_vpkglist_t cudf_pkg_conflicts(cudf_package_t pkg); /* Get provided features of a package */ cudf_vpkglist_t cudf_pkg_provides(cudf_package_t pkg); /* Get extra properties of a package. */ cudf_extra_t cudf_pkg_extra(cudf_package_t pkg); /* Lookup package property by name. Returned string should be manually freed. Return NULL if the property is missing (and has no default value). */ char *cudf_pkg_property(cudf_package_t pkg, const char *prop); /* Lookup request property by name. Returned string should be manually freed. Return NULL if the property is missing (and has no default value). */ char *cudf_req_property(cudf_request_t req, const char *prop); /* Get install section of the request. */ cudf_vpkglist_t cudf_req_install(cudf_request_t req) ; /* Get upgrade section of the request. */ cudf_vpkglist_t cudf_req_upgrade(cudf_request_t req) ; /* Get remove section of the request. */ cudf_vpkglist_t cudf_req_remove(cudf_request_t req) ; /* Lookup preamble property by name. Returned string should be manually freed. Return NULL if the property is missing (and has no default value). */ char *cudf_pre_property(cudf_preamble_t pre, const char *prop); /* Universe management */ /* @param packages list of (pointers to) cudf_package-s; the packages member of a cudf_doc structure is a suitable value @return a freshly allocated universe, which should be freed when no longer needed using cudf_free_universe */ cudf_universe_t cudf_load_universe(GList *packages); /* Return the number of packages in the given universe. */ int cudf_universe_size(cudf_universe_t univ); /* Return the number of installed packages in the given universe. */ int cudf_installed_size(cudf_universe_t univ); /* Check whether the package status of the given universe is consistent * (i.e. dependencies and conflicts or all installed packages are * respected). */ int cudf_is_consistent(cudf_universe_t univ); /* Check whether the given universe contains a proper solution for the given * CUDF (i.e. its package status is consistent and satisfies user request). * * Solution should normally be obtained via cudf_load_solution_from_file(), and * passing cudf->universe to it, e.g.: * * cudf = cudf_load_from_file(...); * sol = cudf_load_solution_from_file(..., cudf->universe); * ok = is_solution(cudf, sol); */ int cudf_is_solution(cudf_t *cudf, cudf_universe_t solution); /* Memory management */ void cudf_free_doc(cudf_doc_t *doc); void cudf_free_cudf(cudf_t *cudf); void cudf_free_universe(cudf_universe_t univ); void cudf_free_vpkg(cudf_vpkg_t *vpkg); void cudf_free_vpkglist(cudf_vpkglist_t l); void cudf_free_vpkgformula(cudf_vpkgformula_t fmla); void cudf_free_value(cudf_value_t *val); void cudf_free_extra(cudf_extra_t extra); #endif /* end of cudf.h */ cudf-0.6.3/c-lib/cudf.pc.in000066400000000000000000000004411200672564300153050ustar00rootroot00000000000000libdir=@LIBDIR@ includedir=@INCDIR@ datarootdir=/usr/share datadir=${datarootdir} ocaml_libdir=@OCAMLLIBDIR@ Name: CUDF Description: access descriptions of package upgrade problems Version: @VERSION@ Requires: glib-2.0 Libs: -L${libdir} -L${ocaml_libdir} -lcudf -lm -ldl -lunix -lncurses cudf-0.6.3/cudf.ml000066400000000000000000000203711200672564300137240ustar00rootroot00000000000000(*****************************************************************************) (* libCUDF - CUDF (Common Upgrade Description Format) manipulation library *) (* Copyright (C) 2009-2012 Stefano Zacchiroli *) (* *) (* This library is free software: you can redistribute it and/or modify *) (* it under the terms of the GNU Lesser General Public License as *) (* published by the Free Software Foundation, either version 3 of the *) (* License, or (at your option) any later version. A special linking *) (* exception to the GNU Lesser General Public License applies to this *) (* library, see the COPYING file for more information. *) (*****************************************************************************) open ExtLib open Printf open Cudf_types open Cudf_types_pp exception Constraint_violation of string type package = { package : pkgname ; version : version ; depends : vpkgformula ; conflicts : vpkglist ; provides : veqpkglist ; installed : bool ; was_installed : bool ; keep : enum_keep ; pkg_extra : typed_value stanza ; } type request = { request_id : string ; install : vpkglist ; remove : vpkglist ; upgrade : vpkglist ; req_extra : typed_value stanza ; } type preamble = { preamble_id : string ; property : typedecl ; univ_checksum: string ; status_checksum: string ; req_checksum: string ; } type cudf_doc = preamble option * package list * request type cudf_item = [ `Preamble of preamble | `Package of package | `Request of request ] type universe = { id2pkg: ((string * int), package) Hashtbl.t; (** -> pkg *) name2pkgs: (string, package) Hashtbl.t; (** name -> pkg (multi-bindings) *) uid2pkgs: (int, package) Hashtbl.t; (** int uid -> pkg *) id2uid: ((pkgname * version), int) Hashtbl.t; (** -> int uid *) features: (string, (package * version option)) Hashtbl.t; (** feature -> avail feature versions (multi-bindings) Each available feature is reported as a pair , where owner is the package providing it. Provided version "None" means "all possible versions" *) mutable univ_size : int; mutable inst_size : int; } type cudf = preamble * universe * request type solution = preamble * universe let universe_size univ = univ.univ_size let installed_size univ = univ.inst_size let (=%) pkg1 pkg2 = pkg1.package = pkg2.package && pkg1.version = pkg2.version let (<%) pkg1 pkg2 = Pervasives.compare (pkg1.package, pkg1.version) (pkg2.package, pkg2.version) let (>%) pkg1 pkg2 = Pervasives.compare (pkg2.package, pkg2.version) (pkg1.package, pkg1.version) let default_preamble = { preamble_id = "" ; property = [] ; univ_checksum = "" ; status_checksum = "" ; req_checksum = "" ; } let default_package = { package = "" ; version = 0 ; depends = [] ; conflicts = [] ; provides = [] ; installed = false ; was_installed = false ; keep = `Keep_none ; pkg_extra = [] ; } let default_request = { request_id = "" ; install = [] ; remove = [] ; upgrade = [] ; req_extra = [] ; } let empty_universe () = { id2pkg = Hashtbl.create 1023 ; uid2pkgs = Hashtbl.create 1023; id2uid = Hashtbl.create 1023; name2pkgs = Hashtbl.create 1023 ; features = Hashtbl.create 1023 ; univ_size = 0 ; inst_size = 0 ; } (** process all features (i.e., Provides) provided by a given package and fill with them a given feature table *) let expand_features pkg features = List.iter (function | name, None -> Hashtbl.add features name (pkg, None) | name, Some (_, ver) -> Hashtbl.add features name (pkg, (Some ver))) pkg.provides let load_universe pkgs = let univ = empty_universe () in let uid = ref 0 in List.iter (fun pkg -> let id = pkg.package, pkg.version in Hashtbl.add univ.uid2pkgs !uid pkg; Hashtbl.add univ.id2uid id !uid; incr uid; if Hashtbl.mem univ.id2pkg id then raise (Constraint_violation (sprintf "duplicate package: <%s, %d>" pkg.package pkg.version)); Hashtbl.add univ.id2pkg id pkg; Hashtbl.add univ.name2pkgs pkg.package pkg; expand_features pkg univ.features; univ.univ_size <- univ.univ_size + 1; if pkg.installed then univ.inst_size <- univ.inst_size + 1) pkgs; univ let package_by_uid univ = Hashtbl.find univ.uid2pkgs let uid_by_package univ pkg = Hashtbl.find univ.id2uid (pkg.package, pkg.version) let lookup_package univ = Hashtbl.find univ.id2pkg let mem_package univ = Hashtbl.mem univ.id2pkg let iter_packages f univ = Hashtbl.iter (fun _id pkg -> f pkg) univ.id2pkg let iteri_packages f univ = Hashtbl.iter (fun _id pkg -> f _id pkg) univ.uid2pkgs let fold_packages f init univ = Hashtbl.fold (fun _id pkg acc -> f acc pkg) univ.id2pkg init let get_packages ?filter univ = match filter with | None -> fold_packages (fun acc pkg -> pkg :: acc) [] univ | Some test -> fold_packages (fun acc pkg -> if test pkg then pkg :: acc else acc) [] univ let (|=) v = function | None -> true | Some (`Eq, v') -> v = v' | Some (`Neq, v') -> v <> v' | Some (`Geq, v') -> v >= v' | Some (`Gt, v') -> v > v' | Some (`Leq, v') -> v <= v' | Some (`Lt, v') -> v < v' let version_matches = (|=) let status univ = let univ' = empty_universe () in Hashtbl.iter (fun id pkg -> match pkg with | { installed = true } -> Hashtbl.add univ'.id2pkg id pkg; Hashtbl.add univ'.name2pkgs pkg.package pkg; expand_features pkg univ'.features | _ -> ()) univ.id2pkg; univ'.inst_size <- univ.inst_size; univ'.univ_size <- univ.inst_size; (* as we filtered on installed pkgs *) univ' let lookup_packages ?(filter=None) univ pkgname = let packages = Hashtbl.find_all univ.name2pkgs pkgname in match filter with None -> packages | Some _ as pred -> List.filter (fun p -> p.version |= pred) packages let get_installed univ pkgname = List.filter (fun { installed = i } -> i) (lookup_packages univ pkgname) let mem_installed ?(include_features = true) ?(ignore = fun _ -> false) univ (name, constr) = let pkg_filter = fun pkg -> not (ignore pkg) in let mem_feature constr = let feats = Hashtbl.find_all univ.features name in List.exists (function | owner_pkg, _ when not owner_pkg.installed -> false | owner_pkg, None -> pkg_filter owner_pkg | owner_pkg, Some v -> pkg_filter owner_pkg && v |= constr) feats in let pkgs = List.filter pkg_filter (get_installed univ name) in List.exists (fun pkg -> pkg.version |= constr) pkgs || (include_features && mem_feature constr) let who_provides ?(installed=true) univ (pkgname, constr) = List.filter (function |pkg , _ when not pkg.installed && installed -> false |_, None -> true | _, Some v -> v |= constr ) (Hashtbl.find_all univ.features pkgname) let lookup_typed_package_property pkg = function | "package" -> `Pkgname pkg.package | "version" -> `Posint pkg.version | "depends" -> `Vpkgformula pkg.depends | "conflicts" -> `Vpkglist pkg.conflicts | "provides" -> `Veqpkglist pkg.provides | "installed" -> `Bool pkg.installed | "keep" -> `Enum (keep_enums, string_of_keep pkg.keep) | prop_name -> List.assoc prop_name pkg.pkg_extra let lookup_typed_request_property req = function | "request" -> `String req.request_id | "install" -> `Vpkglist req.install | "remove" -> `Vpkglist req.remove | "upgrade" -> `Vpkglist req.upgrade | prop_name -> List.assoc prop_name req.req_extra let lookup_typed_preamble_property pre = function | "preamble" -> `String pre.preamble_id | "property" -> `Typedecl pre.property | "univ-checksum" -> `String pre.univ_checksum | "status-checksum" -> `String pre.status_checksum | "req-checksum" -> `String pre.req_checksum | _ -> raise Not_found let lookup_package_property pkg prop = string_of_value (lookup_typed_package_property pkg prop) let lookup_request_property req prop = string_of_value (lookup_typed_request_property req prop) let lookup_preamble_property pre prop = string_of_value (lookup_typed_preamble_property pre prop) let lookup_package_typedecl ?(extra = []) prop = List.assoc prop (Cudf_conf.package_typedecl @ extra) cudf-0.6.3/cudf.mli000066400000000000000000000226271200672564300141030ustar00rootroot00000000000000(*****************************************************************************) (* libCUDF - CUDF (Common Upgrade Description Format) manipulation library *) (* Copyright (C) 2009-2012 Stefano Zacchiroli *) (* *) (* This library is free software: you can redistribute it and/or modify *) (* it under the terms of the GNU Lesser General Public License as *) (* published by the Free Software Foundation, either version 3 of the *) (* License, or (at your option) any later version. A special linking *) (* exception to the GNU Lesser General Public License applies to this *) (* library, see the COPYING file for more information. *) (*****************************************************************************) (** CUDF library *) open Cudf_types (** {6 CUDF documents} *) (** Representation of a parsed package description item. With this representation, optional properties have already been expanded to their default values (if they have one). It is not possible to know whether they were present or not in the CUDF syntax. *) type package = { package : pkgname ; version : version ; depends : vpkgformula ; (* default : [] *) conflicts : vpkglist ; (* default : [] *) provides : veqpkglist ; (* default : [] *) installed : bool ; (* default : false *) was_installed : bool ; (* default : false *) keep : enum_keep ; (* default : `Keep_none *) pkg_extra : typed_value stanza ; (* extra properties *) } (** package equality up to i.e. 2 packages are equal iff they have the same name and version *) val (=%) : package -> package -> bool (** Package comparison up to . Same rules of package equality, but providing a suitable replacement for [Pervasives.compare]; useful for sorting. *) val (<%) : package -> package -> int (** Same as {!Cudf.(<%)}, but sort with greater versions first. *) val (>%) : package -> package -> int type request = { request_id : string ; (* default : "" *) install : vpkglist ; (* default : [] *) remove : vpkglist ; (* default : [] *) upgrade : vpkglist ; (* default : [] *) req_extra : typed_value stanza ; (* default : [] *) } type preamble = { preamble_id : string ; (** text following the "preamble: " postmark *) property : typedecl ; (** extra property declarations *) univ_checksum: string ; (** universe checksum *) status_checksum: string ; (** status checksum *) req_checksum: string ; (** request checksum *) } val default_preamble : preamble (** implement preamble defaults *) val default_package : package (** implement package defaults *) val default_request : request (** implement request defaults *) (** {6 Syntactic CUDF representation} *) (** a CUDF document with its information items *) type cudf_doc = preamble option * package list * request (** a single information item *) type cudf_item = [ `Preamble of preamble | `Package of package | `Request of request ] (** {6 Semantic CUDF representation} *) (** violation of a constraint imposed by CUDF specification @param msg explanation of which constraint has been violated *) exception Constraint_violation of string (** package universe (including package status, i.e., installed packages) *) type universe type cudf = preamble * universe * request (** CUDF-based encoding of solutions, see CUDF 2.0, appendix B A universe encoding a solution matters only for its [installed] packages, which are considered to be the resulting package status *) type solution = preamble * universe (** @raise Constraint_violation when a global CUDF constraint is violated in the given package list *) val load_universe : package list -> universe (** {5 CUDF manipulation} *) (** Lookup a specific package via a key @raise Not_found if the requested package cannot be found *) val lookup_package : universe -> pkgname * version -> package (** Check existence of a specific package in the universe via a key *) val mem_package : universe -> pkgname * version -> bool (** check wheather a given package constraint is satisfied in a given package status (i.e., the universe subset of [installed] packages) @param include_features allow constraint to be satisfied by features (i.e., Provides). Default: true @param ignore make the lookup skip over all packages matching the given package predicate. Default: do not ignore any package *) val mem_installed : ?include_features: bool -> ?ignore:(package -> bool) -> universe -> vpkg -> bool (** Ask who provides a given feature (predicate). @param installed : consider only installed packages (default) @return a list of packages providing the requested feature. Each package is paired with an optional version; if it is None, the given package provides all possible version of the feature; it if is Some v, the given package only provides version [v] of the feature. *) val who_provides : ?installed:bool -> universe -> vpkg -> (package * version option) list (** lookup all available versions of a given package name @param filter filter the found packages according to the given version constraint. Default: None (i.e., no filtering) *) val lookup_packages : ?filter:constr -> universe -> pkgname -> package list (** lookup all installed versions of a given package name. Shorthand for [lookup_packages] composed with filtering on installed=true *) val get_installed : universe -> pkgname -> package list (** return a unique integer identifier for the given package in the universe @raise Not_found if the given package cannot be found in the universe *) val uid_by_package : universe -> package -> int (** return the package corresponding to the given unique identifier @raise Not_found if no package in the universe corresponds to the given unique identifier *) val package_by_uid : universe -> int -> package (** iter over all packages in the universe *) val iter_packages : (package -> unit) -> universe -> unit (** fold over all packages in the universe *) val fold_packages : ('a -> package -> 'a) -> 'a -> universe -> 'a (** iter on all packages in the universe, passing to the iteration function both the package and its unique identifier *) val iteri_packages : (int -> package -> unit) -> universe -> unit (** conversion from universe to plain package list @param filter only return packages matching a given predicate. Default is to return all packages *) val get_packages : ?filter:(package -> bool) -> universe -> package list (** total numer of available packages (no matter whether they are installed or not) *) val universe_size : universe -> int (** total number of installed packages occurring in the universe *) val installed_size : universe -> int (** Projection on packages having "installed: true". Inefficient (involves Hashtbl.t cloning), use with care. *) val status : universe -> universe (** {5 Low-level stanza manipulation} *) (** low-level property lookup: given a package, lookup on it a property by name, returning its (pretty-printed, see {!Cudf_types}) value as a string @param pkg package to be inspected @param property property name to be lookup (case-sensitive) @raise Not_found if the given property name is not associated to the given package (note that "being associated with" does not necessarily mean that the property appears in the stanza, due to default values) *) val lookup_package_property : package -> string -> string (** Same as {!Cudf.lookup_package_property}, but acting on request information items. To lookup the request identifier as a string (which strictly speaking is not a property) you should lookup "request" *) val lookup_request_property : request -> string -> string (** Same as {!Cudf.lookup_package_property}, but acting on preamble information items. To lookup the preamble identifier as a string (which strictly speaking is not a property) you should lookup "preamble" *) val lookup_preamble_property : preamble -> string -> string (** Same as {!Cudf.lookup_package_property}, but return a typed value. *) val lookup_typed_package_property : package -> string -> typed_value (** Same as {!Cudf.lookup_request_property}, but return a typed value. *) val lookup_typed_request_property : request -> string -> typed_value (** Same as {!Cudf.lookup_preamble_property}, but return a typed value. *) val lookup_typed_preamble_property : preamble -> string -> typed_value (** lookup the type declaration of a given property (either core or extra) @param extras if given, list of extra package properties to consider when looking for the type declaration. When not given, which is the default, the lookup is performed only among core package properties Note: [lookup_typedecl name] is not the same as [List.assoc preamble.property name]; only the former takes into account core package properties. See also {!Cudf_conf.package_typedecl}. @raise Not_found if no declaration could be found for the given property *) val lookup_package_typedecl : ?extra:typedecl -> string -> typedecl1 (** Check whether a version matches a version constraint, e.g. [version_matches 1 (Some(`Eq, 2)) = false] *) val version_matches : version -> constr -> bool (** Same as {!Cudf.version_matches} *) val ( |= ) : version -> constr -> bool cudf-0.6.3/cudf.mllib000066400000000000000000000002161200672564300144070ustar00rootroot00000000000000Cudf_types Cudf_conf Cudf_822_parser Cudf_type_parser Cudf_types_pp Cudf_822_lexer Cudf_type_lexer Cudf Cudf_parser Cudf_checker Cudf_printer cudf-0.6.3/cudf.odocl000066400000000000000000000001161200672564300144070ustar00rootroot00000000000000Cudf_types Cudf_conf Cudf_types_pp Cudf Cudf_parser Cudf_checker Cudf_printer cudf-0.6.3/cudf.spec000066400000000000000000000065021200672564300142460ustar00rootroot00000000000000Summary: CUDF (Common Upgradeability Description Format) tools and libraries Name: cudf Version: 0.6 Release: 1 Source: http://gforge.info.ucl.ac.be/frs/?group_id=35 URL: http://www.mancoosi.org/cudf/ License: LGPL Group: Development/Libraries BuildRequires: ocaml ocaml-findlib ocaml-camlp4-devel ocaml-extlib-devel BuildRoot: %{_tmppath}/%{name}-root %description CUDF (for Common Upgradeability Description Format) is a format for describing upgrade scenarios in package-based Free and Open Source Software distribution. libCUDF is a library to manipulate so called CUDF documents. A CUDF document describe an upgrade problem, as faced by package managers in popular package-based GNU/Linux distributions. %package tools Summary: CUDF (Common Upgradeability Description Format) command-line tools %description tools CUDF (for Common Upgradeability Description Format) is a format for describing upgrade scenarios in package-based Free and Open Source Software distribution. libCUDF is a library to manipulate so called CUDF documents. A CUDF document describe an upgrade problem, as faced by package managers in popular package-based GNU/Linux distributions. This package contains command line tools to manipulate CUDF and related documents. In particular it contains cudf-check, which enables checking of document properties such as installation consistency and matching of problems with their solutions. %package devel Summary: CUDF (Common Upgradeability Description Format) C development stuff %description devel CUDF (for Common Upgradeability Description Format) is a format for describing upgrade scenarios in package-based Free and Open Source Software distribution. libCUDF is a library to manipulate so called CUDF documents. A CUDF document describe an upgrade problem, as faced by package managers in popular package-based GNU/Linux distributions. This package contains the development stuff needed to use libCUDF in your C programs. %package ocaml-devel Summary: CUDF (Common Upgradeability Description Format) OCaml development stuff %description ocaml-devel CUDF (for Common Upgradeability Description Format) is a format for describing upgrade scenarios in package-based Free and Open Source Software distribution. libCUDF is a library to manipulate so called CUDF documents. A CUDF document describe an upgrade problem, as faced by package managers in popular package-based GNU/Linux distributions. This package contains the development stuff needed to use libCUDF in your OCaml programs. %prep %setup -q %build make all c-lib which /usr/bin/ocamlopt > /dev/null && make opt c-lib-opt %install rm -rf "$RPM_BUILD_ROOT" make install \ DESTDIR="$RPM_BUILD_ROOT" \ LIBDIR="%{_libdir}" \ OCAMLLIBDIR="%{_libdir}/ocaml" %check make test %clean rm -rf "$RPM_BUILD_ROOT" %files tools %defattr(-,root,root) %{_bindir}/cudf-check %{_bindir}/cudf-parse-822 %files devel %defattr(-,root,root) %{_includedir}/cudf.h %{_libdir}/*.a %{_libdir}/pkgconfig/cudf.pc %files ocaml-devel %defattr(-,root,root) %{_libdir}/ocaml/cudf %changelog * Tue Dec 22 2009 Stefano Zacchiroli - use default rpm installation paths (in particular, /usr/lib64 on x86_64) * Sat Dec 19 2009 Stefano Zacchiroli - various adjustments (deps, description, native code, ...) * Fri Dec 18 2009 Jeff Johnson - create. cudf-0.6.3/cudf_822_lexer.mll000066400000000000000000000037161200672564300156760ustar00rootroot00000000000000(*****************************************************************************) (* libCUDF - CUDF (Common Upgrade Description Format) manipulation library *) (* Copyright (C) 2009-2012 Stefano Zacchiroli *) (* *) (* This library is free software: you can redistribute it and/or modify *) (* it under the terms of the GNU Lesser General Public License as *) (* published by the Free Software Foundation, either version 3 of the *) (* License, or (at your option) any later version. A special linking *) (* exception to the GNU Lesser General Public License applies to this *) (* library, see the COPYING file for more information. *) (*****************************************************************************) (** Lexer for CUDF 822 surface syntax *) { open Cudf_types open Cudf_822_parser let get_range { Lexing.lex_start_p = start_pos; Lexing.lex_curr_p = end_pos } = (start_pos, end_pos) (* Lexing.new_line is only available in OCaml 3.11 or greater *) (* let lexing_new_line = Lexing.new_line *) let lexing_new_line lexbuf = let lcp = lexbuf.Lexing.lex_curr_p in lexbuf.Lexing.lex_curr_p <- { lcp with Lexing.pos_lnum = lcp.Lexing.pos_lnum + 1; Lexing.pos_bol = lcp.Lexing.pos_cnum; } } let lower_letter = [ 'a' - 'z' ] let digit = [ '0' - '9' ] let blank = [ ' ' '\t' ] let ident = lower_letter (lower_letter | digit | '-')* rule token_822 = parse | (ident as field) ':' ' ' ([^'\n']* as rest) { FIELD(field, (get_range lexbuf, rest)) } | ' ' ([^'\n']* as rest) { CONT(get_range lexbuf, rest) } | '#' [^'\n']* ('\n'|eof) { token_822 lexbuf } | blank* '\n' { lexing_new_line lexbuf; EOL } | eof { EOF } | _ { raise (Parse_error_822 ("unexpected RFC 822 token", (lexbuf.Lexing.lex_start_p, lexbuf.Lexing.lex_curr_p))) } cudf-0.6.3/cudf_822_parser.mly000066400000000000000000000051431200672564300160640ustar00rootroot00000000000000/*****************************************************************************/ /* libCUDF - CUDF (Common Upgrade Description Format) manipulation library */ /* Copyright (C) 2009-2012 Stefano Zacchiroli */ /* */ /* This library is free software: you can redistribute it and/or modify */ /* it under the terms of the GNU Lesser General Public License as */ /* published by the Free Software Foundation, either version 3 of the */ /* License, or (at your option) any later version. A special linking */ /* exception to the GNU Lesser General Public License applies to this */ /* library, see the COPYING file for more information. */ /*****************************************************************************/ /* RFC822-like parser: surface parser for CUDF stanzas This parser handle the surface syntax of CUDF documents: it recognizes RFC822 stanzas, folds together line continuations, and throws away comments and empty lines */ %{ open ExtLib exception Dup_stanza let join (r1, v) (r2, cont) = Cudf_types.extend_loc r1 r2, v ^ cont %} %token FIELD %token CONT %token EOL EOF %type <(string * (Cudf_types.loc * string)) list list> doc_822 %type <(string * (Cudf_types.loc * string)) list option> stanza_822 %start doc_822 stanza_822 %% doc_822: | stanzas { $1 } | eols stanzas { $2 } ; stanza_822: | stanza { Some $1 } | eols stanza { Some $2 } | eols EOF { None } | EOF { None } ; eols: | EOL {} | EOL eols {} ; stanzas: | { [] } | stanza EOF { [ $1 ] } | stanza eols stanzas { $1 :: $3 } ; stanza: | fields { let keys = List.map fst $1 in (* check for re-defined keys *) if List.length (List.unique keys) < List.length keys then raise Dup_stanza else $1 } ; fields: | field { [ $1 ] } | field fields { $1 :: $2 } ; field: | FIELD EOL { $1 } | FIELD EOL linecont { let k, v = $1 in k, (join v $3) } ; linecont: | CONT EOL { $1 } | CONT EOL linecont { join $1 $3 } ; %% let error_wrapper f = fun lexer lexbuf -> try f lexer lexbuf with | Parsing.Parse_error -> raise (Cudf_types.Parse_error_822 ("RFC 822 (stanza structure) parse error", Cudf_types.loc_of_lexbuf lexbuf)) | Dup_stanza -> raise (Cudf_types.Parse_error_822 ("duplicate keys in stanza", Cudf_types.loc_of_lexbuf lexbuf)) let doc_822 = error_wrapper doc_822 let stanza_822 = error_wrapper stanza_822 cudf-0.6.3/cudf_c.ml000066400000000000000000000032141200672564300142230ustar00rootroot00000000000000(*****************************************************************************) (* libCUDF - CUDF (Common Upgrade Description Format) manipulation library *) (* Copyright (C) 2009-2012 Stefano Zacchiroli *) (* *) (* This library is free software: you can redistribute it and/or modify *) (* it under the terms of the GNU Lesser General Public License as *) (* published by the Free Software Foundation, either version 3 of the *) (* License, or (at your option) any later version. A special linking *) (* exception to the GNU Lesser General Public License applies to this *) (* library, see the COPYING file for more information. *) (*****************************************************************************) let () = Callback.register "parse_from_file" (Cudf_parser.parse_from_file ?typedecl:None); Callback.register "load_from_file" (Cudf_parser.load_from_file ?typedecl:None); Callback.register "load_solution_from_file" Cudf_parser.load_solution_from_file; Callback.register "lookup_package_property" Cudf.lookup_package_property; Callback.register "lookup_request_property" Cudf.lookup_request_property; Callback.register "lookup_preamble_property" Cudf.lookup_preamble_property; Callback.register "universe_size" Cudf.universe_size; Callback.register "installed_size" Cudf.installed_size; Callback.register "is_consistent" Cudf_checker.is_consistent; Callback.register "is_solution" Cudf_checker.is_solution; Callback.register "load_universe" Cudf.load_universe; cudf-0.6.3/cudf_checker.ml000066400000000000000000000153531200672564300154140ustar00rootroot00000000000000(*****************************************************************************) (* libCUDF - CUDF (Common Upgrade Description Format) manipulation library *) (* Copyright (C) 2009-2012 Stefano Zacchiroli *) (* *) (* This library is free software: you can redistribute it and/or modify *) (* it under the terms of the GNU Lesser General Public License as *) (* published by the Free Software Foundation, either version 3 of the *) (* License, or (at your option) any later version. A special linking *) (* exception to the GNU Lesser General Public License applies to this *) (* library, see the COPYING file for more information. *) (*****************************************************************************) open ExtLib open Printf open Cudf_types open Cudf module PP = Cudf_types_pp let (!!) pred = fun x -> not (pred x) type inconsistency_reason = [ `Unsat_dep of (pkgname * version) * vpkgformula | `Conflict of (pkgname * version) * vpkglist ] type bad_solution_reason = [ inconsistency_reason | `Missing_install of vpkglist | `Missing_upgrade of vpkglist | `Unremoved of vpkglist | `Downgrade of vpkglist | `Multi_upgrade of pkgname list | `Not_kept of pkgname * version * enum_keep ] let explain_reason = function | `Unsat_dep ((name, ver), fmla) -> sprintf "Cannot satisfy dependencies %s of package %s (version %d)" (PP.string_of_vpkgformula fmla) name ver | `Conflict ((name, ver), pkgs) -> sprintf "Unresolved conflicts %s of package %s (version %d)" (PP.string_of_vpkglist pkgs) name ver | `Missing_install vpkgs -> "Unmet installation request, missing packages: " ^ PP.string_of_vpkglist vpkgs | `Missing_upgrade vpkgs -> "Unmet upgrade request, missing packages: " ^ PP.string_of_vpkglist vpkgs | `Unremoved vpkgs -> "Unmet remove request, still present packages: " ^ PP.string_of_vpkglist vpkgs | `Downgrade vpkgs -> "Unmet upgrade request, not-upgraded: " ^ PP.string_of_vpkglist vpkgs | `Multi_upgrade pkgs -> "Unmet upgrade request, not-unique: " ^ String.concat ", " pkgs | `Not_kept (name, ver, keep) -> sprintf "Unmet \"Keep\" request %s of package %s (version %d)" (PP.string_of_keep keep) name ver (* XXX not tail-recursive *) let satisfy_formula univ fmla = let reason = ref [] in let sat_pkg = mem_installed ~include_features:true univ in let sat = match List.filter (!! (List.exists sat_pkg)) fmla with [] -> true | unsat -> reason := unsat ; false in sat, !reason let disjoint univ ?ignore pkgs = match List.filter (mem_installed ?ignore ~include_features:true univ) pkgs with | [] -> true, [] | pkgs -> false, pkgs let is_consistent univ = let msg = ref None in try iter_packages (fun pkg -> if pkg.installed then begin (match satisfy_formula univ pkg.depends with false, fmla -> msg := Some (`Unsat_dep ((pkg.package, pkg.version), fmla)); raise Exit | _ -> ()); (match disjoint univ ~ignore:((=%) pkg) pkg.conflicts with | false, pkgs -> msg := Some (`Conflict ((pkg.package, pkg.version), pkgs)); raise Exit | _ -> ()); end) univ; true, !msg with Exit -> false, !msg (* for reference, see CUDF §2.3.4, "semantics of requests" *) let is_solution (univ, req) sol = let _ = if universe_size sol <> installed_size sol then prerr_endline ("WARNING: solution contains not-installed packages," ^ " they have been ignored") in let sat vpkg = fst (satisfy_formula sol [[vpkg]]) in let and_formula = List.map (fun vpkg -> [(vpkg :> vpkg)]) in let is_succ () = (* XXX not implemented, as it will be pointless with a diff-like encoding of solutions *) true, [] in let is_cons () = (* check solution consistency (i.e., dep./conflicts) *) match is_consistent sol with | true, _ -> true, [] | false, None -> assert false | false, Some reason -> false, [reason] in let install_ok () = (* check "Install" property semantics *) match List.filter (!! sat) req.install with | [] -> true, [] | l -> false, [`Missing_install l] in let remove_ok () = (* check "Remove" property semantics *) match disjoint sol req.remove with | true, _ -> true, [] | false, pkgs -> false, [`Unremoved pkgs] in let upgrade_ok () = (* check "Upgrade" property semantics *) match List.filter (!! sat) req.upgrade with | (_ :: _) as l -> false, [`Missing_upgrade l] | [] -> let versions_of univ name = List.map (* real packages *) (fun pkg -> Some pkg.version) (get_installed univ name) @ List.map (* virtual packages; "None" means "all versions" *) (fun (_pkg, version) -> version) (who_provides univ (name, None)) in let res = List.fold_left (fun (ok, downgrades, multi) ((name, _constr) as vpkg) -> match versions_of sol name with | [Some v] -> let old_installed = versions_of univ name in if not (List.for_all (function Some v' -> v' <= v | None -> false) (* XXX: this None will report attempted upgrade of unversioned virtual packages as downgrades. Maybe right, maybe not *) old_installed) then false, vpkg :: downgrades, multi else true && ok, downgrades, multi | [] -> (* impossible: cause the formula is satisfied *) assert false | _ -> false, downgrades, name :: multi) (true, [], []) req.upgrade in (match res with | true, _, _ -> true, [] | false, downgrades, multi -> false, (if downgrades <> [] then [`Downgrade downgrades] else []) @ (if multi <> [] then [`Multi_upgrade multi] else [])) in let keep_ok () = (* check "Keep" property semantics *) let to_be_kept = get_packages ~filter:(fun pkg -> pkg.installed && pkg.keep <> `Keep_none) univ in List.fold_left (fun (ok, reasons) pkg -> let pkg_ok = match pkg.keep with | `Keep_version -> (try (lookup_package sol (pkg.package, pkg.version)).installed with Not_found -> false) | `Keep_package -> mem_installed ~include_features:false sol (pkg.package, None) | `Keep_feature -> fst (satisfy_formula sol (and_formula pkg.provides)) | _ -> assert false (* [get_packages ~filter] is broken *) in if pkg_ok then ok, reasons else false, (`Not_kept (pkg.package, pkg.version, pkg.keep)) :: reasons) (true, []) to_be_kept in List.fold_left (fun (is_sol, msgs) test -> let res, msg = test () in res && is_sol, msg @ msgs) (true, []) [is_succ; is_cons; install_ok; remove_ok; upgrade_ok; keep_ok] cudf-0.6.3/cudf_checker.mli000066400000000000000000000071141200672564300155610ustar00rootroot00000000000000(*****************************************************************************) (* libCUDF - CUDF (Common Upgrade Description Format) manipulation library *) (* Copyright (C) 2009-2012 Stefano Zacchiroli *) (* *) (* This library is free software: you can redistribute it and/or modify *) (* it under the terms of the GNU Lesser General Public License as *) (* published by the Free Software Foundation, either version 3 of the *) (* License, or (at your option) any later version. A special linking *) (* exception to the GNU Lesser General Public License applies to this *) (* library, see the COPYING file for more information. *) (*****************************************************************************) (** Checkers for CUDF documents Consistency and problem-solution matching. *) open Cudf_types open Cudf type inconsistency_reason = [ `Unsat_dep of (pkgname * version) * vpkgformula (** unsatisfied dep. *) | `Conflict of (pkgname * version) * vpkglist (** unsolved conflict(s) *) ] type bad_solution_reason = [ inconsistency_reason | `Missing_install of vpkglist (** install pkgs missing *) | `Missing_upgrade of vpkglist (** upgrade pkgs missing *) | `Unremoved of vpkglist (** remove pkgs still there *) | `Downgrade of vpkglist (** upgrade pkgs downgraded *) | `Multi_upgrade of pkgname list (** upgrade pkgs aren't singleton *) | `Not_kept of pkgname * version * enum_keep (** unattended "Keep" *) ] (** provide a string explaining a given reason, meant for error messages *) val explain_reason : bad_solution_reason -> string (** check whether a given package formula is satisfied by a given package status @return [true, []] if the formula is satisfied; [false, f] otherwise, where f is a sub-formula of the input denoting an unsatisfiable formula (ideally, a witness of the unsatisfiability of the input formula) *) val satisfy_formula : universe -> vpkgformula -> bool * vpkgformula (** check whether a package list is not satisfied by a given package status @return [true, []] if the list is disjoint; [false, l] otherwise, where l is a list of packages satisfied by the universe (ideally, the reason of the non-disjointness) *) val disjoint : universe -> ?ignore:(package -> bool) -> vpkglist -> bool * vpkglist (** @return [true, None] if the given installation is consistent, [false, Some r] otherwise, where r is the inconsistency reason *) val is_consistent : universe -> bool * inconsistency_reason option (** [is_solution (status, req) sol] checks whether [sol] fulfills the CUDF upgrade scenario described by [(status, req)] {b Note}: the [sol] package universe must contain all relevant package metadata (e.g. Depends, Conflicts, etc.), copied from [status], a compact universe only containing package names and versions won't be enough. To load compact universes see {!Cudf_parser.load_solution}. {b Note}: in accordance with CUDF semantics, for a solution to be valid, the solution shall correspond to a consistent universe. A solution that does satisfy user request, but at the same time proposes an inconsistent universe (as per {!Cudf_checker.is_consistent}) will be reported by [is_solution] as not being a valid solution. @return [true, []] if this is the case, [false, l] otherwise, where r explains why the solution is bad *) val is_solution : (universe * request) -> universe -> bool * bad_solution_reason list cudf-0.6.3/cudf_conf.ml000066400000000000000000000033571200672564300147360ustar00rootroot00000000000000(*****************************************************************************) (* libCUDF - CUDF (Common Upgrade Description Format) manipulation library *) (* Copyright (C) 2009-2012 Stefano Zacchiroli *) (* *) (* This library is free software: you can redistribute it and/or modify *) (* it under the terms of the GNU Lesser General Public License as *) (* published by the Free Software Foundation, either version 3 of the *) (* License, or (at your option) any later version. A special linking *) (* exception to the GNU Lesser General Public License applies to this *) (* library, see the COPYING file for more information. *) (*****************************************************************************) open Cudf_types type stanza_typedecl = (string * typedecl) list let preamble_typedecl = [ "preamble", `String None ; "property", `Typedecl (Some []) ; "univ-checksum", `String (Some "") ; "status-checksum", `String (Some "") ; "req-checksum", `String (Some "") ; ] let package_typedecl = [ "package", `Pkgname None ; "version", `Posint None ; "depends", `Vpkgformula (Some []) ; "conflicts", `Vpkglist (Some []) ; "provides", `Veqpkglist (Some []) ; "installed", `Bool (Some false) ; "was-installed", `Bool (Some false) ; "keep", `Enum (keep_enums, Some "none") ; ] let request_typedecl = [ "request", `String None ; "install", `Vpkglist (Some []) ; "remove", `Vpkglist (Some []) ; "upgrade", `Vpkglist (Some []) ; ] let stanza_typedecl = [ "preamble", preamble_typedecl ; "package", package_typedecl ; "request", request_typedecl ; ] cudf-0.6.3/cudf_conf.mli000066400000000000000000000035501200672564300151020ustar00rootroot00000000000000(*****************************************************************************) (* libCUDF - CUDF (Common Upgrade Description Format) manipulation library *) (* Copyright (C) 2009-2012 Stefano Zacchiroli *) (* *) (* This library is free software: you can redistribute it and/or modify *) (* it under the terms of the GNU Lesser General Public License as *) (* published by the Free Software Foundation, either version 3 of the *) (* License, or (at your option) any later version. A special linking *) (* exception to the GNU Lesser General Public License applies to this *) (* library, see the COPYING file for more information. *) (*****************************************************************************) open Cudf_types (** Mapping (in the form of associative list) from stanza postmarks to type declarations. Keys in the map are usually only those prescribed by the CUDF specification, namely "preamble", "package", and "request". Values in the map are type declarations for each supported property of that stanza; usually they only represent core property schemata (see CUDF §2.2.3). *) type stanza_typedecl = (string * typedecl) list (** {5 Global configuration} *) (** Default stanza types for parsing CUDF documents. For what concerns package stanzas, available types can be extended by using "property" declaration in the preamble stanza. *) val stanza_typedecl: stanza_typedecl (** {6 Direct access to per-stanza type declaration} *) (** Preamble schemata *) val preamble_typedecl: typedecl (** Package description schemata I.e. type declarataion for all core package properties *) val package_typedecl: typedecl (** Request schemata *) val request_typedecl: typedecl cudf-0.6.3/cudf_parser.ml000066400000000000000000000232141200672564300152770ustar00rootroot00000000000000(*****************************************************************************) (* libCUDF - CUDF (Common Upgrade Description Format) manipulation library *) (* Copyright (C) 2009-2012 Stefano Zacchiroli *) (* *) (* This library is free software: you can redistribute it and/or modify *) (* it under the terms of the GNU Lesser General Public License as *) (* published by the Free Software Foundation, either version 3 of the *) (* License, or (at your option) any later version. A special linking *) (* exception to the GNU Lesser General Public License applies to this *) (* library, see the COPYING file for more information. *) (*****************************************************************************) open ExtLib open Printf open Cudf open Cudf_types type cudf_parser = { lexbuf: Lexing.lexbuf ; fname: string ; mutable typedecl: Cudf_conf.stanza_typedecl ; } type loc_map = (string * loc) list exception Parse_error of string * loc let parse_error loc msg = raise (Parse_error (msg, loc)) let from_in_channel ?(typedecl=Cudf_conf.stanza_typedecl) ic = { lexbuf = Lexing.from_channel ic ; typedecl = typedecl ; fname = "" ; } let from_IO_in_channel ?(typedecl=Cudf_conf.stanza_typedecl) ic = let f s n = try IO.input ic s 0 n with IO.No_more_input -> 0 in { lexbuf = Lexing.from_function f; typedecl = typedecl ; fname = "" ; } let from_file ?(typedecl=Cudf_conf.stanza_typedecl) fname = (* Syntax error with OCaml 3.10.2: * { from_in_channel ?typedecl (open_in fname) * with fname = fname } *) { lexbuf = Lexing.from_channel (open_in fname) ; typedecl = typedecl ; fname = fname ; } let close p = () let parse_stanza p = try (match Cudf_822_parser.stanza_822 Cudf_822_lexer.token_822 p.lexbuf with | Some stanza -> List.fold_right (* split loc_map from (string * loc) stanzas *) (* non tail recursive, but should be ok: stanzas are short *) (fun (k, (loc, v)) (locs, stanza) -> (k, loc) :: locs, (k, v) :: stanza) stanza ([], []) | None -> raise End_of_file) with Parse_error_822 (msg, loc) -> raise (Syntax_error (msg, loc)) let loc_lookuper locs = (fun p -> try List.assoc p locs with Not_found -> prerr_endline "non located property" ; assert false) let type_check_stanza ?locs stanza types = let lookup_loc = match locs with | None -> (fun p -> dummy_loc) | Some locs -> loc_lookuper locs in let typed_stanza = List.map (fun (k, v) -> try let decl = List.assoc k types in let typed_v = Cudf_types_pp.parse_value (type_of_typedecl decl) v in k, typed_v with | Not_found -> parse_error (lookup_loc k) (sprintf "unexpected property \"%s\" in this stanza" k) | Cudf_types_pp.Type_error (typ, v) -> (* localize type errors *) raise (Cudf_types.Type_error (typ, v, lookup_loc k))) stanza in let defaults, missing = (* deal with missing properties *) List.fold_left (fun (defaults, missing) (name, ty1) -> match value_of_typedecl ty1, List.mem_assoc name typed_stanza with | None, true -> defaults, missing (* mandatory, present *) | None, false -> defaults, (name :: missing) (* mandatory, missing *) | Some v, true -> defaults, missing (* optional, present *) | Some v, false -> (* optional, missing *) (name, v) :: defaults, missing) ([], []) types in if missing <> [] then begin let loc = match stanza with [] -> dummy_loc | (k,_) :: _ -> lookup_loc k in parse_error loc (sprintf "missing mandatory properties: %s" (String.concat ", " missing)) end; typed_stanza @ defaults (** Cast a typed stanza starting with "package: " to a {!Cudf.package}. ASSUMPTION: type checking of the stanza has already happend, in particular all extra properties have already been checked for allowance. *) let bless_package stanza = let p = default_package in (* assumption: should be completely overrode *) let rec aux p = function | ("package", `Pkgname v) :: tl -> aux { p with package = v } tl | ("version", `Posint v) :: tl -> aux { p with version = v } tl | ("depends", `Vpkgformula v) :: tl -> aux { p with depends = v } tl | ("conflicts", `Vpkglist v) :: tl -> aux { p with conflicts = v } tl | ("provides", `Veqpkglist v) :: tl -> aux { p with provides = v } tl | ("installed", `Bool v) :: tl -> aux { p with installed = v } tl | ("was-installed", `Bool v) :: tl -> aux { p with was_installed = v } tl | ("keep", `Enum (_, v)) :: tl -> aux { p with keep = Cudf_types_pp.parse_keep v } tl | (k, (v: typed_value)) :: tl -> aux { p with pkg_extra = (k, v) :: p.pkg_extra } tl | [] -> p in let p' = aux p stanza in { p' with pkg_extra = List.rev p'.pkg_extra } (** Cast a typed stanza starting with "preamble: " to a {!Cudf.preamble} ASSUMPTION: as per {!Cudf_parser.bless_package} above. *) let bless_preamble stanza = let p = default_preamble in (* assumption: should be completely overrode *) let rec aux p = function | ("preamble", `String v) :: tl -> aux { p with preamble_id = v } tl | ("property", `Typedecl v) :: tl -> aux { p with property = v } tl | ("univ-checksum", `String v) :: tl -> aux { p with univ_checksum = v } tl | ("status-checksum", `String v) :: tl -> aux { p with status_checksum = v } tl | ("req-checksum", `String v) :: tl -> aux { p with req_checksum = v } tl | [] -> p | _ -> assert false in aux p stanza (** Cast a typed stanza starting with "request: " to a {!Cudf.request}. ASSUMPTION: as per {!Cudf_parser.bless_package} above. *) let bless_request stanza = let r = default_request in (* assumption: should be completely overrode *) let rec aux r = function | ("request", `String v) :: tl -> aux { r with request_id = v } tl | ("install", `Vpkglist v) :: tl -> aux { r with install = v } tl | ("remove", `Vpkglist v) :: tl -> aux { r with remove = v } tl | ("upgrade", `Vpkglist v) :: tl -> aux { r with upgrade = v } tl | (k, (v: typed_value)) :: tl -> aux { r with req_extra = (k, v) :: r.req_extra } tl | [] -> r in let r' = aux r stanza in { r' with req_extra = List.rev r'.req_extra } let parse_item' p = let locs, stanza = try parse_stanza p with Syntax_error (msg, loc) -> parse_error loc msg in let lookup_loc = loc_lookuper locs in let typed_stanza = match stanza with | [] -> eprintf "empty stanza\n%!"; assert false | (postmark, _) :: _ -> (try type_check_stanza ~locs stanza (List.assoc postmark p.typedecl) with Not_found -> parse_error (lookup_loc postmark) (sprintf "Unknown stanza type, starting with \"%s\" postmark." postmark)) in let item = match typed_stanza with | [] -> assert false | ("preamble", _) :: _ -> let preamble = bless_preamble typed_stanza in p.typedecl <- (* update type declaration for "package" stanza *) (let pkg_typedecl = (List.assoc "package" p.typedecl) @ preamble.property in ("package", pkg_typedecl) :: List.remove_assoc "package" p.typedecl); `Preamble preamble | ("package", _) :: _ -> `Package (bless_package typed_stanza) | ("request", _) :: _ -> `Request (bless_request typed_stanza) | _ -> assert false in (locs, item) let parse_item p = snd (parse_item' p) let get_postmark = function | `Package pkg -> pkg.package | `Request req -> req.request_id | `Preamble pre -> pre.preamble_id let parse p = let pre, pkgs, req = ref None, ref [], ref None in let rec aux_pkg () = match parse_item' p with | locs, `Package pkg -> pkgs := pkg :: !pkgs ; aux_pkg () | locs, `Request req' -> req := Some req' (* stop recursion after req *) | locs, `Preamble pre -> parse_error (loc_lookuper locs pre.preamble_id) "late preamble" in let parse () = try (match parse_item p with (* parse first item *) | `Preamble pre' -> pre := Some pre' ; (try aux_pkg () with End_of_file -> ()) | `Package pkg -> pkgs := [pkg] ; (try aux_pkg () with End_of_file -> ()) | `Request req' -> req := Some req') with End_of_file -> () in (try parse () ; with Cudf_types.Type_error (typ, v, loc) -> parse_error loc (sprintf ("a value of type \"%s\" was expected, but \"%s\" has been found") (Cudf_types_pp.string_of_type typ) (Cudf_types_pp.string_of_value v))); (try (* check for forbidden trailing content *) let locs, item = parse_item' p in parse_error (loc_lookuper locs (get_postmark item)) "trailing stanzas after final request stanza" with End_of_file -> ()); (!pre, List.rev !pkgs, !req) let load p = let pre, pkgs, req = parse p in (pre, load_universe pkgs, req) let load_solution p univ = let pre, sol_pkgs, _ = parse p in let expand_package pkg = let old_pkg = try lookup_package univ (pkg.package, pkg.version) with Not_found -> parse_error dummy_loc (sprintf "unknown package (%s,%d) found in solution" pkg.package pkg.version) in { old_pkg with installed = pkg.installed } in let sol_univ = load_universe (List.map expand_package sol_pkgs) in pre, sol_univ let parser_wrapper ?typedecl fname f = let ic = open_in fname in let p = from_in_channel ?typedecl ic in finally (fun () -> close_in ic ; close p) f p let parse_from_file ?typedecl fname = parser_wrapper ?typedecl fname parse let load_from_file ?typedecl fname = parser_wrapper ?typedecl fname load let load_solution_from_file fname univ = parser_wrapper fname (fun p -> load_solution p univ) cudf-0.6.3/cudf_parser.mli000066400000000000000000000140231200672564300154460ustar00rootroot00000000000000(*****************************************************************************) (* libCUDF - CUDF (Common Upgrade Description Format) manipulation library *) (* Copyright (C) 2009-2012 Stefano Zacchiroli *) (* *) (* This library is free software: you can redistribute it and/or modify *) (* it under the terms of the GNU Lesser General Public License as *) (* published by the Free Software Foundation, either version 3 of the *) (* License, or (at your option) any later version. A special linking *) (* exception to the GNU Lesser General Public License applies to this *) (* library, see the COPYING file for more information. *) (*****************************************************************************) (** Parser for CUDF related documents *) open Cudf open Cudf_types (** a CUDF parser opened on some input source *) type cudf_parser (** Error during parsing (syntax error, type error, ...). Arguments are error message and error location. *) exception Parse_error of string * loc (** create a CUDF parser reading data from an input channel @param typedecl (initial) per-stanza and per-property type declarations to be used while parsing. Default: {!Cudf_conf.stanza_typedecl} *) val from_in_channel : ?typedecl:Cudf_conf.stanza_typedecl -> in_channel -> cudf_parser (** create a CUDF parser reading data from an Extlib input channel @param typedecl (initial) per-stanza and per-property type declarations to be used while parsing. Default: {!Cudf_conf.stanza_typedecl} *) val from_IO_in_channel : ?typedecl:Cudf_conf.stanza_typedecl -> IO.input -> cudf_parser (** create a CUDF parser reading data from a file @param typedecl as per {!Cudf_parser.from_in_channel} *) val from_file : ?typedecl:Cudf_conf.stanza_typedecl -> string -> cudf_parser (** Dispose a CUDF parser. Afterwards, the parser should not be used any longer *) val close : cudf_parser -> unit (** {6 Full CUDF document parsing} "parse_*" functions offer plain syntax parsing, with no semantic interpretation of what is being parsed. "load_*" functions offer the latter, hence also checking for semantic constraints (such as the lack of key duplication). All full parsing function are granted to raise only {!Cudf_parser.Parse_error}; finer grained exception are mapped to it. *) (** parse a CUDF document (or a universe) as a whole @return a triple [preamble, packages, request] where preamble and request are returned only if actually met in the parsed document. Note that a document with no request part is not a valid CUDF document (but might still be used to represent solver solutions, for instance). @raise Parse_error when an error during parsing is encountered (might be a syntax error, a type error, ..) *) val parse : cudf_parser -> preamble option * package list * request option (** same as {!Cudf_parser.parse}, but additionally loads the package list as an abstract {!Cudf.universe}. {b Note}: to load compact universes (i.e. only containing package names, versions, and installed status) that will be tested as solutions you should use {!Cudf_parser.load_solution} instead: the present function does not expand missing metadata with respect to the initial status. @raise Parse_error as {!Cudf_parser.parse} does @raise Cudf.Constraint_violation as {!Cudf.load_universe} does *) val load : cudf_parser -> preamble option * universe * request option (** Load a solution wrt to a given CUDF document, whose universe is given. Solution format is as per Appendix B of CUDF 2.0 spec @raise Parse_error as {!Cudf_parser.parse} does *) val load_solution : cudf_parser -> universe -> preamble option * universe (** Shorthand: parse a file given its name *) val parse_from_file : ?typedecl:Cudf_conf.stanza_typedecl -> string -> preamble option * package list * request option (** Shorthand: load from a file given its name *) val load_from_file : ?typedecl:Cudf_conf.stanza_typedecl -> string -> preamble option * universe * request option (** Shorthand: load a solution from a file given its name *) val load_solution_from_file : string -> universe -> preamble option * universe (** {6 Item-by-item CUDF parsing} *) (** Parse the next information item (either a package description, a user request, or a preamble) from the given input channel. Beware that parsing is stateful; in particular when the preamble is parsed, the list of allowed properties for future package stanzas is internally updated. *) val parse_item : cudf_parser -> cudf_item (** {6 Low-level parsing functions} The following parsing function usually raise fine grained exceptions such as {!Cudf_types.Syntax_error} and {!Cudf_types.Type_error}. *) type loc_map = (string * loc) list (** Parse a file stanza (i.e., a RFC822-like stanza, with the notable simplification that all field/value pairs are one-liners). Strip any heading blanks lines leading to the first available field/value pair. @return an associative list mapping field name to field values and a location map mapping field names to locations @raise End_of_file if no other stanza is available due to reached EOF @raise Cudf_types.Syntax_error when a syntax error is encountered *) val parse_stanza : cudf_parser -> loc_map * string stanza (** Type check an untyped stanza according to a given set of type declarations. Also take care of default values, adding missing properties where needed; fail if a required property is missing. @param loc location map from prop name to locations, default is None (i.e. use dummy locations) @raise Syntax_error if a property does not match its declared type; this exception is also raised when an undeclared property is encountered @raise Type_error when a property has a value of the wrong type *) val type_check_stanza : ?locs:loc_map -> string stanza -> typedecl -> typed_value stanza cudf-0.6.3/cudf_printer.ml000066400000000000000000000130571200672564300154720ustar00rootroot00000000000000(*****************************************************************************) (* libCUDF - CUDF (Common Upgrade Description Format) manipulation library *) (* Copyright (C) 2009-2012 Stefano Zacchiroli *) (* *) (* This library is free software: you can redistribute it and/or modify *) (* it under the terms of the GNU Lesser General Public License as *) (* published by the Free Software Foundation, either version 3 of the *) (* License, or (at your option) any later version. A special linking *) (* exception to the GNU Lesser General Public License applies to this *) (* library, see the COPYING file for more information. *) (*****************************************************************************) open ExtLib open Printf open Cudf open Cudf_types open Cudf_types_pp let pp_property out (n, s) = fprintf out "%s: %s\n" n s let pp_io_property out (n, s) = IO.printf out "%s: %s\n" n s let pp_sep out = output_char out '\n' let pp_io_sep out = IO.write out '\n' let pp_package_gen ~pp_property out pkg = let pp = pp_property out in pp ("package", string_of_pkgname pkg.package); pp ("version", string_of_version pkg.version); if pkg.depends <> default_package.depends then pp ("depends", string_of_vpkgformula pkg.depends); if pkg.conflicts <> default_package.conflicts then pp ("conflicts", string_of_vpkglist pkg.conflicts); if pkg.provides <> default_package.provides then pp ("provides", string_of_vpkglist (pkg.provides :> vpkg list)); if pkg.installed <> default_package.installed then pp ("installed", string_of_bool pkg.installed); if pkg.was_installed <> default_package.was_installed then pp ("was-installed", string_of_bool pkg.was_installed); if pkg.keep <> default_package.keep then pp ("keep", string_of_keep pkg.keep); List.iter (fun (k, v) -> pp (k, string_of_value v)) pkg.pkg_extra let pp_request_gen ~pp_property out req = let pp = pp_property out in pp ("request", req.request_id); if req.install <> default_request.install then pp ("install", string_of_vpkglist req.install); if req.remove <> default_request.remove then pp ("remove", string_of_vpkglist req.remove); if req.upgrade <> default_request.upgrade then pp ("upgrade", string_of_vpkglist req.upgrade); List.iter (fun (k, v) -> pp (k, string_of_value v)) req.req_extra let pp_preamble_gen ~pp_property out pre = let pp = pp_property out in pp ("preamble", pre.preamble_id); if pre.property <> default_preamble.property then pp ("property", string_of_typedecl pre.property); if pre.univ_checksum <> default_preamble.univ_checksum then pp ("univ-checksum", pre.univ_checksum); if pre.status_checksum <> default_preamble.status_checksum then pp ("status-checksum", pre.status_checksum); if pre.req_checksum <> default_preamble.req_checksum then pp ("req-checksum", pre.req_checksum) let pp_universe_gen ~pp_package ~pp_sep out univ = iter_packages (fun pkg -> pp_package out pkg; pp_sep out) univ let pp_packages_gen ~pp_package ~pp_sep out pkgs = List.iter (fun pkg -> pp_package out pkg; pp_sep out) pkgs let pp_cudf_gen ~pp_preamble ~pp_universe ~pp_request ~pp_sep out (pre, univ, req) = pp_preamble out pre; pp_sep out; pp_universe out univ; pp_request out req let pp_doc_gen ~pp_preamble ~pp_packages ~pp_request ~pp_sep out (pre, pkgs, req) = Option.may (fun pre -> pp_preamble out pre; pp_sep out) pre; pp_packages out pkgs; pp_request out req let pp_solution_gen ~pp_preamble ~pp_universe ~pp_sep out (pre, univ) = pp_preamble out pre; pp_sep out; pp_universe out univ let pp_item_gen ~pp_package ~pp_request ~pp_preamble out = function | `Package pkg -> pp_package out pkg | `Request req -> pp_request out req | `Preamble pre -> pp_preamble out pre (** {6 Pretty print to standard output channels} *) let pp_package out p = pp_package_gen ~pp_property out p let pp_request out r = pp_request_gen ~pp_property out r let pp_preamble out p = pp_preamble_gen ~pp_property out p let pp_universe out u = pp_universe_gen ~pp_package ~pp_sep out u let pp_packages out p = pp_packages_gen ~pp_package ~pp_sep out p let pp_cudf out c = pp_cudf_gen ~pp_preamble ~pp_universe ~pp_request ~pp_sep out c let pp_doc out d = pp_doc_gen ~pp_preamble ~pp_packages ~pp_request ~pp_sep out d let pp_solution out s = pp_solution_gen ~pp_preamble ~pp_universe ~pp_sep out s let pp_item out i = pp_item_gen ~pp_package ~pp_request ~pp_preamble out i (** {6 Pretty print to abstract output channels} *) let pp_io_package out p = pp_package_gen ~pp_property:pp_io_property out p let pp_io_request out r = pp_request_gen ~pp_property:pp_io_property out r let pp_io_preamble out p = pp_preamble_gen ~pp_property:pp_io_property out p let pp_io_universe out u = pp_universe_gen ~pp_package:pp_io_package ~pp_sep:pp_io_sep out u let pp_io_packages out p = pp_packages_gen ~pp_package:pp_io_package ~pp_sep:pp_io_sep out p let pp_io_cudf out c = pp_cudf_gen ~pp_preamble:pp_io_preamble ~pp_universe:pp_io_universe ~pp_request:pp_io_request ~pp_sep:pp_io_sep out c let pp_io_doc out d = pp_doc_gen ~pp_preamble:pp_io_preamble ~pp_packages:pp_io_packages ~pp_request:pp_io_request ~pp_sep:pp_io_sep out d let pp_io_solution out s = pp_solution_gen ~pp_preamble:pp_io_preamble ~pp_universe:pp_io_universe ~pp_sep:pp_io_sep out s let pp_io_item out i = pp_item_gen ~pp_package:pp_io_package ~pp_request:pp_io_request ~pp_preamble:pp_io_preamble out i cudf-0.6.3/cudf_printer.mli000066400000000000000000000077171200672564300156510ustar00rootroot00000000000000(*****************************************************************************) (* libCUDF - CUDF (Common Upgrade Description Format) manipulation library *) (* Copyright (C) 2009-2012 Stefano Zacchiroli *) (* *) (* This library is free software: you can redistribute it and/or modify *) (* it under the terms of the GNU Lesser General Public License as *) (* published by the Free Software Foundation, either version 3 of the *) (* License, or (at your option) any later version. A special linking *) (* exception to the GNU Lesser General Public License applies to this *) (* library, see the COPYING file for more information. *) (*****************************************************************************) (** Pretty printing of CUDF macro-components (documents, stanzas, ...) For pretty printing of micro-components see {!module: Cudf_types_pp}. *) open Cudf (** {6 Pretty print to standard output channels} *) val pp_cudf : out_channel -> cudf -> unit val pp_doc : out_channel -> cudf_doc -> unit val pp_solution : out_channel -> solution -> unit val pp_item : out_channel -> cudf_item -> unit val pp_package : out_channel -> package -> unit val pp_preamble : out_channel -> preamble -> unit val pp_request : out_channel -> request -> unit val pp_packages : out_channel -> package list -> unit val pp_universe : out_channel -> universe -> unit (** {6 Pretty print to abstract output channels} Note: you can write to string using these methods using the following pattern: [let o = IO.output_string () in ... Cudf_printer.pp_* o ...; IO.close_out o] *) val pp_io_cudf : 'a IO.output -> cudf -> unit val pp_io_doc : 'a IO.output -> cudf_doc -> unit val pp_io_solution : 'a IO.output -> solution -> unit val pp_io_item : 'a IO.output -> cudf_item -> unit val pp_io_package : 'a IO.output -> package -> unit val pp_io_preamble : 'a IO.output -> preamble -> unit val pp_io_request : 'a IO.output -> request -> unit val pp_io_packages : 'a IO.output -> package list -> unit val pp_io_universe : 'a IO.output -> universe -> unit (** {6 Generic, higher-order pretty printers} Usually, you shouldn't need those and you should be well served by the above printers. To bootstrap usage of the generic printers, you'll need to provide a pp_property argument --- that takes a property as a pair of name/value strings and print them on a generic output --- and then proceed composing generic printers together. *) val pp_package_gen : pp_property:('out -> string * string -> unit) -> 'out -> Cudf.package -> unit val pp_request_gen : pp_property:('out -> string * string -> unit) -> 'out -> Cudf.request -> unit val pp_preamble_gen : pp_property:('out -> string * string -> unit) -> 'out -> Cudf.preamble -> unit val pp_universe_gen : pp_package:('out -> Cudf.package -> unit) -> pp_sep:('out -> unit) -> 'out -> Cudf.universe -> unit val pp_packages_gen : pp_package:('out -> Cudf.package -> unit) -> pp_sep:('out -> unit) -> 'out -> Cudf.package list -> unit val pp_cudf_gen : pp_preamble:('out -> Cudf.preamble -> unit) -> pp_universe:('out -> Cudf.universe -> unit) -> pp_request:('out -> Cudf.request -> unit) -> pp_sep:('out -> unit) -> 'out -> Cudf.cudf -> unit val pp_doc_gen : pp_preamble:('out -> Cudf.preamble -> unit) -> pp_packages:('out -> Cudf.package list -> unit) -> pp_request:('out -> Cudf.request -> unit) -> pp_sep:('out -> unit) -> 'out -> Cudf.cudf_doc -> unit val pp_solution_gen : pp_preamble:('out -> Cudf.preamble -> unit) -> pp_universe:('out -> Cudf.universe -> unit) -> pp_sep:('out -> unit) -> 'out -> Cudf.solution -> unit val pp_item_gen : pp_package:('out -> Cudf.package -> unit) -> pp_request:('out -> Cudf.request -> unit) -> pp_preamble:('out -> Cudf.preamble -> unit) -> 'out -> Cudf.cudf_item -> unit cudf-0.6.3/cudf_type_lexer.mll000066400000000000000000000045131200672564300163400ustar00rootroot00000000000000(*****************************************************************************) (* libCUDF - CUDF (Common Upgrade Description Format) manipulation library *) (* Copyright (C) 2009-2012 Stefano Zacchiroli *) (* *) (* This library is free software: you can redistribute it and/or modify *) (* it under the terms of the GNU Lesser General Public License as *) (* published by the Free Software Foundation, either version 3 of the *) (* License, or (at your option) any later version. A special linking *) (* exception to the GNU Lesser General Public License applies to this *) (* library, see the COPYING file for more information. *) (*****************************************************************************) (** Lexer for CUDF values *) { open Cudf_types open Cudf_type_parser } let lower_letter = [ 'a' - 'z' ] let upper_letter = [ 'A' - 'Z' ] let letter = lower_letter | upper_letter let digit = [ '0' - '9' ] let blank = [ ' ' '\t' ] let blanks = blank+ let ident = lower_letter (lower_letter | digit | '-')* let pkgname = (letter | digit | ['-' '+' '.' '/' '@' '(' ')' '%'])+ rule token_cudf = parse | "true!" { VPKGTRUE } | "false!" { VPKGFALSE } | ident as s { IDENT s } | '+'? (digit+ as s) { POSINT s } | '-' digit+ as s { NEGINT s } | pkgname as s { PKGNAME s } | (">=" | "<=") as op { RELOP op } | "!=" as op { RELOP op } | ('>' | '<') as op { RELOP (String.make 1 op) } | '[' { LBRACKET } | ']' { RBRACKET } | '(' { LPAREN } | ')' { RPAREN } | ',' { COMMA } | '|' { PIPE } | ':' { COLON } | '=' { EQ } | '"' { let buf = Buffer.create 11 in qstring buf lexbuf } | blank+ { token_cudf lexbuf } | eof { EOL } (* single-line parsing: EOF means in fact EOL *) and qstring buf = parse | "\\\"" { Buffer.add_string buf "\""; qstring buf lexbuf } | "\\\\" { Buffer.add_string buf "\\"; qstring buf lexbuf } | '"' { QSTRING (Buffer.contents buf) } | [^ '\n' '\r' '\\' '"']+ as s { Buffer.add_string buf s; qstring buf lexbuf } | _ { raise (Parse_error_822 ("unexpected end of quoted string", (lexbuf.Lexing.lex_start_p, lexbuf.Lexing.lex_curr_p))) } cudf-0.6.3/cudf_type_parser.mly000066400000000000000000000131771200672564300165400ustar00rootroot00000000000000/*****************************************************************************/ /* libCUDF - CUDF (Common Upgrade Description Format) manipulation library */ /* Copyright (C) 2009-2012 Stefano Zacchiroli */ /* */ /* This library is free software: you can redistribute it and/or modify */ /* it under the terms of the GNU Lesser General Public License as */ /* published by the Free Software Foundation, either version 3 of the */ /* License, or (at your option) any later version. A special linking */ /* exception to the GNU Lesser General Public License applies to this */ /* library, see the COPYING file for more information. */ /*****************************************************************************/ /* CUDF type parser: parse values belonging to CUDF types. Used as the basic building block to parse CUDF stanzas retuned by Cudf_822_paser. Generally, this parser does not need to parse multi-line values (as they are all normalized to single-line values by Cudf_822_parser.) */ %{ (** a non-located parse error carrying an error message (...) *) exception Parse_error_msg of string let parse_relop = function | "=" -> `Eq | "!=" -> `Neq | ">=" -> `Geq | ">" -> `Gt | "<=" -> `Leq | "<" -> `Lt | _ -> assert false (* lexer shouldn't have returned such a RELOP! *) (** parse a type declaration with no default value *) let parse_typename = function | "int" -> `Int | "posint" -> `Posint | "nat" -> `Nat | "bool" -> `Bool | "string" -> `String | "pkgname" -> `Pkgname | "ident" -> `Ident | "vpkg" -> `Vpkg | "vpkgformula" -> `Vpkgformula | "vpkglist" -> `Vpkglist | "veqpkg" -> `Veqpkg | "veqpkglist" -> `Veqpkglist | s -> raise (Parse_error_msg ("unknown type name: " ^ s)) %} %token IDENT PKGNAME QSTRING RELOP %token POSINT NEGINT %token LBRACKET RBRACKET LPAREN RPAREN %token COMMA PIPE COLON EQ %token VPKGTRUE VPKGFALSE %token EOL %type int_top %type ident_top qstring_top %type pkgname_top %type vpkg_top %type vpkglist_top %type vpkgformula_top %type typedecl_top %type type_top %start int_top ident_top qstring_top pkgname_top type_top %start vpkg_top vpkglist_top vpkgformula_top typedecl_top %% int_top: int EOL { $1 } ; ident_top: ident EOL { $1 } ; qstring_top: qstring EOL { $1 } ; pkgname_top: pkgname EOL { $1 } ; vpkg_top: vpkg EOL { $1 } ; vpkglist_top: vpkglist EOL { $1 } ; vpkgformula_top: vpkgformula EOL { $1 } ; typedecl_top: typedecl EOL { $1 } ; type_top: type_ EOL { $1 } ; ident: IDENT { $1 } ; qstring: QSTRING { $1 } ; version: POSINT { int_of_string $1 } ; pkgname: | PKGNAME { $1 } | IDENT { $1 } | POSINT { $1 } | NEGINT { $1 } ; relop: | RELOP { parse_relop $1 } | EQ { `Eq } ; int: | POSINT { int_of_string $1 } | NEGINT { int_of_string $1 } ; vpkg: | pkgname { ($1, None) } | pkgname relop version { ($1, Some ($2, $3)) } ; vpkglist: | { [] } | vpkglist_ne { $1 } ; vpkglist_ne: | vpkg { [ $1 ] } | vpkg COMMA vpkglist_ne { $1 :: $3 } ; vpkgformula: | and_formula { $1 } | VPKGTRUE { [] } | VPKGFALSE { [ [] ] } ; and_formula: | or_formula { [ $1 ] } | or_formula COMMA and_formula { $1 :: $3 } ; or_formula: | vpkg { [ $1 ] } | vpkg PIPE or_formula { $1 :: $3 } ; /* non trivial formula, i.e. a formula based which is syntactially different from both an integer and an identifier */ vpkgformula_ntriv: | and_formula_ntriv { $1 } | VPKGTRUE { [] } | VPKGFALSE { [ [] ] } ; and_formula_ntriv: | or_formula_ntriv { [ $1 ] } | or_formula COMMA and_formula { $1 :: $3 } ; or_formula_ntriv: | vpkg_ntriv { [ $1 ] } | vpkg PIPE or_formula { $1 :: $3 } ; vpkg_ntriv: | PKGNAME { ($1, None) } | pkgname relop version { ($1, Some ($2, $3)) } ; typedecl: | { [] } | typedecl_ne { $1 } ; typedecl_ne: | typedecl_ { [ $1 ] } | typedecl_ COMMA typedecl_ne { $1 :: $3 } ; typedecl_: | ident COLON type_ { ($1, Cudf_types.typedecl_of_type $3) } | ident COLON type_ EQ LBRACKET typed_value RBRACKET { let name, typ, v = $1, $3, $6 in (name, Cudf_types.typedecl_of_value (Cudf_types.cast typ v)) } ; type_: | ident { parse_typename $1 } | ident LBRACKET enums RBRACKET { if $1 = "enum" then `Enum $3 else raise Parsing.Parse_error } ; enums: | ident { [ $1 ] } | ident COMMA enums { $1 :: $3 } ; typed_value: | { `Vpkglist [] } | ident { `Ident $1 } | int { `Int $1 } | qstring { `String $1 } | vpkgformula_ntriv { `Vpkgformula $1 } ; %% open ExtLib let error_wrapper f = fun lexer lexbuf -> let syntax_error msg = raise (Cudf_types.Syntax_error (msg, Cudf_types.loc_of_lexbuf lexbuf)) in try f lexer lexbuf with | Parsing.Parse_error -> syntax_error "parse error" | Failure _m when String.starts_with _m "lexing" -> syntax_error "lexer error" | Cudf_types.Type_error _ -> syntax_error "type error" | Parse_error_msg msg -> syntax_error msg let int_top = error_wrapper int_top let ident_top = error_wrapper ident_top let pkgname_top = error_wrapper pkgname_top let vpkg_top = error_wrapper vpkg_top let vpkglist_top = error_wrapper vpkglist_top let vpkgformula_top = error_wrapper vpkgformula_top let typedecl_top = error_wrapper typedecl_top let qstring_top = error_wrapper qstring_top let type_top = error_wrapper type_top cudf-0.6.3/cudf_types.ml000066400000000000000000000164151200672564300151540ustar00rootroot00000000000000(*****************************************************************************) (* libCUDF - CUDF (Common Upgrade Description Format) manipulation library *) (* Copyright (C) 2009-2012 Stefano Zacchiroli *) (* *) (* This library is free software: you can redistribute it and/or modify *) (* it under the terms of the GNU Lesser General Public License as *) (* published by the Free Software Foundation, either version 3 of the *) (* License, or (at your option) any later version. A special linking *) (* exception to the GNU Lesser General Public License applies to this *) (* library, see the COPYING file for more information. *) (*****************************************************************************) open ExtLib open Printf type version = int type relop = [`Eq|`Neq|`Geq|`Gt|`Leq|`Lt] type constr = (relop * version) option type pkgname = string type vpkg = pkgname * constr type vpkglist = vpkg list type vpkgformula = vpkg list list type veqpkg = pkgname * ([`Eq] * version) option type veqpkglist = veqpkg list type enum_keep = [`Keep_version | `Keep_package | `Keep_feature | `Keep_none ] type typ = [ `Int | `Posint | `Nat | `Bool | `String | `Enum of string list | `Pkgname | `Ident | `Vpkg | `Vpkgformula | `Vpkglist | `Veqpkg | `Veqpkglist | `Typedecl ] type typedecl1 = [ `Int of int option | `Posint of int option | `Nat of int option | `Bool of bool option | `String of string option | `Pkgname of string option | `Ident of string option | `Enum of string list * string option | `Vpkg of vpkg option | `Vpkgformula of vpkgformula option | `Vpkglist of vpkglist option | `Veqpkg of veqpkg option | `Veqpkglist of veqpkglist option | `Typedecl of typedecl option ] and typedecl = (string * typedecl1) list type typed_value = [ `Int of int | `Posint of int | `Nat of int | `Bool of bool | `String of string | `Pkgname of string | `Ident of string | `Enum of string list * string | `Vpkg of vpkg | `Vpkgformula of vpkgformula | `Vpkglist of vpkglist | `Veqpkg of veqpkg | `Veqpkglist of veqpkglist | `Typedecl of typedecl ] type 'ty stanza = (string * 'ty) list type loc = Lexing.position * Lexing.position let dummy_loc: loc = Lexing.dummy_pos, Lexing.dummy_pos let extend_loc (r1_start, _r1_end) (_r2_start, r2_end) = (r1_start, r2_end) let loc_of_lexbuf b = (b.Lexing.lex_start_p, b.Lexing.lex_curr_p) exception Parse_error_822 of string * loc (* *) exception Syntax_error of string * loc (* *) exception Type_error of typ * typed_value * loc (* *) let keep_enums = ["version"; "package"; "feature"; "none"] let keep_type = `Enum keep_enums let type_of_typedecl = function | `Int _ -> `Int | `Posint _ -> `Posint | `Nat _ -> `Nat | `Bool _ -> `Bool | `String _ -> `String | `Pkgname _ -> `Pkgname | `Ident _ -> `Ident | `Enum (enums, _) -> `Enum enums | `Vpkg _ -> `Vpkg | `Vpkgformula _ -> `Vpkgformula | `Vpkglist _ -> `Vpkglist | `Veqpkg _ -> `Veqpkg | `Veqpkglist _ -> `Veqpkglist | `Typedecl _ -> `Typedecl let typedecl_of_type = function | `Int -> `Int None | `Posint -> `Posint None | `Nat -> `Nat None | `Bool -> `Bool None | `String -> `String None | `Pkgname -> `Pkgname None | `Ident -> `Ident None | `Enum enums -> `Enum (enums, None) | `Vpkg -> `Vpkg None | `Vpkgformula -> `Vpkgformula None | `Vpkglist -> `Vpkglist None | `Veqpkg -> `Veqpkg None | `Veqpkglist -> `Veqpkglist None | `Typedecl -> `Typedecl None let typedecl_of_value = function | `Int n -> `Int (Some n) | `Posint n -> `Posint (Some n) | `Nat n -> `Nat (Some n) | `Bool b -> `Bool (Some b) | `String s -> `String (Some s) | `Pkgname s -> `Pkgname (Some s) | `Ident s -> `Ident (Some s) | `Enum (enums, s) -> `Enum (enums, Some s) | `Vpkg p -> `Vpkg (Some p) | `Vpkgformula f -> `Vpkgformula (Some f) | `Vpkglist l -> `Vpkglist (Some l) | `Veqpkg p -> `Veqpkg (Some p) | `Veqpkglist l -> `Veqpkglist (Some l) | `Typedecl l -> `Typedecl (Some l) let value_of_typedecl = function | `Int (Some v) -> Some (`Int v) | `Posint (Some v) -> Some (`Posint v) | `Nat (Some v) -> Some (`Nat v) | `Bool (Some v) -> Some (`Bool v) | `String (Some v) -> Some (`String v) | `Pkgname (Some v) -> Some (`Pkgname v) | `Ident (Some v) -> Some (`Ident v) | `Enum (enums, (Some v)) -> Some (`Enum (enums, v)) | `Vpkg (Some v) -> Some (`Vpkg v) | `Vpkgformula (Some v) -> Some (`Vpkgformula v) | `Vpkglist (Some v) -> Some (`Vpkglist v) | `Veqpkg (Some v) -> Some (`Veqpkg v) | `Veqpkglist (Some v) -> Some (`Veqpkglist v) | `Typedecl (Some v) -> Some (`Typedecl v) | _ -> None let type_of_value = function | `Int n -> `Int | `Posint n -> `Posint | `Nat n -> `Nat | `Bool b -> `Bool | `String s -> `String | `Pkgname s -> `Pkgname | `Ident s -> `Ident | `Enum (enums, s) -> `Enum enums | `Vpkg p -> `Vpkg | `Vpkgformula f -> `Vpkgformula | `Vpkglist l -> `Vpkglist | `Veqpkg p -> `Veqpkg | `Veqpkglist l -> `Veqpkglist | `Typedecl l -> `Typedecl let rec cast typ v = let type_error () = raise (Type_error (typ, v, dummy_loc)) in match typ, v with | `Posint, `Int n when n > 0 -> `Posint n | `Nat, `Int n when n >= 0 -> `Nat n | `Bool, `Ident "true" -> `Bool true | `Bool, `Ident "false" -> `Bool false | `Pkgname, `Vpkgformula [[(pkg, None)]] -> `Pkgname pkg | `Pkgname, (`Int n | `Posint n | `Nat n) -> `Pkgname (string_of_int n) | `Pkgname, `Ident i-> `Pkgname i | (`Vpkg | `Veqpkg | `Vpkglist | `Veqpkglist), (`Int n | `Posint n | `Nat n) -> cast typ (`Vpkgformula [[string_of_int n, None]]) | (`Vpkg | `Veqpkg | `Vpkglist | `Veqpkglist), `Ident i -> cast typ (`Vpkgformula [[i, None]]) | `Vpkg, `Vpkgformula [[vpkg]] -> `Vpkg vpkg | (`Vpkglist | `Veqpkglist), (`Vpkgformula [] (* "true!" *) | `Vpkgformula [ [] ] (* "false!" *)) -> type_error () | `Vpkglist, `Vpkgformula f -> if List.exists (function _ :: _ :: _ -> true | _ -> false) f then type_error () (* there are OR-ed deps *) else `Vpkglist (List.map (function [vpkg] -> vpkg | _ -> assert false) f) | `Veqpkg, `Vpkgformula [[ (_, (Some (`Eq, _) | None)) as vpkg ]] -> `Veqpkg vpkg | `Veqpkglist, `Vpkgformula f -> `Veqpkglist (List.fold_right (fun or_deps veqpkgs -> match or_deps with | [ (_, (Some (`Eq, _) | None)) as vpkg ] -> vpkg :: veqpkgs | _ -> type_error ()) f []) | `Veqpkg, `Vpkg ((_, (Some (`Eq, _) | None)) as vpkg) -> `Veqpkg vpkg | `Veqpkglist, `Vpkglist l -> `Veqpkglist (List.fold_right (fun vpkg veqpkgs -> match vpkg with | (_, (Some (`Eq, _) | None)) as vpkg -> vpkg :: veqpkgs | _ -> type_error ()) l []) | `Enum enums, `Ident i when List.mem i enums -> `Enum (enums, i) | `Vpkgformula, `Ident i -> `Vpkgformula [[i, None]] | `Vpkgformula, `Int n -> `Vpkgformula [[string_of_int n, None]] | typ, v when type_of_value v = typ -> v (* identity cast *) | _ -> type_error () let rec is_eq_formula f = not (List.exists (fun vpkgs -> List.exists (function | (_, Some ((`Neq | `Geq | `Gt | `Leq | `Lt), _)) -> true | _ -> false) vpkgs) f) cudf-0.6.3/cudf_types.mli000066400000000000000000000125351200672564300153240ustar00rootroot00000000000000(*****************************************************************************) (* libCUDF - CUDF (Common Upgrade Description Format) manipulation library *) (* Copyright (C) 2009-2012 Stefano Zacchiroli *) (* *) (* This library is free software: you can redistribute it and/or modify *) (* it under the terms of the GNU Lesser General Public License as *) (* published by the Free Software Foundation, either version 3 of the *) (* License, or (at your option) any later version. A special linking *) (* exception to the GNU Lesser General Public License applies to this *) (* library, see the COPYING file for more information. *) (*****************************************************************************) (** CUDF type library Implement core CUDF types (see CUDF spec. §2.2.2). For parsing and pretty printing of CUDF types see {!Cudf_types_pp}. *) (** {5 CUDF types} *) type version = int (* required to be non 0 *) type relop = [`Eq | `Neq | `Geq | `Gt | `Leq | `Lt] type constr = (relop * version) option (** {6 CUDF spec. types} *) type pkgname = string type vpkg = pkgname * constr type vpkglist = vpkg list type enum_keep = [`Keep_version | `Keep_package | `Keep_feature | `Keep_none ] (** CNF formula. Inner lists are OR-ed, outer AND-ed. E.g.: - "Depends: foo, baz | baz" --> [ [ foo ] ; [ bar ; baz ] ] - "Depends: true!" --> [ ] - "Depends: false!" --> [ [] ] *) type vpkgformula = vpkg list list type veqpkg = pkgname * ([`Eq] * version) option type veqpkglist = veqpkg list (** CUDF types *) type typ = [ `Int | `Posint | `Nat | `Bool | `String | `Enum of string list | `Pkgname | `Ident | `Vpkg | `Vpkgformula | `Vpkglist | `Veqpkg | `Veqpkglist | `Typedecl ] val keep_type : typ val keep_enums : string list (** (Single) type declaration: each variant denotes a type, its argument the default value, None if missing *) type typedecl1 = [ `Int of int option | `Posint of int option | `Nat of int option | `Bool of bool option | `String of string option | `Pkgname of string option | `Ident of string option | `Enum of string list * string option (** enums, default enum *) | `Vpkg of vpkg option | `Vpkgformula of vpkgformula option | `Vpkglist of vpkglist option | `Veqpkg of veqpkg option | `Veqpkglist of veqpkglist option | `Typedecl of typedecl option ] and typedecl = (string * typedecl1) list (** Typed value in the value space of all CUDF types *) type typed_value = [ `Int of int | `Posint of int | `Nat of int | `Bool of bool | `String of string | `Pkgname of string | `Ident of string | `Enum of string list * string | `Vpkg of vpkg | `Vpkgformula of vpkgformula | `Vpkglist of vpkglist | `Veqpkg of veqpkg | `Veqpkglist of veqpkglist | `Typedecl of typedecl ] (** {5 Manipulation of typed values} *) (** extract the type of a (single) type declaration *) val type_of_typedecl : typedecl1 -> typ (** Create a (single) type declaration having as default value the given typed value (i.e. apply the "Some" monad to typed values) *) val typedecl_of_value : typed_value -> typedecl1 (** Extract the default value from a type declaration (or return [None]) *) val value_of_typedecl : typedecl1 -> typed_value option (** Create a (single) type declaration with no default value *) val typedecl_of_type : typ -> typedecl1 (** @return the type of a given value *) val type_of_value : typed_value -> typ (** [cast ty v] attempt a runtime cast of a given (typed) value to a different type. @raise Type_error if casting is not possible *) val cast: typ -> typed_value -> typed_value (** {6 CUDF syntactic types} Types used in parsing, before values are injected into the CUDF type system. *) (** RFC-822-like stanza, i.e. an associative list mapping property names to property values. Values are typed according to the type variable ['ty]. Usually, libCUDF uses either [string stanza] (for untyped stanzas) or [Cudf_types.typed_value stanza] (for typed stanzas). *) type 'ty stanza = (string * 'ty) list (**/**) (** {5 Parsing helpers} Used internally for pasring, generally otherwise uninteresting. *) (** Range in a file being parsed *) type loc = Lexing.position * Lexing.position (** Dummy location, pointing nowhere, going nowhere, ... *) val dummy_loc : loc (** [extend_range (p1, _) (_, p2)] return [(p1, p2)] *) val extend_loc : loc -> loc -> loc (** Get file range corresponding to the last read token *) val loc_of_lexbuf : Lexing.lexbuf -> loc (**/**) (** {5 Various errors} *) (** Error while parsing RFC822-like syntax of CUDF documents. arguments: error message and file range, respectively. *) exception Parse_error_822 of string * loc (** Syntax error while parsing some literal value arguments: error message and file range, respectively *) exception Syntax_error of string * loc (** Type error: mismatch between typed value and expected type arguments: expected type, found value *) exception Type_error of typ * typed_value * loc (** {5 Accessors, predicates, etc.} *) (** Check whether a formula uses only equality tests over package versions. *) val is_eq_formula : vpkgformula -> bool cudf-0.6.3/cudf_types_pp.ml000066400000000000000000000161371200672564300156540ustar00rootroot00000000000000(*****************************************************************************) (* libCUDF - CUDF (Common Upgrade Description Format) manipulation library *) (* Copyright (C) 2009-2012 Stefano Zacchiroli *) (* *) (* This library is free software: you can redistribute it and/or modify *) (* it under the terms of the GNU Lesser General Public License as *) (* published by the Free Software Foundation, either version 3 of the *) (* License, or (at your option) any later version. A special linking *) (* exception to the GNU Lesser General Public License applies to this *) (* library, see the COPYING file for more information. *) (*****************************************************************************) open ExtLib open Printf open Cudf_types (* note: Type_error <> Cudf_types.Type_error, this one is not located *) exception Type_error of typ * typed_value let lexbuf_wrapper type_parser typ = fun s -> try type_parser Cudf_type_lexer.token_cudf (Lexing.from_string s) with Cudf_types.Syntax_error (_msg, loc) -> raise (Type_error (typ, `String s)) let lexbuf_wrapper' type_parser = fun s -> type_parser Cudf_type_lexer.token_cudf (Lexing.from_string s) let parse_int = lexbuf_wrapper Cudf_type_parser.int_top `Int let parse_ident = lexbuf_wrapper Cudf_type_parser.ident_top `Ident let parse_pkgname = lexbuf_wrapper Cudf_type_parser.pkgname_top `Pkgname let parse_vpkg = lexbuf_wrapper Cudf_type_parser.vpkg_top `Vpkg let parse_vpkglist = lexbuf_wrapper Cudf_type_parser.vpkglist_top `Vpkglist let parse_vpkgformula = lexbuf_wrapper Cudf_type_parser.vpkgformula_top `Vpkgformula let parse_typedecl = lexbuf_wrapper Cudf_type_parser.typedecl_top `Typedecl let parse_qstring = lexbuf_wrapper' Cudf_type_parser.qstring_top let parse_type = lexbuf_wrapper' Cudf_type_parser.type_top (** DEFCON 4, use with care! Rationale: to avoid duplicating code we have the cast checks enclosed only in the [cast] function. After having used it however, we will have to extract the contained typed value. To avoid writing several functions extracting the appropriate value and [assert false] everywhere else we cheat with [Obj.magic]. *) let unbox v = snd (Obj.magic v: 'a * 'b) let cast' typ v = try cast typ v with Cudf_types.Type_error _ -> raise (Type_error (typ, v)) let parse_posint s: int = unbox (cast' `Posint (`Int (parse_int s))) let parse_nat s: int = unbox (cast' `Nat (`Int (parse_int s))) let parse_bool s: bool = unbox (cast' `Bool (`Ident (parse_ident s))) let parse_veqpkg s: veqpkg = unbox (cast' `Veqpkg (`Vpkg (parse_vpkg s))) let parse_veqpkglist s: veqpkglist = unbox (cast' `Veqpkglist (`Vpkglist (parse_vpkglist s))) let parse_enum ~enums s = match cast' (`Enum enums) (`Ident (parse_ident s)) with | `Enum (_, i) -> i | _ -> assert false let parse_keep = function | "version" -> `Keep_version | "feature" -> `Keep_feature | "package" -> `Keep_package | "none" -> `Keep_none | i -> raise (Type_error (Cudf_types.keep_type, `Ident i)) let parse_string s = let type_error () = raise (Type_error (`String, `String s)) in (try ignore (String.index s '\n') ; type_error () with Not_found -> ()); (try ignore (String.index s '\r') ; type_error () with Not_found -> ()); s let parse_value ty s = match ty with | `Int -> `Int (parse_int s) | `Posint -> `Posint (parse_posint s) | `Nat -> `Nat (parse_nat s) | `Bool -> `Bool (parse_bool s) | `String -> `String (parse_string s) | `Enum l -> `Enum (l, parse_enum l s) | `Pkgname -> `Pkgname (parse_pkgname s) | `Ident -> `Ident (parse_ident s) | `Vpkg -> `Vpkg (parse_vpkg s) | `Vpkglist -> `Vpkglist (parse_vpkglist s) | `Vpkgformula -> `Vpkgformula (parse_vpkgformula s) | `Veqpkg -> `Veqpkg (parse_veqpkg s) | `Veqpkglist -> `Veqpkglist (parse_veqpkglist s) | `Typedecl -> `Typedecl (parse_typedecl s) (** Pretty printers *) let string_of_int = Pervasives.string_of_int let string_of_posint = string_of_int let string_of_nat = string_of_int let string_of_bool = Pervasives.string_of_bool let string_of_keep = function `Keep_version -> "version" | `Keep_package -> "package" | `Keep_feature -> "feature" | `Keep_none -> "none" let string_of_pkgname pkgname = pkgname let string_of_version = string_of_int let string_of_relop = function `Eq -> "=" | `Neq -> "!=" | `Geq -> ">=" | `Gt -> ">" | `Leq -> "<=" | `Lt -> "<" let string_of_vpkg = function (name, None) -> name | (name, Some (relop, v)) -> sprintf "%s %s %d" name (string_of_relop relop) v let string_of_list string_of_item sep l = let buf = Buffer.create 1023 in let rec aux = function | [] -> assert false | [last] -> (* last item, no trailing sep *) Buffer.add_string buf (string_of_item last) | item :: tl -> (* at least one item in tl *) Buffer.add_string buf (string_of_item item); Buffer.add_string buf sep; aux tl in let _ = match l with | [] -> () | [sole] -> Buffer.add_string buf (string_of_item sole) | _ -> aux l in Buffer.contents buf let string_of_vpkglist = string_of_list string_of_vpkg " , " (** ASSUMPTION: formula is in CNF *) let rec string_of_vpkgformula = function | [] -> "true!" | [ [] ] -> "false!" | [] :: _ -> eprintf "malformed vpkgformula: `[] :: _' ; aborting\n%!"; assert false | fmla -> let string_of_OR = string_of_list string_of_vpkg " | " in let string_of_AND = string_of_list string_of_OR " , " in string_of_AND fmla let string_of_veqpkglist l = string_of_vpkglist (l :> vpkglist) let string_of_veqpkg = string_of_vpkg let string_of_type = function | `Int -> "int" | `Posint -> "posint" | `Nat -> "nat" | `Bool -> "bool" | `String -> "string" | `Enum enums -> sprintf "enum[%s]" (String.concat "," enums) | `Pkgname -> "pkgname" | `Ident -> "ident" | `Vpkg -> "vpkg" | `Vpkgformula -> "vpkgformula" | `Vpkglist -> "vpkglist" | `Veqpkg -> "veqpkg" | `Veqpkglist -> "veqpkglist" | `Typedecl -> "typedecl" let rec string_of_typedecl' (name, decl1) = let string_escape = String.replace_chars (function '"' -> "\\\"" | '\\' -> "\\\\" | c -> String.of_char c) in match value_of_typedecl decl1 with | None -> sprintf "%s: %s" name (string_of_type (type_of_typedecl decl1)) | Some (`String s) -> sprintf "%s: string = [\"%s\"]" name (string_escape s) | Some v -> sprintf "%s: %s = [%s]" name (string_of_type (type_of_typedecl decl1)) (string_of_value v) and string_of_value (v: typed_value) = match v with | (`Int i | `Posint i | `Nat i) -> string_of_int i | `Bool b -> string_of_bool b | (`String s | `Pkgname s | `Ident s | `Enum (_, s)) -> s | `Vpkg p -> string_of_vpkg p | `Veqpkg p -> string_of_vpkg p | `Vpkglist l -> string_of_vpkglist l | `Veqpkglist l -> string_of_veqpkglist l | `Vpkgformula f -> string_of_vpkgformula f | `Typedecl d -> string_of_typedecl d and string_of_typedecl decl = string_of_list string_of_typedecl' ", " decl cudf-0.6.3/cudf_types_pp.mli000066400000000000000000000072521200672564300160230ustar00rootroot00000000000000(*****************************************************************************) (* libCUDF - CUDF (Common Upgrade Description Format) manipulation library *) (* Copyright (C) 2009-2012 Stefano Zacchiroli *) (* *) (* This library is free software: you can redistribute it and/or modify *) (* it under the terms of the GNU Lesser General Public License as *) (* published by the Free Software Foundation, either version 3 of the *) (* License, or (at your option) any later version. A special linking *) (* exception to the GNU Lesser General Public License applies to this *) (* library, see the COPYING file for more information. *) (*****************************************************************************) (** CUDF type library: parsing and pretty printing Implement parsing and pretty printing of CUDF types (see CUDF spec. §2.2.2). For the actual CUDF type definition see {!module: Cudf_types}. For pretty printing of macro-components see {!module: Cudf_printer}. *) open Cudf_types (** {5 Errors} *) exception Type_error of typ * typed_value (** {5 Parsers} *) (** {6 Public types} All parsing function are granted to raise only {!Cudf_types_pp.Type_error}, lower lever exception (e.g. syntax errors) are wrapped into it *) val parse_int : string -> int val parse_posint : string -> int val parse_nat : string -> int val parse_bool : string -> bool val parse_string : string -> string val parse_pkgname : string -> pkgname val parse_ident : string -> string val parse_enum : enums:string list -> string -> string val parse_vpkg : string -> vpkg val parse_vpkglist : string -> vpkglist val parse_vpkgformula : string -> vpkgformula val parse_veqpkg : string -> veqpkg val parse_veqpkglist : string -> veqpkglist val parse_typedecl : string -> typedecl (** {6 Parsing of other CUDF entities} Mostly for application relying on CUDF conventions *) (** Parse a quoted string, enclosed by double quotes as it happens within the "property" property of preamble stanzas. The only place where such strings are allowed in CUDF are within type declarations; see {!Cudf_types_pp.parse_typedecl}. @return the parsed string after having resolved escaping and removed surrounding double quotes @raise Cudf_types.Syntax_error when the quoted string cannot be parsed *) val parse_qstring : string -> string (** Parse a CUDF type expression. At present it can be either a typename or an enum with its values. @raise Cudf_types.Syntax_error when the given string is not a valid type expression *) val parse_type : string -> typ (** Parse the enum value corresponding to the "keep" core property of package stanzas. Shorthand to avoid parsing the corresponding `Enum and then casting to {!Cudf_types.enum_keep} *) val parse_keep : string -> enum_keep (** generic, type-based parsing *) val parse_value : typ -> string -> typed_value (** {5 Pretty printers} *) (** {6 Pretty print to string} *) val string_of_int : int -> string val string_of_posint : int -> string val string_of_nat : int -> string val string_of_bool : bool -> string val string_of_keep : enum_keep -> string val string_of_pkgname : pkgname -> string val string_of_version : version -> string val string_of_vpkg : vpkg -> string val string_of_vpkglist : vpkglist -> string val string_of_vpkgformula : vpkgformula -> string val string_of_veqpkg : veqpkg -> string val string_of_veqpkglist : veqpkglist -> string val string_of_typedecl : typedecl -> string val string_of_type : typ -> string val string_of_value : typed_value -> string cudf-0.6.3/examples/000077500000000000000000000000001200672564300142645ustar00rootroot00000000000000cudf-0.6.3/examples/_tags000066400000000000000000000000421200672564300153000ustar00rootroot00000000000000<*.byte> or <*.native> : pkg_cudf cudf-0.6.3/examples/cudf-sort.ml000066400000000000000000000026331200672564300165300ustar00rootroot00000000000000(*****************************************************************************) (* libCUDF - CUDF (Common Upgrade Description Format) manipulation library *) (* Copyright (C) 2009 Stefano Zacchiroli *) (* *) (* This library is free software: you can redistribute it and/or modify *) (* it under the terms of the GNU Lesser General Public License as *) (* published by the Free Software Foundation, either version 3 of the *) (* License, or (at your option) any later version. A special linking *) (* exception to the GNU Lesser General Public License applies to this *) (* library, see the COPYING file for more information. *) (*****************************************************************************) (** Sort by an input CUDF or universe file *) open Cudf let pkg_compare p1 p2 = Pervasives.compare (p1.package, p1.version) (p2.package, p2.version) let main () = let ic = open_in Sys.argv.(1) in let p = Cudf_parser.from_in_channel ic in let pkgs, req = Cudf_parser.parse p in let pkgs' = List.fast_sort pkg_compare pkgs in let s = match req with | None -> Cudf_printer.string_of_packages pkgs' | Some req -> Cudf_printer.string_of_doc (pkgs', req) in print_endline s let _ = main () cudf-0.6.3/examples/legacy-sol-bad.cudf000066400000000000000000000012321200672564300177100ustar00rootroot00000000000000preamble: property: suite: enum[stable,testing,unstable] = [stable], bugs: int = [0], description: string = ["no description"] univ-checksum: 8c6d8b4d0cf7027cd523ad095d6408b4901ac31c package: car version: 1 depends: engine, wheel, door, battery installed: true description: 4-wheeled, motor-powered vehicle package: battery version: 3 provides: huge-battery installed: true package: wheel version: 3 conflicts: wheel installed: true suite: testing package: door version: 1 conflicts: door installed: true package: electric-engine version: 1 depends: solar-collector | huge-battery provides: engine conflicts: engine, electric-engine installed: true bugs: 12 cudf-0.6.3/examples/legacy-sol.cudf000066400000000000000000000013671200672564300171750ustar00rootroot00000000000000preamble: property: suite: enum[stable,testing,unstable] = [stable], bugs: int = [0], description: string = ["no description"] univ-checksum: 8c6d8b4d0cf7027cd523ad095d6408b4901ac31c package: car version: 1 depends: engine, wheel, door, battery installed: true description: 4-wheeled, motor-powered vehicle package: battery version: 3 provides: huge-battery installed: true package: wheel version: 3 conflicts: wheel installed: true suite: testing package: door version: 1 conflicts: door installed: true package: bicycle version: 7 installed: true description: 2-wheeled, "pedal-powered" vehicle package: electric-engine version: 1 depends: solar-collector | huge-battery provides: engine conflicts: engine, electric-engine installed: true bugs: 12 cudf-0.6.3/examples/universe-broken.cudf000066400000000000000000000024041200672564300202450ustar00rootroot00000000000000package: car version: 1 depends: engine, wheel, door, battery installed: true package: bicycle version: 7 package: gasoline-engine version: 1 depends: turbo provides: engine conflicts: engine, gasoline-engine installed: true package: gasoline-engine version: 2 conflicts: engine, gasoline-engine package: electric-engine version: 1 depends: solar-collector | huge-battery provides: engine conflicts: engine, electric-engine package: electric-engine version: 2 depends: solar-collector | huge-battery provides: engine conflicts: engine, electric-engine package: solar-collector version: 1 package: battery version: 3 provides: huge-battery installed: true package: wheel version: 2 conflicts: wheel installed: true package: wheel version: 3 conflicts: wheel package: door version: 1 conflicts: door installed: true package: door version: 2 depends: window conflicts: door package: turbo version: 1 installed: false package: tire version: 1 conflicts: tire package: tire version: 2 conflicts: tire package: window version: 1 conflicts: window package: window version: 2 depends: glass = 1 conflicts: window package: window version: 3 depends: glass = 2 conflicts: window package: glass version: 1 conflicts: glass package: glass version: 2 conflicts: glass, tire = 2 cudf-0.6.3/examples/universe.cudf000066400000000000000000000024031200672564300167660ustar00rootroot00000000000000package: car version: 1 depends: engine, wheel, door, battery installed: true package: bicycle version: 7 package: gasoline-engine version: 1 depends: turbo provides: engine conflicts: engine, gasoline-engine installed: true package: gasoline-engine version: 2 conflicts: engine, gasoline-engine package: electric-engine version: 1 depends: solar-collector | huge-battery provides: engine conflicts: engine, electric-engine package: electric-engine version: 2 depends: solar-collector | huge-battery provides: engine conflicts: engine, electric-engine package: solar-collector version: 1 package: battery version: 3 provides: huge-battery installed: true package: wheel version: 2 conflicts: wheel installed: true package: wheel version: 3 conflicts: wheel package: door version: 1 conflicts: door installed: true package: door version: 2 depends: window conflicts: door package: turbo version: 1 installed: true package: tire version: 1 conflicts: tire package: tire version: 2 conflicts: tire package: window version: 1 conflicts: window package: window version: 2 depends: glass = 1 conflicts: window package: window version: 3 depends: glass = 2 conflicts: window package: glass version: 1 conflicts: glass package: glass version: 2 conflicts: glass, tire = 2 cudf-0.6.3/header.txt000066400000000000000000000010101200672564300144270ustar00rootroot00000000000000libCUDF - CUDF (Common Upgrade Description Format) manipulation library Copyright (C) 2009-2012 Stefano Zacchiroli This library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. A special linking exception to the GNU Lesser General Public License applies to this library, see the COPYING file for more information. cudf-0.6.3/main_cudf_check.ml000066400000000000000000000116151200672564300160660ustar00rootroot00000000000000(*****************************************************************************) (* libCUDF - CUDF (Common Upgrade Description Format) manipulation library *) (* Copyright (C) 2009-2012 Stefano Zacchiroli *) (* *) (* This library is free software: you can redistribute it and/or modify *) (* it under the terms of the GNU Lesser General Public License as *) (* published by the Free Software Foundation, either version 3 of the *) (* License, or (at your option) any later version. A special linking *) (* exception to the GNU Lesser General Public License applies to this *) (* library, see the COPYING file for more information. *) (*****************************************************************************) open ExtLib open Printf open Cudf open Cudf_checker let cudf_arg = ref "" let univ_arg = ref "" let sol_arg = ref "" let dump_arg = ref false let cudf = ref None let univ = ref None let sol = ref None let arg_spec = [ "-cudf", Arg.Set_string cudf_arg, "parse the given CUDF (universe + request)" ; "-univ", Arg.Set_string univ_arg, "parse the given package universe" ; "-sol", Arg.Set_string sol_arg, "parse the given problem solution" ; "-dump", Arg.Set dump_arg, "dump parse results to standard output" ; ] let usage_msg = "Usage: cudf-check [OPTION...] In particular: cudf-check -cudf FILE validate CUDF cudf-check -cudf FILE -sol FILE validate CUDF and its solution cudf-check -univ FILE validate package universe (no request) Options:" let die_usage () = Arg.usage arg_spec usage_msg ; exit (-2) let print_inst_info inst = match is_consistent inst with | true, _ -> printf "original installation status consistent\n%!" | false, Some r -> printf "original installation status inconsistent (reason: %s)\n%!" (explain_reason (r :> bad_solution_reason)) | _ -> assert false let print_cudf (pre, univ, req) = if !dump_arg then begin let pre' = Option.default Cudf.default_preamble pre in Cudf_printer.pp_cudf stdout (pre', univ, req) end let print_univ univ = if !dump_arg then Cudf_printer.pp_universe stdout univ let print_sol_info inst sol = match is_solution inst sol with | true, _ -> printf "is_solution: true\n%!" | false, rs -> printf "is_solution: false (reason: %s)\n%!" (String.concat "; " (List.map explain_reason rs)) let pp_loc (start_pos, end_pos) = let line { Lexing.pos_lnum = l } = l in if line start_pos = line end_pos then sprintf "line: %d" (line start_pos) else sprintf "lines: %d-%d" (line start_pos) (line end_pos) let main () = let load_univ p = let pre,univ,req = Cudf_parser.load p in univ in let fail_parse source msg loc = eprintf "Error while parsing %s: %s\n" source msg ; eprintf "Location: %s\n%!" (pp_loc loc) ; exit 1 in if !cudf_arg <> "" then begin try let p = Cudf_parser.from_in_channel (open_in !cudf_arg) in eprintf "loading CUDF ...\n%!"; (match Cudf_parser.load p with | pre, univ, None -> eprintf "Error: missing request description item.\n%!"; exit (-1) | pre, univ, Some req -> cudf := Some (pre, univ, req)) with | Cudf_parser.Parse_error (msg, loc) -> fail_parse "CUDF" msg loc | Cudf.Constraint_violation _ as exn -> eprintf "Error while loading CUDF from %s: %s\n%!" !cudf_arg (Printexc.to_string exn); exit (-1) end; if !univ_arg <> "" then begin try let p = Cudf_parser.from_in_channel (open_in !univ_arg) in eprintf "loading package universe ...\n%!"; univ := Some (load_univ p) with | Cudf_parser.Parse_error (msg, loc) -> fail_parse "universe" msg loc | Cudf.Constraint_violation _ as exn -> eprintf "Error while loading universe from %s: %s\n%!" !univ_arg (Printexc.to_string exn); exit (-1) end; if !sol_arg <> "" then (* postpone solution parsing, we need the input CUDF for that *) sol := Some (Cudf_parser.from_in_channel (open_in !sol_arg)); match !cudf, !univ, !sol with | Some (pre,univ,req), None, None -> print_inst_info univ; print_cudf (pre,univ,req) | Some (pre,univ,req), None, Some sol_parser -> (try eprintf "loading solution ...\n%!"; let _pre', sol = Cudf_parser.load_solution sol_parser univ in print_inst_info univ; print_sol_info (univ,req) sol; print_cudf (pre,univ,req) with | Cudf_parser.Parse_error (msg, loc) -> fail_parse "solution" msg loc | Cudf.Constraint_violation _ as exn -> eprintf "Error while loading solution from %s: %s\n%!" !sol_arg (Printexc.to_string exn); exit (-1)) | None, Some univ, None -> print_inst_info univ; print_univ univ | _ -> die_usage () let _ = Arg.parse arg_spec ignore usage_msg; main() cudf-0.6.3/main_cudf_parse_822.ml000066400000000000000000000034171200672564300165170ustar00rootroot00000000000000(*****************************************************************************) (* libCUDF - CUDF (Common Upgrade Description Format) manipulation library *) (* Copyright (C) 2009-2012 Stefano Zacchiroli *) (* *) (* This library is free software: you can redistribute it and/or modify *) (* it under the terms of the GNU Lesser General Public License as *) (* published by the Free Software Foundation, either version 3 of the *) (* License, or (at your option) any later version. A special linking *) (* exception to the GNU Lesser General Public License applies to this *) (* library, see the COPYING file for more information. *) (*****************************************************************************) open Printf open Cudf_types let file_arg = ref "" let arg_spec = [ ] let usage_msg = "Usage: cudf-parse-822 FILE" let die_usage () = Arg.usage arg_spec usage_msg ; exit (-2) let pp_822 = let pp_stanza stanza = List.iter (fun (k, (_loc, v)) -> printf "%s: %s\n%!" k v) stanza; print_newline () in List.iter pp_stanza let pp_lpos { Lexing.pos_fname = _fname; pos_lnum = lnum; pos_bol = bol; pos_cnum = cnum } = sprintf "%d:%d" lnum (cnum - bol) let main () = Arg.parse arg_spec ((:=) file_arg) usage_msg; if !file_arg = "" then die_usage (); let ic = open_in !file_arg in let lexbuf = Lexing.from_channel ic in try let stanzas = Cudf_822_parser.doc_822 Cudf_822_lexer.token_822 lexbuf in pp_822 stanzas with Parse_error_822 (msg, (startpos, endpos)) -> failwith (sprintf "Parse error on file %s:%s--%s" !file_arg (pp_lpos startpos) (pp_lpos endpos)) let _ = main () cudf-0.6.3/myocamlbuild.ml000066400000000000000000000076621200672564300154740ustar00rootroot00000000000000(*****************************************************************************) (* libCUDF - CUDF (Common Upgrade Description Format) manipulation library *) (* Copyright (C) 2009-2012 Stefano Zacchiroli *) (* *) (* This library is free software: you can redistribute it and/or modify *) (* it under the terms of the GNU Lesser General Public License as *) (* published by the Free Software Foundation, either version 3 of the *) (* License, or (at your option) any later version. A special linking *) (* exception to the GNU Lesser General Public License applies to this *) (* library, see the COPYING file for more information. *) (*****************************************************************************) open Ocamlbuild_plugin (* these functions are not really officially exported *) let run_and_read = Ocamlbuild_pack.My_unix.run_and_read let blank_sep_strings = Ocamlbuild_pack.Lexers.blank_sep_strings let split s ch = let x = ref [] in let rec go s = let pos = String.index s ch in x := (String.before s pos)::!x; go (String.after s (pos + 1)) in try go s with Not_found -> !x let split_nl s = split s '\n' let before_space s = try String.before s (String.index s ' ') with Not_found -> s (* this lists all supported packages *) let find_packages () = List.map before_space (split_nl & run_and_read "ocamlfind list") (* this is supposed to list available syntaxes, but I don't know how to do it. *) let find_syntaxes () = ["camlp4o"; "camlp4r"] (* ocamlfind command *) let ocamlfind x = S[A"ocamlfind"; x] let _ = dispatch begin function | Before_options -> (* by using Before_options one let command line options have an higher priority on the contrary using After_options will guarantee to have the higher priority *) (* override default commands by ocamlfind ones *) Options.ocamlc := ocamlfind & A"ocamlc"; Options.ocamlopt := ocamlfind & A"ocamlopt"; Options.ocamldep := ocamlfind & A"ocamldep"; Options.ocamldoc := ocamlfind & A"ocamldoc"; Options.ocamlmktop := ocamlfind & A"ocamlmktop" | After_rules -> (* When one link an OCaml library/binary/package, one should use -linkpkg *) flag ["ocaml"; "link"] & A"-linkpkg"; (* For each ocamlfind package one inject the -package option when compiling, computing dependencies, generating documentation and linking. *) List.iter begin fun pkg -> flag ["ocaml"; "compile"; "pkg_"^pkg] & S[A"-package"; A pkg]; flag ["ocaml"; "ocamldep"; "pkg_"^pkg] & S[A"-package"; A pkg]; flag ["ocaml"; "doc"; "pkg_"^pkg] & S[A"-package"; A pkg]; flag ["ocaml"; "link"; "pkg_"^pkg] & S[A"-package"; A pkg]; end (find_packages ()); (* Like -package but for extensions syntax. Morover -syntax is useless when linking. *) List.iter begin fun syntax -> flag ["ocaml"; "compile"; "syntax_"^syntax] & S[A"-syntax"; A syntax]; flag ["ocaml"; "ocamldep"; "syntax_"^syntax] & S[A"-syntax"; A syntax]; flag ["ocaml"; "doc"; "syntax_"^syntax] & S[A"-syntax"; A syntax]; end (find_syntaxes ()); (* The default "thread" tag is not compatible with ocamlfind. Indeed, the default rules add the "threads.cma" or "threads.cmxa" options when using this tag. When using the "-linkpkg" option with ocamlfind, this module will then be added twice on the command line. To solve this, one approach is to add the "-thread" option when using the "threads" package using the previous plugin. *) flag ["ocaml"; "pkg_threads"; "compile"] (S[A "-thread"]); flag ["ocaml"; "pkg_threads"; "link"] (S[A "-thread"]) | _ -> () end cudf-0.6.3/test.ml000066400000000000000000000016331200672564300137620ustar00rootroot00000000000000(*****************************************************************************) (* libCUDF - CUDF (Common Upgrade Description Format) manipulation library *) (* Copyright (C) 2009-2012 Stefano Zacchiroli *) (* *) (* This library is free software: you can redistribute it and/or modify *) (* it under the terms of the GNU Lesser General Public License as *) (* published by the Free Software Foundation, either version 3 of the *) (* License, or (at your option) any later version. A special linking *) (* exception to the GNU Lesser General Public License applies to this *) (* library, see the COPYING file for more information. *) (*****************************************************************************) let _ = OUnit.run_test_tt_main Tests.all cudf-0.6.3/tests.ml000066400000000000000000000601421200672564300141450ustar00rootroot00000000000000(*****************************************************************************) (* libCUDF - CUDF (Common Upgrade Description Format) manipulation library *) (* Copyright (C) 2009-2012 Stefano Zacchiroli *) (* *) (* This library is free software: you can redistribute it and/or modify *) (* it under the terms of the GNU Lesser General Public License as *) (* published by the Free Software Foundation, either version 3 of the *) (* License, or (at your option) any later version. A special linking *) (* exception to the GNU Lesser General Public License applies to this *) (* library, see the COPYING file for more information. *) (*****************************************************************************) open ExtLib open OUnit open Printf open Cudf_types open Cudf let cudf_test_path name = sprintf "./tests/%s.cudf" name let good_cudfs = [ (* CUDF whose parsing must suceed *) "empty-vpkglist-default" ; "empty-vpkglist-explicit" ; "comment-within-stanza" ; "comment-at-eof" ; "only-request" ; ] let bad_cudfs = [ (* CUDF whose parsing must fail (@ location) *) "line-111", (111, 111) ; "miss-mandatory-prop", (9, 9) ; "default-type-check-error", (2, 2) ; "dup-property", (5, 6) ; "missing-stanza-sep-1", (5, 6) ; "missing-stanza-sep-2", (3, 3) ; ] let consistent_univs = [ (* CUDF whose status is expected to be consistent *) "assert-true" ; ] let inconsistent_univs = [ (* CUDF whose status has some broken dep *) "assert-false" ; ] let good_pkgs = [ (* universes whose parsing must suceed *) "conflict-comma-sep" ; "plus-in-pkgname" ; "empty" ; ] let bad_pkgs = [ (* universes whose parsing must fail (@ location) *) "multiline-error", (93, 95) ; ] let good_prob_sol = [ (* pairs cudf/sol, with sol being a good solution *) "legacy", "legacy-sol" ; "fresher", "fresher-sol-good" ; "upgrade-singleton", "upgrade-singleton-sol-good" ; "keep", "keep-sol-good"; "virt-upgrade", "virt-upgrade-sol-good"; "keep-uninst", "keep-uninst-good"; ] let bad_prob_sol = [ (* pairs cudf/sol, with sol being a bad solution *) "fresher", "fresher-sol-bad" ; "upgrade-singleton", "upgrade-singleton-sol-bad" ; "keep", "keep-sol-bad"; "keep", "keep-sol-bad2"; "keep", "keep-sol-bad3"; "virt-upgrade", "virt-upgrade-sol-bad"; "virt-upgrade", "virt-upgrade-sol-bad2"; "virt-upgrade", "virt-upgrade-sol-bad3"; "unknown-pkg", "unknown-pkg.sol"; ] (** {5 Helpers} *) (** {6 OUnit helpers} i.e., missing stuff which should better be integrated into OUnit *) let assert_no_exn f = assert_equal true (try f () ; true with _ -> false) let assert_exn f = assert_equal true (try f () ; false with _ -> true) let assert_raises' ?(cmp = (=)) ~exn f = assert_equal true (try f () ; false with exn' -> cmp exn exn') (** {6 CUDF helpers} *) let parse_test ~parse_fun name = let ic = open_in (cudf_test_path name) in let p = Cudf_parser.from_in_channel ic in let out = parse_fun p in close_in ic; out let parse_cudf_wrapper p = match Cudf_parser.parse p with | pre, pkgs, Some req -> pre, pkgs, req | pre, pkgs, None -> raise (Cudf_parser.Parse_error ("", dummy_loc)) let parse_pkgs_wrapper p = match Cudf_parser.parse p with | pre, pkgs, Some req -> raise (Cudf_parser.Parse_error ("", dummy_loc)) | pre, pkgs, None -> pkgs let load_cudf_wrapper p = match Cudf_parser.load p with | pre, pkgs, Some req -> pre, pkgs, req | pre, pkgs, None -> raise (Cudf_parser.Parse_error ("", dummy_loc)) let load_pkgs_wrapper p = match Cudf_parser.load p with | pre, pkgs, Some req -> raise (Cudf_parser.Parse_error ("", dummy_loc)) | pre, pkgs, None -> pkgs let parse_cudf_test = parse_test ~parse_fun:parse_cudf_wrapper let parse_pkgs_test = parse_test ~parse_fun:parse_pkgs_wrapper let load_cudf_test = parse_test ~parse_fun:load_cudf_wrapper let load_univ_test = parse_test ~parse_fun:load_pkgs_wrapper (** {!OUnit.assert_equal} proxy for {!Cudf_types.typed_value} values *) let assert_equal_tyval ?cmp ?pp_diff ?msg expected real = let printer = Cudf_types_pp.string_of_value in OUnit.assert_equal ?cmp ~printer ?pp_diff ?msg expected real let assert_equal_string ?cmp ?pp_diff ?msg expected real = let printer s = s in OUnit.assert_equal ?cmp ~printer ?pp_diff ?msg expected real let string_of_int_list l = sprintf "[%s]" (String.concat ";" (List.map string_of_int l)) (** {5 Test builders} *) let good_parse ~parse_fun name = TestCase (fun _ -> assert_no_exn (fun () -> parse_test ~parse_fun name)) let bad_parse ~parse_fun name (l1, l2) = TestCase (fun _ -> assert_raises' ~cmp:(fun e1 e2 -> match e1, e2 with | Cudf_parser.Parse_error _, Cudf_parser.Parse_error (_msg, (loc1, loc2)) -> loc1.Lexing.pos_lnum = l1 && loc2.Lexing.pos_lnum = l2 | _ -> false) ~exn:(Cudf_parser.Parse_error ("", dummy_loc)) (fun () -> parse_test ~parse_fun name)) let good_solution prob_name sol_name = TestCase (fun _ -> let (_,univ,req), sol = load_cudf_test prob_name, load_univ_test sol_name in sprintf "problem with correct solution: (%s,%s)" prob_name sol_name @? fst (Cudf_checker.is_solution (univ,req) sol)) let bad_solution prob_name sol_name = TestCase (fun _ -> let (_,univ,req), sol = load_cudf_test prob_name, load_univ_test sol_name in sprintf "problem with correct solution: (%s,%s)" prob_name sol_name @? not (fst (Cudf_checker.is_solution (univ,req) sol))) (** {5 Test suites} *) (** {6 Big suites} *) let good_cudf_parse_suite = "parsing of good CUDFs" >::: List.map (fun n -> n >: good_parse ~parse_fun:parse_cudf_wrapper n) good_cudfs let bad_cudf_parse_suite = "parsing of bad CUDFs" >::: List.map (fun (n, (l1, l2)) -> n >: bad_parse ~parse_fun:parse_cudf_wrapper n (l1, l2)) bad_cudfs let good_pkgs_parse_suite = "parsing of good package universes" >::: List.map (fun n -> n >: good_parse ~parse_fun:parse_pkgs_wrapper n) good_pkgs let bad_pkgs_parse_suite = "parsing of bad package universes" >::: List.map (fun (n, (l1, l2)) -> n >: bad_parse ~parse_fun:parse_pkgs_wrapper n (l1,l2)) bad_pkgs (** {6 Regression tests} *) let value_parse_suite = let value_parse_ok (desc, typ, s, v) = desc >: TestCase (fun _ -> assert_equal_tyval (Cudf_types_pp.parse_value typ s) v) in let value_parse_ko (desc, typ, s) = desc >: TestCase (fun _ -> assert_raises' ~cmp:(fun e1 e2 -> match e1, e2 with | Cudf_types_pp.Type_error _, Cudf_types_pp.Type_error _ -> true | _ -> e1 = e2) ~exn:(Cudf_types_pp.Type_error (`Int, `Int ~-1)) (fun () -> Cudf_types_pp.parse_value typ s)) in "value parsing" >::: [ "good" >::: List.map value_parse_ok [ "int 1", `Int, "1", `Int 1 ; "int -1", `Int, "-1", `Int ~-1 ; "posint", `Posint, "1", `Posint 1 ; "nat 0", `Nat, "0", `Nat 0 ; "bool true", `Bool, "true", `Bool true ; "bool false", `Bool, "false", `Bool false ; "string", `String, "asfkjg 1%!@$% aaa", `String "asfkjg 1%!@$% aaa" ; "pkgname", `Pkgname, "foo", `Pkgname "foo" ; "pkgname /", `Pkgname, "/bin/bash", `Pkgname "/bin/bash" ; "pkgname @", `Pkgname, "libfoo@bar", `Pkgname "libfoo@bar" ; "pkgname ()", `Pkgname, "libfoo(bar)", `Pkgname "libfoo(bar)" ; "ident", `Ident, "foo", `Ident "foo" ; "ident -", `Ident, "foo-bar", `Ident "foo-bar" ; "ident num", `Ident, "foo12", `Ident "foo12" ; "enum", `Enum ["foo";"bar";"baz"], "foo", `Enum(["foo";"bar";"baz"], "foo") ; "keep", keep_type, "feature", `Enum (keep_enums, "feature") ; "vpkg dumb", `Vpkg, "foo", `Vpkg ("foo", None) ; "vpkg", `Vpkg, "foo > 1", `Vpkg ("foo", Some (`Gt, 1)) ; "fmla vpkg", `Vpkgformula, "foo", `Vpkgformula [["foo", None]] ; "fmla true", `Vpkgformula, "true!", `Vpkgformula [] ; "fmla false", `Vpkgformula, "false!", `Vpkgformula [ [] ] ; "fmla and", `Vpkgformula, "foo, bar > 1", `Vpkgformula [ ["foo", None] ; ["bar", Some (`Gt, 1)] ] ; "fmla or", `Vpkgformula, "foo < 7 | bar", `Vpkgformula [ ["foo", Some (`Lt, 7) ; "bar", None] ] ; "fmla cnf", `Vpkgformula, "foo | bar, quux | baz | sup", `Vpkgformula [ ["foo",None; "bar",None] ; ["quux",None; "baz",None; "sup",None] ] ; "vpkgs nil", `Vpkglist, "", `Vpkglist [] ; "vpkgs one", `Vpkglist, "foo", `Vpkglist ["foo", None] ; "vpkgs cons", `Vpkglist, "foo != 1, bar", `Vpkglist [ "foo", Some (`Neq, 1) ; "bar", None ] ; "veqpkg", `Veqpkg, "foo = 7", `Veqpkg ("foo", Some (`Eq, 7)) ; "veqpkgs", `Veqpkglist, "foo = 7", `Veqpkglist [("foo", Some (`Eq, 7))] ; "typedecl", `Typedecl, "foo: vpkgformula = [ foo, bar | baz ]", `Typedecl ["foo", `Vpkgformula (Some [["foo",None];["bar",None;"baz",None]])] ; "typedecls", `Typedecl, "foo: int, bar: string = [\"baz quux\"]", `Typedecl ["foo", `Int None ; "bar", `String (Some "baz quux")] ; "typedecl enum", `Typedecl, "p: enum[a,b,c]", `Typedecl ["p", `Enum (["a"; "b"; "c"], None)] ; "typedecl enum def", `Typedecl, "p: enum[a,b,c] = [a]", `Typedecl ["p", `Enum (["a"; "b"; "c"], Some "a")] ; "typedecl pkgname ident", `Typedecl, "p: pkgname = [ pkg ]", `Typedecl ["p", `Pkgname (Some "pkg")] ; "typedecl pkgname int", `Typedecl, "p: pkgname = [ 1 ]", `Typedecl ["p", `Pkgname (Some "1")] ; "typedecl vpkg ident", `Typedecl, "p: vpkg = [ pkg ]", `Typedecl ["p", `Vpkg (Some ("pkg", None))] ; "typedecl vpkg int", `Typedecl, "p: vpkg = [ 1 ]", `Typedecl ["p", `Vpkg (Some ("1", None))] ; "typedecl veqpkg int", `Typedecl, "p: veqpkg = [ 1 ]", `Typedecl ["p", `Veqpkg (Some ("1", None))] ; "typedecl vpkgs ident", `Typedecl, "l: vpkglist = [ pkg ]", `Typedecl ["l", `Vpkglist (Some [("pkg", None)])] ; "typedecl vpkgs int", `Typedecl, "l: vpkglist = [ 1 ]", `Typedecl ["l", `Vpkglist (Some [("1", None)])] ; "typedecl veqpkgs int", `Typedecl, "l: veqpkglist = [ 1 ]", `Typedecl ["l", `Veqpkglist (Some [("1", None)])] ; ] ; "bad" >::: List.map value_parse_ko [ "int garbage", `Int, "78 gotcha" ; "posint neg", `Posint, "-1" ; "posint zero", `Posint, "0" ; "nat neg", `Nat, "-1" ; "bool", `Bool, "xxx" ; "bool", `Bool, "foo" ; "bool garbage", `Bool, "true gotcha" ; "string \\n", `String, "foo\nbar" ; "string \\r", `String, "foo\rbar" ; "pkgname !", `Pkgname, "foo!bar" ; "pkgname !", `Pkgname, "foo!bar" ; "ident numstart", `Ident, "12foo" ; "ident caps", `Ident, "foAo" ; "ident symb", `Ident, "fo/o" ; "enum", `Enum ["foo"], "bar" ; "keep", keep_type, "foo" ; "empty fmla", `Vpkgformula, "" ; "vpkg garbage", `Vpkg, "foo > 1 gotcha" ; "vpkgs trail", `Vpkglist, "foo ," ; "veqpkg", `Veqpkg, "foo > 1" ; "enum bad def", `Typedecl, "p: enum[a,b,c] = [z]" ; ] ; ] let property_access_suite = let pre, univ, req = load_cudf_test "legacy" in let pre = Option.get pre in let pkg = lookup_package univ ("gasoline-engine", 1) in let pre_ty (p, v) = p >:: (fun _ -> assert_equal_tyval v (lookup_typed_preamble_property pre p)) in let pkg_ty (p, v) = p >:: (fun _ -> assert_equal_tyval v (lookup_typed_package_property pkg p)) in let req_ty (p, v) = p >:: (fun _ -> assert_equal_tyval v (lookup_typed_request_property req p)) in let pre_raw (p, v) = p >:: (fun _ -> assert_equal_string v (lookup_preamble_property pre p)) in let pkg_raw (p, v) = p >:: (fun _ -> assert_equal_string v (lookup_package_property pkg p)) in let req_raw (p, v) = p >:: (fun _ -> assert_equal_string v (lookup_request_property req p)) in "property access" >::: [ "raw" >::: [ "preamble" >::: List.map pre_raw [ "univ-checksum", "8c6d8b4d0cf7027cd523ad095d6408b4901ac31c"; "status-checksum", "6936ce910eb716ad97190393f80c14ab04d95b3d"; "req-checksum", "17259225eaf63642f9ab99a627b9857a5b27c5f7"; ] ; "package" >::: List.map pkg_raw [ "package", "gasoline-engine"; "version", "1"; "depends", "turbo"; "provides", "engine"; "conflicts", "engine , gasoline-engine"; "installed", "true"; ] ; "request" >::: List.map req_raw [ "request", "http://www.example.org/8f46e388-042f-415e-8aab-df4eeb974444.dudf"; "install", "bicycle , electric-engine = 1"; "upgrade", "door , wheel > 2"; ] ; ] ; "typed" >::: [ "preamble" >::: List.map pre_ty [ "univ-checksum", (`String "8c6d8b4d0cf7027cd523ad095d6408b4901ac31c"); "status-checksum", (`String "6936ce910eb716ad97190393f80c14ab04d95b3d"); "req-checksum", (`String "17259225eaf63642f9ab99a627b9857a5b27c5f7"); ] ; "package" >::: List.map pkg_ty [ "package", (`Pkgname "gasoline-engine"); "version", (`Posint 1); "depends", (`Vpkgformula [["turbo", None]]); "provides", (`Veqpkglist ["engine", None]); "conflicts", (`Vpkglist ["engine", None; "gasoline-engine", None]); "installed", (`Bool true); ] ; "request" >::: List.map req_ty [ "request", (`String "http://www.example.org/8f46e388-042f-415e-8aab-df4eeb974444.dudf"); "install", (`Vpkglist ["bicycle", None; "electric-engine", Some (`Eq, 1)]); "upgrade", (`Vpkglist ["door", None; "wheel", Some (`Gt, 2)]); ] ; ] ] let value_pp_suite = let value_pp_ok (desc, v, s) = desc >: TestCase (fun _ -> assert_equal_string (Cudf_types_pp.string_of_value v) s) in let decl_pp_ok (desc, v, s) = desc >: TestCase (fun _ -> assert_equal_string (Cudf_types_pp.string_of_typedecl v) s) in "value pretty printing" >::: [ "good value" >::: List.map value_pp_ok [ ] ; "good decl" >::: List.map decl_pp_ok [ "default string", ["source", `String (Some "")], "source: string = [\"\"]" ; "default string escape", ["source", `String (Some "\"")], "source: string = [\"\\\"\"]" ; ] ; "bad vpkgformula" >:: (fun () -> assert_exn (fun () -> (* should "assert false" *) Cudf_types_pp.string_of_vpkgformula [ []; [] ])) ] let cudf_pp_suite = (** check that the pretty printing roundtrip (parse -> pp -> parse) returns the same document than plain parsing *) let cudf_pp_roundtrip name = name >: TestCase (fun _ -> let (pre, univ, req) as doc = parse_cudf_test name in let fname, oc = Filename.open_temp_file "libcudf-test." ".cudf" in finally (fun () -> Sys.remove fname) (fun () -> Cudf_printer.pp_doc oc doc; close_out oc; let doc' = Cudf_parser.parse_from_file fname in let doc = pre, univ, Some req in assert_equal doc doc') ()) in (** check that pretty printing of a document returns some canonical pretty printed document (hence, this test is more fragile than [cudf_pp_roundtrip] above) *) let cudf_pp_canonical name = name >: TestCase (fun _ -> let (pre, univ, req) as doc = parse_cudf_test name in let fname, oc = Filename.open_temp_file "libcudf-test." ".cudf" in finally (fun () -> Sys.remove fname) (fun () -> let expected_pp_file = cudf_test_path (sprintf "%s.pp" name) in let expected_pp = input_file expected_pp_file in Cudf_printer.pp_doc oc doc; close_out oc; let actual_pp = input_file fname in if expected_pp != actual_pp then ignore (Sys.command (sprintf "diff %s %s" expected_pp_file fname)); assert_equal expected_pp actual_pp) ()) in "cudf pretty printing" >::: [ "roundtrip" >::: List.map cudf_pp_roundtrip [ "legacy" ]; "canonical" >::: List.map cudf_pp_canonical [ "legacy" ]; ] let misc_parse_suite = "misc parsing" >::: [ "qstring" >::: [ "base" >:: (fun () -> assert_equal_string (Cudf_types_pp.parse_qstring "\"foo\"") "foo") ; "escape \"" >:: (fun () -> assert_equal_string (Cudf_types_pp.parse_qstring "\"fo\\\"o\"") "fo\"o") ; "escape \\" >:: (fun () -> assert_equal_string (Cudf_types_pp.parse_qstring "\"fo\\\\o\"") "fo\\o") ; "dangling \"" >:: (fun () -> "unexpected parse success" @? (try ignore (Cudf_types_pp.parse_qstring "\"fo\"o\"") ; false with _ -> true)) ; "typename ident" >:: (fun () -> assert_equal ~printer:Cudf_types_pp.string_of_type (Cudf_types_pp.parse_type "ident") `Ident) ; ]; "pkg comparison" >::: [ "=%" >:: (fun () -> let pkg1 = { default_package with installed = true } in let pkg2 = { default_package with installed = false } in assert_equal ~cmp:(=%) pkg1 pkg2); "<%" >:: (fun () -> let pkg1 = { default_package with installed = true } in let pkg2 = { default_package with installed = false } in let l1 = [ pkg1 ; pkg2 ] in let l2 = [ pkg2 ; pkg1 ] in let rec pkgs_eq pkgs1 pkgs2 = match pkgs1, pkgs2 with | [], [] -> true | p1::t1, p2::t2 -> (p1 =% p2) && pkgs_eq t1 t2 | _ -> assert false in assert_equal ~cmp:pkgs_eq (List.sort ~cmp:(<%) l1) (List.sort ~cmp:(<%) l2)); ]; ] let or_dep = "disjunctive dependencies" >:: (fun () -> assert_equal ~printer:Cudf_types_pp.string_of_vpkgformula (lookup_package (load_univ_test "or-dep") ("electric-engine", 1)).depends [["solar-collector", None; "huge-battery", None]]) let parse_reg_suite = "regression tests - parsing" >::: [ or_dep ; ] (** {6 New feature tests} i.e., kinda test-driven development *) let status_filtering = "status projection" >:: (fun () -> "status projection returned an \"installed: false\" package" @? let _, univ, _ = load_cudf_test "legacy" in List.for_all (fun { installed = i } -> i) (get_packages (status univ))) let status_sizes = "status projection size" >:: (fun _ -> let _, univ, _ = load_cudf_test "legacy" in let status = status univ in let assert_equal' x y = assert_equal ~printer:string_of_int x y in assert_equal' 6 (universe_size status); assert_equal' 6 (installed_size status); assert_equal' (installed_size univ) (installed_size status)) let inst_version_lookup = "lookup installed versions" >:: (fun () -> let univ = load_univ_test "multi-versions" in let versions pkg = List.map (fun p -> p.version) (get_installed univ pkg) in assert_equal ~printer:string_of_int_list (List.sort (versions "gasoline-engine")) [1; 2]; assert_equal ~printer:string_of_int_list (versions "battery") [3]; assert_equal ~printer:string_of_int_list (versions "not-installed") []; assert_equal ~printer:string_of_int_list (versions "not-existent") []) let mem_installed = "check whether an installation satisfy a package constraint" >:: (fun () -> let _, univ, _ = load_cudf_test "legacy" in let mem = mem_installed ~include_features:true univ in let mem' = mem_installed ~include_features:false univ in "'car' unsatisfied" @? mem ("car", None); "'car = 1' unsatisfied" @? mem ("car", Some (`Eq, 1)); "'car > 1' satisfied'" @? not (mem ("car", Some (`Gt, 1))); "'car >= 1' unsatisfied" @? mem ("car", Some (`Leq, 1)); "'engine' unsatisfied w features" @? mem ("engine", None); "'engine' satisfied w/o features" @? not (mem' ("engine", None)); ) let mem_package = "Cudf.mem_package" >:: (fun () -> let _, univ, _ = load_cudf_test "legacy" in let mem = mem_package univ in " available" @? mem ("car", 1); " unavailable" @? not (mem ("car", 2)); " available" @? mem ("bicycle", 7); " unavailable" @? not (mem ("bicycle", 8)); " unavailable" @? not (mem ("zuff", 1)); ) let satisfy_formula = "check formula satisfaction" >:: (fun () -> let _, univ, _ = load_cudf_test "legacy" in let sat f = fst (Cudf_checker.satisfy_formula univ f) in "true unsatisfied (WTF?)" @? sat []; "conjunction unsatisfied" @? sat [["battery", None]; ["wheel", None]]; "disjunction unsatisfied" @? sat [["solar-collector", None; "wheel", None]]; "unsat formula satisfied" @? not (sat [["wheel", Some (`Gt, 2); "tire", None]]); ) let disjoint = "check package disjunction (i.e., conflicts)" >:: (fun () -> let _, univ, _ = load_cudf_test "legacy" in let disj ps = fst (Cudf_checker.disjoint univ ps) in "missing package reported as existing" @? disj ["fubar", None]; "undetected conflict" @? not (disj ["door", Some (`Eq, 1)]); "undetected partial conflict" @? not (disj ["door", Some (`Gt, 1); "turbo", None]); ) let self_conflicts = "check self-conflicts" >:: (fun () -> let consist u = fst (Cudf_checker.is_consistent u) in "direct self-conflict" @? consist (load_univ_test "direct-self-conflict"); "indirect self-conflict" @? consist (load_univ_test "indirect-self-conflict")) let consistency = "check universe consistency" >::: [ "legacy example consistency" >:: (fun () -> let _, univ, _ = load_cudf_test "legacy" in "inconsistent legacy example" @? fst (Cudf_checker.is_consistent univ)) ] let univ_sizes = let univ = lazy (let _, univ, _ = load_cudf_test "legacy" in univ) in "check universe size measuring" >::: [ "total size" >:: (fun () -> assert_equal ~printer:string_of_int (universe_size (Lazy.force univ)) 20); "installed size" >:: (fun () -> assert_equal ~printer:string_of_int (installed_size (Lazy.force univ)) 6); ] let default_value = let univ = lazy (let _, univ, _ = load_cudf_test "legacy" in univ) in "default value of opt prop" >::: [ "bugs" >:: (fun () -> let car = lookup_package (Lazy.force univ) ("car", 1) in let bugs = List.assoc "bugs" car.pkg_extra in assert_equal_tyval (`Int 0) bugs) ] let good_solution_suite = "good solutions" >::: List.map (fun (prob, sol) -> good_solution prob sol) good_prob_sol let bad_solution_suite = "bad solutions" >::: List.map (fun (prob, sol) -> bad_solution prob sol) bad_prob_sol let consistency_suite = "consistent universes" >::: List.map (fun u -> TestCase (fun () -> "consistent" @? fst (Cudf_checker.is_consistent (load_univ_test u)))) consistent_univs let inconsistency_suite = "inconsistent universes" >::: List.map (fun u -> TestCase (fun () -> "inconsistent" @? not (fst (Cudf_checker.is_consistent (load_univ_test u))))) inconsistent_univs let typedecl_lookup = "type declaration lookup" >::: let pre, _univ, _req = load_cudf_test "legacy" in let pre = Option.get pre in let test_typedecl (prop, typedecl1) = prop >:: (fun _ -> assert_equal ~printer:Std.dump (* TODO use/write a better printer *) typedecl1 (lookup_package_typedecl ~extra:pre.property prop)) in List.map test_typedecl [ "package", `Pkgname None; "version", `Posint None; "depends", `Vpkgformula (Some []); "conflicts", `Vpkglist (Some []); "provides", `Veqpkglist (Some []); "installed", `Bool (Some false); "was-installed", `Bool (Some false); "keep", `Enum (keep_enums, Some "none"); "suite", `Enum (["stable"; "testing"; "unstable"], Some "stable"); "bugs", `Int (Some 0); "description", `String (Some "no description"); ] (** {6 Test suites} *) let feature_suite = "new feature tests" >::: [ status_filtering ; status_sizes ; inst_version_lookup ; mem_installed ; mem_package ; satisfy_formula ; disjoint ; self_conflicts ; consistency ; univ_sizes ; default_value ; typedecl_lookup ; ] (* let test_encode = "encode" >:: (fun () -> let s = "@/bin/*-+" in assert_equal (Cudf_types.encode s) "@/bin/%2a-+" ) ;; let test_decode = "encode" >:: (fun () -> let s = "@/bin/%2a-+" in assert_equal (Cudf_types.decode s) "@/bin/*-+" ) ;; let encoding_suite = "encoding / decoding tests" >::: [ test_encode; test_decode ] *) (** {5 Assemble and run tests} *) let all = "all tests" >::: [ value_parse_suite ; value_pp_suite ; property_access_suite ; cudf_pp_suite ; misc_parse_suite ; good_cudf_parse_suite ; bad_cudf_parse_suite ; good_pkgs_parse_suite ; bad_pkgs_parse_suite ; consistency_suite ; inconsistency_suite ; good_solution_suite ; bad_solution_suite ; parse_reg_suite ; feature_suite ; (* encoding_suite ; *) ] cudf-0.6.3/tests/000077500000000000000000000000001200672564300136105ustar00rootroot00000000000000cudf-0.6.3/tests/assert-false.cudf000066400000000000000000000000711200672564300170420ustar00rootroot00000000000000package: hard depends: false! installed: true version: 1 cudf-0.6.3/tests/assert-true.cudf000066400000000000000000000000701200672564300167260ustar00rootroot00000000000000package: easy depends: true! installed: true version: 1 cudf-0.6.3/tests/comment-at-eof.cudf000066400000000000000000000000721200672564300172650ustar00rootroot00000000000000preamble: package: a version: 1 request: none # commentcudf-0.6.3/tests/comment-within-stanza.cudf000066400000000000000000000001121200672564300207050ustar00rootroot00000000000000preamble: package: a version: 1 # comment depends: true! request: none cudf-0.6.3/tests/conflict-comma-sep.cudf000066400000000000000000000001671200672564300201370ustar00rootroot00000000000000package: gasoline-engine version: 1 depends: turbo provides: engine conflicts: engine, gasoline-engine installed: true cudf-0.6.3/tests/default-type-check-error.cudf000066400000000000000000000001501200672564300212540ustar00rootroot00000000000000preamble: property: replaces: vpkglist = [ true! ] package: foo version: 1 request: foo install: foo cudf-0.6.3/tests/direct-self-conflict.cudf000066400000000000000000000000671200672564300204560ustar00rootroot00000000000000package: foo version: 1 conflicts: foo installed: true cudf-0.6.3/tests/dup-property.cudf000066400000000000000000000000761200672564300171300ustar00rootroot00000000000000package: a version: 1 depends: b depends: c request: nothing cudf-0.6.3/tests/empty-vpkglist-default.cudf000066400000000000000000000007361200672564300211020ustar00rootroot00000000000000preamble: property: installedsize: nat = [0], size: nat = [0], sourceversion: string = [""], source: string = [""], number: string = [""], recommends: vpkgformula = [true!], replaces: vpkglist = [ ] package: libcdio-paranoia-dev version: 1 depends: libcdio-paranoia0 = 1 , libcdio-cdda-dev , libcdio-dev , libc6-dev | libc-dev--virtual | libc-dev conflicts: libcdio-paranoia-dev number: 0.76-1 source: libcdio sourceversion: 0.76-1 request: foo install: libcdio-paranoia-dev cudf-0.6.3/tests/empty-vpkglist-explicit.cudf000066400000000000000000000005111200672564300212660ustar00rootroot00000000000000preamble: property: replaces: vpkglist # note the trailing space after colon in "replaces:" package: libcdio-paranoia-dev version: 1 depends: libcdio-paranoia0 = 1 , libcdio-cdda-dev , libcdio-dev , libc6-dev | libc-dev--virtual | libc-dev conflicts: libcdio-paranoia-dev replaces: request: foo install: libcdio-paranoia-dev cudf-0.6.3/tests/empty.cudf000066400000000000000000000000001200672564300155770ustar00rootroot00000000000000cudf-0.6.3/tests/fresher-sol-bad.cudf000066400000000000000000000000501200672564300174230ustar00rootroot00000000000000package: foo version: 1 installed: true cudf-0.6.3/tests/fresher-sol-good.cudf000066400000000000000000000000501200672564300176250ustar00rootroot00000000000000package: foo version: 2 installed: true cudf-0.6.3/tests/fresher.cudf000066400000000000000000000002471200672564300161140ustar00rootroot00000000000000package: foo version: 2 installed: true package: foo version: 1 package: foo version: 3 request: source: test 850394e40e69d891d824db71bcda548559040edf upgrade: foo cudf-0.6.3/tests/indirect-self-conflict.cudf000066400000000000000000000001051200672564300207760ustar00rootroot00000000000000package: foo version: 1 provides: bar conflicts: bar installed: true cudf-0.6.3/tests/keep-sol-bad.cudf000066400000000000000000000003411200672564300167140ustar00rootroot00000000000000package: keep-version version: 2 installed: true package: keep-package version: 1 installed: true package: provide-foo provides: foo version: 1 installed: true package: provide-bar provides: bar version: 1 installed: true cudf-0.6.3/tests/keep-sol-bad2.cudf000066400000000000000000000002751200672564300170040ustar00rootroot00000000000000package: keep-version version: 1 installed: true keep: version package: provide-foo provides: foo version: 1 installed: true package: provide-bar provides: bar version: 1 installed: true cudf-0.6.3/tests/keep-sol-bad3.cudf000066400000000000000000000002601200672564300167770ustar00rootroot00000000000000package: keep-version version: 1 installed: true keep: version package: keep-package version: 1 installed: true package: provide-foo provides: foo version: 1 installed: true cudf-0.6.3/tests/keep-sol-good.cudf000066400000000000000000000003571200672564300171250ustar00rootroot00000000000000package: keep-version version: 1 installed: true keep: version package: keep-package version: 1 installed: true package: provide-foo provides: foo version: 1 installed: true package: provide-bar provides: bar version: 1 installed: true cudf-0.6.3/tests/keep-uninst-good.cudf000066400000000000000000000000471200672564300176440ustar00rootroot00000000000000package: bb version: 2 installed: true cudf-0.6.3/tests/keep-uninst.cudf000066400000000000000000000001761200672564300167210ustar00rootroot00000000000000package: aa version: 1 installed: false keep: version package: bb version: 2 installed: true keep: version request: nothing cudf-0.6.3/tests/keep.cudf000066400000000000000000000006521200672564300154020ustar00rootroot00000000000000package: keep-version version: 1 installed: true keep: version package: keep-version version: 2 package: keep-package version: 1 installed: true keep: package package: keep-feature version: 1 provides: foo, bar installed: true keep: feature package: provide-foo provides: foo version: 1 package: provide-bar provides: bar version: 1 request: source: debian/dudf 733fffffb9fe1f78fd551ad20485b217 upgrade: keep-version cudf-0.6.3/tests/legacy-sol.cudf000066400000000000000000000007061200672564300165150ustar00rootroot00000000000000package: car version: 1 depends: engine, wheel, door, battery installed: true package: battery version: 3 provides: huge-battery installed: true package: wheel version: 3 conflicts: wheel installed: true package: door version: 1 conflicts: door installed: true package: bicycle version: 7 installed: true package: electric-engine version: 1 depends: solar-collector | huge-battery provides: engine conflicts: engine, electric-engine installed: true cudf-0.6.3/tests/legacy.cudf000066400000000000000000000037041200672564300157230ustar00rootroot00000000000000preamble: property: suite: enum[stable,testing,unstable] = [stable], bugs: int = [0], description: string = ["no description"] univ-checksum: 8c6d8b4d0cf7027cd523ad095d6408b4901ac31c status-checksum: 6936ce910eb716ad97190393f80c14ab04d95b3d req-checksum: 17259225eaf63642f9ab99a627b9857a5b27c5f7 package: car version: 1 depends: engine, wheel, door, battery installed: true description: 4-wheeled, motor-powered vehicle package: bicycle version: 7 description: 2-wheeled, "pedal-powered" vehicle package: gasoline-engine version: 1 depends: turbo provides: engine conflicts: engine, gasoline-engine installed: true package: gasoline-engine version: 2 provides: engine conflicts: engine, gasoline-engine suite: testing package: electric-engine version: 1 depends: solar-collector | huge-battery provides: engine conflicts: engine, electric-engine bugs: 12 package: electric-engine version: 2 depends: solar-collector | huge-battery provides: engine conflicts: engine, electric-engine suite: unstable bugs: 180 package: solar-collector version: 1 package: battery version: 3 provides: huge-battery installed: true package: wheel version: 2 conflicts: wheel installed: true suite: stable package: wheel version: 3 conflicts: wheel suite: testing package: door version: 1 conflicts: door installed: true package: door version: 2 depends: window conflicts: door suite: unstable package: turbo version: 1 installed: true package: tire version: 1 conflicts: tire package: tire version: 2 conflicts: tire suite: testing package: window version: 1 conflicts: window package: window version: 2 depends: glass = 1 conflicts: window suite: testing package: window version: 3 depends: glass = 2 conflicts: window suite: unstable package: glass version: 1 conflicts: glass package: glass version: 2 conflicts: glass, tire = 2 suite: testing request: http://www.example.org/8f46e388-042f-415e-8aab-df4eeb974444.dudf install: bicycle, electric-engine = 1 upgrade: door, wheel > 2 cudf-0.6.3/tests/legacy.pp.cudf000066400000000000000000000053561200672564300163460ustar00rootroot00000000000000preamble: property: suite: enum[stable,testing,unstable] = [stable], bugs: int = [0], description: string = ["no description"] univ-checksum: 8c6d8b4d0cf7027cd523ad095d6408b4901ac31c status-checksum: 6936ce910eb716ad97190393f80c14ab04d95b3d req-checksum: 17259225eaf63642f9ab99a627b9857a5b27c5f7 package: car version: 1 depends: engine , wheel , door , battery installed: true description: 4-wheeled, motor-powered vehicle bugs: 0 suite: stable package: bicycle version: 7 description: 2-wheeled, "pedal-powered" vehicle bugs: 0 suite: stable package: gasoline-engine version: 1 depends: turbo conflicts: engine , gasoline-engine provides: engine installed: true description: no description bugs: 0 suite: stable package: gasoline-engine version: 2 conflicts: engine , gasoline-engine provides: engine suite: testing description: no description bugs: 0 package: electric-engine version: 1 depends: solar-collector | huge-battery conflicts: engine , electric-engine provides: engine bugs: 12 description: no description suite: stable package: electric-engine version: 2 depends: solar-collector | huge-battery conflicts: engine , electric-engine provides: engine suite: unstable bugs: 180 description: no description package: solar-collector version: 1 description: no description bugs: 0 suite: stable package: battery version: 3 provides: huge-battery installed: true description: no description bugs: 0 suite: stable package: wheel version: 2 conflicts: wheel installed: true suite: stable description: no description bugs: 0 package: wheel version: 3 conflicts: wheel suite: testing description: no description bugs: 0 package: door version: 1 conflicts: door installed: true description: no description bugs: 0 suite: stable package: door version: 2 depends: window conflicts: door suite: unstable description: no description bugs: 0 package: turbo version: 1 installed: true description: no description bugs: 0 suite: stable package: tire version: 1 conflicts: tire description: no description bugs: 0 suite: stable package: tire version: 2 conflicts: tire suite: testing description: no description bugs: 0 package: window version: 1 conflicts: window description: no description bugs: 0 suite: stable package: window version: 2 depends: glass = 1 conflicts: window suite: testing description: no description bugs: 0 package: window version: 3 depends: glass = 2 conflicts: window suite: unstable description: no description bugs: 0 package: glass version: 1 conflicts: glass description: no description bugs: 0 suite: stable package: glass version: 2 conflicts: glass , tire = 2 suite: testing description: no description bugs: 0 request: http://www.example.org/8f46e388-042f-415e-8aab-df4eeb974444.dudf install: bicycle , electric-engine = 1 upgrade: door , wheel > 2 cudf-0.6.3/tests/line-111.cudf000066400000000000000000000037121200672564300157050ustar00rootroot00000000000000preamble: property: suite: enum[stable,testing,unstable] = [stable], bugs: int = [0], description: string = ["no description"] univ-checksum: 8c6d8b4d0cf7027cd523ad095d6408b4901ac31c status-checksum: 6936ce910eb716ad97190393f80c14ab04d95b3d req-checksum: 17259225eaf63642f9ab99a627b9857a5b27c5f7 package: car version: 1 depends: engine, wheel, door, battery installed: true description: 4-wheeled, motor-powered vehicle package: bicycle version: 7 description: 2-wheeled, "pedal-powered" vehicle package: gasoline-engine version: 1 depends: turbo provides: engine conflicts: engine, gasoline-engine installed: true package: gasoline-engine version: 2 provides: engine conflicts: engine, gasoline-engine suite: testing package: electric-engine version: 1 depends: solar-collector | huge-battery provides: engine conflicts: engine, electric-engine bugs: 12 package: electric-engine version: 2 depends: solar-collector | huge-battery provides: engine conflicts: engine, electric-engine suite: unstable bugs: 180 package: solar-collector version: 1 package: battery version: 3 provides: huge-battery installed: true package: wheel version: 2 conflicts: wheel installed: true suite: stable package: wheel version: 3 conflicts: wheel suite: testing package: door version: 1 conflicts: door installed: true package: door version: 2 depends: window conflicts: door suite: unstable package: turbo version: 1 installed: true package: tire version: 1 conflicts: tire package: tire version: 2 conflicts: tire suite: testing package: window version: 1 conflicts: window package: window version: 2 depends: glass = 1 conflicts: window suite: testing package: window version: 3 depends: glass = 2 conflicts: window suite: unstable package: glass version: 1 conflicts: glass package: glass version: 2gotcha conflicts: glass, tire = 2 suite: testing request: http://www.example.org/8f46e388-042f-415e-8aab-df4eeb974444.dudf install: bicycle, electric-engine = 1 upgrade: door, wheel > 2 cudf-0.6.3/tests/miss-mandatory-prop.cudf000066400000000000000000000006771200672564300204120ustar00rootroot00000000000000preamble: property: suite: enum[stable,testing,unstable] = [stable], bugs: int, description: string univ-checksum: 8c6d8b4d0cf7027cd523ad095d6408b4901ac31c status-checksum: 6936ce910eb716ad97190393f80c14ab04d95b3d req-checksum: 17259225eaf63642f9ab99a627b9857a5b27c5f7 package: car version: 1 installed: true description: 4-wheeled, motor-powered vehicle request: http://www.example.org/8f46e388-042f-415e-8aab-dfaaaaaa7777.dudf install: car cudf-0.6.3/tests/missing-stanza-sep-1.cudf000066400000000000000000000000731200672564300203450ustar00rootroot00000000000000package: a version: 1 package: b version: 2 request: none cudf-0.6.3/tests/missing-stanza-sep-2.cudf000066400000000000000000000000441200672564300203440ustar00rootroot00000000000000package: a version: 1 request: none cudf-0.6.3/tests/multi-versions.cudf000066400000000000000000000004661200672564300174610ustar00rootroot00000000000000package: gasoline-engine version: 1 depends: turbo provides: engine conflicts: engine, gasoline-engine installed: true package: gasoline-engine version: 2 conflicts: engine, gasoline-engine installed: true package: battery version: 3 provides: huge-battery installed: true package: not-installed version: 4 cudf-0.6.3/tests/multiline-error.cudf000066400000000000000000000032231200672564300176040ustar00rootroot00000000000000preamble: property: suite: enum[stable,testing,unstable] = [stable], bugs: int = [0], description: string = ["no description"] package: car version: 1 depends: engine, wheel, door, battery installed: true description: 4-wheeled, motor-powered vehicle package: bicycle version: 7 description: 2-wheeled, "pedal-powered" vehicle package: gasoline-engine version: 1 depends: turbo provides: engine conflicts: engine, gasoline-engine installed: true package: gasoline-engine version: 2 provides: engine conflicts: engine, gasoline-engine suite: testing package: electric-engine version: 1 depends: solar-collector | huge-battery provides: engine conflicts: engine, electric-engine bugs: 12 package: electric-engine version: 2 depends: solar-collector | huge-battery provides: engine conflicts: engine, electric-engine suite: unstable bugs: 180 package: solar-collector version: 1 package: battery version: 3 provides: huge-battery installed: true package: wheel version: 2 conflicts: wheel installed: true suite: stable package: wheel version: 3 conflicts: wheel suite: testing package: door version: 1 conflicts: door installed: true package: door version: 2 depends: window conflicts: door suite: unstable package: turbo version: 1 installed: true package: tire version: 1 conflicts: tire package: tire version: 2 conflicts: tire suite: testing package: window version: 1 conflicts: window package: window version: 2 depends: glass = a conflicts: window suite: testing package: window version: 3 depends: glass = 2 conflicts: window suite: unstable package: glass version: 1 conflicts: glass package: glass version: 2 conflicts: glass, tire = 2 suite: testing cudf-0.6.3/tests/only-request.cudf000066400000000000000000000000161200672564300171170ustar00rootroot00000000000000 request: foo cudf-0.6.3/tests/or-dep.cudf000066400000000000000000000002001200672564300156310ustar00rootroot00000000000000package: electric-engine version: 1 depends: solar-collector | huge-battery provides: engine conflicts: engine, electric-engine cudf-0.6.3/tests/plus-in-pkgname.cudf000066400000000000000000000000371200672564300174620ustar00rootroot00000000000000package: libstdc++6 version: 1 cudf-0.6.3/tests/unknown-pkg.cudf000066400000000000000000000001761200672564300167350ustar00rootroot00000000000000package: aa version: 1 installed: false keep: version package: bb version: 2 installed: true keep: version request: nothing cudf-0.6.3/tests/unknown-pkg.sol.cudf000066400000000000000000000000471200672564300175260ustar00rootroot00000000000000package: aa version: 2 installed: true cudf-0.6.3/tests/upgrade-singleton-sol-bad.cudf000066400000000000000000000001211200672564300214130ustar00rootroot00000000000000package: foo version: 1 installed: true package: foo version: 2 installed: true cudf-0.6.3/tests/upgrade-singleton-sol-good.cudf000066400000000000000000000000501200672564300216160ustar00rootroot00000000000000package: foo version: 2 installed: true cudf-0.6.3/tests/upgrade-singleton.cudf000066400000000000000000000002361200672564300201030ustar00rootroot00000000000000package: foo version: 1 installed: true package: foo version: 2 installed: true request: source: test 68a2d0dd26aa1de89b635183dfd6743f0befccfa upgrade: foo cudf-0.6.3/tests/virt-upgrade-sol-bad.cudf000066400000000000000000000001751200672564300204060ustar00rootroot00000000000000package: foo version: 1 provides: virtual = 1 installed: true package: bar version: 1 provides: virtual = 2 installed: true cudf-0.6.3/tests/virt-upgrade-sol-bad2.cudf000066400000000000000000000000721200672564300204640ustar00rootroot00000000000000package: baz version: 1 provides: virtual installed: true cudf-0.6.3/tests/virt-upgrade-sol-bad3.cudf000066400000000000000000000000761200672564300204710ustar00rootroot00000000000000package: foo version: 1 provides: virtual = 1 installed: true cudf-0.6.3/tests/virt-upgrade-sol-good.cudf000066400000000000000000000000761200672564300206100ustar00rootroot00000000000000package: bar version: 1 provides: virtual = 2 installed: true cudf-0.6.3/tests/virt-upgrade.cudf000066400000000000000000000003331200672564300170630ustar00rootroot00000000000000package: foo version: 1 provides: virtual = 1 installed: true package: bar version: 1 provides: virtual = 2 package: baz version: 1 provides: virtual request: source test 12545215421521452145 upgrade: virtual >= 2 cudf-0.6.3/tests/vpkgformula-prop.cudf000066400000000000000000000011641200672564300177700ustar00rootroot00000000000000preamble: property: suite: enum[stable,testing,unstable] = [stable], bugs: int = [0], description: string = ["no description"], recommends: vpkgformula = [ true! ] univ-checksum: 8c6d8b4d0cf7027cd523ad095d6408b4901ac31c status-checksum: 6936ce910eb716ad97190393f80c14ab04d95b3d req-checksum: 17259225eaf63642f9ab99a627b9857a5b27c5f7 package: car version: 1 depends: engine, wheel, door, battery installed: true description: 4-wheeled, motor-powered vehicle recommends: gasoline-engine request: http://www.example.org/8f46e388-042f-415e-8aab-df4eeb974444.dudf install: bicycle, electric-engine = 1 upgrade: door, wheel > 2